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