1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
14 * @author Toni Kalajainen
16 package org.simantics.scenegraph.g2d.events.adapter;
18 import java.awt.Component;
19 import java.awt.dnd.DnDConstants;
20 import java.awt.dnd.DragGestureEvent;
21 import java.awt.dnd.DragGestureListener;
22 import java.awt.dnd.DragSource;
23 import java.awt.event.InputEvent;
24 import java.awt.event.MouseEvent;
25 import java.awt.event.MouseListener;
26 import java.awt.event.MouseMotionListener;
27 import java.awt.event.MouseWheelEvent;
28 import java.awt.event.MouseWheelListener;
29 import java.awt.geom.Point2D;
30 import java.util.function.UnaryOperator;
32 import org.simantics.scenegraph.g2d.events.EventDebugPolicy;
33 import org.simantics.scenegraph.g2d.events.IEventHandler;
34 import org.simantics.scenegraph.g2d.events.IEventQueue;
35 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent;
36 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent;
37 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDoubleClickedEvent;
38 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin;
39 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseEnterEvent;
40 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseExitEvent;
41 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;
42 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseWheelMovedEvent;
46 * Adapts AWT mouse events into G2D events.
48 * Sends adapted events to IEventHandler
50 public class AWTMouseEventAdapter extends AbstractEventAdapter implements MouseListener, MouseMotionListener, MouseWheelListener {
52 private final boolean DEBUG = EventDebugPolicy.AWT_MOUSE_EVENT_ADAPTION;
54 private final boolean IGNORE_CONSUMED_EVENTS = false;
56 /** Mouse id of the default mouse */
57 public static final int MOUSE_ID = 0;
59 private final long [] pressTime = new long[5];
65 * @param sender the sender field in the events
66 * @param delegator the target of the adapted events
68 public AWTMouseEventAdapter(Object sender, IEventHandler delegator) {
69 super(sender, delegator);
74 * @param sender the sender field in the events
77 public AWTMouseEventAdapter(Object sender, IEventQueue queue) {
81 public static Point2D getControlPosition(MouseEvent e)
83 return new Point2D.Double(e.getX(), e.getY());
86 public static Point2D getScreenPosition(MouseEvent e)
88 return e.getLocationOnScreen();
91 public static int getStateMask(MouseEvent e) {
92 int modifiers = e.getModifiersEx();
94 if((modifiers & InputEvent.CTRL_DOWN_MASK) != 0)
95 stateMask |= org.simantics.scenegraph.g2d.events.MouseEvent.CTRL_MASK;
96 if((modifiers & InputEvent.ALT_DOWN_MASK) != 0)
97 stateMask |= org.simantics.scenegraph.g2d.events.MouseEvent.ALT_MASK;
98 if((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0)
99 stateMask |= org.simantics.scenegraph.g2d.events.MouseEvent.ALT_GRAPH_MASK;
100 if((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0)
101 stateMask |= org.simantics.scenegraph.g2d.events.MouseEvent.SHIFT_MASK;
105 public static int getMouseButton(MouseEvent e)
107 int awtMouseButton = e.getButton();
108 if (awtMouseButton == MouseEvent.BUTTON1)
109 return org.simantics.scenegraph.g2d.events.MouseEvent.LEFT_BUTTON;
110 if (awtMouseButton == MouseEvent.BUTTON2)
111 return org.simantics.scenegraph.g2d.events.MouseEvent.MIDDLE_BUTTON;
112 if (awtMouseButton == MouseEvent.BUTTON3)
113 return org.simantics.scenegraph.g2d.events.MouseEvent.RIGHT_BUTTON;
114 return awtMouseButton;
118 * Converts AWT {@link MouseEvent#getModifiersEx()} mouse button status to
119 * G2D mouse button status. Only supports three buttons while AWT supports
125 public static int getButtonStatus(MouseEvent e) {
126 int modex = e.getModifiersEx();
128 status |= (modex & MouseEvent.BUTTON1_DOWN_MASK) != 0 ? org.simantics.scenegraph.g2d.events.MouseEvent.LEFT_MASK : 0;
129 status |= (modex & MouseEvent.BUTTON2_DOWN_MASK) != 0 ? org.simantics.scenegraph.g2d.events.MouseEvent.MIDDLE_MASK : 0;
130 status |= (modex & MouseEvent.BUTTON3_DOWN_MASK) != 0 ? org.simantics.scenegraph.g2d.events.MouseEvent.RIGHT_MASK : 0;
135 public void mouseEntered(MouseEvent e) {
136 if (IGNORE_CONSUMED_EVENTS) {
137 if (e.isConsumed()) {
139 System.out.println("AWT mouse entered but already consumed: " + e);
144 System.out.println("AWT mouse entered: " + e);
145 buttonStatus = getButtonStatus(e);
146 MouseEnterEvent me = new MouseEnterEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), getControlPosition(e), getScreenPosition(e));
151 public void mouseExited(MouseEvent e) {
152 if (IGNORE_CONSUMED_EVENTS) {
153 if (e.isConsumed()) {
155 System.out.println("AWT mouse exited but already consumed: " + e);
160 System.out.println("AWT mouse exited: " + e);
162 MouseExitEvent me = new MouseExitEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), getControlPosition(e), getScreenPosition(e));
167 public void mousePressed(MouseEvent e) {
168 if (IGNORE_CONSUMED_EVENTS) {
169 if (e.isConsumed()) {
171 System.out.println("AWT mouse pressed but already consumed: " + e);
176 System.out.println("AWT mouse pressed: " + e);
178 int mouseButton = getMouseButton(e);
179 if (mouseButton == MouseEvent.NOBUTTON) {
180 // This is strange, seems to happen on Linux constantly when pressing buttons rapidly.
181 //System.out.println("NO BUTTON EVENT: " + e);
185 if (mouseButton<=pressTime.length) pressTime[mouseButton-1] = e.getWhen();
186 buttonStatus |= 1 << (mouseButton-1);
188 handleEvent(new MouseButtonPressedEvent(sender, e.getWhen(), MOUSE_ID,
189 buttonStatus, getStateMask(e), mouseButton, getControlPosition(e), getScreenPosition(e)));
190 if (e.getClickCount() == 2) {
191 handleEvent(new MouseDoubleClickedEvent(sender, e.getWhen(),
192 MOUSE_ID, buttonStatus, getStateMask(e), mouseButton, getControlPosition(e), getScreenPosition(e)));
197 public void mouseReleased(MouseEvent e) {
198 if (IGNORE_CONSUMED_EVENTS) {
199 if (e.isConsumed()) {
201 System.out.println("AWT mouse released but already consumed: " + e);
206 System.out.println("AWT mouse released: " + e);
208 int mouseButton = getMouseButton(e);
209 if (mouseButton == MouseEvent.NOBUTTON) {
210 // This is strange, seems to happen on Linux constantly when pressing buttons rapidly.
211 //System.out.println("NO BUTTON EVENT: " + e);
215 long holdTime = Long.MAX_VALUE;
216 if (mouseButton<=pressTime.length)
217 holdTime = e.getWhen() - pressTime[mouseButton-1];
219 int stateMask = getStateMask(e);
221 // This works around the problem of AWT putting the ALT_DOWN_MASK in the
222 // mouse event extended modifiers when button 2 is pressed.
223 if (mouseButton == org.simantics.scenegraph.g2d.events.MouseEvent.MIDDLE_BUTTON) {
224 stateMask &= ~(org.simantics.scenegraph.g2d.events.MouseEvent.ALT_MASK);
227 buttonStatus &=~ (1<<(mouseButton-1));
228 MouseButtonReleasedEvent me = new MouseButtonReleasedEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, stateMask, mouseButton, holdTime, getControlPosition(e), getScreenPosition(e));
233 public void mouseDragged(MouseEvent e) {
234 if (IGNORE_CONSUMED_EVENTS) {
235 if (e.isConsumed()) {
237 System.out.println("AWT mouse dragged but already consumed: " + e);
242 System.out.println("AWT mouse dragged: " + e);
243 MouseMovedEvent me = new MouseMovedEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), getControlPosition(e), getScreenPosition(e));
248 public void mouseMoved(MouseEvent e) {
249 if (IGNORE_CONSUMED_EVENTS) {
250 if (e.isConsumed()) {
252 System.out.println("AWT mouse moved but already consumed: " + e);
257 System.out.println("AWT mouse moved: " + e);
258 MouseMovedEvent me = new MouseMovedEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), getControlPosition(e), getScreenPosition(e));
263 public void mouseWheelMoved(MouseWheelEvent e) {
264 if (IGNORE_CONSUMED_EVENTS) {
265 if (e.isConsumed()) {
267 System.out.println("AWT mouse wheel moved but already consumed: " + e);
272 System.out.println("AWT mouse wheel moved: " + e);
273 int wheelRotation = 0;
274 if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {
275 wheelRotation = -e.getUnitsToScroll();
277 wheelRotation = -e.getWheelRotation();
279 handleEvent(new MouseWheelMovedEvent(
280 sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), getControlPosition(e), getScreenPosition(e),
281 e.getScrollType(), e.getScrollAmount(), wheelRotation
287 public void mouseClicked(MouseEvent e) {
288 if (IGNORE_CONSUMED_EVENTS) {
289 if (e.isConsumed()) {
291 System.out.println("AWT mouse clicked but already consumed: " + e);
296 System.out.println("AWT mouse clicked: " + e);
299 public void initDragGestureListener(Component rootPane, UnaryOperator<Point2D> controlToCanvas) {
300 final DragSource ds = new DragSource();
301 DragGestureListener dgl = new DragGestureListener() {
303 public void dragGestureRecognized(DragGestureEvent dge) {
304 InputEvent ie = dge.getTriggerEvent();
305 if (ie instanceof java.awt.event.MouseEvent) {
306 java.awt.event.MouseEvent e = (java.awt.event.MouseEvent) ie;
307 Point2D controlPos = getControlPosition(e);
308 Point2D canvasPos = controlToCanvas.apply(controlPos);
310 MouseDragBegin event = new MouseDragBegin(this,
318 getScreenPosition(e));
320 syncHandleEvent(event);
322 if (event.transferable != null) {
323 ds.startDrag(dge, null, event.transferable, null);
328 ds.createDefaultDragGestureRecognizer(
330 DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK,