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