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