1 /* 2 * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 @test 28 @bug 6383903 8144166 29 @summary REGRESSION: componentMoved is now getting called for some hidden components 30 @author andrei.dmitriev: area=awt.component 31 @run main CompEventOnHiddenComponent 32 */ 33 34 import java.awt.*; 35 import java.awt.event.*; 36 import javax.swing.*; 37 38 public class CompEventOnHiddenComponent 39 { 40 transient static boolean moved = false; 41 transient static boolean resized = false; 42 43 transient static boolean ancestor_moved = false; 44 transient static boolean ancestor_resized = false; 45 static String passed = ""; 46 47 private static void init() 48 { 49 String[] instructions = 50 { 51 "This is an AUTOMATIC test, simply wait until it is done.", 52 "The result (passed or failed) will be shown in the", 53 "message window below." 54 }; 55 Sysout.createDialog( ); 56 Sysout.printInstructions( instructions ); 57 58 Robot robot; 59 try { 60 robot = new Robot(); 61 }catch(Exception ex) { 62 ex.printStackTrace(); 63 throw new RuntimeException("Unexpected failure"); 64 } 65 66 EventQueue.invokeLater(new Runnable(){ 67 public void run(){ 68 JFrame f = new JFrame("JFrame"); 69 JButton b = new JButton("JButton"); 70 f.add(b); 71 new JOptionPane(). 72 createInternalFrame(b, "Test"). 73 addComponentListener(new ComponentAdapter() { 74 public void componentMoved(ComponentEvent e) { 75 moved = true; 76 System.out.println(e); 77 } 78 public void componentResized(ComponentEvent e) { 79 resized = true; 80 System.out.println(e); 81 } 82 }); 83 } 84 }); 85 86 robot.waitForIdle(); 87 88 if (moved || resized){ 89 passed = "Hidden component got COMPONENT_MOVED or COMPONENT_RESIZED event"; 90 } else { 91 System.out.println("Stage 1 passed."); 92 } 93 94 EventQueue.invokeLater(new Runnable() { 95 public void run() { 96 JFrame parentWindow = new JFrame("JFrame 1"); 97 JButton component = new JButton("JButton 1");; 98 JButton smallButton = new JButton("Small Button"); 99 100 101 smallButton.addHierarchyBoundsListener(new HierarchyBoundsAdapter() { 102 public void ancestorMoved(HierarchyEvent e) { 103 ancestor_moved = true; 104 System.out.println("SMALL COMPONENT >>>>>"+e); 105 } 106 public void ancestorResized(HierarchyEvent e) { 107 ancestor_resized = true; 108 System.out.println("SMALL COMPONENT >>>>>"+e); 109 } 110 }); 111 112 113 parentWindow.add(component); 114 component.add(smallButton); 115 116 component.setSize(100, 100); 117 component.setLocation(100, 100); 118 119 } 120 }); 121 122 robot.waitForIdle(); 123 124 if (!ancestor_resized || !ancestor_moved){ 125 passed = "Hidden component didn't get ANCESTOR event"; 126 } else { 127 System.out.println("Stage 2 passed."); 128 } 129 130 robot.waitForIdle(); 131 132 if (passed.equals("")){ 133 CompEventOnHiddenComponent.pass(); 134 } else { 135 CompEventOnHiddenComponent.fail(passed); 136 } 137 138 }//End init() 139 140 141 142 /***************************************************** 143 * Standard Test Machinery Section 144 * DO NOT modify anything in this section -- it's a 145 * standard chunk of code which has all of the 146 * synchronisation necessary for the test harness. 147 * By keeping it the same in all tests, it is easier 148 * to read and understand someone else's test, as 149 * well as insuring that all tests behave correctly 150 * with the test harness. 151 * There is a section following this for test- 152 * classes 153 ******************************************************/ 154 private static boolean theTestPassed = false; 155 private static boolean testGeneratedInterrupt = false; 156 private static String failureMessage = ""; 157 158 private static Thread mainThread = null; 159 160 private static int sleepTime = 300000; 161 162 // Not sure about what happens if multiple of this test are 163 // instantiated in the same VM. Being static (and using 164 // static vars), it aint gonna work. Not worrying about 165 // it for now. 166 public static void main( String args[] ) throws InterruptedException 167 { 168 mainThread = Thread.currentThread(); 169 try 170 { 171 init(); 172 } 173 catch( TestPassedException e ) 174 { 175 //The test passed, so just return from main and harness will 176 // interepret this return as a pass 177 return; 178 } 179 //At this point, neither test pass nor test fail has been 180 // called -- either would have thrown an exception and ended the 181 // test, so we know we have multiple threads. 182 183 //Test involves other threads, so sleep and wait for them to 184 // called pass() or fail() 185 try 186 { 187 Thread.sleep( sleepTime ); 188 //Timed out, so fail the test 189 throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); 190 } 191 catch (InterruptedException e) 192 { 193 //The test harness may have interrupted the test. If so, rethrow the exception 194 // so that the harness gets it and deals with it. 195 if( ! testGeneratedInterrupt ) throw e; 196 197 //reset flag in case hit this code more than once for some reason (just safety) 198 testGeneratedInterrupt = false; 199 200 if ( theTestPassed == false ) 201 { 202 throw new RuntimeException( failureMessage ); 203 } 204 } 205 206 }//main 207 208 public static synchronized void setTimeoutTo( int seconds ) 209 { 210 sleepTime = seconds * 1000; 211 } 212 213 public static synchronized void pass() 214 { 215 Sysout.println( "The test passed." ); 216 Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); 217 //first check if this is executing in main thread 218 if ( mainThread == Thread.currentThread() ) 219 { 220 //Still in the main thread, so set the flag just for kicks, 221 // and throw a test passed exception which will be caught 222 // and end the test. 223 theTestPassed = true; 224 throw new TestPassedException(); 225 } 226 theTestPassed = true; 227 testGeneratedInterrupt = true; 228 mainThread.interrupt(); 229 }//pass() 230 231 public static synchronized void fail() 232 { 233 //test writer didn't specify why test failed, so give generic 234 fail( "it just plain failed! :-)" ); 235 } 236 237 public static synchronized void fail( String whyFailed ) 238 { 239 Sysout.println( "The test failed: " + whyFailed ); 240 Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); 241 //check if this called from main thread 242 if ( mainThread == Thread.currentThread() ) 243 { 244 //If main thread, fail now 'cause not sleeping 245 throw new RuntimeException( whyFailed ); 246 } 247 theTestPassed = false; 248 testGeneratedInterrupt = true; 249 failureMessage = whyFailed; 250 mainThread.interrupt(); 251 }//fail() 252 253 }// class CompEventOnHiddenComponent 254 255 //This exception is used to exit from any level of call nesting 256 // when it's determined that the test has passed, and immediately 257 // end the test. 258 class TestPassedException extends RuntimeException 259 { 260 } 261 262 //*********** End Standard Test Machinery Section ********** 263 264 265 //************ Begin classes defined for the test **************** 266 267 // if want to make listeners, here is the recommended place for them, then instantiate 268 // them in init() 269 270 /* Example of a class which may be written as part of a test 271 class NewClass implements anInterface 272 { 273 static int newVar = 0; 274 275 public void eventDispatched(AWTEvent e) 276 { 277 //Counting events to see if we get enough 278 eventCount++; 279 280 if( eventCount == 20 ) 281 { 282 //got enough events, so pass 283 284 CompEventOnHiddenComponent.pass(); 285 } 286 else if( tries == 20 ) 287 { 288 //tried too many times without getting enough events so fail 289 290 CompEventOnHiddenComponent.fail(); 291 } 292 293 }// eventDispatched() 294 295 }// NewClass class 296 297 */ 298 299 300 //************** End classes defined for the test ******************* 301 302 303 304 305 /**************************************************** 306 Standard Test Machinery 307 DO NOT modify anything below -- it's a standard 308 chunk of code whose purpose is to make user 309 interaction uniform, and thereby make it simpler 310 to read and understand someone else's test. 311 ****************************************************/ 312 313 /** 314 This is part of the standard test machinery. 315 It creates a dialog (with the instructions), and is the interface 316 for sending text messages to the user. 317 To print the instructions, send an array of strings to Sysout.createDialog 318 WithInstructions method. Put one line of instructions per array entry. 319 To display a message for the tester to see, simply call Sysout.println 320 with the string to be displayed. 321 This mimics System.out.println but works within the test harness as well 322 as standalone. 323 */ 324 325 class Sysout 326 { 327 private static TestDialog dialog; 328 329 public static void createDialogWithInstructions( String[] instructions ) 330 { 331 dialog = new TestDialog( new Frame(), "Instructions" ); 332 dialog.printInstructions( instructions ); 333 dialog.setVisible(true); 334 println( "Any messages for the tester will display here." ); 335 } 336 337 public static void createDialog( ) 338 { 339 dialog = new TestDialog( new Frame(), "Instructions" ); 340 String[] defInstr = { "Instructions will appear here. ", "" } ; 341 dialog.printInstructions( defInstr ); 342 dialog.setVisible(true); 343 println( "Any messages for the tester will display here." ); 344 } 345 346 347 public static void printInstructions( String[] instructions ) 348 { 349 dialog.printInstructions( instructions ); 350 } 351 352 353 public static void println( String messageIn ) 354 { 355 dialog.displayMessage( messageIn ); 356 System.out.println(messageIn); 357 } 358 359 }// Sysout class 360 361 /** 362 This is part of the standard test machinery. It provides a place for the 363 test instructions to be displayed, and a place for interactive messages 364 to the user to be displayed. 365 To have the test instructions displayed, see Sysout. 366 To have a message to the user be displayed, see Sysout. 367 Do not call anything in this dialog directly. 368 */ 369 class TestDialog extends Dialog 370 { 371 372 TextArea instructionsText; 373 TextArea messageText; 374 int maxStringLength = 80; 375 376 //DO NOT call this directly, go through Sysout 377 public TestDialog( Frame frame, String name ) 378 { 379 super( frame, name ); 380 int scrollBoth = TextArea.SCROLLBARS_BOTH; 381 instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); 382 add( "North", instructionsText ); 383 384 messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); 385 add("Center", messageText); 386 387 pack(); 388 389 setVisible(true); 390 }// TestDialog() 391 392 //DO NOT call this directly, go through Sysout 393 public void printInstructions( String[] instructions ) 394 { 395 //Clear out any current instructions 396 instructionsText.setText( "" ); 397 398 //Go down array of instruction strings 399 400 String printStr, remainingStr; 401 for( int i=0; i < instructions.length; i++ ) 402 { 403 //chop up each into pieces maxSringLength long 404 remainingStr = instructions[ i ]; 405 while( remainingStr.length() > 0 ) 406 { 407 //if longer than max then chop off first max chars to print 408 if( remainingStr.length() >= maxStringLength ) 409 { 410 //Try to chop on a word boundary 411 int posOfSpace = remainingStr. 412 lastIndexOf( ' ', maxStringLength - 1 ); 413 414 if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; 415 416 printStr = remainingStr.substring( 0, posOfSpace + 1 ); 417 remainingStr = remainingStr.substring( posOfSpace + 1 ); 418 } 419 //else just print 420 else 421 { 422 printStr = remainingStr; 423 remainingStr = ""; 424 } 425 426 instructionsText.append( printStr + "\n" ); 427 428 }// while 429 430 }// for 431 432 }//printInstructions() 433 434 //DO NOT call this directly, go through Sysout 435 public void displayMessage( String messageIn ) 436 { 437 messageText.append( messageIn + "\n" ); 438 System.out.println(messageIn); 439 } 440 441 }// TestDialog class