-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-/*\r
- *\r
- * @author Toni Kalajainen\r
- */\r
-package org.simantics.g2d.participant;\r
-\r
-import java.awt.geom.Point2D;\r
-import java.util.Collection;\r
-import java.util.HashMap;\r
-import java.util.Map;\r
-import java.util.Map.Entry;\r
-\r
-import org.simantics.g2d.canvas.Hints;\r
-import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;\r
-import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;\r
-import org.simantics.g2d.canvas.impl.HintReflection.HintListener;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent;\r
-import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseEnterEvent;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseExitEvent;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;\r
-import org.simantics.utils.datastructures.hints.IHintObservable;\r
-import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
-\r
-/**\r
- * MouseUtil tracks position and button status of mice.\r
- * It remembers where mouse was on control and on diagram when each of its button\r
- * was pressed. \r
- * \r
- * MouseUtil generates synthetic mouse events {@link MouseClickEvent} and\r
- * {@link MouseDragBegin} for convenience. \r
- * \r
- * It also tracks distance how far mouse has moved since each of its \r
- * button was pressed (used for click).\r
- * <p>\r
- * There is also debug cursor painter which can be enabled/disabled with \r
- * hint KEY_CURSOR_STATUS.\r
- * \r
- * @TODO From to mouse monitor and mouse painter classes\r
- */\r
-public class MouseUtil extends AbstractCanvasParticipant { \r
-\r
- protected @Dependency TransformUtil util;\r
-\r
- /** Mice info */\r
- protected Map<Integer, MouseInfo> miceInfo = new HashMap<Integer, MouseInfo>();\r
- protected Map<Integer, MouseInfo> micePressedInfo = new HashMap<Integer, MouseInfo>();\r
-\r
- public static class MouseClickProfile {\r
- public static final MouseClickProfile DEFAULT = new MouseClickProfile(); \r
- /** Maximum time of holding a button down that counts as a click */ \r
- public long clickHoldTimeTolerance = 300L;\r
- /** Maximum number of pixels mouse may move while pressed to count a click */ \r
- public double movementTolerance = 3.5;\r
- /** Maximum time to wait for clicks to count as consecutive */\r
- public long consecutiveToleranceTime = 380L;\r
- }\r
-\r
- protected MouseClickProfile profile = MouseClickProfile.DEFAULT;\r
-\r
- @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM")\r
- public void transformChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {\r
- if (oldValue != null && oldValue.equals(newValue)) return;\r
- sendMicePos();\r
- }\r
-\r
- @EventHandler(priority = Integer.MAX_VALUE)\r
- public boolean handleMouseEvent(MouseEvent e) \r
- {\r
- assertDependencies();\r
- if (e instanceof MouseEnterEvent)\r
- {\r
- Point2D canvasPosition = util.controlToCanvas(e.controlPosition, null);\r
- // Reset mouse\r
- MouseInfo mi = new MouseInfo(e.mouseId, e.controlPosition, canvasPosition, e.buttons);\r
- miceInfo.put(e.mouseId, mi);\r
- } else \r
- if (e instanceof MouseExitEvent)\r
- {\r
- miceInfo.remove(e.mouseId);\r
- } else\r
- if (e instanceof MouseMovedEvent)\r
- {\r
- Point2D canvasPosition = util.controlToCanvas(e.controlPosition, null);\r
- double deltaDistance = 0;\r
- MouseInfo mi = miceInfo.get(e.mouseId);\r
- if (mi==null) {\r
- mi = new MouseInfo(e.mouseId, e.controlPosition, canvasPosition, 0/*e.buttons*/);\r
- miceInfo.put(e.mouseId, mi);\r
- } else {\r
- deltaDistance = e.controlPosition.distance(mi.controlPosition);\r
- mi.controlPosition = e.controlPosition;\r
- mi.canvasPosition = canvasPosition;\r
- }\r
-\r
- if (deltaDistance>0)\r
- mi.addDistanceForButtons(deltaDistance);\r
-\r
- // Send mouse drag events.\r
- for (ButtonInfo bi : mi.buttonPressInfo.values())\r
- {\r
- if (!bi.down) continue;\r
- if (bi.deltaMotion<=profile.movementTolerance) continue;\r
- if (bi.drag) continue;\r
- bi.drag = true;\r
- MouseDragBegin db = new MouseDragBegin(\r
- this, e.time, e.mouseId, e.buttons, e.stateMask, bi.button,\r
- bi.canvasPosition, bi.controlPosition,\r
- e.controlPosition, e.screenPosition\r
- );\r
- getContext().getEventQueue().queueFirst(db);\r
- }\r
-\r
- } else\r
- if (e instanceof MouseButtonPressedEvent)\r
- {\r
- Point2D canvasPosition = util.controlToCanvas(e.controlPosition, null);\r
- MouseButtonPressedEvent me = (MouseButtonPressedEvent) e;\r
- MouseInfo mi = miceInfo.get(e.mouseId);\r
- if (mi==null) {\r
- mi = new MouseInfo(e.mouseId, e.controlPosition, canvasPosition, e.buttons);\r
- miceInfo.put(e.mouseId, mi);\r
- micePressedInfo.put(e.mouseId, mi);\r
- } else {\r
- mi.controlPosition = e.controlPosition;\r
- mi.canvasPosition = canvasPosition;\r
- micePressedInfo.put(e.mouseId, \r
- new MouseInfo(e.mouseId, e.controlPosition, canvasPosition, e.buttons));\r
- } \r
- mi.setButtonPressed(me.button, e.stateMask, e.controlPosition, canvasPosition, e.time);\r
- } else if (e instanceof MouseButtonReleasedEvent) {\r
- MouseButtonReleasedEvent me = (MouseButtonReleasedEvent) e;\r
- Point2D canvasPosition = util.controlToCanvas(me.controlPosition, null);\r
- MouseInfo mi = miceInfo.get(me.mouseId);\r
- if (mi==null) {\r
- mi = new MouseInfo(e.mouseId, me.controlPosition, canvasPosition, 0/*me.buttons*/);\r
- miceInfo.put(me.mouseId, mi);\r
- } else {\r
- mi.controlPosition = me.controlPosition;\r
- mi.canvasPosition = canvasPosition;\r
- }\r
- ButtonInfo bi = mi.releaseButton(me.button, me.time);\r
- if (bi==null) return false;\r
-\r
- if (me.holdTime > profile.clickHoldTimeTolerance) return false;\r
- if (bi.deltaMotion>profile.movementTolerance) return false;\r
- // This is a click\r
-\r
- long timeSinceLastClick = me.time - bi.lastClickEventTime;\r
- bi.lastClickEventTime = me.time;\r
-\r
- // reset click counter\r
- if (timeSinceLastClick>profile.consecutiveToleranceTime) \r
- bi.clickCount = 1;\r
- else\r
- bi.clickCount++;\r
-\r
- MouseClickEvent ce = \r
- new MouseClickEvent(getContext(), e.time, e.mouseId, e.buttons, e.stateMask, me.button, bi.clickCount, me.controlPosition, me.screenPosition); \r
- getContext().getEventQueue().queueFirst(ce);\r
- }\r
- return false;\r
- }\r
-\r
- /**\r
- * Get last known position of a mouse\r
- * \r
- * @param mouseId mouse id\r
- * @return mouse position in canvas coordinates or null if mouse exited\r
- * canvas\r
- */\r
- public MouseInfo getMouseInfo(int mouseId) {\r
- return miceInfo.get(mouseId);\r
- }\r
-\r
- public MouseInfo getMousePressedInfo(int mouseId) {\r
- return micePressedInfo.get(mouseId);\r
- }\r
-\r
- /**\r
- * Get button info\r
- * @param mouseId mouse id\r
- * @param buttonId button id\r
- * @return null if button has never been pressed, or button info\r
- */\r
- public ButtonInfo getButtonInfo(int mouseId, int buttonId)\r
- {\r
- MouseInfo mi = miceInfo.get(mouseId);\r
- if (mi==null) return null;\r
- return mi.getButtonPressInfo(buttonId);\r
- }\r
-\r
- /**\r
- * Get a snapshot of statuses of all mice\r
- * @return a snapshot\r
- */\r
- public Map<Integer, MouseInfo> getMiceInfo()\r
- {\r
- return new HashMap<Integer, MouseInfo>(miceInfo);\r
- }\r
-\r
- public int getMouseCount()\r
- {\r
- return miceInfo.size();\r
- }\r
-\r
- public MouseClickProfile getProfile() {\r
- return profile;\r
- }\r
-\r
- public void setProfile(MouseClickProfile profile) {\r
- assert(profile!=null);\r
- this.profile = profile;\r
- }\r
-\r
- public static final class MouseInfo {\r
- public int mouseId;\r
- public Point2D controlPosition;\r
- public Point2D canvasPosition;\r
- public int buttons;\r
- public MouseInfo(int mouseId, Point2D initialControlPos, Point2D initialCanvasPosition, int initialButtonMask) {\r
- this.mouseId = mouseId;\r
- this.controlPosition = initialControlPos;\r
- this.canvasPosition = initialCanvasPosition;\r
- int buttonId = 0;\r
- while (initialButtonMask!=0) {\r
- if ((initialButtonMask & 1)==1)\r
- setButtonPressed(buttonId, 0, initialControlPos, initialCanvasPosition, Long.MIN_VALUE);\r
- initialButtonMask >>>= 1;\r
- buttonId++;\r
- }\r
- }\r
-\r
- public boolean isMouseButtonPressed(int buttonId)\r
- {\r
- ButtonInfo bi = buttonPressInfo.get(buttonId);\r
- return bi!=null && bi.down;\r
- }\r
- private void _countButtonMask() {\r
- int result = 0;\r
- for (ButtonInfo pi : buttonPressInfo.values())\r
- {\r
- if (!pi.down) continue;\r
- result |= 1 << (pi.button-1);\r
- }\r
- this.buttons = result;\r
- }\r
- public Map<Integer, ButtonInfo> buttonPressInfo = new HashMap<Integer, ButtonInfo>();\r
- public void setButtonPressed(int buttonId, int stateMask, Point2D controlPos, Point2D canvasPos, long eventTime) {\r
- ButtonInfo bi = getOrCreateButtonInfo(buttonId); \r
- bi.canvasPosition = canvasPos;\r
- bi.controlPosition = controlPos;\r
- bi.systemTime = System.currentTimeMillis();\r
- bi.eventTime = eventTime;\r
- bi.down = true;\r
- bi.deltaMotion = 0;\r
- bi.drag = false;\r
- bi.stateMask = stateMask;\r
- _countButtonMask();\r
- }\r
- public ButtonInfo releaseButton(int buttonId, long eventTime) {\r
- ButtonInfo bi = getButtonPressInfo(buttonId);\r
- if (bi==null) return null;\r
- bi.down = false;\r
- bi.holdTime = eventTime - bi.eventTime;\r
- _countButtonMask();\r
- return bi;\r
- }\r
- ButtonInfo getOrCreateButtonInfo(int buttonId)\r
- {\r
- ButtonInfo bi = buttonPressInfo.get(buttonId);\r
- if (bi==null) bi = new ButtonInfo(buttonId);\r
- buttonPressInfo.put(buttonId, bi);\r
- return bi;\r
- }\r
- public ButtonInfo getButtonPressInfo(int buttonId) {\r
- return buttonPressInfo.get(buttonId);\r
- }\r
- public void addDistanceForButtons(double distance) {\r
- for (ButtonInfo bi : buttonPressInfo.values())\r
- {\r
- if (!bi.down) continue;\r
- bi.deltaMotion += distance;\r
- }\r
- }\r
- public Collection<ButtonInfo> getButtonInfos() {\r
- return buttonPressInfo.values();\r
- }\r
- }\r
-\r
- /** Status of mouse's button press */\r
- public static final class ButtonInfo {\r
- /** Position on press */\r
- public Point2D controlPosition;\r
- /** Position on press */\r
- public Point2D canvasPosition;\r
- public final int button;\r
- public int stateMask;\r
- /** System time when pressed */\r
- public long systemTime;\r
- /** Event time when pressed */\r
- public long eventTime;\r
- /** Hold time when released */\r
- public long holdTime;\r
- /** Current up / down status */\r
- public boolean down = false;\r
- /** Total movement in pixels since press */ \r
- public double deltaMotion = 0.0;\r
- /** Click Count */\r
- public int clickCount = 0;\r
- /** Time of last click */\r
- public long lastClickEventTime = Long.MIN_VALUE;\r
- /** Dragged (set true when possibility for click is excluded) */\r
- public boolean drag = false;\r
- public ButtonInfo(int button) {\r
- this.button = button;\r
- }\r
- }\r
-\r
- /**\r
- * Sends mice positions as an event\r
- */\r
- private void sendMicePos()\r
- {\r
- long time = System.currentTimeMillis();\r
- for (Entry<Integer, MouseInfo> e : miceInfo.entrySet()) {\r
- MouseInfo mi = e.getValue();\r
- MouseMovedEvent mme;\r
- // FIXME: screenPosition as null (requires adding screenPos into MouseInfo)\r
- mme = new MouseMovedEvent(getContext(), time, e.getKey(), mi.buttons, 0 /* FIXME ??? */, mi.controlPosition, null);\r
- getContext().getEventQueue().queueEvent(mme);\r
- }\r
- }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+/*
+ *
+ * @author Toni Kalajainen
+ */
+package org.simantics.g2d.participant;
+
+import java.awt.geom.Point2D;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.simantics.g2d.canvas.Hints;
+import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;
+import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
+import org.simantics.g2d.canvas.impl.HintReflection.HintListener;
+import org.simantics.scenegraph.g2d.events.MouseEvent;
+import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent;
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent;
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent;
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin;
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseEnterEvent;
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseExitEvent;
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;
+import org.simantics.utils.datastructures.hints.IHintObservable;
+import org.simantics.utils.datastructures.hints.IHintContext.Key;
+
+/**
+ * MouseUtil tracks position and button status of mice.
+ * It remembers where mouse was on control and on diagram when each of its button
+ * was pressed.
+ *
+ * MouseUtil generates synthetic mouse events {@link MouseClickEvent} and
+ * {@link MouseDragBegin} for convenience.
+ *
+ * It also tracks distance how far mouse has moved since each of its
+ * button was pressed (used for click).
+ * <p>
+ * There is also debug cursor painter which can be enabled/disabled with
+ * hint KEY_CURSOR_STATUS.
+ *
+ * @TODO From to mouse monitor and mouse painter classes
+ */
+public class MouseUtil extends AbstractCanvasParticipant {
+
+ protected @Dependency TransformUtil util;
+
+ /** Mice info */
+ protected Map<Integer, MouseInfo> miceInfo = new HashMap<Integer, MouseInfo>();
+ protected Map<Integer, MouseInfo> micePressedInfo = new HashMap<Integer, MouseInfo>();
+
+ public static class MouseClickProfile {
+ public static final MouseClickProfile DEFAULT = new MouseClickProfile();
+ /** Maximum time of holding a button down that counts as a click */
+ public long clickHoldTimeTolerance = 300L;
+ /** Maximum number of pixels mouse may move while pressed to count a click */
+ public double movementTolerance = 3.5;
+ /** Maximum time to wait for clicks to count as consecutive */
+ public long consecutiveToleranceTime = 380L;
+ }
+
+ protected MouseClickProfile profile = MouseClickProfile.DEFAULT;
+
+ @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM")
+ public void transformChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
+ if (oldValue != null && oldValue.equals(newValue)) return;
+ sendMicePos();
+ }
+
+ @EventHandler(priority = Integer.MAX_VALUE)
+ public boolean handleMouseEvent(MouseEvent e)
+ {
+ assertDependencies();
+ if (e instanceof MouseEnterEvent)
+ {
+ Point2D canvasPosition = util.controlToCanvas(e.controlPosition, null);
+ // Reset mouse
+ MouseInfo mi = new MouseInfo(e.mouseId, e.controlPosition, canvasPosition, e.buttons);
+ miceInfo.put(e.mouseId, mi);
+ } else
+ if (e instanceof MouseExitEvent)
+ {
+ miceInfo.remove(e.mouseId);
+ } else
+ if (e instanceof MouseMovedEvent)
+ {
+ Point2D canvasPosition = util.controlToCanvas(e.controlPosition, null);
+ double deltaDistance = 0;
+ MouseInfo mi = miceInfo.get(e.mouseId);
+ if (mi==null) {
+ mi = new MouseInfo(e.mouseId, e.controlPosition, canvasPosition, 0/*e.buttons*/);
+ miceInfo.put(e.mouseId, mi);
+ } else {
+ deltaDistance = e.controlPosition.distance(mi.controlPosition);
+ mi.controlPosition = e.controlPosition;
+ mi.canvasPosition = canvasPosition;
+ }
+
+ if (deltaDistance>0)
+ mi.addDistanceForButtons(deltaDistance);
+
+ // Send mouse drag events.
+ for (ButtonInfo bi : mi.buttonPressInfo.values())
+ {
+ if (!bi.down) continue;
+ if (bi.deltaMotion<=profile.movementTolerance) continue;
+ if (bi.drag) continue;
+ bi.drag = true;
+ MouseDragBegin db = new MouseDragBegin(
+ this, e.time, e.mouseId, e.buttons, e.stateMask, bi.button,
+ bi.canvasPosition, bi.controlPosition,
+ e.controlPosition, e.screenPosition
+ );
+ getContext().getEventQueue().queueFirst(db);
+ }
+
+ } else
+ if (e instanceof MouseButtonPressedEvent)
+ {
+ Point2D canvasPosition = util.controlToCanvas(e.controlPosition, null);
+ MouseButtonPressedEvent me = (MouseButtonPressedEvent) e;
+ MouseInfo mi = miceInfo.get(e.mouseId);
+ if (mi==null) {
+ mi = new MouseInfo(e.mouseId, e.controlPosition, canvasPosition, e.buttons);
+ miceInfo.put(e.mouseId, mi);
+ micePressedInfo.put(e.mouseId, mi);
+ } else {
+ mi.controlPosition = e.controlPosition;
+ mi.canvasPosition = canvasPosition;
+ micePressedInfo.put(e.mouseId,
+ new MouseInfo(e.mouseId, e.controlPosition, canvasPosition, e.buttons));
+ }
+ mi.setButtonPressed(me.button, e.stateMask, e.controlPosition, canvasPosition, e.time);
+ } else if (e instanceof MouseButtonReleasedEvent) {
+ MouseButtonReleasedEvent me = (MouseButtonReleasedEvent) e;
+ Point2D canvasPosition = util.controlToCanvas(me.controlPosition, null);
+ MouseInfo mi = miceInfo.get(me.mouseId);
+ if (mi==null) {
+ mi = new MouseInfo(e.mouseId, me.controlPosition, canvasPosition, 0/*me.buttons*/);
+ miceInfo.put(me.mouseId, mi);
+ } else {
+ mi.controlPosition = me.controlPosition;
+ mi.canvasPosition = canvasPosition;
+ }
+ ButtonInfo bi = mi.releaseButton(me.button, me.time);
+ if (bi==null) return false;
+
+ if (me.holdTime > profile.clickHoldTimeTolerance) return false;
+ if (bi.deltaMotion>profile.movementTolerance) return false;
+ // This is a click
+
+ long timeSinceLastClick = me.time - bi.lastClickEventTime;
+ bi.lastClickEventTime = me.time;
+
+ // reset click counter
+ if (timeSinceLastClick>profile.consecutiveToleranceTime)
+ bi.clickCount = 1;
+ else
+ bi.clickCount++;
+
+ MouseClickEvent ce =
+ new MouseClickEvent(getContext(), e.time, e.mouseId, e.buttons, e.stateMask, me.button, bi.clickCount, me.controlPosition, me.screenPosition);
+ getContext().getEventQueue().queueFirst(ce);
+ }
+ return false;
+ }
+
+ /**
+ * Get last known position of a mouse
+ *
+ * @param mouseId mouse id
+ * @return mouse position in canvas coordinates or null if mouse exited
+ * canvas
+ */
+ public MouseInfo getMouseInfo(int mouseId) {
+ return miceInfo.get(mouseId);
+ }
+
+ public MouseInfo getMousePressedInfo(int mouseId) {
+ return micePressedInfo.get(mouseId);
+ }
+
+ /**
+ * Get button info
+ * @param mouseId mouse id
+ * @param buttonId button id
+ * @return null if button has never been pressed, or button info
+ */
+ public ButtonInfo getButtonInfo(int mouseId, int buttonId)
+ {
+ MouseInfo mi = miceInfo.get(mouseId);
+ if (mi==null) return null;
+ return mi.getButtonPressInfo(buttonId);
+ }
+
+ /**
+ * Get a snapshot of statuses of all mice
+ * @return a snapshot
+ */
+ public Map<Integer, MouseInfo> getMiceInfo()
+ {
+ return new HashMap<Integer, MouseInfo>(miceInfo);
+ }
+
+ public int getMouseCount()
+ {
+ return miceInfo.size();
+ }
+
+ public MouseClickProfile getProfile() {
+ return profile;
+ }
+
+ public void setProfile(MouseClickProfile profile) {
+ assert(profile!=null);
+ this.profile = profile;
+ }
+
+ public static final class MouseInfo {
+ public int mouseId;
+ public Point2D controlPosition;
+ public Point2D canvasPosition;
+ public int buttons;
+ public MouseInfo(int mouseId, Point2D initialControlPos, Point2D initialCanvasPosition, int initialButtonMask) {
+ this.mouseId = mouseId;
+ this.controlPosition = initialControlPos;
+ this.canvasPosition = initialCanvasPosition;
+ int buttonId = 0;
+ while (initialButtonMask!=0) {
+ if ((initialButtonMask & 1)==1)
+ setButtonPressed(buttonId, 0, initialControlPos, initialCanvasPosition, Long.MIN_VALUE);
+ initialButtonMask >>>= 1;
+ buttonId++;
+ }
+ }
+
+ public boolean isMouseButtonPressed(int buttonId)
+ {
+ ButtonInfo bi = buttonPressInfo.get(buttonId);
+ return bi!=null && bi.down;
+ }
+ private void _countButtonMask() {
+ int result = 0;
+ for (ButtonInfo pi : buttonPressInfo.values())
+ {
+ if (!pi.down) continue;
+ result |= 1 << (pi.button-1);
+ }
+ this.buttons = result;
+ }
+ public Map<Integer, ButtonInfo> buttonPressInfo = new HashMap<Integer, ButtonInfo>();
+ public void setButtonPressed(int buttonId, int stateMask, Point2D controlPos, Point2D canvasPos, long eventTime) {
+ ButtonInfo bi = getOrCreateButtonInfo(buttonId);
+ bi.canvasPosition = canvasPos;
+ bi.controlPosition = controlPos;
+ bi.systemTime = System.currentTimeMillis();
+ bi.eventTime = eventTime;
+ bi.down = true;
+ bi.deltaMotion = 0;
+ bi.drag = false;
+ bi.stateMask = stateMask;
+ _countButtonMask();
+ }
+ public ButtonInfo releaseButton(int buttonId, long eventTime) {
+ ButtonInfo bi = getButtonPressInfo(buttonId);
+ if (bi==null) return null;
+ bi.down = false;
+ bi.holdTime = eventTime - bi.eventTime;
+ _countButtonMask();
+ return bi;
+ }
+ ButtonInfo getOrCreateButtonInfo(int buttonId)
+ {
+ ButtonInfo bi = buttonPressInfo.get(buttonId);
+ if (bi==null) bi = new ButtonInfo(buttonId);
+ buttonPressInfo.put(buttonId, bi);
+ return bi;
+ }
+ public ButtonInfo getButtonPressInfo(int buttonId) {
+ return buttonPressInfo.get(buttonId);
+ }
+ public void addDistanceForButtons(double distance) {
+ for (ButtonInfo bi : buttonPressInfo.values())
+ {
+ if (!bi.down) continue;
+ bi.deltaMotion += distance;
+ }
+ }
+ public Collection<ButtonInfo> getButtonInfos() {
+ return buttonPressInfo.values();
+ }
+ }
+
+ /** Status of mouse's button press */
+ public static final class ButtonInfo {
+ /** Position on press */
+ public Point2D controlPosition;
+ /** Position on press */
+ public Point2D canvasPosition;
+ public final int button;
+ public int stateMask;
+ /** System time when pressed */
+ public long systemTime;
+ /** Event time when pressed */
+ public long eventTime;
+ /** Hold time when released */
+ public long holdTime;
+ /** Current up / down status */
+ public boolean down = false;
+ /** Total movement in pixels since press */
+ public double deltaMotion = 0.0;
+ /** Click Count */
+ public int clickCount = 0;
+ /** Time of last click */
+ public long lastClickEventTime = Long.MIN_VALUE;
+ /** Dragged (set true when possibility for click is excluded) */
+ public boolean drag = false;
+ public ButtonInfo(int button) {
+ this.button = button;
+ }
+ }
+
+ /**
+ * Sends mice positions as an event
+ */
+ private void sendMicePos()
+ {
+ long time = System.currentTimeMillis();
+ for (Entry<Integer, MouseInfo> e : miceInfo.entrySet()) {
+ MouseInfo mi = e.getValue();
+ MouseMovedEvent mme;
+ // FIXME: screenPosition as null (requires adding screenPos into MouseInfo)
+ mme = new MouseMovedEvent(getContext(), time, e.getKey(), mi.buttons, 0 /* FIXME ??? */, mi.controlPosition, null);
+ getContext().getEventQueue().queueEvent(mme);
+ }
+ }
+
+}