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 @summary Make sure that we can handle mouse and key events in a relatively simple component heirarchy 27 @summary This test creates a frame with several nested panels (as well as several labels that tell where things are) 28 @summary It then makes sure the frame is visible, requests focus in the top panel, and then either clicks or types in this panel 29 @summary com.apple.junit.java.awt.Event; 30 @library ../../regtesthelpers 31 @build RobotUtilities 32 @build VisibilityValidator 33 @run main EventHeirachyWithListeners 34 */ 35 36 import junit.framework.*; 37 38 import java.awt.*; 39 import java.awt.event.*; 40 import java.util.*; 41 42 import test.java.awt.regtesthelpers.RobotUtilities; 43 import test.java.awt.regtesthelpers.VisibilityValidator; 44 45 public class EventHeirachyWithListeners extends TestCase { 46 static final Random rand = new Random(161566); 47 static final boolean DEBUG = false; 48 private static final int TIMEOUT = 5000; // Timeout for expected events 49 protected Timer ticktock; 50 protected TestFrame f; 51 52 53 // Make a frame with several nested panels 54 // These panels needs some knowledge of what focus events and click events the test will generate 55 @SuppressWarnings("serial") 56 class TestFrame extends Frame { 57 static final int NUM_NESTED_PANELS = 6; 58 static final int BOTTOM_PANEL = 0; 59 static final int TOP_PANEL = NUM_NESTED_PANELS-1; 60 TestPanel fPanels[] = new TestPanel[NUM_NESTED_PANELS]; 61 Label fStatusLabel = new Label("Waiting for the test to get around to putting some status into this label."); 62 private volatile int fEventCount; 63 private volatile boolean fFocused; 64 65 // This is a sub-panel set up with listeners which watch for our test events 66 class TestPanel extends Panel { 67 // Panel identifier, for debug purposes 68 int id; 69 70 public TestPanel( int id) { 71 this.id = id; 72 setMinimumSize(new Dimension(200, 100)); 73 74 // Give it a vaguely interesting color 75 Color color = new Color( 0x80 + rand.nextInt(0x80), 0x80 + rand.nextInt(0x80), 0x80 + rand.nextInt(0x80) ); 76 setBackground(color); 77 78 // Hack in some spacers so we can see the nesting 79 setLayout( new BorderLayout()); 80 add( new Label( "-"+id+"-", Label.CENTER), BorderLayout.NORTH); 81 add( new Label( "-"+id+"-", Label.CENTER), BorderLayout.SOUTH); 82 add( new Label( "-"+id+"-", Label.CENTER), BorderLayout.EAST); 83 add( new Label( "-"+id+"-", Label.CENTER), BorderLayout.WEST); 84 85 // Add the listners 86 TestFrame.this.doListeners( this ); 87 } 88 89 // Painting, mostly for debug purposes 90 @Override 91 public void paint(Graphics g) { 92 super.paint(g); 93 Dimension size = getSize(); 94 g.setColor( Color.BLACK ); 95 g.drawString (" Panel " + id , 30, size.height/2 ); 96 } 97 98 // A more informative toString() for debugging 99 @Override 100 public String toString() { 101 String me = "Test Panel " + id; 102 if (id == BOTTOM_PANEL) { 103 me += " - bottom "; 104 } 105 if (id == TOP_PANEL) { 106 me += " - top"; 107 } 108 return me; 109 } 110 } 111 112 // Constructor to build the frame and add the sub-panels 113 public TestFrame( int width, int height ) throws Exception { 114 setLayout( new BorderLayout()); 115 add(fStatusLabel,BorderLayout.NORTH); 116 117 for (int i = 0; i < fPanels.length; i++) { 118 fPanels[i] = new TestPanel(i); 119 if (i != BOTTOM_PANEL) { 120 fPanels[i-1].add(fPanels[i],BorderLayout.CENTER); 121 } 122 else { 123 add( fPanels[BOTTOM_PANEL],BorderLayout.CENTER); 124 } 125 } 126 127 // explicitly watch for a focus event on the top panel 128 // this get us out of our loopForFocus() in the tests below 129 fPanels[TOP_PANEL].addFocusListener(new FocusAdapter() { 130 @Override 131 public void focusGained(FocusEvent e) { 132 if (DEBUG) {System.out.println(e);} 133 handleFocusEvent(); 134 } 135 }); 136 137 setMinimumSize(new Dimension(width, height)); 138 pack(); 139 } 140 141 // events will get us out of the loopForEvents below 142 synchronized void handleRobotEvent() { 143 fEventCount++; 144 notify(); 145 } 146 147 // events will get us out of the loopForFocus loop below 148 synchronized void handleFocusEvent() { 149 fFocused = true; 150 notify(); 151 } 152 153 // Accessor for the top panel 154 public TestPanel getTopPanel() { 155 return (fPanels[TOP_PANEL]); 156 } 157 158 // Add in the key/mouse listeners 159 void doListeners( Component c) { 160 c.addKeyListener( new KeyAdapter() { 161 @Override 162 public void keyPressed( KeyEvent e ) { 163 if (DEBUG) {System.out.println(e);} 164 handleRobotEvent(); 165 } 166 } ); 167 c.addMouseListener( new MouseAdapter() { 168 @Override 169 public void mousePressed( MouseEvent e ) { 170 handleRobotEvent(); 171 if (DEBUG) {System.out.println(e);} 172 } 173 } ); 174 175 } 176 177 // smart loop waiting for focus event 178 synchronized public boolean loopForFocus() throws Exception { 179 long endtime = System.currentTimeMillis() + TIMEOUT; 180 int count = 0; 181 while (fFocused == false) { 182 // Debugging feedback 183 if (System.currentTimeMillis() < endtime) { 184 fStatusLabel.setText((count++) + " Waiting for the top panel to get focus."); 185 fStatusLabel.repaint(); 186 wait( TIMEOUT / 100 ); 187 } 188 else { 189 break; 190 } 191 } 192 return (fFocused); 193 } 194 195 // smart loop waiting for key/mouse events 196 synchronized public boolean loopForEvents( int total, long timeout ) throws Exception { 197 long endtime = System.currentTimeMillis() + timeout; 198 int count = 0; 199 while (fEventCount < total) { 200 // Debugging feedback 201 if (System.currentTimeMillis() < endtime) { 202 fStatusLabel.setText((count++) + " Waiting for the Robot to press any key or click mouse..."); 203 fStatusLabel.repaint(); 204 wait( timeout / 100 ); 205 } 206 else { 207 break; 208 } 209 } 210 return (fEventCount == total); 211 } 212 } 213 214 215 // setUp delivers a test frame with a focused top panel 216 @Override 217 protected void setUp() throws Exception { 218 ticktock = new Timer(); 219 f = new TestFrame( 400, 500 ); 220 VisibilityValidator.setVisibleAndConfirm(f); 221 222 // In a few seconds, make the top panel the fFocused 223 TimerTask action = new TimerTask() { 224 @Override 225 public void run() { 226 Panel p = f.getTopPanel(); 227 if (DEBUG) {System.out.println("Grabbing Focus" + p);} 228 p.requestFocus(); 229 230 } 231 }; 232 ticktock.schedule( action, TIMEOUT/4 ); 233 234 // Meanwhile, wait for the event 235 boolean focusOK = f.loopForFocus( ); 236 assertTrue( "Top panel never got a focus event", focusOK ); 237 238 } 239 240 // tearDown destroys a test frame 241 @Override 242 protected void tearDown() throws Exception { 243 // Thread.sleep(50000); 244 f.dispose(); 245 ticktock.cancel(); 246 } 247 248 // Make sure we can handle a simple mouse click 249 public void testMouseEvent() throws Exception { 250 251 // In a few more seconds, click the mouse 252 TimerTask action = new TimerTask() { 253 @Override 254 public void run() { 255 Panel p = f.getTopPanel(); 256 RobotUtilities.click(p); 257 } 258 }; 259 ticktock.schedule( action, TIMEOUT/4 ); 260 261 // Meanwhile, wait for the event 262 boolean gotEvent = f.loopForEvents( 1, TIMEOUT ); 263 assertTrue( "We should have gotten a single mouse click", gotEvent ); 264 } 265 266 267 // Make sure we can handle a simple key event 268 public void testKeyEvent() throws Exception { 269 270 // In a few more seconds, hit the space bar 271 TimerTask action = new TimerTask() { 272 @Override 273 public void run() { 274 RobotUtilities.typeKey( KeyEvent.VK_SPACE ); 275 } 276 }; 277 ticktock.schedule( action, TIMEOUT/4 ); 278 279 // Meanwhile, wait for the event 280 boolean gotEvent = f.loopForEvents( 1, TIMEOUT ); 281 assertTrue( "We should have gotten a single keyboard space bar pressed", gotEvent ); 282 } 283 284 285 // Make sure diableEvent works 286 public void testKeyEventDisabled() throws Exception { 287 288 // Disable the top panel 289 Panel p = f.getTopPanel(); 290 p.setEnabled(false); 291 292 // In a few more seconds, hit the space bar 293 TimerTask action = new TimerTask() { 294 @Override 295 public void run() { 296 RobotUtilities.typeKey( KeyEvent.VK_SPACE ); 297 } 298 }; 299 ticktock.schedule( action, TIMEOUT/4 ); 300 301 // We expect to hit the timeout, as we have disabled the component that gets the event 302 // Use a shorter timeout -- 5 seconds is a long time... 303 boolean gotEvent = f.loopForEvents( 1, TIMEOUT/3 ); 304 305 // We should not get events, as we are disabled 306 assertFalse( "We should time out without ever getting any events", gotEvent ); 307 } 308 309 public static Test suite() { 310 return new TestSuite( EventHeirachyWithListeners.class); 311 } 312 313 public static void main (String[] args) throws RuntimeException { 314 TestResult tr = junit.textui.TestRunner.run(suite()); 315 if((tr.errorCount() != 0) || (tr.failureCount() != 0)) { 316 throw new RuntimeException("### Unexpected JUnit errors or failures."); 317 } 318 } 319 }