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.  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 package javafx.scene;
  27 
  28 import static org.junit.Assert.assertEquals;
  29 
  30 import java.util.Arrays;
  31 import java.util.Collection;
  32 
  33 import javafx.event.Event;
  34 import javafx.event.EventHandler;
  35 import javafx.event.EventType;
  36 import javafx.scene.input.KeyCode;
  37 import javafx.scene.input.KeyEvent;
  38 import javafx.scene.input.MouseButton;
  39 import javafx.scene.input.MouseEvent;
  40 import javafx.scene.shape.Rectangle;
  41 
  42 import org.junit.Test;
  43 import org.junit.runner.RunWith;
  44 import org.junit.runners.Parameterized;
  45 import org.junit.runners.Parameterized.Parameters;
  46 
  47 import com.sun.javafx.test.PropertyReference;
  48 import com.sun.javafx.test.MouseEventGenerator;
  49 import javafx.scene.input.ContextMenuEvent;
  50 import javafx.scene.input.SwipeEvent;
  51 
  52 @RunWith(Parameterized.class)
  53 public final class Scenegraph_eventHandlers_Test {
  54     private final EventType<?> eventType;
  55     private final PropertyReference sceneOnHandlerPropRef;
  56     private final PropertyReference nodeOnHandlerPropRef;
  57     private final Event triggeringEvent;
  58 
  59     @Parameters
  60     public static Collection data() {
  61         final MouseEventGenerator mouseEventGenerator =
  62                 new MouseEventGenerator();
  63         return Arrays.asList(new Object[][] {
  64             {
  65                 KeyEvent.KEY_PRESSED,
  66                 "onKeyPressed",
  67                 createTestKeyEvent(KeyEvent.KEY_PRESSED)
  68             }, {
  69                 KeyEvent.KEY_RELEASED,
  70                 "onKeyReleased",
  71                 createTestKeyEvent(KeyEvent.KEY_RELEASED)
  72             }, {
  73                 KeyEvent.KEY_TYPED,
  74                 "onKeyTyped",
  75                 createTestKeyEvent(KeyEvent.KEY_TYPED)
  76             }, {
  77                 MouseEvent.MOUSE_PRESSED,
  78                 "onMousePressed",
  79                 mouseEventGenerator.generateMouseEvent(
  80                         MouseEvent.MOUSE_PRESSED, 0, 0)
  81             }, {
  82                 MouseEvent.MOUSE_RELEASED,
  83                 "onMouseReleased",
  84                 mouseEventGenerator.generateMouseEvent(
  85                         MouseEvent.MOUSE_RELEASED, 0, 0)
  86             }, {
  87                 MouseEvent.MOUSE_CLICKED,
  88                 "onMouseClicked",
  89                 mouseEventGenerator.generateMouseEvent(
  90                         MouseEvent.MOUSE_CLICKED, 0, 0)
  91             }, {
  92                 MouseEvent.MOUSE_ENTERED,
  93                 "onMouseEntered",
  94                 mouseEventGenerator.generateMouseEvent(
  95                         MouseEvent.MOUSE_ENTERED, 0, 0)
  96             }, {
  97                 MouseEvent.MOUSE_EXITED,
  98                 "onMouseExited",
  99                 mouseEventGenerator.generateMouseEvent(
 100                         MouseEvent.MOUSE_EXITED, 0, 0)
 101             }, {
 102                 MouseEvent.MOUSE_MOVED,
 103                 "onMouseMoved",
 104                 mouseEventGenerator.generateMouseEvent(
 105                         MouseEvent.MOUSE_MOVED, 0, 0)
 106             }, {
 107                 MouseEvent.MOUSE_DRAGGED,
 108                 "onMouseDragged",
 109                 mouseEventGenerator.generateMouseEvent(
 110                         MouseEvent.MOUSE_DRAGGED, 0, 0)
 111             }, {
 112                 SwipeEvent.SWIPE_LEFT,
 113                 "onSwipeLeft",
 114                 createSwipeEvent(SwipeEvent.SWIPE_LEFT)
 115             }, {
 116                 SwipeEvent.SWIPE_RIGHT,
 117                 "onSwipeRight",
 118                 createSwipeEvent(SwipeEvent.SWIPE_RIGHT)
 119             }, {
 120                 SwipeEvent.SWIPE_UP,
 121                 "onSwipeUp",
 122                 createSwipeEvent(SwipeEvent.SWIPE_UP)
 123             }, {
 124                 SwipeEvent.SWIPE_DOWN,
 125                 "onSwipeDown",
 126                 createSwipeEvent(SwipeEvent.SWIPE_DOWN)
 127             }, {
 128                 ContextMenuEvent.CONTEXT_MENU_REQUESTED,
 129                 "onContextMenuRequested",
 130                 createContextMenuEvent()
 131             }
 132         });
 133     }
 134 
 135     public Scenegraph_eventHandlers_Test(
 136             final EventType<?> eventType,
 137             final String onHandlerName,
 138             final Event triggeringEvent) {
 139         this.eventType = eventType;
 140         this.sceneOnHandlerPropRef =
 141                 PropertyReference.createForBean(Scene.class, onHandlerName);
 142         this.nodeOnHandlerPropRef =
 143                 PropertyReference.createForBean(Node.class, onHandlerName);
 144         this.triggeringEvent = triggeringEvent;
 145     }
 146 
 147     @Test
 148     public void shouldCallRegisteredHandlers() {
 149         final EventCountingHandler sceneHandler = new EventCountingHandler();
 150         final EventCountingHandler lNodeHandler = new EventCountingHandler();
 151         final EventCountingHandler rNodeHandler = new EventCountingHandler();
 152         final EventCountingHandler rlNodeHandler = new EventCountingHandler();
 153 
 154         setEventHandler(TEST_SCENE, sceneOnHandlerPropRef, sceneHandler);
 155         setEventHandler(TEST_L_NODE, nodeOnHandlerPropRef, lNodeHandler);
 156         TEST_R_NODE.addEventHandler(eventType, rNodeHandler);
 157         setEventHandler(TEST_RL_NODE, nodeOnHandlerPropRef, rlNodeHandler);
 158 
 159         Event.fireEvent(TEST_RL_NODE, triggeringEvent);
 160         assertEquals(1, sceneHandler.getCounter());
 161         assertEquals(0, lNodeHandler.getCounter());
 162         assertEquals(1, rNodeHandler.getCounter());
 163         assertEquals(1, rlNodeHandler.getCounter());
 164 
 165         Event.fireEvent(TEST_RR_NODE, triggeringEvent);
 166         assertEquals(2, sceneHandler.getCounter());
 167         assertEquals(0, lNodeHandler.getCounter());
 168         assertEquals(2, rNodeHandler.getCounter());
 169         assertEquals(1, rlNodeHandler.getCounter());
 170 
 171         Event.fireEvent(TEST_R_NODE, triggeringEvent);
 172         assertEquals(3, sceneHandler.getCounter());
 173         assertEquals(0, lNodeHandler.getCounter());
 174         assertEquals(3, rNodeHandler.getCounter());
 175         assertEquals(1, rlNodeHandler.getCounter());
 176         
 177         Event.fireEvent(TEST_L_NODE, triggeringEvent);
 178         assertEquals(4, sceneHandler.getCounter());
 179         assertEquals(1, lNodeHandler.getCounter());
 180         assertEquals(3, rNodeHandler.getCounter());
 181         assertEquals(1, rlNodeHandler.getCounter());
 182 
 183         Event.fireEvent(TEST_SCENE, triggeringEvent);
 184         assertEquals(5, sceneHandler.getCounter());
 185         assertEquals(1, lNodeHandler.getCounter());
 186         assertEquals(3, rNodeHandler.getCounter());
 187         assertEquals(1, rlNodeHandler.getCounter());
 188 
 189         Event.fireEvent(TEST_RL_NODE, TEST_EVENT);
 190         assertEquals(5, sceneHandler.getCounter());
 191         assertEquals(1, lNodeHandler.getCounter());
 192         assertEquals(3, rNodeHandler.getCounter());
 193         assertEquals(1, rlNodeHandler.getCounter());
 194 
 195         setEventHandler(TEST_SCENE, sceneOnHandlerPropRef, null);
 196         setEventHandler(TEST_L_NODE, nodeOnHandlerPropRef, null);
 197         TEST_R_NODE.removeEventHandler(eventType, rNodeHandler);
 198         setEventHandler(TEST_RL_NODE, nodeOnHandlerPropRef, null);
 199 
 200         Event.fireEvent(TEST_RL_NODE, triggeringEvent);
 201         assertEquals(5, sceneHandler.getCounter());
 202         assertEquals(1, lNodeHandler.getCounter());
 203         assertEquals(3, rNodeHandler.getCounter());
 204         assertEquals(1, rlNodeHandler.getCounter());
 205     }
 206 
 207     @Test
 208     public void shouldNotCallHandlersWithoutDispatcher() {
 209         final EventCountingHandler sceneHandler = new EventCountingHandler();
 210         final EventCountingHandler rootHandler = new EventCountingHandler();
 211         final EventCountingHandler leafHandler = new EventCountingHandler();
 212 
 213         final Node testLeafNode = new Rectangle();
 214         final Group testRootNode = new Group(testLeafNode);
 215         final Scene testScene = new Scene(testRootNode);
 216 
 217         setEventHandler(testScene, sceneOnHandlerPropRef, sceneHandler);
 218         setEventHandler(testRootNode, nodeOnHandlerPropRef, rootHandler);
 219         testLeafNode.addEventHandler(eventType, leafHandler);
 220 
 221         testRootNode.setEventDispatcher(null);
 222 
 223         Event.fireEvent(testLeafNode, triggeringEvent);
 224         assertEquals(1, sceneHandler.getCounter());
 225         assertEquals(0, rootHandler.getCounter());
 226         assertEquals(1, leafHandler.getCounter());
 227 
 228         testLeafNode.setEventDispatcher(null);
 229 
 230         Event.fireEvent(testLeafNode, triggeringEvent);
 231         assertEquals(2, sceneHandler.getCounter());
 232         assertEquals(0, rootHandler.getCounter());
 233         assertEquals(1, leafHandler.getCounter());
 234 
 235         testScene.setEventDispatcher(null);
 236 
 237         Event.fireEvent(testLeafNode, triggeringEvent);
 238         assertEquals(2, sceneHandler.getCounter());
 239         assertEquals(0, rootHandler.getCounter());
 240         assertEquals(1, leafHandler.getCounter());
 241     }
 242 
 243     @Test
 244     public void shouldNotPropagateConsumedCapturingEvents() {
 245         final EventCountingHandler sceneHandler = new EventCountingHandler();
 246         final EventCountingHandler rlNodeHandler = new EventCountingHandler();
 247 
 248         setEventHandler(TEST_SCENE, sceneOnHandlerPropRef, sceneHandler);
 249         setEventHandler(TEST_RL_NODE, nodeOnHandlerPropRef, rlNodeHandler);
 250 
 251         TEST_L_NODE.addEventFilter(eventType, EVENT_CONSUMING_HANDLER);
 252         Event.fireEvent(TEST_RL_NODE, triggeringEvent);
 253         assertEquals(1, sceneHandler.getCounter());
 254         assertEquals(1, rlNodeHandler.getCounter());
 255         TEST_L_NODE.removeEventFilter(eventType, EVENT_CONSUMING_HANDLER);
 256 
 257         TEST_R_NODE.addEventFilter(eventType, EVENT_CONSUMING_HANDLER);
 258         Event.fireEvent(TEST_RL_NODE, triggeringEvent);
 259         assertEquals(1, sceneHandler.getCounter());
 260         assertEquals(1, rlNodeHandler.getCounter());
 261         TEST_R_NODE.removeEventFilter(eventType, EVENT_CONSUMING_HANDLER);
 262         Event.fireEvent(TEST_RL_NODE, triggeringEvent);
 263         assertEquals(2, sceneHandler.getCounter());
 264         assertEquals(2, rlNodeHandler.getCounter());
 265 
 266         TEST_SCENE.addEventFilter(eventType, EVENT_CONSUMING_HANDLER);
 267         Event.fireEvent(TEST_RL_NODE, triggeringEvent);
 268         assertEquals(2, sceneHandler.getCounter());
 269         assertEquals(2, rlNodeHandler.getCounter());
 270         TEST_SCENE.removeEventFilter(eventType, EVENT_CONSUMING_HANDLER);
 271         Event.fireEvent(TEST_RL_NODE, triggeringEvent);
 272         assertEquals(3, sceneHandler.getCounter());
 273         assertEquals(3, rlNodeHandler.getCounter());
 274 
 275         setEventHandler(TEST_SCENE, sceneOnHandlerPropRef, null);
 276         setEventHandler(TEST_RL_NODE, nodeOnHandlerPropRef, null);
 277     }
 278 
 279     @Test
 280     public void shouldNotPropagateConsumedBubblingEvents() {
 281         final EventCountingHandler sceneHandler = new EventCountingHandler();
 282         final EventCountingHandler rootNodeHandler = new EventCountingHandler();
 283         final EventCountingHandler rlNodeHandler = new EventCountingHandler();
 284 
 285         setEventHandler(TEST_SCENE, sceneOnHandlerPropRef, sceneHandler);
 286         setEventHandler(TEST_ROOT_NODE, nodeOnHandlerPropRef, rootNodeHandler);
 287         setEventHandler(TEST_RL_NODE, nodeOnHandlerPropRef, rlNodeHandler);
 288 
 289         setEventHandler(TEST_L_NODE, nodeOnHandlerPropRef,
 290                         EVENT_CONSUMING_HANDLER);
 291         Event.fireEvent(TEST_RL_NODE, triggeringEvent);
 292         assertEquals(1, sceneHandler.getCounter());
 293         assertEquals(1, rootNodeHandler.getCounter());
 294         assertEquals(1, rlNodeHandler.getCounter());
 295         setEventHandler(TEST_L_NODE, nodeOnHandlerPropRef, null);
 296 
 297         TEST_RL_NODE.addEventHandler(eventType, EVENT_CONSUMING_HANDLER);
 298         Event.fireEvent(TEST_RL_NODE, triggeringEvent);
 299         assertEquals(1, sceneHandler.getCounter());
 300         assertEquals(1, rootNodeHandler.getCounter());
 301         assertEquals(2, rlNodeHandler.getCounter());
 302         TEST_RL_NODE.removeEventHandler(eventType, EVENT_CONSUMING_HANDLER);
 303 
 304         setEventHandler(TEST_R_NODE, nodeOnHandlerPropRef,
 305                         EVENT_CONSUMING_HANDLER);
 306         Event.fireEvent(TEST_RL_NODE, triggeringEvent);
 307         assertEquals(1, sceneHandler.getCounter());
 308         assertEquals(1, rootNodeHandler.getCounter());
 309         assertEquals(3, rlNodeHandler.getCounter());
 310         setEventHandler(TEST_R_NODE, nodeOnHandlerPropRef, null);
 311 
 312         TEST_ROOT_NODE.addEventHandler(eventType, EVENT_CONSUMING_HANDLER);
 313         Event.fireEvent(TEST_RL_NODE, triggeringEvent);
 314         assertEquals(1, sceneHandler.getCounter());
 315         assertEquals(2, rootNodeHandler.getCounter());
 316         assertEquals(4, rlNodeHandler.getCounter());
 317         TEST_ROOT_NODE.removeEventHandler(eventType, EVENT_CONSUMING_HANDLER);
 318 
 319         TEST_SCENE.addEventHandler(eventType, EVENT_CONSUMING_HANDLER);
 320         Event.fireEvent(TEST_RL_NODE, triggeringEvent);
 321         assertEquals(2, sceneHandler.getCounter());
 322         assertEquals(3, rootNodeHandler.getCounter());
 323         assertEquals(5, rlNodeHandler.getCounter());
 324         TEST_SCENE.removeEventHandler(eventType, EVENT_CONSUMING_HANDLER);
 325 
 326         setEventHandler(TEST_SCENE, sceneOnHandlerPropRef, null);
 327         setEventHandler(TEST_ROOT_NODE, nodeOnHandlerPropRef, null);
 328         setEventHandler(TEST_RL_NODE, nodeOnHandlerPropRef, null);
 329     }
 330 
 331     private static final Node TEST_RL_NODE = new Rectangle();
 332     private static final Node TEST_RR_NODE = new Rectangle();
 333     private static final Node TEST_L_NODE = new Rectangle();
 334     private static final Group TEST_R_NODE =
 335             new Group(TEST_RL_NODE, TEST_RR_NODE);
 336     private static final Group TEST_ROOT_NODE =
 337             new Group(TEST_L_NODE, TEST_R_NODE);
 338     private static final Scene TEST_SCENE = new Scene(TEST_ROOT_NODE);
 339     private static final Event TEST_EVENT = new Event(new EventType<Event>());
 340 
 341     private static final EventHandler<Event> EVENT_CONSUMING_HANDLER =
 342             new EventHandler<Event>() {
 343                 @Override
 344                 public void handle(final Event event) {
 345                     event.consume();
 346                 }
 347             };
 348 
 349     private static final class EventCountingHandler 
 350             implements EventHandler<Event> {
 351         private int counter;
 352 
 353         @Override
 354         public void handle(final Event event) {
 355             ++counter;
 356         }
 357 
 358         public int getCounter() {
 359             return counter;
 360         }
 361     }
 362 
 363     private static Event createTestKeyEvent(
 364             final EventType<KeyEvent> keyEventType) {
 365         String character;
 366         String text;
 367         KeyCode keyCode;
 368         if (keyEventType == KeyEvent.KEY_TYPED) {
 369             character = "q";
 370             text = "";
 371             keyCode = KeyCode.UNDEFINED;
 372         } else {
 373             character = KeyEvent.CHAR_UNDEFINED;
 374             text = KeyCode.Q.getName();
 375             keyCode = KeyCode.Q;
 376         }
 377 
 378         return new KeyEvent(keyEventType, character, text,
 379                                       keyCode,
 380                                       false, false, false, false);
 381     }
 382 
 383     private static Event createContextMenuEvent() {
 384         return new ContextMenuEvent(ContextMenuEvent.CONTEXT_MENU_REQUESTED, 10, 10,
 385           10, 10, false, null);
 386     }
 387 
 388     private static Event createSwipeEvent(final EventType<SwipeEvent> type) {
 389         return new SwipeEvent(
 390                 type,
 391                 100, 100, 100, 100,
 392                 false, false, false, false, true, 1, null);
 393     }
 394 
 395     private static void setEventHandler(
 396             final Object bean,
 397             final PropertyReference handlerPropertyReference,
 398             final EventHandler<? extends Event> handler) {
 399         handlerPropertyReference.setValue(bean, handler);
 400     }
 401 }