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