]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/element/handler/impl/AbstractGrabbable.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / element / handler / impl / AbstractGrabbable.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.g2d.element.handler.impl;
13
14 import java.awt.geom.Point2D;
15 import java.util.HashMap;
16 import java.util.Map;
17 import java.util.Map.Entry;
18
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;
35
36 /**
37  * Base implementation for handlers that handle grabbable objects.
38  * 
39  * TODO Esc button cancels grab
40  * 
41  * @author Toni Kalajainen
42  */
43 public abstract class AbstractGrabbable implements HandleMouseEvent {
44
45         private static final long serialVersionUID = -3620527648364111724L;
46         Double strayDistance;
47         protected int grabMouseButton = MouseEvent.LEFT_BUTTON;
48         
49         /**
50          * Create grabbable
51          * @param strayDistance stray distance or null for no limit
52          */
53         public AbstractGrabbable(Double strayDistance)
54         {
55                 this.strayDistance = strayDistance;
56         }
57
58         public AbstractGrabbable()
59         {
60                 this.strayDistance = 1000.0;
61         }
62         
63         @Override
64         public boolean handleMouseEvent(IElement e, ICanvasContext ctx, MouseEvent me) {
65                 int     pointerId               = me.mouseId;
66                 GrabInfo gi                             = getGrabInfo(e, ctx, pointerId);
67                 
68                 if ((me instanceof MouseClickEvent)||(me instanceof MouseDragBegin)) {
69                         return gi!=null;                                
70                 }
71                 
72                 if ((me instanceof MouseMovedEvent)) {
73                         MouseMovedEvent mme = (MouseMovedEvent) me;
74                         if (gi==null) return false;
75
76                         gi.prevPosCanvas.setLocation( gi.dragPosCanvas );
77                         gi.prevPosControl.setLocation( gi.dragPosControl );
78                         gi.prevPosElement.setLocation( gi.dragPosElement );
79                         
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);                    
86
87                         // Pointer has strayed too far -> release the pointer from the button
88                         if (dist>strayDistance)
89                         {
90                                 releaseGrab(e, ctx, pointerId);
91                                 onGrabCancel(gi, ctx);
92                                 return true;
93                         }
94
95                         // Handle event
96                         onDrag(gi, ctx);
97                         // Consume event
98                         return true;
99                 }
100                 
101                 // Mouse released
102                 if (me instanceof MouseButtonReleasedEvent)
103                 {
104                         MouseButtonEvent mbe = (MouseButtonEvent) me;
105                         if (mbe.button != grabMouseButton) return false;
106                         if (gi==null) return false;                     
107                         releaseGrab(e, ctx, pointerId);
108                         onRelease(gi, ctx);
109                         return true;
110                 }
111                 // Mouse pressed
112                 if (me instanceof MouseButtonPressedEvent)
113                 {
114                         MouseButtonEvent mbe = (MouseButtonEvent) me;
115                         if (mbe.button != grabMouseButton) return false;
116                         if (!onGrabCheck(e, ctx, pointerId, me.controlPosition))
117                                 return false;
118                         gi = grabMouse(e, ctx, pointerId, me.controlPosition);
119                         onGrab(gi,ctx);
120                         return true;
121                 }
122                 
123                 return false;
124         }
125         
126         /**
127          * Checks whether grab accepted
128          * @param e element
129          * @param pickPos pick position in element coordinates 
130          * @return true if position is grabbable
131          */
132         protected abstract boolean onGrabCheck(IElement e, ICanvasContext ctx, int pointerId, Point2D pickPos);
133         
134         protected abstract void onGrab(GrabInfo gi, ICanvasContext ctx);
135
136         /**
137          * Event when grab is released (and not canceled)
138          * Invoked after grab is released.
139          * @param gi
140          * @param ctx
141          */
142         protected abstract void onRelease(GrabInfo gi, ICanvasContext ctx);
143         
144         protected abstract void onDrag(GrabInfo gi, ICanvasContext ctx);
145         
146         /**
147          * Event notified when grab is canceled. Canceling occurs automatically
148          * when mouse strays too far and when user sends cancel command (presses esc) 
149          * 
150          * @param e
151          * @param grabPos
152          */
153         protected abstract void onGrabCancel(GrabInfo gi, ICanvasContext ctx);
154         
155         protected void cancelGrab() {           
156         }
157                 
158         public static class GrabInfo {
159                 // Grabbed element
160                 public IElement e;
161                 // grabbing pointer
162                 public int pointerId;
163                 // Grab position
164                 public Point2D grabPosControl = new Point2D.Double();
165                 public Point2D grabPosCanvas = new Point2D.Double();
166                 public Point2D grabPosElement = new Point2D.Double();
167                 // Drag position
168                 public Point2D dragPosControl = new Point2D.Double();  
169                 public Point2D dragPosCanvas  = new Point2D.Double();
170                 public Point2D dragPosElement = new Point2D.Double();
171                 // Prev position
172                 public Point2D prevPosControl = new Point2D.Double();  
173                 public Point2D prevPosCanvas  = new Point2D.Double();
174                 public Point2D prevPosElement = new Point2D.Double();
175                 // Capture handle
176                 private IMouseCaptureHandle hnd;
177         }               
178
179         /**
180          * Remove GrabInfo object
181          * @param e
182          * @param ctx
183          * @param pointerId
184          */
185         private void removeGrabInfo(IElement e, ICanvasContext ctx, int pointerId)
186         {
187                 DiagramParticipant dp = ctx.getSingleItem(DiagramParticipant.class);
188                 Key key = new MouseSpecificKeyOf(pointerId, GrabInfo.class);
189                 dp.removeElementHint(e, key);
190         }
191         
192         /**
193          * Set GrabInfo object
194          * @param e
195          * @param ctx
196          * @param pointerId
197          * @param gi
198          */
199         private void setGrabInfo(IElement e, ICanvasContext ctx, int pointerId, GrabInfo gi)
200         {
201                 DiagramParticipant dp = ctx.getSingleItem(DiagramParticipant.class);
202                 Key key = new MouseSpecificKeyOf(pointerId, GrabInfo.class);
203                 dp.setElementHint(e, key, gi);
204                 
205         }
206         
207         /**
208          * Get GrabInfo Object
209          * @param e
210          * @param ctx
211          * @param pointerId
212          * @return
213          */
214         private GrabInfo getGrabInfo(IElement e, ICanvasContext ctx, int pointerId)
215         {
216                 DiagramParticipant dp = ctx.getSingleItem(DiagramParticipant.class);
217                 Key key = new MouseSpecificKeyOf(pointerId, GrabInfo.class);            
218                 return dp.getElementHint(e, key);
219         }
220         
221         /**
222          * Get all pointer grabs
223          * @return
224          */
225         protected Map<Integer, GrabInfo> getGrabs(IElement e, ICanvasContext ctx)
226         {
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())
232                 {
233                         if (!(entry.getValue() instanceof GrabInfo)) continue;
234                         GrabInfo gi = (GrabInfo) entry.getValue();
235                         result.put(gi.pointerId, gi);
236                 }
237                 return result;
238         }       
239         
240         protected int getGrabCount(IElement e, ICanvasContext ctx)
241         {
242                 DiagramParticipant dp = ctx.getSingleItem(DiagramParticipant.class);
243                 Map<Key, Object> map = dp.getElementHints(e);
244                 if (map==null) return 0;
245                 int result = 0;
246                 for (Entry<Key, Object> entry : map.entrySet())
247                 {
248                         if (!(entry.getValue() instanceof GrabInfo)) continue;
249                         result ++;
250                 }
251                 return result;
252         }
253         
254         /**
255          * Release grab of a pointer
256          * @param e
257          * @param ctx
258          * @param pointerId
259          */
260         protected void releaseGrab(IElement e, ICanvasContext ctx, int pointerId)
261         {
262                 GrabInfo gi = getGrabInfo(e, ctx, pointerId);
263                 if (gi==null) return;
264                 gi.hnd.release();
265                 removeGrabInfo(e, ctx, pointerId);
266         }
267         
268         /**
269          * Grab a pointer
270          * @param e
271          * @param ctx
272          * @param pointerId
273          * @param grabPointControl
274          * @return
275          */
276         private GrabInfo grabMouse(IElement e, ICanvasContext ctx, int pointerId, Point2D grabPointControl)
277         {
278                 // Release previous capture, if exists
279                 releaseGrab(e, ctx, pointerId);         
280                 
281                 ElementInteractor ei = ctx.getSingleItem(ElementInteractor.class);
282                 IMouseCaptureHandle hnd = ei.captureMouse(e, pointerId);
283                 if (hnd == null) return null;
284
285                 Point2D grabPointCanvas = ElementUtils.controlToCanvasCoordinate(ctx, grabPointControl, new Point2D.Double());
286                 Point2D grabPointElement = ElementUtils.controlToElementCoordinate(e, ctx, grabPointControl, new Point2D.Double());
287                 
288                 GrabInfo gi = new GrabInfo();
289                 gi.e = e;
290                 gi.hnd = hnd;
291                 gi.pointerId = pointerId;
292                 gi.grabPosControl.setLocation(grabPointControl);
293                 gi.grabPosCanvas.setLocation(grabPointCanvas);
294                 gi.grabPosElement.setLocation(grabPointElement);
295                 
296                 gi.dragPosControl.setLocation(grabPointControl);
297                 gi.dragPosCanvas.setLocation(grabPointCanvas);
298                 gi.dragPosElement.setLocation(grabPointElement);
299                                 
300                 gi.prevPosControl.setLocation(grabPointControl);
301                 gi.prevPosCanvas.setLocation(grabPointCanvas);
302                 gi.prevPosElement.setLocation(grabPointElement);
303                 
304                 setGrabInfo(e, ctx, pointerId, gi);
305                 
306                 return gi;
307         }       
308
309 }