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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.g2d.element.handler.impl;
\r
14 import java.awt.geom.Point2D;
\r
15 import java.util.HashMap;
\r
16 import java.util.Map;
\r
17 import java.util.Map.Entry;
\r
19 import org.simantics.g2d.canvas.ICanvasContext;
\r
20 import org.simantics.g2d.canvas.IMouseCaptureHandle;
\r
21 import org.simantics.g2d.diagram.participant.DiagramParticipant;
\r
22 import org.simantics.g2d.diagram.participant.ElementInteractor;
\r
23 import org.simantics.g2d.element.ElementUtils;
\r
24 import org.simantics.g2d.element.IElement;
\r
25 import org.simantics.g2d.element.handler.HandleMouseEvent;
\r
26 import org.simantics.scenegraph.g2d.events.MouseEvent;
\r
27 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonEvent;
\r
28 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent;
\r
29 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent;
\r
30 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent;
\r
31 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin;
\r
32 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;
\r
33 import org.simantics.utils.datastructures.hints.IHintContext.Key;
\r
34 import org.simantics.utils.datastructures.hints.IHintContext.MouseSpecificKeyOf;
\r
37 * Base implementation for handlers that handle grabbable objects.
\r
39 * TODO Esc button cancels grab
\r
41 * @author Toni Kalajainen
\r
43 public abstract class AbstractGrabbable implements HandleMouseEvent {
\r
45 private static final long serialVersionUID = -3620527648364111724L;
\r
46 Double strayDistance;
\r
47 protected int grabMouseButton = MouseEvent.LEFT_BUTTON;
\r
51 * @param strayDistance stray distance or null for no limit
\r
53 public AbstractGrabbable(Double strayDistance)
\r
55 this.strayDistance = strayDistance;
\r
58 public AbstractGrabbable()
\r
60 this.strayDistance = 1000.0;
\r
64 public boolean handleMouseEvent(IElement e, ICanvasContext ctx, MouseEvent me) {
\r
65 int pointerId = me.mouseId;
\r
66 GrabInfo gi = getGrabInfo(e, ctx, pointerId);
\r
68 if ((me instanceof MouseClickEvent)||(me instanceof MouseDragBegin)) {
\r
72 if ((me instanceof MouseMovedEvent)) {
\r
73 MouseMovedEvent mme = (MouseMovedEvent) me;
\r
74 if (gi==null) return false;
\r
76 gi.prevPosCanvas.setLocation( gi.dragPosCanvas );
\r
77 gi.prevPosControl.setLocation( gi.dragPosControl );
\r
78 gi.prevPosElement.setLocation( gi.dragPosElement );
\r
80 // Update drag positions
\r
81 gi.dragPosControl.setLocation(me.controlPosition);
\r
82 ElementUtils.controlToCanvasCoordinate(ctx, mme.controlPosition, gi.dragPosCanvas);
\r
83 ElementUtils.controlToElementCoordinate(e, ctx, mme.controlPosition, gi.dragPosElement);
\r
84 // Check if pointer has strayed too far, if so release grab
\r
85 double dist = gi.dragPosControl.distance(gi.grabPosControl);
\r
87 // Pointer has strayed too far -> release the pointer from the button
\r
88 if (dist>strayDistance)
\r
90 releaseGrab(e, ctx, pointerId);
\r
91 onGrabCancel(gi, ctx);
\r
102 if (me instanceof MouseButtonReleasedEvent)
\r
104 MouseButtonEvent mbe = (MouseButtonEvent) me;
\r
105 if (mbe.button != grabMouseButton) return false;
\r
106 if (gi==null) return false;
\r
107 releaseGrab(e, ctx, pointerId);
\r
108 onRelease(gi, ctx);
\r
112 if (me instanceof MouseButtonPressedEvent)
\r
114 MouseButtonEvent mbe = (MouseButtonEvent) me;
\r
115 if (mbe.button != grabMouseButton) return false;
\r
116 if (!onGrabCheck(e, ctx, pointerId, me.controlPosition))
\r
118 gi = grabMouse(e, ctx, pointerId, me.controlPosition);
\r
127 * Checks whether grab accepted
\r
129 * @param pickPos pick position in element coordinates
\r
130 * @return true if position is grabbable
\r
132 protected abstract boolean onGrabCheck(IElement e, ICanvasContext ctx, int pointerId, Point2D pickPos);
\r
134 protected abstract void onGrab(GrabInfo gi, ICanvasContext ctx);
\r
137 * Event when grab is released (and not canceled)
\r
138 * Invoked after grab is released.
\r
142 protected abstract void onRelease(GrabInfo gi, ICanvasContext ctx);
\r
144 protected abstract void onDrag(GrabInfo gi, ICanvasContext ctx);
\r
147 * Event notified when grab is canceled. Canceling occurs automatically
\r
148 * when mouse strays too far and when user sends cancel command (presses esc)
\r
153 protected abstract void onGrabCancel(GrabInfo gi, ICanvasContext ctx);
\r
155 protected void cancelGrab() {
\r
158 public static class GrabInfo {
\r
161 // grabbing pointer
\r
162 public int pointerId;
\r
164 public Point2D grabPosControl = new Point2D.Double();
\r
165 public Point2D grabPosCanvas = new Point2D.Double();
\r
166 public Point2D grabPosElement = new Point2D.Double();
\r
168 public Point2D dragPosControl = new Point2D.Double();
\r
169 public Point2D dragPosCanvas = new Point2D.Double();
\r
170 public Point2D dragPosElement = new Point2D.Double();
\r
172 public Point2D prevPosControl = new Point2D.Double();
\r
173 public Point2D prevPosCanvas = new Point2D.Double();
\r
174 public Point2D prevPosElement = new Point2D.Double();
\r
176 private IMouseCaptureHandle hnd;
\r
180 * Remove GrabInfo object
\r
185 private void removeGrabInfo(IElement e, ICanvasContext ctx, int pointerId)
\r
187 DiagramParticipant dp = ctx.getSingleItem(DiagramParticipant.class);
\r
188 Key key = new MouseSpecificKeyOf(pointerId, GrabInfo.class);
\r
189 dp.removeElementHint(e, key);
\r
193 * Set GrabInfo object
\r
199 private void setGrabInfo(IElement e, ICanvasContext ctx, int pointerId, GrabInfo gi)
\r
201 DiagramParticipant dp = ctx.getSingleItem(DiagramParticipant.class);
\r
202 Key key = new MouseSpecificKeyOf(pointerId, GrabInfo.class);
\r
203 dp.setElementHint(e, key, gi);
\r
208 * Get GrabInfo Object
\r
214 private GrabInfo getGrabInfo(IElement e, ICanvasContext ctx, int pointerId)
\r
216 DiagramParticipant dp = ctx.getSingleItem(DiagramParticipant.class);
\r
217 Key key = new MouseSpecificKeyOf(pointerId, GrabInfo.class);
\r
218 return dp.getElementHint(e, key);
\r
222 * Get all pointer grabs
\r
225 protected Map<Integer, GrabInfo> getGrabs(IElement e, ICanvasContext ctx)
\r
227 DiagramParticipant dp = ctx.getSingleItem(DiagramParticipant.class);
\r
228 Map<Key, Object> map = dp.getElementHints(e);
\r
229 if (map==null) return null;
\r
230 Map<Integer, GrabInfo> result = new HashMap<Integer, GrabInfo>();
\r
231 for (Entry<Key, Object> entry : map.entrySet())
\r
233 if (!(entry.getValue() instanceof GrabInfo)) continue;
\r
234 GrabInfo gi = (GrabInfo) entry.getValue();
\r
235 result.put(gi.pointerId, gi);
\r
240 protected int getGrabCount(IElement e, ICanvasContext ctx)
\r
242 DiagramParticipant dp = ctx.getSingleItem(DiagramParticipant.class);
\r
243 Map<Key, Object> map = dp.getElementHints(e);
\r
244 if (map==null) return 0;
\r
246 for (Entry<Key, Object> entry : map.entrySet())
\r
248 if (!(entry.getValue() instanceof GrabInfo)) continue;
\r
255 * Release grab of a pointer
\r
260 protected void releaseGrab(IElement e, ICanvasContext ctx, int pointerId)
\r
262 GrabInfo gi = getGrabInfo(e, ctx, pointerId);
\r
263 if (gi==null) return;
\r
265 removeGrabInfo(e, ctx, pointerId);
\r
273 * @param grabPointControl
\r
276 private GrabInfo grabMouse(IElement e, ICanvasContext ctx, int pointerId, Point2D grabPointControl)
\r
278 // Release previous capture, if exists
\r
279 releaseGrab(e, ctx, pointerId);
\r
281 ElementInteractor ei = ctx.getSingleItem(ElementInteractor.class);
\r
282 IMouseCaptureHandle hnd = ei.captureMouse(e, pointerId);
\r
283 if (hnd == null) return null;
\r
285 Point2D grabPointCanvas = ElementUtils.controlToCanvasCoordinate(ctx, grabPointControl, new Point2D.Double());
\r
286 Point2D grabPointElement = ElementUtils.controlToElementCoordinate(e, ctx, grabPointControl, new Point2D.Double());
\r
288 GrabInfo gi = new GrabInfo();
\r
291 gi.pointerId = pointerId;
\r
292 gi.grabPosControl.setLocation(grabPointControl);
\r
293 gi.grabPosCanvas.setLocation(grabPointCanvas);
\r
294 gi.grabPosElement.setLocation(grabPointElement);
\r
296 gi.dragPosControl.setLocation(grabPointControl);
\r
297 gi.dragPosCanvas.setLocation(grabPointCanvas);
\r
298 gi.dragPosElement.setLocation(grabPointElement);
\r
300 gi.prevPosControl.setLocation(grabPointControl);
\r
301 gi.prevPosCanvas.setLocation(grabPointCanvas);
\r
302 gi.prevPosElement.setLocation(grabPointElement);
\r
304 setGrabInfo(e, ctx, pointerId, gi);
\r