Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.scene.input; 027 028import com.sun.javafx.tk.Toolkit; 029import javafx.event.Event; 030import javafx.event.EventTarget; 031import javafx.event.EventType; 032import javafx.geometry.Point3D; 033import javafx.scene.Node; 034 035import com.sun.javafx.scene.input.InputEventUtils; 036import java.io.IOException; 037 038// PENDING_DOC_REVIEW 039/** 040 * When mouse event occurs, the top-most node under cursor is picked and 041 * the event is delivered to it through capturing and bubbling phases 042 * described at {@link javafx.event.EventDispatcher EventDispatcher}. 043 * <p> 044 * The mouse (pointer's) location is available relative to several 045 * coordinate systems: x,y - relative to the origin of the 046 * MouseEvent's node, sceneX,sceneY - relative to to the 047 * origin of the {@code Scene} that contains the node, 048 * screenX,screenY - relative to origin of the screen that 049 * contains the mouse pointer. 050 * 051 * <h4>Dragging gestures</h4> 052 * <p> 053 * There are three types of dragging gestures. They are all initiated by 054 * a mouse press event and terminated as a result of a mouse released 055 * event, the source node decides which gesture will take place. 056 * <p> 057 * The simple press-drag-release gesture is default. It's best used to allow 058 * changing size of a shape, dragging it around and so on. Whole 059 * press-drag-release gesture is delivered to one node. When mouse 060 * button is pressed, the top-most node is picked and all subsequent 061 * mouse events are delivered to the same node until the button is released. 062 * If a mouse clicked event is generated from these events, it is still 063 * delivered to the same node. 064 * <p> 065 * During simple press-drag-release gesture, the other nodes are not involved 066 * and don't get any events. If these nodes need to be involved in the gesture, 067 * full press-drag-release gesture has to be activated. This gesture is 068 * best used for connecting nodes by "wires", dragging nodes to other nodes etc. 069 * This gesture type is more closely described at 070 * {@link javafx.scene.input.MouseDragEvent MouseDragEvent} which contains 071 * the events delivered to the gesture targets. 072 * <p> 073 * The third gesture type is platform-supported drag-and-drop gesture. It serves 074 * best to transfer data and works also between (not necessarily FX) 075 * applications. This gesture type is more closely described 076 * at {@link javafx.scene.input.DragEvent DragEvent}. 077 * <p> 078 * In a short summary, simple press-drag-release gesture is activated 079 * automatically when a mouse button is pressed and delivers all 080 * {@code MouseEvent}s to the gesture source. When you start dragging, 081 * eventually the {@code DRAG_DETECTED} event arrives. In its handler 082 * you can either start full press-drag-release gesture by calling 083 * {@code startFullDrag} method on a node or scene - the {@code MouseDragEvent}s 084 * start to be delivered to gesture targets, or you can start drag and drop 085 * gesture by calling {@code startDragAndDrop} method on a node or scene - 086 * the system switches into the drag and drop mode and {@code DragEvent}s start 087 * to be delivered instead of {@code MouseEvent}s. If you don't call any of 088 * those methods, the simple press-drag-release gesture continues. 089 * <p> 090 * Note that dragging a finger over touch screen produces mouse dragging events, 091 * but also scroll gesture events. If it means a conflict in an application 092 * (the physical dragging action is handled by two different handlers), the 093 * {@code isSynthesized()} method may be used to detect the problem and make the 094 * dragging handlers behave accordingly. 095 * 096 * <h4>Mouse enter/exit handling</h4> 097 * <p> 098 * When mouse enters a node, the node gets {@code MOUSE_ENTERED} event, when 099 * it leaves, it gets {@code MOUSE_EXITED} event. These events are delivered 100 * only to the entered/exited node and seemingly don't go through the 101 * capturing/bubbling phases. This is the most common use-case. 102 * <p> 103 * When the capturing or bubbling is desired, there are 104 * {@code MOUSE_ENTERED_TARGET}/{@code MOUSE_EXITED_TARGET} events. These events 105 * go through capturing/bubbling phases normally. This means that parent may 106 * receive the {@code MOUSE_ENTERED_TARGET} event when mouse entered 107 * either the parent itself or some of its children. To distinguish between 108 * these two cases event target can be tested on equality with the node. 109 * <p> 110 * These two types are closely connected: 111 * {@code MOUSE_ENTERED}/{@code MOUSE_EXITED} are subtypes 112 * of {@code MOUSE_ENTERED_TARGET}/{@code MOUSE_EXITED_TARGET}. 113 * During capturing phase, 114 * {@code MOUSE_ENTERED_TARGET} is delivered to the 115 * parents. When the event is delivered to the event target (the node that 116 * has actually been entered), its type is switched to 117 * {@code MOUSE_ENTERED}. Then the type is switched back to 118 * {@code MOUSE_ENTERED_TARGET} for the bubbling phase. 119 * It's still one event just switching types, so if it's filtered or consumed, 120 * it affects both event variants. Thanks to the subtype-relationship, a 121 * {@code MOUSE_ENTERED_TARGET} event handler will receive the 122 * {@code MOUSE_ENTERED} event on target. 123 * 124 * <h4>Notes</h4> 125 * <ul> 126 * <li>For triggering context menus see the {@link ContextMenuEvent}.</li> 127 * </ul> 128 */ 129public class MouseEvent extends InputEvent { 130 131 private static final long serialVersionUID = 20121107L; 132 133 /** 134 * Common supertype for all mouse event types. 135 */ 136 public static final EventType<MouseEvent> ANY = 137 new EventType<MouseEvent>(InputEvent.ANY, "MOUSE"); 138 139 /** 140 * This event occurs when mouse button is pressed. This activates a 141 * press-drag-release gesture, so all subsequent mouse events until 142 * the button is released are delivered to the same node. 143 */ 144 public static final EventType<MouseEvent> MOUSE_PRESSED = 145 new EventType<MouseEvent>(MouseEvent.ANY, "MOUSE_PRESSED"); 146 147 /** 148 * This event occurs when mouse button is released. It is delivered 149 * to the same node where the button has been pressed which activated 150 * a press-drag-release gesture. 151 */ 152 public static final EventType<MouseEvent> MOUSE_RELEASED = 153 new EventType<MouseEvent>(MouseEvent.ANY, "MOUSE_RELEASED"); 154 155 /** 156 * This event occurs when mouse button has been clicked (pressed and 157 * released on the same node). This event provides a button-like behavior 158 * to any node. Note that even long drags can generate click event (it 159 * is delivered to the top-most node on which the mouse was both 160 * pressed and released). 161 */ 162 public static final EventType<MouseEvent> MOUSE_CLICKED = 163 new EventType<MouseEvent>(MouseEvent.ANY, "MOUSE_CLICKED"); 164 165 /** 166 * This event occurs when mouse enters a node. It's the bubbling variant, 167 * which is delivered also to all parents of the entered node (unless it 168 * was consumed). When notifications about mouse entering some of node's 169 * children are not desired, {@code MOUSE_ENTERED} event handler should 170 * be used. 171 * 172 * @see MouseEvent MouseEvent for more information about mouse entered/exited handling 173 */ 174 public static final EventType<MouseEvent> MOUSE_ENTERED_TARGET = 175 new EventType<MouseEvent>(MouseEvent.ANY, "MOUSE_ENTERED_TARGET"); 176 177 /** 178 * This event occurs when mouse enters a node. This event type is delivered 179 * only to the entered node, if parents want to filter it or get the 180 * bubbling event, they need to use {@code MOUSE_ENTERED_TARGET}. 181 * 182 * @see MouseEvent MouseEvent for more information about mouse entered/exited handling 183 */ 184 public static final EventType<MouseEvent> MOUSE_ENTERED = 185 new EventType<MouseEvent>(MouseEvent.MOUSE_ENTERED_TARGET, "MOUSE_ENTERED"); 186 187 /** 188 * This event occurs when mouse exits a node. It's the bubbling variant, 189 * which is delivered also to all parents of the exited node (unless it 190 * was consumed). When notifications about mouse exiting some of node's 191 * children are not desired, {@code MOUSE_EXITED} event handler should 192 * be used. 193 * 194 * @see MouseEvent MouseEvent for more information about mouse entered/exited handling 195 */ 196 public static final EventType<MouseEvent> MOUSE_EXITED_TARGET = 197 new EventType<MouseEvent>(MouseEvent.ANY, "MOUSE_EXITED_TARGET"); 198 199 /** 200 * This event occurs when mouse exits a node. This event type is delivered 201 * only to the exited node, if parents want to filter it or get the 202 * bubbling event, they need to use {@code MOUSE_EXITED_TARGET}. 203 * 204 * @see MouseEvent MouseEvent for more information about mouse entered/exited handling 205 */ 206 public static final EventType<MouseEvent> MOUSE_EXITED = 207 new EventType<MouseEvent>(MouseEvent.MOUSE_EXITED_TARGET, "MOUSE_EXITED"); 208 209 /** 210 * This event occurs when mouse moves within a node and no buttons 211 * are pressed. If any mouse button is pressed, MOUSE_DRAGGED event 212 * occurs instead. 213 */ 214 public static final EventType<MouseEvent> MOUSE_MOVED = 215 new EventType<MouseEvent>(MouseEvent.ANY, "MOUSE_MOVED"); 216 217 /** 218 * This event occurs when mouse moves with a pressed button. 219 * It is delivered to the same node where the button has been pressed 220 * which activated a press-drag-release gesture. It is delivered 221 * regardless of the mouse being within bounds of the node. 222 */ 223 public static final EventType<MouseEvent> MOUSE_DRAGGED = 224 new EventType<MouseEvent>(MouseEvent.ANY, "MOUSE_DRAGGED"); 225 226 /** 227 * This event is delivered to a node that is identified as a source of a 228 * dragging gesture. Handler of this event is the only place where 229 * full press-drag-release gesture or a drag and drop gesture can be 230 * started (by calling {@link javafx.scene.Node#startFullDrag startFullDrag()} 231 * of {@link javafx.scene.Node#startDragAndDrop startDragAndDrop()} method). 232 * If none of them is called, simple press-drag-release gesture will continue. 233 * <p> 234 * Note that his event is generated based on dragging the mouse over a 235 * platform-specific distance threshold. You can modify this behavior 236 * by calling {@code setDragDetect} method on any MOUSE_PRESSED or 237 * MOUSE_DRAGGED event. 238 * 239 * @see MouseEvent MouseEvent for more details about simple press-drag-release gestures 240 * @see MouseDragEvent MouseDragEvent for more details about full press-drag-release gestures 241 * @see DragEvent DragEvent for more details about drag and drop gestures 242 */ 243 public static final EventType<MouseEvent> DRAG_DETECTED = 244 new EventType<MouseEvent>(MouseEvent.ANY, "DRAG_DETECTED"); 245 246 /** 247 * Fills the given event by this event's coordinates recomputed to the given 248 * source object 249 * @param newEvent Event whose coordinates are to be filled 250 * @param newSource Source object to compute coordinates for 251 */ 252 void recomputeCoordinatesToSource(MouseEvent oldEvent, Object newSource) { 253 254 final Point3D newCoordinates = InputEventUtils.recomputeCoordinates( 255 pickResult, newSource); 256 257 x = newCoordinates.getX(); 258 y = newCoordinates.getY(); 259 z = newCoordinates.getZ(); 260 } 261 262 @Override 263 public EventType<? extends MouseEvent> getEventType() { 264 return (EventType<? extends MouseEvent>) super.getEventType(); 265 } 266 267 /** 268 * Copies this event for a different source and target. 269 * In most cases you don't need to use this method, it's called 270 * automatically when you fire the event. 271 * @param newSource New event source 272 * @param newTarget New event target 273 * @return copy of this event for a different source and target 274 */ 275 @Override 276 public MouseEvent copyFor(Object newSource, EventTarget newTarget) { 277 MouseEvent e = (MouseEvent) super.copyFor(newSource, newTarget); 278 e.recomputeCoordinatesToSource(this, newSource); 279 return e; 280 } 281 282 /** 283 * Creates a copy of the given event with the given fields substituted. 284 * @param source the new source of the copied event 285 * @param target the new target of the copied event 286 * @param eventType the new eventType 287 * @return the event copy with the fields substituted 288 */ 289 public MouseEvent copyFor(Object newSource, EventTarget newTarget, EventType<? extends MouseEvent> eventType) { 290 MouseEvent e = copyFor(newSource, newTarget); 291 e.eventType = eventType; 292 return e; 293 } 294 295 //SB-dependency: RT-21224. Need to be sure that SB does use new API before removing this. 296 /** 297 * @treatAsPrivate implementation detail 298 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 299 */ 300 @Deprecated 301 public static MouseEvent impl_mouseEvent(double _x, double _y, 302 double _screenX, double _screenY, 303 MouseButton _button, 304 int _clickCount, 305 boolean _shiftDown, 306 boolean _controlDown, 307 boolean _altDown, 308 boolean _metaDown, 309 boolean _popupTrigger, 310 boolean _primaryButtonDown, 311 boolean _middleButtonDown, 312 boolean _secondaryButtonDown, 313 boolean _synthesized, 314 EventType<? extends MouseEvent> _eventType 315 ) { 316 return new MouseEvent( 317 _eventType, _x, _y, _screenX, _screenY, 318 _button, _clickCount, 319 _shiftDown, _controlDown, _altDown, _metaDown, 320 _primaryButtonDown, _middleButtonDown, _secondaryButtonDown, 321 _synthesized, _popupTrigger, false, null); 322 } 323 324 /** 325 * Constructs new MouseEvent event with null source and target. 326 * @param eventType The type of the event. 327 * @param x The x with respect to the scene. 328 * @param y The y with respect to the scene. 329 * @param screenX The x coordinate relative to screen. 330 * @param screenY The y coordinate relative to screen. 331 * @param button the mouse button used 332 * @param clickCount number of click counts 333 * @param shiftDown true if shift modifier was pressed. 334 * @param controlDown true if control modifier was pressed. 335 * @param altDown true if alt modifier was pressed. 336 * @param metaDown true if meta modifier was pressed. 337 * @param primaryButtonDown true if primary button was pressed. 338 * @param middleButtonDown true if middle button was pressed. 339 * @param secondaryButtonDown true if secondary button was pressed. 340 * @param synthesized if this event was synthesized 341 * @param popupTrigger whether this event denotes a popup trigger for current platform 342 * @param stillSincePress see {@link #isStillSincePress() } 343 * @param pickResult pick result. Can be null, in this case a 2D pick result 344 * without any further values is constructed 345 * based on the scene coordinates 346 */ 347 public MouseEvent( 348 EventType<? extends MouseEvent> eventType, 349 double x, double y, 350 double screenX, double screenY, 351 MouseButton button, 352 int clickCount, 353 boolean shiftDown, 354 boolean controlDown, 355 boolean altDown, 356 boolean metaDown, 357 boolean primaryButtonDown, 358 boolean middleButtonDown, 359 boolean secondaryButtonDown, 360 boolean synthesized, 361 boolean popupTrigger, 362 boolean stillSincePress, 363 PickResult pickResult) { 364 this(null, null, eventType, x, y, screenX, screenY, button, clickCount, 365 shiftDown, controlDown, altDown, metaDown, 366 primaryButtonDown, middleButtonDown, secondaryButtonDown, 367 synthesized, popupTrigger, stillSincePress, pickResult); 368 } 369 370 /** 371 * Constructs new MouseEvent event. 372 * @param source the source of the event. Can be null. 373 * @param target the target of the event. Can be null. 374 * @param eventType The type of the event. 375 * @param x The x with respect to the source. Should be in scene coordinates if source == null or source is not a Node. 376 * @param y The y with respect to the source. Should be in scene coordinates if source == null or source is not a Node. 377 * @param screenX The x coordinate relative to screen. 378 * @param screenY The y coordinate relative to screen. 379 * @param button the mouse button used 380 * @param clickCount number of click counts 381 * @param shiftDown true if shift modifier was pressed. 382 * @param controlDown true if control modifier was pressed. 383 * @param altDown true if alt modifier was pressed. 384 * @param metaDown true if meta modifier was pressed. 385 * @param primaryButtonDown true if primary button was pressed. 386 * @param middleButtonDown true if middle button was pressed. 387 * @param secondaryButtonDown true if secondary button was pressed. 388 * @param synthesized if this event was synthesized 389 * @param popupTrigger whether this event denotes a popup trigger for current platform 390 * @param stillSincePress see {@link #isStillSincePress() } 391 * @param pickResult pick result. Can be null, in this case a 2D pick result 392 * without any further values is constructed 393 * based on the scene coordinates and target 394 */ 395 public MouseEvent(Object source, EventTarget target, 396 EventType<? extends MouseEvent> eventType, 397 double x, double y, 398 double screenX, double screenY, 399 MouseButton button, 400 int clickCount, 401 boolean shiftDown, 402 boolean controlDown, 403 boolean altDown, 404 boolean metaDown, 405 boolean primaryButtonDown, 406 boolean middleButtonDown, 407 boolean secondaryButtonDown, 408 boolean synthesized, 409 boolean popupTrigger, 410 boolean stillSincePress, 411 PickResult pickResult) { 412 super(source, target, eventType); 413 this.x = x; 414 this.y = y; 415 this.screenX = screenX; 416 this.screenY = screenY; 417 this.sceneX = x; 418 this.sceneY = y; 419 this.button = button; 420 this.clickCount = clickCount; 421 this.shiftDown = shiftDown; 422 this.controlDown = controlDown; 423 this.altDown = altDown; 424 this.metaDown = metaDown; 425 this.primaryButtonDown = primaryButtonDown; 426 this.middleButtonDown = middleButtonDown; 427 this.secondaryButtonDown = secondaryButtonDown; 428 this.synthesized = synthesized; 429 this.stillSincePress = stillSincePress; 430 this.popupTrigger = popupTrigger; 431 this.pickResult = pickResult; 432 this.pickResult = pickResult != null ? pickResult : new PickResult(target, x, y); 433 final Point3D p = InputEventUtils.recomputeCoordinates(this.pickResult, null); 434 this.x = p.getX(); 435 this.y = p.getY(); 436 this.z = p.getZ(); 437 } 438 439 /** 440 * Creates a copy of this mouse event of MouseDragEvent type 441 * @param e the mouse event to copy 442 * @param source the new source of the copied event 443 * @param target the new target of the copied event 444 * @param type the new MouseDragEvent type 445 * @param gestureSource the new source of the gesture 446 * @param pickResult pick result. Can be null, in this case a 2D pick result 447 * without any further values is constructed 448 * based on the scene coordinates 449 * @return new MouseDragEvent that was created from MouseEvent 450 */ 451 public static MouseDragEvent copyForMouseDragEvent( 452 MouseEvent e, 453 Object source, EventTarget target, 454 EventType<MouseDragEvent> type, 455 Object gestureSource, PickResult pickResult) { 456 MouseDragEvent ev = new MouseDragEvent(source, target, 457 type, e.sceneX, e.sceneY, e.screenX, e.screenY, 458 e.button, e.clickCount, e.shiftDown, e.controlDown, 459 e.altDown, e.metaDown, e.primaryButtonDown, e.middleButtonDown, 460 e.secondaryButtonDown, e.synthesized, e.popupTrigger, 461 pickResult, gestureSource); 462 ev.recomputeCoordinatesToSource(e, source); 463 return ev; 464 } 465 private final Flags flags = new Flags(); 466 467 /** 468 * Determines whether this event will be followed by {@code DRAG_DETECTED} 469 * event. It has effect only with {@code MOUSE_PRESSED} and 470 * {@code MOUSE_DRAGGED} events. 471 * 472 * @return true if the {@code DRAG_DETECTED} event will follow 473 */ 474 public boolean isDragDetect() { 475 return flags.dragDetect; 476 } 477 478 /** 479 * Augments drag detection behavior. The value says whether this event 480 * will be followed by {@code DRAG_DETECTED} event. It has effect only 481 * with {@code MOUSE_PRESSED} and {@code MOUSE_DRAGGED} events. 482 * 483 * @param dragDetect Whether {@code DRAG_DETECTED} event will follow 484 */ 485 public void setDragDetect(boolean dragDetect) { 486 flags.dragDetect = dragDetect; 487 } 488 489 /** 490 * Horizontal x position of the event relative to the 491 * origin of the MouseEvent's node. 492 */ 493 private transient double x; 494 495 /** 496 * Horizontal position of the event relative to the 497 * origin of the MouseEvent's source. 498 * 499 * @return horizontal position of the event relative to the 500 * origin of the MouseEvent's source. 501 */ 502 public final double getX() { 503 return x; 504 } 505 506 /** 507 * Vertical y position of the event relative to the 508 * origin of the MouseEvent's node. 509 */ 510 private transient double y; 511 512 /** 513 * Vertical position of the event relative to the 514 * origin of the MouseEvent's source. 515 * 516 * @return vertical position of the event relative to the 517 * origin of the MouseEvent's source. 518 */ 519 public final double getY() { 520 return y; 521 } 522 523 /** 524 * Depth z position of the event relative to the 525 * origin of the MouseEvent's node. 526 */ 527 private transient double z; 528 529 /** 530 * Depth position of the event relative to the 531 * origin of the MouseEvent's source. 532 * 533 * @return depth position of the event relative to the 534 * origin of the MouseEvent's source. 535 */ 536 public final double getZ() { 537 return z; 538 } 539 540 /** 541 * Absolute horizontal x position of the event. 542 */ 543 private final double screenX; 544 545 /** 546 * Returns absolute horizontal position of the event. 547 * @return absolute horizontal position of the event 548 */ 549 public final double getScreenX() { 550 return screenX; 551 } 552 553 /** 554 * Absolute vertical y position of the event. 555 */ 556 private final double screenY; 557 558 /** 559 * Returns absolute vertical position of the event. 560 * @return absolute vertical position of the event 561 */ 562 public final double getScreenY() { 563 return screenY; 564 } 565 566 /** 567 * Horizontal x position of the event relative to the 568 * origin of the {@code Scene} that contains the MouseEvent's node. 569 * If the node is not in a {@code Scene}, then the value is relative to 570 * the boundsInParent of the root-most parent of the MouseEvent's node. 571 */ 572 private final double sceneX; 573 574 /** 575 * Returns horizontal position of the event relative to the 576 * origin of the {@code Scene} that contains the MouseEvent's source. 577 * If the node is not in a {@code Scene}, then the value is relative to 578 * the boundsInParent of the root-most parent of the MouseEvent's node. 579 * Note that in 3D scene, this represents the flat coordinates after 580 * applying the projection transformations. 581 * 582 * @return horizontal position of the event relative to the 583 * origin of the {@code Scene} that contains the MouseEvent's source 584 */ 585 public final double getSceneX() { 586 return sceneX; 587 } 588 589 /** 590 * Vertical y position of the event relative to the 591 * origin of the {@code Scene} that contains the MouseEvent's node. 592 * If the node is not in a {@code Scene}, then the value is relative to 593 * the boundsInParent of the root-most parent of the MouseEvent's node. 594 */ 595 private final double sceneY; 596 597 /** 598 * Returns vertical position of the event relative to the 599 * origin of the {@code Scene} that contains the MouseEvent's source. 600 * If the node is not in a {@code Scene}, then the value is relative to 601 * the boundsInParent of the root-most parent of the MouseEvent's node. 602 * Note that in 3D scene, this represents the flat coordinates after 603 * applying the projection transformations. 604 * 605 * @return vertical position of the event relative to the 606 * origin of the {@code Scene} that contains the MouseEvent's source 607 */ 608 public final double getSceneY() { 609 return sceneY; 610 } 611 612 /** 613 * Which, if any, of the mouse buttons is responsible for this event. 614 */ 615 private final MouseButton button; 616 617 /** 618 * Which, if any, of the mouse buttons is responsible for this event. 619 * 620 * @return mouse button whose state change caused this event 621 */ 622 public final MouseButton getButton() { 623 return button; 624 } 625 626 /** 627 * Number of mouse clicks associated with this event. 628 * All MOUSE_MOVED events have the clickCount value equal to 0. The 629 * value is increased with MOUSE_PRESSED event and stays like 630 * that for all subsequent events till MOUSE_RELEASED, including the 631 * afterwards generated MOUSE_CLICKED event. The value is increased 632 * to numbers higher than one if all the events between two subsequent 633 * presses happen on a small region and in a small time (according 634 * to native operating system configuration). 635 */ 636 private final int clickCount; 637 638 /** 639 * Returns number of mouse clicks associated with this event. 640 * All MOUSE_MOVED events have the clickCount value equal to 0. The 641 * value is increased with MOUSE_PRESSED event and stays like 642 * that for all subsequent events till MOUSE_RELEASED, including the 643 * afterwards generated MOUSE_CLICKED event. The value is increased 644 * to numbers higher than one if all the events between two subsequent 645 * presses happen on a small region and in a small time (according 646 * to native operating system configuration). 647 * 648 * @return number of mouse clicks associated with this event 649 */ 650 public final int getClickCount() { 651 return clickCount; 652 } 653 654 /** 655 * Whether the mouse cursor left the hysteresis region since the previous 656 * press. 657 */ 658 private final boolean stillSincePress; 659 660 /** 661 * Indicates whether the mouse cursor stayed in the system-provided 662 * hysteresis area since last pressed event that occurred before this event. 663 * <p> 664 * Click event is generated for a node if mouse was both pressed and 665 * released over the node, regardless of mouse movements between the press 666 * and release. If a node wants to react differently on a simple click and 667 * on a mouse drag, it should use a system-supplied short distance 668 * threshold to decide between click and drag (users often perform 669 * inadvertent tiny movements during a click). It can be easily achieved 670 * by ignoring all drags with this method returning {@code true} and 671 * ignoring all clicks with this method returning {@code false}. 672 * 673 * @return true if there were no significant mouse movements (out of 674 * system hysteresis area) since the last pressed event that occurred 675 * before this event. 676 */ 677 public final boolean isStillSincePress() { 678 return stillSincePress; 679 } 680 681 /** 682 * Whether or not the Shift modifier is down on this event. 683 */ 684 private final boolean shiftDown; 685 686 /** 687 * Whether or not the Shift modifier is down on this event. 688 * @return true if the Shift modifier is down on this event 689 */ 690 public final boolean isShiftDown() { 691 return shiftDown; 692 } 693 694 /** 695 * Whether or not the Control modifier is down on this event. 696 */ 697 private final boolean controlDown; 698 699 /** 700 * Whether or not the Control modifier is down on this event. 701 * @return true if the Control modifier is down on this event 702 */ 703 public final boolean isControlDown() { 704 return controlDown; 705 } 706 707 /** 708 * Whether or not the Alt modifier is down on this event. 709 */ 710 private final boolean altDown; 711 712 /** 713 * Whether or not the Alt modifier is down on this event. 714 * @return true if the Alt modifier is down on this event 715 */ 716 public final boolean isAltDown() { 717 return altDown; 718 } 719 720 /** 721 * Whether or not the Meta modifier is down on this event. 722 */ 723 private final boolean metaDown; 724 725 /** 726 * Whether or not the Meta modifier is down on this event. 727 * @return true if the Meta modifier is down on this event 728 */ 729 public final boolean isMetaDown() { 730 return metaDown; 731 } 732 733 private final boolean synthesized; 734 735 /** 736 * Indicates whether this event is synthesized from using a touch screen 737 * instead of usual mouse event source devices like mouse or track pad. 738 * When a finger is dragged over a touch screen, both scrolling gesture 739 * and mouse dragging are produced. If it causes a conflict in an 740 * application, this flag can be used to tell apart the usual mouse dragging 741 * from the touch screen dragging already handled as scroll events. 742 * @return true if this event is synthesized from using a touch screen 743 * @since 2.2 744 */ 745 public boolean isSynthesized() { 746 return synthesized; 747 } 748 749 /** 750 * Returns whether or not the host platform common shortcut modifier is 751 * down on this event. This common shortcut modifier is a modifier key which 752 * is used commonly in shortcuts on the host platform. It is for example 753 * {@code control} on Windows and {@code meta} (command key) on Mac. 754 * 755 * @return {@code true} if the shortcut modifier is down, {@code false} 756 * otherwise 757 */ 758 public final boolean isShortcutDown() { 759 switch (Toolkit.getToolkit().getPlatformShortcutKey()) { 760 case SHIFT: 761 return shiftDown; 762 763 case CONTROL: 764 return controlDown; 765 766 case ALT: 767 return altDown; 768 769 case META: 770 return metaDown; 771 772 default: 773 return false; 774 } 775 } 776 777 /** 778 * Whether or not this mouse event is the popup menu 779 * trigger event for the platform. 780 * <p><b>Note</b>: Popup menus are triggered differently 781 * on different systems. Therefore, {@code popupTrigger} 782 * should be checked in both {@code onMousePressed} 783 * and {@code mouseReleased} for proper cross-platform functionality. 784 */ 785 private final boolean popupTrigger; 786 787 public final boolean isPopupTrigger() { 788 return popupTrigger; 789 } 790 791 /** 792 * {@code true} if primary button (button 1, usually the left) is currently 793 * pressed. Note that this is different from the {@link #getButton() button} 794 * variable in that the {@code button} variable indicates which button press was 795 * responsible for this event while this variable indicates whether the 796 * primary button is depressed. 797 */ 798 private final boolean primaryButtonDown; 799 800 /** 801 * Returns {@code true} if primary button (button 1, usually the left) 802 * is currently pressed. Note that this is different from the 803 * {@code getButton()} method that indicates which button press was 804 * responsible for this event while this method indicates whether the 805 * primary button is depressed. 806 * 807 * @return {@code true} if primary button (button 1, usually the left) 808 * is currently pressed 809 */ 810 public final boolean isPrimaryButtonDown() { 811 return primaryButtonDown; 812 } 813 814 /** 815 * {@code true} if secondary button (button 3, usually the right) is currently 816 * pressed. Note that this is different from the {@link #getButton() button} 817 * variable in that the {@code button} variable indicates which button press was 818 * responsible for this event while this variable indicates whether the 819 * primary button is depressed. 820 */ 821 private final boolean secondaryButtonDown; 822 823 /** 824 * Returns {@code true} if secondary button (button 1, usually the right) 825 * is currently pressed. Note that this is different from the 826 * {@code getButton()} method that indicates which button press was 827 * responsible for this event while this method indicates whether the 828 * secondary button is depressed. 829 * 830 * @return {@code true} if secondary button (button 3, usually the right) 831 * is currently pressed 832 */ 833 public final boolean isSecondaryButtonDown() { 834 return secondaryButtonDown; 835 } 836 837 /** 838 * {@code true} if middle button (button 2) is currently pressed. 839 * Note that this is different from the {@link #getButton() button} variable in 840 * that the {@code button} variable indicates which button press was 841 * responsible for this event while this variable indicates whether the 842 * middle button is depressed. 843 */ 844 private final boolean middleButtonDown; 845 846 /** 847 * Returns {@code true} if middle button (button 2) 848 * is currently pressed. Note that this is different from the 849 * {@code getButton()} method that indicates which button press was 850 * responsible for this event while this method indicates whether the 851 * middle button is depressed. 852 * 853 * @return {@code true} if middle button (button 2) is currently pressed 854 */ 855 public final boolean isMiddleButtonDown() { 856 return middleButtonDown; 857 } 858 859 /** 860 * Returns a string representation of this {@code MouseEvent} object. 861 * @return a string representation of this {@code MouseEvent} object. 862 */ 863 @Override public String toString() { 864 final StringBuilder sb = new StringBuilder("MouseEvent ["); 865 866 sb.append("source = ").append(getSource()); 867 sb.append(", target = ").append(getTarget()); 868 sb.append(", eventType = ").append(getEventType()); 869 sb.append(", consumed = ").append(isConsumed()); 870 871 sb.append(", x = ").append(getX()).append(", y = ").append(getY()) 872 .append(", z = ").append(getZ()); 873 874 if (getButton() != null) { 875 sb.append(", button = ").append(getButton()); 876 } 877 if (getClickCount() > 1) { 878 sb.append(", clickCount = ").append(getClickCount()); 879 } 880 if (isPrimaryButtonDown()) { 881 sb.append(", primaryButtonDown"); 882 } 883 if (isMiddleButtonDown()) { 884 sb.append(", middleButtonDown"); 885 } 886 if (isSecondaryButtonDown()) { 887 sb.append(", secondaryButtonDown"); 888 } 889 if (isShiftDown()) { 890 sb.append(", shiftDown"); 891 } 892 if (isControlDown()) { 893 sb.append(", controlDown"); 894 } 895 if (isAltDown()) { 896 sb.append(", altDown"); 897 } 898 if (isMetaDown()) { 899 sb.append(", metaDown"); 900 } 901 if (isShortcutDown()) { 902 sb.append(", shortcutDown"); 903 } 904 if (isSynthesized()) { 905 sb.append(", synthesized"); 906 } 907 sb.append(", pickResult = ").append(getPickResult()); 908 909 return sb.append("]").toString(); 910 } 911 912 /** 913 * Information about the pick if the picked {@code Node} is a 914 * {@code Shape3D} node and its pickOnBounds is false. 915 */ 916 private PickResult pickResult; 917 918 /** 919 * Returns information about the pick. 920 * 921 * @return new PickResult object that contains information about the pick 922 */ 923 public final PickResult getPickResult() { 924 return pickResult; 925 } 926 927 /** 928 * These properties need to live in a separate object shared among all the 929 * copied events to make sure that the values are propagated to the 930 * original event. 931 */ 932 private static class Flags implements Cloneable { 933 /** 934 * Whether dragDetected event is going to be sent after this event. 935 * Applies only to MOUSE_PRESSED and MOUSE_MOVED event types. 936 */ 937 boolean dragDetect = true; 938 939 @Override 940 public Flags clone() { 941 try { 942 return (Flags) super.clone(); 943 } catch (CloneNotSupportedException e) { 944 /* won't happen */ 945 return null; 946 } 947 } 948 } 949 950 private void readObject(java.io.ObjectInputStream in) 951 throws IOException, ClassNotFoundException { 952 in.defaultReadObject(); 953 x = sceneX; 954 y = sceneY; 955 } 956}