]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/dnd/DragInteractor.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / dnd / DragInteractor.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 package org.simantics.g2d.dnd;\r
13 \r
14 import java.awt.Component;\r
15 import java.awt.Cursor;\r
16 import java.awt.Point;\r
17 import java.awt.datatransfer.Transferable;\r
18 import java.awt.dnd.DnDConstants;\r
19 import java.awt.dnd.DragGestureEvent;\r
20 import java.awt.dnd.DragGestureListener;\r
21 import java.awt.dnd.DragGestureRecognizer;\r
22 import java.awt.dnd.DragSource;\r
23 import java.awt.dnd.DragSourceDragEvent;\r
24 import java.awt.dnd.DragSourceDropEvent;\r
25 import java.awt.dnd.DragSourceEvent;\r
26 import java.awt.dnd.DragSourceListener;\r
27 import java.awt.dnd.InvalidDnDOperationException;\r
28 import java.awt.event.InputEvent;\r
29 import java.awt.event.MouseEvent;\r
30 import java.util.Collection;\r
31 import java.util.TooManyListenersException;\r
32 \r
33 import org.simantics.g2d.canvas.Hints;\r
34 import org.simantics.g2d.canvas.ICanvasContext;\r
35 import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;\r
36 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;\r
37 import org.simantics.g2d.participant.MouseUtil;\r
38 import org.simantics.g2d.participant.MouseUtil.ButtonInfo;\r
39 import org.simantics.g2d.participant.MouseUtil.MouseInfo;\r
40 import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;\r
41 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent;\r
42 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin;\r
43 import org.simantics.utils.ui.ErrorLogger;\r
44 \r
45 /**\r
46  * This participant handles drop operations.\r
47  * \r
48  * To implement a drop operation add an implementation of IDragParticipant to the canvas.\r
49  * \r
50  * Drag interactor is added by chassis.\r
51  * \r
52  * @author Toni Kalajainen\r
53  */\r
54 public class DragInteractor extends AbstractCanvasParticipant implements DragSourceListener {\r
55 \r
56     private final Component component;\r
57     private IDragSourceParticipant dragParticipant;\r
58     @Dependency\r
59     MouseUtil mouseUtil;\r
60 \r
61     public DragInteractor(Component component) {\r
62         super();\r
63         this.component = component;\r
64     }\r
65 \r
66     @Override\r
67     public void addedToContext(ICanvasContext ctx) {\r
68         super.addedToContext(ctx);\r
69         installDragSource();\r
70     }\r
71 \r
72     @Override\r
73     public void removedFromContext(ICanvasContext ctx) {\r
74         DRAG_SOURCE.removeDragSourceListener(this);\r
75         super.removedFromContext(ctx);\r
76     }\r
77 \r
78     int getAllowedOps() {\r
79         int result = 0;\r
80         for (IDragSourceParticipant p : getDragParticipants())\r
81             result |= p.getAllowedOps();\r
82         return result;\r
83     }\r
84 \r
85     class MyDragGestureRecognizer extends DragGestureRecognizer {\r
86 \r
87         private static final long serialVersionUID = 920532285869166322L;\r
88 \r
89         protected MyDragGestureRecognizer(DragSource ds, Component c, int actionMask) {\r
90             super(ds, c, actionMask);\r
91         }\r
92 \r
93         @Override\r
94         protected void registerListeners() {\r
95         }\r
96 \r
97         @Override\r
98         protected void unregisterListeners() {\r
99         }\r
100         public boolean handleDrag(MouseDragBegin me) {\r
101             for (IDragSourceParticipant p : getDragParticipants()) {\r
102                 int op = p.canDrag(me);\r
103                 if (op==0) continue;\r
104                 int x = (int)me.controlPosition.getX();\r
105                 int y = (int)me.controlPosition.getY();\r
106                 InputEvent awtie = new MouseEvent(component, 0, me.time, 0, x, y, 1, false);\r
107                 appendEvent(awtie);\r
108                 fireDragGestureRecognized(op, new Point(x, y));\r
109                 return true;\r
110             }\r
111             return false;\r
112         }\r
113     }\r
114 \r
115     static DragSource DRAG_SOURCE = new DragSource();\r
116     MyDragGestureRecognizer dgr;\r
117 \r
118     @EventHandler(priority = -1000)\r
119     public boolean handleDrag(MouseDragBegin me) {\r
120         return dgr.handleDrag(me);\r
121     }\r
122 \r
123     void installDragSource() {\r
124         Integer actionMask = getHint(Hints.KEY_ALLOWED_DRAG_ACTIONS);\r
125         if (actionMask == null)\r
126             actionMask = DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_REFERENCE;\r
127 \r
128         dgr = new MyDragGestureRecognizer(DRAG_SOURCE, component, actionMask);\r
129         try {\r
130             dgr.addDragGestureListener(new DragGestureListener() {\r
131                 @Override\r
132                 public void dragGestureRecognized(DragGestureEvent e) {\r
133                     // Start drag\r
134                     try {\r
135                         // Create transferable from selection\r
136                         Transferable transferable = null;\r
137                         IDragSourceParticipant activeParticipant = null;\r
138                         for (IDragSourceParticipant p : getDragParticipants())\r
139                         {\r
140                             transferable = p.dragStart(e);\r
141                             if (transferable!=null) {\r
142                                 activeParticipant = p;\r
143                                 break;\r
144                             }\r
145                         }\r
146 \r
147                         if (transferable==null)\r
148                             return;\r
149 \r
150                         //initial cursor, transferable, dsource listener\r
151 \r
152 //                        int allowedOps = activeParticipant.getAllowedOps();\r
153 //                        int action = e.getDragAction();\r
154 //                        Cursor cursor = getCursor(action, allowedOps);\r
155 //                        DRAG_SOURCE.startDrag(e, cursor, transferable, DragInteractor.this);\r
156 \r
157                         DRAG_SOURCE.startDrag(e, null, transferable, DragInteractor.this);\r
158                         DragInteractor.this.dragParticipant = activeParticipant;\r
159 \r
160                         // synthetisize mouse button release\r
161                         MouseInfo mi = mouseUtil.getMouseInfo(0);\r
162                         if (mi!=null) {\r
163                             long time = System.currentTimeMillis();\r
164                             for (ButtonInfo bi : mi.getButtonInfos())\r
165                             {\r
166                                 if (!bi.down) continue;\r
167                                 // FIXME : screenPos null (requires changes in MouseInfo)\r
168                                 MouseButtonReleasedEvent mbre = new MouseButtonReleasedEvent(null, time, mi.mouseId, mi.buttons, bi.stateMask, bi.button, time-bi.eventTime, mi.controlPosition, null);\r
169                                 getContext().getEventQueue().queueEvent(mbre);\r
170                             }\r
171                         }\r
172 \r
173                     } catch( InvalidDnDOperationException idoe ) {\r
174                         ErrorLogger.defaultLogError(idoe);\r
175                     }\r
176                 }});\r
177         } catch (TooManyListenersException e) {\r
178             // Should not happen\r
179             e.printStackTrace();\r
180         }\r
181         DRAG_SOURCE.addDragSourceListener(this);\r
182     }\r
183 \r
184     protected Collection<IDragSourceParticipant> getDragParticipants() {\r
185         return getContext().getItemsByClass(IDragSourceParticipant.class);\r
186     }\r
187 \r
188     @Override\r
189     public void dragEnter(final DragSourceDragEvent dsde) {\r
190         if (dragParticipant==null) return;\r
191         syncExec(new Runnable() {\r
192             @Override\r
193             public void run() {\r
194                 if (dragParticipant==null) return;\r
195 \r
196 //                int allowedOps = dragParticipant.getAllowedOps();\r
197 //                int action = dsde.getDropAction();\r
198 //                Cursor cursor = getCursor(action, allowedOps);\r
199 //                dsde.getDragSourceContext().setCursor( cursor );\r
200 \r
201                 dragParticipant.dragEnter(dsde);\r
202             }});\r
203     }\r
204 \r
205     @Override\r
206     public void dragDropEnd(final DragSourceDropEvent dsde) {\r
207         if (dragParticipant==null) return;\r
208         syncExec(new Runnable() {\r
209             @Override\r
210             public void run() {\r
211                 if (dragParticipant==null) return;\r
212                 dragParticipant.dragDropEnd(dsde);\r
213                 endDrag();\r
214             }\r
215         });\r
216     }\r
217 \r
218     @Override\r
219     public void dragExit(final DragSourceEvent dse) {\r
220         if (dragParticipant==null) return;\r
221         syncExec(new Runnable() {\r
222             @Override\r
223             public void run() {\r
224                 if (dragParticipant==null) return;\r
225                 dragParticipant.dragExit(dse);\r
226                 endDrag();\r
227             }\r
228         });\r
229     }\r
230 \r
231     @Override\r
232     public void dragOver(final DragSourceDragEvent dsde) {\r
233         syncExec(new Runnable() {\r
234             @Override\r
235             public void run() {\r
236                 if (dragParticipant==null) return;\r
237                 dragParticipant.dragOver(dsde);\r
238             }\r
239         });\r
240     }\r
241 \r
242     public static Cursor getCursor(int action, int allowedOps)\r
243     {\r
244         boolean allowed = (action & allowedOps) != 0;\r
245         if (action == DnDConstants.ACTION_LINK)\r
246             return allowed ? DragSource.DefaultLinkDrop : DragSource.DefaultLinkNoDrop;\r
247         else if (action == DnDConstants.ACTION_COPY)\r
248             return allowed ? DragSource.DefaultCopyDrop : DragSource.DefaultCopyNoDrop;\r
249         else if (action == DnDConstants.ACTION_MOVE)\r
250             return allowed ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop;\r
251         return DragSource.DefaultCopyNoDrop;\r
252     }\r
253 \r
254     @Override\r
255     public void dropActionChanged(final DragSourceDragEvent dsde) {\r
256 \r
257         if (dragParticipant==null) return;\r
258         syncExec(new Runnable() {\r
259             @Override\r
260             public void run() {\r
261                 if (dragParticipant==null) return;\r
262 \r
263 //                int allowedOps = dragParticipant.getAllowedOps();\r
264 //                int action = dsde.getDropAction();\r
265 //                Cursor cursor = getCursor(action, allowedOps);\r
266 //                dsde.getDragSourceContext().setCursor( cursor );\r
267 \r
268                 dragParticipant.dropActionChanged(dsde);\r
269             }\r
270         });\r
271     }\r
272 \r
273     public void endDrag()\r
274     {\r
275         Collection<DragPainter> dragPainters = getContext().getItemsByClass(DragPainter.class);\r
276         if (dragPainters.size()==0) return;\r
277         for (DragPainter dp : dragPainters)\r
278             dp.remove();\r
279         dragParticipant = null;\r
280         getContext().getContentContext().setDirty();\r
281     }\r
282 \r
283 }\r