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