Sync git svn branch with SVN repository r33269.
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / g2d / events / adapter / AWTMouseEventAdapter.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 /*\r
13  *\r
14  * @author Toni Kalajainen\r
15  */\r
16 package org.simantics.scenegraph.g2d.events.adapter;\r
17 \r
18 import java.awt.event.InputEvent;\r
19 import java.awt.event.MouseEvent;\r
20 import java.awt.event.MouseListener;\r
21 import java.awt.event.MouseMotionListener;\r
22 import java.awt.event.MouseWheelEvent;\r
23 import java.awt.event.MouseWheelListener;\r
24 import java.awt.geom.Point2D;\r
25 \r
26 import org.simantics.scenegraph.g2d.events.EventDebugPolicy;\r
27 import org.simantics.scenegraph.g2d.events.IEventHandler;\r
28 import org.simantics.scenegraph.g2d.events.IEventQueue;\r
29 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent;\r
30 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent;\r
31 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDoubleClickedEvent;\r
32 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseEnterEvent;\r
33 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseExitEvent;\r
34 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;\r
35 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseWheelMovedEvent;\r
36 \r
37 \r
38 /**\r
39  * Adapts AWT mouse events into G2D events.\r
40  * \r
41  * Sends adapted events to IEventHandler\r
42  */\r
43 public class AWTMouseEventAdapter extends AbstractEventAdapter implements MouseListener, MouseMotionListener, MouseWheelListener {\r
44 \r
45     private final boolean   DEBUG                  = EventDebugPolicy.AWT_MOUSE_EVENT_ADAPTION;\r
46 \r
47     private final boolean   IGNORE_CONSUMED_EVENTS = false;\r
48 \r
49     /** Mouse id of the default mouse */\r
50     public static final int MOUSE_ID = 0;\r
51 \r
52     private final long [] pressTime = new long[5];\r
53 \r
54     int buttonStatus = 0;\r
55 \r
56     /**\r
57      * create new adapter\r
58      * @param sender the sender field in the events\r
59      * @param delegator the target of the adapted events\r
60      */\r
61     public AWTMouseEventAdapter(Object sender, IEventHandler delegator) {\r
62         super(sender, delegator);\r
63     }\r
64 \r
65     /**\r
66      * create new adapter\r
67      * @param sender the sender field in the events\r
68      * @param queue\r
69      */\r
70     public AWTMouseEventAdapter(Object sender, IEventQueue queue) {\r
71         super(sender, queue);\r
72     }\r
73 \r
74     public static Point2D getControlPosition(MouseEvent e)\r
75     {\r
76         return new Point2D.Double(e.getX(), e.getY());\r
77     }\r
78 \r
79     public static Point2D getScreenPosition(MouseEvent e)\r
80     {\r
81         return e.getLocationOnScreen();\r
82     }\r
83 \r
84     public static int getStateMask(MouseEvent e) {\r
85         int modifiers = e.getModifiersEx();\r
86         int stateMask = 0;\r
87         if((modifiers & InputEvent.CTRL_DOWN_MASK) != 0)\r
88             stateMask |= org.simantics.scenegraph.g2d.events.MouseEvent.CTRL_MASK;\r
89         if((modifiers & InputEvent.ALT_DOWN_MASK) != 0)\r
90             stateMask |= org.simantics.scenegraph.g2d.events.MouseEvent.ALT_MASK;\r
91         if((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0)\r
92             stateMask |= org.simantics.scenegraph.g2d.events.MouseEvent.ALT_GRAPH_MASK;\r
93         if((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0)\r
94             stateMask |= org.simantics.scenegraph.g2d.events.MouseEvent.SHIFT_MASK;\r
95         return stateMask;\r
96     }\r
97 \r
98     public static int getMouseButton(MouseEvent e)\r
99     {\r
100         int awtMouseButton = e.getButton();\r
101         if (awtMouseButton == MouseEvent.BUTTON1)\r
102             return org.simantics.scenegraph.g2d.events.MouseEvent.LEFT_BUTTON;\r
103         if (awtMouseButton == MouseEvent.BUTTON2)\r
104             return org.simantics.scenegraph.g2d.events.MouseEvent.MIDDLE_BUTTON;\r
105         if (awtMouseButton == MouseEvent.BUTTON3)\r
106             return org.simantics.scenegraph.g2d.events.MouseEvent.RIGHT_BUTTON;\r
107         return awtMouseButton;\r
108     }\r
109 \r
110     /**\r
111      * Converts AWT {@link MouseEvent#getModifiersEx()} mouse button status to\r
112      * G2D mouse button status. Only supports three buttons while AWT supports\r
113      * plenty more.\r
114      * \r
115      * @param e\r
116      * @return\r
117      */\r
118     public static int getButtonStatus(MouseEvent e) {\r
119         int modex = e.getModifiersEx();\r
120         int status = 0;\r
121         status |= (modex & MouseEvent.BUTTON1_DOWN_MASK) != 0 ? org.simantics.scenegraph.g2d.events.MouseEvent.LEFT_MASK : 0;\r
122         status |= (modex & MouseEvent.BUTTON2_DOWN_MASK) != 0 ? org.simantics.scenegraph.g2d.events.MouseEvent.MIDDLE_MASK : 0;\r
123         status |= (modex & MouseEvent.BUTTON3_DOWN_MASK) != 0 ? org.simantics.scenegraph.g2d.events.MouseEvent.RIGHT_MASK : 0;\r
124         return status;\r
125     }\r
126 \r
127     @Override\r
128     public void mouseEntered(MouseEvent e) {\r
129         if (IGNORE_CONSUMED_EVENTS) {\r
130             if (e.isConsumed()) {\r
131                 if (DEBUG)\r
132                     System.out.println("AWT mouse entered but already consumed: " + e);\r
133                 return;\r
134             }\r
135         }\r
136         if (DEBUG)\r
137             System.out.println("AWT mouse entered: " + e);\r
138         buttonStatus = getButtonStatus(e);\r
139         MouseEnterEvent me = new MouseEnterEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), getControlPosition(e), getScreenPosition(e));\r
140         handleEvent(me);\r
141     }\r
142 \r
143     @Override\r
144     public void mouseExited(MouseEvent e) {\r
145         if (IGNORE_CONSUMED_EVENTS) {\r
146             if (e.isConsumed()) {\r
147                 if (DEBUG)\r
148                     System.out.println("AWT mouse exited but already consumed: " + e);\r
149                 return;\r
150             }\r
151         }\r
152         if (DEBUG)\r
153             System.out.println("AWT mouse exited: " + e);\r
154 \r
155         MouseExitEvent me = new MouseExitEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), getControlPosition(e), getScreenPosition(e));\r
156         handleEvent(me);\r
157     }\r
158 \r
159     @Override\r
160     public void mousePressed(MouseEvent e) {\r
161         if (IGNORE_CONSUMED_EVENTS) {\r
162             if (e.isConsumed()) {\r
163                 if (DEBUG)\r
164                     System.out.println("AWT mouse pressed but already consumed: " + e);\r
165                 return;\r
166             }\r
167         }\r
168         if (DEBUG)\r
169             System.out.println("AWT mouse pressed: " + e);\r
170 \r
171         int mouseButton = getMouseButton(e);\r
172         if (mouseButton == MouseEvent.NOBUTTON) {\r
173                 // This is strange, seems to happen on Linux constantly when pressing buttons rapidly.\r
174                 //System.out.println("NO BUTTON EVENT: " + e);\r
175                 return;\r
176         }\r
177         \r
178         if (mouseButton<=pressTime.length) pressTime[mouseButton-1] = e.getWhen();\r
179         buttonStatus |= 1 << (mouseButton-1);\r
180 \r
181         handleEvent(new MouseButtonPressedEvent(sender, e.getWhen(), MOUSE_ID,\r
182                 buttonStatus, getStateMask(e), mouseButton, getControlPosition(e), getScreenPosition(e)));\r
183         if (e.getClickCount() == 2) {\r
184             handleEvent(new MouseDoubleClickedEvent(sender, e.getWhen(),\r
185                     MOUSE_ID, buttonStatus, getStateMask(e), mouseButton, getControlPosition(e), getScreenPosition(e)));\r
186         }\r
187     }\r
188 \r
189     @Override\r
190     public void mouseReleased(MouseEvent e) {\r
191         if (IGNORE_CONSUMED_EVENTS) {\r
192             if (e.isConsumed()) {\r
193                 if (DEBUG)\r
194                     System.out.println("AWT mouse released but already consumed: " + e);\r
195                 return;\r
196             }\r
197         }\r
198         if (DEBUG)\r
199             System.out.println("AWT mouse released: " + e);\r
200 \r
201         int mouseButton = getMouseButton(e);\r
202         if (mouseButton == MouseEvent.NOBUTTON) {\r
203             // This is strange, seems to happen on Linux constantly when pressing buttons rapidly.\r
204             //System.out.println("NO BUTTON EVENT: " + e);\r
205             return;\r
206         }\r
207 \r
208         long holdTime = Long.MAX_VALUE;\r
209         if (mouseButton<=pressTime.length)\r
210             holdTime = e.getWhen() - pressTime[mouseButton-1];\r
211 \r
212         int stateMask = getStateMask(e);\r
213 \r
214         // This works around the problem of AWT putting the ALT_DOWN_MASK in the\r
215         // mouse event extended modifiers when button 2 is pressed.\r
216         if (mouseButton == org.simantics.scenegraph.g2d.events.MouseEvent.MIDDLE_BUTTON) {\r
217             stateMask &= ~(org.simantics.scenegraph.g2d.events.MouseEvent.ALT_MASK);\r
218         }\r
219 \r
220         buttonStatus &=~ (1<<(mouseButton-1));\r
221         MouseButtonReleasedEvent me = new MouseButtonReleasedEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, stateMask, mouseButton, holdTime, getControlPosition(e), getScreenPosition(e));\r
222         handleEvent(me);\r
223     }\r
224 \r
225     @Override\r
226     public void mouseDragged(MouseEvent e) {\r
227         if (IGNORE_CONSUMED_EVENTS) {\r
228             if (e.isConsumed()) {\r
229                 if (DEBUG)\r
230                     System.out.println("AWT mouse dragged but already consumed: " + e);\r
231                 return;\r
232             }\r
233         }\r
234         if (DEBUG)\r
235             System.out.println("AWT mouse dragged: " + e);\r
236         MouseMovedEvent me = new MouseMovedEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), getControlPosition(e), getScreenPosition(e));\r
237         handleEvent(me);\r
238     }\r
239 \r
240     @Override\r
241     public void mouseMoved(MouseEvent e) {\r
242         if (IGNORE_CONSUMED_EVENTS) {\r
243             if (e.isConsumed()) {\r
244                 if (DEBUG)\r
245                     System.out.println("AWT mouse moved but already consumed: " + e);\r
246                 return;\r
247             }\r
248         }\r
249         if (DEBUG)\r
250             System.out.println("AWT mouse moved: " + e);\r
251         MouseMovedEvent me = new MouseMovedEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), getControlPosition(e), getScreenPosition(e));\r
252         handleEvent(me);\r
253     }\r
254 \r
255     @Override\r
256     public void mouseWheelMoved(MouseWheelEvent e) {\r
257         if (IGNORE_CONSUMED_EVENTS) {\r
258             if (e.isConsumed()) {\r
259                 if (DEBUG)\r
260                     System.out.println("AWT mouse wheel moved but already consumed: " + e);\r
261                 return;\r
262             }\r
263         }\r
264         if (DEBUG)\r
265             System.out.println("AWT mouse wheel moved: " + e);\r
266         int wheelRotation = 0;\r
267         if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {\r
268             wheelRotation = -e.getUnitsToScroll();\r
269         } else {\r
270             wheelRotation = -e.getWheelRotation();\r
271         }\r
272         handleEvent(new MouseWheelMovedEvent(\r
273                 sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), getControlPosition(e), getScreenPosition(e),\r
274                 e.getScrollType(), e.getScrollAmount(), wheelRotation\r
275         ));\r
276 \r
277     }\r
278 \r
279     @Override\r
280     public void mouseClicked(MouseEvent e) {\r
281         if (IGNORE_CONSUMED_EVENTS) {\r
282             if (e.isConsumed()) {\r
283                 if (DEBUG)\r
284                     System.out.println("AWT mouse clicked but already consumed: " + e);\r
285                 return;\r
286             }\r
287         }\r
288         if (DEBUG)\r
289             System.out.println("AWT mouse clicked: " + e);\r
290     }\r
291 \r
292 }\r