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