1 /*
   2  * Copyright (c) 2011, 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   @bug 6431076
  27   @summary Mouse cursor must remain DEFAULT over scrollbar when text is typed
  28   @author Andrei Dmitriev: area=TextArea
  29   @run main/manual Test
  30 */
  31 
  32 import java.awt.*;
  33 import java.awt.event.*;
  34 
  35 public class Test {
  36     private static void init()  {
  37         Frame f = new Frame("Test for cursor");
  38         final int dim = 100;
  39         String line = "";
  40         for( int i=0; i<dim; ++i ) {
  41             line += "a";
  42         }
  43         String text = "";
  44         for( int i=0; i<dim; ++i ) {
  45             text += line;
  46             if( i < dim-1 ) {
  47                 text += "\n";
  48             }
  49         }
  50 
  51         f.setLayout( new BorderLayout () );
  52         f.add( new TextArea( text ) );
  53         f.setSize(400, 300);
  54 
  55         f.setVisible(true);
  56 
  57         String[] instructions = {
  58             "1. Place keyboard cursor inside TextArea.",
  59             "2. Repeat steps 2.* for each of two TextArea's scrollbars.",
  60             "2.1. Place mouse cursor over TextArea's scrollbar.",
  61             "2.2. If mouse cursor is not DEFAULT_CURSOR (arrow), test failed.",
  62             "2.3. Type any symbol into TextArea.",
  63             "2.4. Type ENTER symbol into TextArea.",
  64             "2.5. If mouse cursor changes to TEXT_CURSOR (beam), test failed",
  65             "(if cursor disappears on Windows, it's OK).",
  66             "3. Test passed.",
  67         };
  68 
  69         Sysout.createDialogWithInstructions( instructions );
  70     }
  71 
  72 
  73 
  74     /*****************************************************
  75      * Standard Test Machinery Section
  76      * DO NOT modify anything in this section -- it's a
  77      * standard chunk of code which has all of the
  78      * synchronisation necessary for the test harness.
  79      * By keeping it the same in all tests, it is easier
  80      * to read and understand someone else's test, as
  81      * well as insuring that all tests behave correctly
  82      * with the test harness.
  83      * There is a section following this for test-defined
  84      * classes
  85      ******************************************************/
  86     private static boolean theTestPassed = false;
  87     private static boolean testGeneratedInterrupt = false;
  88     private static String failureMessage = "";
  89 
  90     private static Thread mainThread = null;
  91 
  92     private static int sleepTime = 300000;
  93 
  94     public static void main( String args[] ) throws InterruptedException
  95     {
  96         mainThread = Thread.currentThread();
  97         try
  98         {
  99             init();
 100         }
 101         catch( TestPassedException e )
 102         {
 103             //The test passed, so just return from main and harness will
 104             // interepret this return as a pass
 105             return;
 106         }
 107         //At this point, neither test passed nor test failed has been
 108         // called -- either would have thrown an exception and ended the
 109         // test, so we know we have multiple threads.
 110 
 111         //Test involves other threads, so sleep and wait for them to
 112         // called pass() or fail()
 113         try
 114         {
 115             Thread.sleep( sleepTime );
 116             //Timed out, so fail the test
 117             throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
 118         }
 119         catch (InterruptedException e)
 120         {
 121             if( ! testGeneratedInterrupt ) throw e;
 122 
 123             //reset flag in case hit this code more than once for some reason (just safety)
 124             testGeneratedInterrupt = false;
 125             if ( theTestPassed == false )
 126             {
 127                 throw new RuntimeException( failureMessage );
 128             }
 129         }
 130 
 131     }//main
 132 
 133     public static synchronized void setTimeoutTo( int seconds )
 134     {
 135         sleepTime = seconds * 1000;
 136     }
 137 
 138     public static synchronized void pass()
 139     {
 140         Sysout.println( "The test passed." );
 141         Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
 142         //first check if this is executing in main thread
 143         if ( mainThread == Thread.currentThread() )
 144         {
 145             //Still in the main thread, so set the flag just for kicks,
 146             // and throw a test passed exception which will be caught
 147             // and end the test.
 148             theTestPassed = true;
 149             throw new TestPassedException();
 150         }
 151         //pass was called from a different thread, so set the flag and interrupt
 152         // the main thead.
 153         theTestPassed = true;
 154         testGeneratedInterrupt = true;
 155         if (mainThread != null){
 156             mainThread.interrupt();
 157         }
 158     }//pass()
 159 
 160     public static synchronized void fail()
 161     {
 162         //test writer didn't specify why test failed, so give generic
 163         fail( "it just plain failed! :-)" );
 164     }
 165 
 166     public static synchronized void fail( String whyFailed )
 167     {
 168         Sysout.println( "The test failed: " + whyFailed );
 169         Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
 170         //check if this called from main thread
 171         if ( mainThread == Thread.currentThread() )
 172         {
 173             //If main thread, fail now 'cause not sleeping
 174             throw new RuntimeException( whyFailed );
 175         }
 176         theTestPassed = false;
 177         testGeneratedInterrupt = true;
 178         failureMessage = whyFailed;
 179         mainThread.interrupt();
 180     }//fail()
 181 
 182 }// class
 183 
 184 //This exception is used to exit from any level of call nesting
 185 // when it's determined that the test has passed, and immediately
 186 // end the test.
 187 class TestPassedException extends RuntimeException
 188 {
 189 }
 190 
 191 //*********** End Standard Test Machinery Section **********
 192 
 193 
 194 //************ Begin classes defined for the test ****************
 195 
 196 // make listeners in a class defined here, and instantiate them in init()
 197 
 198 /* Example of a class which may be written as part of a test
 199 class NewClass implements anInterface
 200  {
 201    static int newVar = 0;
 202 
 203    public void eventDispatched(AWTEvent e)
 204     {
 205       //Counting events to see if we get enough
 206       eventCount++;
 207 
 208       if( eventCount == 20 )
 209        {
 210          //got enough events, so pass
 211 
 212          ManualMainTest.pass();
 213        }
 214       else if( tries == 20 )
 215        {
 216          //tried too many times without getting enough events so fail
 217 
 218          ManualMainTest.fail();
 219        }
 220 
 221     }// eventDispatched()
 222 
 223  }// NewClass class
 224 
 225 */
 226 
 227 
 228 //************** End classes defined for the test *******************
 229 
 230 
 231 
 232 
 233 /****************************************************
 234  Standard Test Machinery
 235  DO NOT modify anything below -- it's a standard
 236   chunk of code whose purpose is to make user
 237   interaction uniform, and thereby make it simpler
 238   to read and understand someone else's test.
 239  ****************************************************/
 240 
 241 /**
 242  This is part of the standard test machinery.
 243  It creates a dialog (with the instructions), and is the interface
 244   for sending text messages to the user.
 245  To print the instructions, send an array of strings to Sysout.createDialog
 246   WithInstructions method.  Put one line of instructions per array entry.
 247  To display a message for the tester to see, simply call Sysout.println
 248   with the string to be displayed.
 249  This mimics System.out.println but works within the test harness as well
 250   as standalone.
 251  */
 252 
 253 class Sysout
 254 {
 255     private static TestDialog dialog;
 256     private static boolean numbering = false;
 257     private static int messageNumber = 0;
 258 
 259     public static void createDialogWithInstructions( String[] instructions )
 260     {
 261         dialog = new TestDialog( new Frame(), "Instructions" );
 262         dialog.printInstructions( instructions );
 263         dialog.setVisible(true);
 264         println( "Any messages for the tester will display here." );
 265     }
 266 
 267     public static void createDialog( )
 268     {
 269         dialog = new TestDialog( new Frame(), "Instructions" );
 270         String[] defInstr = { "Instructions will appear here. ", "" } ;
 271         dialog.printInstructions( defInstr );
 272         dialog.setVisible(true);
 273         println( "Any messages for the tester will display here." );
 274     }
 275 
 276 
 277     /* Enables message counting for the tester. */
 278     public static void enableNumbering(boolean enable){
 279         numbering = enable;
 280     }
 281 
 282     public static void printInstructions( String[] instructions )
 283     {
 284         dialog.printInstructions( instructions );
 285     }
 286 
 287 
 288     public static void println( String messageIn )
 289     {
 290         if (numbering) {
 291             messageIn = "" + messageNumber + " " + messageIn;
 292             messageNumber++;
 293         }
 294         dialog.displayMessage( messageIn );
 295     }
 296 
 297 }// Sysout  class
 298 
 299 /**
 300   This is part of the standard test machinery.  It provides a place for the
 301    test instructions to be displayed, and a place for interactive messages
 302    to the user to be displayed.
 303   To have the test instructions displayed, see Sysout.
 304   To have a message to the user be displayed, see Sysout.
 305   Do not call anything in this dialog directly.
 306   */
 307 class TestDialog extends Dialog implements ActionListener
 308 {
 309 
 310     TextArea instructionsText;
 311     TextArea messageText;
 312     int maxStringLength = 80;
 313     Panel  buttonP = new Panel();
 314     Button passB = new Button( "pass" );
 315     Button failB = new Button( "fail" );
 316 
 317     //DO NOT call this directly, go through Sysout
 318     public TestDialog( Frame frame, String name )
 319     {
 320         super( frame, name );
 321         int scrollBoth = TextArea.SCROLLBARS_BOTH;
 322         instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
 323         add( "North", instructionsText );
 324 
 325         messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
 326         add("Center", messageText);
 327 
 328         passB = new Button( "pass" );
 329         passB.setActionCommand( "pass" );
 330         passB.addActionListener( this );
 331         buttonP.add( "East", passB );
 332 
 333         failB = new Button( "fail" );
 334         failB.setActionCommand( "fail" );
 335         failB.addActionListener( this );
 336         buttonP.add( "West", failB );
 337 
 338         add( "South", buttonP );
 339         pack();
 340 
 341         setVisible(true);
 342     }// TestDialog()
 343 
 344     //DO NOT call this directly, go through Sysout
 345     public void printInstructions( String[] instructions )
 346     {
 347         //Clear out any current instructions
 348         instructionsText.setText( "" );
 349 
 350         //Go down array of instruction strings
 351 
 352         String printStr, remainingStr;
 353         for( int i=0; i < instructions.length; i++ )
 354         {
 355             //chop up each into pieces maxSringLength long
 356             remainingStr = instructions[ i ];
 357             while( remainingStr.length() > 0 )
 358             {
 359                 //if longer than max then chop off first max chars to print
 360                 if( remainingStr.length() >= maxStringLength )
 361                 {
 362                     //Try to chop on a word boundary
 363                     int posOfSpace = remainingStr.
 364                         lastIndexOf( ' ', maxStringLength - 1 );
 365 
 366                     if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
 367 
 368                     printStr = remainingStr.substring( 0, posOfSpace + 1 );
 369                     remainingStr = remainingStr.substring( posOfSpace + 1 );
 370                 }
 371                 //else just print
 372                 else
 373                 {
 374                     printStr = remainingStr;
 375                     remainingStr = "";
 376                 }
 377 
 378                 instructionsText.append( printStr + "\n" );
 379 
 380             }// while
 381 
 382         }// for
 383 
 384     }//printInstructions()
 385 
 386     //DO NOT call this directly, go through Sysout
 387     public void displayMessage( String messageIn )
 388     {
 389         messageText.append( messageIn + "\n" );
 390         System.out.println(messageIn);
 391     }
 392 
 393     //catch presses of the passed and failed buttons.
 394     //simply call the standard pass() or fail() static methods of
 395     //ManualMainTest
 396     public void actionPerformed( ActionEvent e )
 397     {
 398         if( e.getActionCommand() == "pass" )
 399         {
 400             Test.pass();
 401         }
 402         else
 403         {
 404             Test.fail();
 405         }
 406     }
 407 
 408 }// TestDialog  class