]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/dnd/DropInteractor.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / dnd / DropInteractor.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 /*\r
13  *\r
14  * @author Toni Kalajainen\r
15  */\r
16 package org.simantics.g2d.dnd;\r
17 \r
18 import java.awt.Component;\r
19 import java.awt.Point;\r
20 import java.awt.dnd.DropTarget;\r
21 import java.awt.dnd.DropTargetDragEvent;\r
22 import java.awt.dnd.DropTargetDropEvent;\r
23 import java.awt.dnd.DropTargetEvent;\r
24 import java.awt.dnd.DropTargetListener;\r
25 import java.awt.geom.Point2D;\r
26 import java.util.ArrayList;\r
27 import java.util.Collection;\r
28 import java.util.Collections;\r
29 import java.util.Comparator;\r
30 \r
31 import org.simantics.g2d.canvas.ICanvasContext;\r
32 import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;\r
33 \r
34 \r
35 /**\r
36  * This participant handles drop operations of a canvas.\r
37  * \r
38  * To implement a drop operation add an implementation of {@link IDropTargetParticipant} to the canvas.\r
39  * \r
40  * Intantiates DragPainter for the duration of drag operations.\r
41  * \r
42  * DropInteractor is added by chassis.\r
43  */\r
44 public class DropInteractor extends AbstractCanvasParticipant implements DropTargetListener {\r
45 \r
46     private final Component component;\r
47     @SuppressWarnings("unused")\r
48     private DropTarget dropTarget;\r
49     private DnDContext dropCtx;\r
50     int allowedOps;\r
51 \r
52     /**\r
53      * Create new abstract drop interactor\r
54      * @param context\r
55      * @param component\r
56      * @param ops  see DnDConstants\r
57      */\r
58     public DropInteractor(Component component) {\r
59         super();\r
60         this.component = component;\r
61     }\r
62 \r
63     @Override\r
64     public void addedToContext(ICanvasContext ctx) {\r
65         super.addedToContext(ctx);\r
66         installDropTarget();\r
67     }\r
68 \r
69     @Override\r
70     public void removedFromContext(ICanvasContext ctx) {\r
71         super.removedFromContext(ctx);\r
72         component.setDropTarget(null);\r
73     }\r
74 \r
75     private int getAllowedOps() {\r
76         int result = 0;\r
77         for (IDropTargetParticipant p : getDropParticipants())\r
78             result |= p.getAllowedOps();\r
79         return result;\r
80     }\r
81 \r
82     void installDropTarget() {\r
83         allowedOps = getAllowedOps();\r
84         dropTarget = new DropTarget(component, allowedOps, this);\r
85     }\r
86 \r
87     protected Collection<IDropTargetParticipant> getDropParticipants() {\r
88         ArrayList<IDropTargetParticipant> participants = new ArrayList<IDropTargetParticipant>(getContext().getItemsByClass(IDropTargetParticipant.class));\r
89         Collections.sort(participants, new Comparator<IDropTargetParticipant>() {\r
90                         @Override\r
91                         public int compare(IDropTargetParticipant o1, IDropTargetParticipant o2) {\r
92                                 return Double.compare(o2.getPriority(), o1.getPriority());\r
93                         }\r
94                 });\r
95         return participants;\r
96     }\r
97 \r
98     IDropTargetParticipant dropAccepter = null;\r
99     private DragPainter currentDragPainter;\r
100 \r
101     public Collection<DragPainter> getDragPainters() {\r
102         return getContext().getItemsByClass(DragPainter.class);\r
103     }\r
104 \r
105     @Override\r
106     public void dragEnter(final DropTargetDragEvent dtde) {\r
107         dropAccepter = null;\r
108         final Collection<IDropTargetParticipant> participants = getDropParticipants();\r
109         if (participants.isEmpty()) {\r
110             dtde.rejectDrag();\r
111             return;\r
112         }\r
113         dropCtx = new DnDContext();\r
114         syncExec(new Runnable() {\r
115             @Override\r
116             public void run() {\r
117                 for (IDropTargetParticipant p : participants) {\r
118                     p.dragEnter(dtde, dropCtx);\r
119                     if (dropCtx.toArray().length > 0) {\r
120                         dropAccepter = p;\r
121                         break;\r
122                     }\r
123 \r
124                 }\r
125             }});\r
126 \r
127         if (dropCtx.toArray().length==0)\r
128             dtde.rejectDrag();\r
129         else\r
130             dtde.acceptDrag(dtde.getDropAction());\r
131 \r
132         // if drag is accepted, start drag interactor\r
133         Point mouseLocation = dtde.getLocation();\r
134         Point2D mouseControlPos = new Point2D.Double(mouseLocation.getX(), mouseLocation.getY());\r
135         currentDragPainter = new DragPainter(dropCtx, mouseControlPos);\r
136         getContext().add(currentDragPainter);\r
137 \r
138         setDirty();\r
139     }\r
140 \r
141     @Override\r
142     public void dragExit(final DropTargetEvent dte) {\r
143         syncExec(new Runnable() {\r
144             @Override\r
145             public void run() {\r
146                 if (dropAccepter != null)\r
147                     dropAccepter.dragExit(dte, dropCtx);\r
148 //                final Collection<IDropTargetParticipant> participants = getDropParticipants();\r
149 //                for (IDropTargetParticipant p : participants)\r
150 //                    p.dragExit(dte, dropCtx);\r
151 \r
152                 endDrag();\r
153             }\r
154         });\r
155     }\r
156 \r
157 \r
158 \r
159     @Override\r
160     public void dragOver(final DropTargetDragEvent dtde) {\r
161         final Collection<DragPainter> interactors = getDragPainters();\r
162         if (interactors.isEmpty()) {\r
163             dtde.rejectDrag();\r
164             return;\r
165         }\r
166 \r
167         syncExec(new Runnable() {\r
168             @Override\r
169             public void run() {\r
170                 Point mouseLocation = dtde.getLocation();\r
171                 Point2D mouseControlPos = new Point2D.Double(mouseLocation.getX(), mouseLocation.getY());\r
172                 for (DragPainter interactor : interactors)\r
173                     interactor.setMousePos( mouseControlPos );\r
174 \r
175                 if (dropAccepter != null)\r
176                     dropAccepter.dragOver(dtde, dropCtx);\r
177 //                final Collection<IDropTargetParticipant> participants = getDropParticipants();\r
178 //                for (IDropTargetParticipant p : participants)\r
179 //                    p.dragOver(dtde, dropCtx);\r
180 \r
181             }\r
182         });\r
183     }\r
184 \r
185     @Override\r
186     public void drop(final DropTargetDropEvent dtde) {\r
187 //        ITask task = ThreadLogger.getInstance().begin("Drop");\r
188         final Collection<DragPainter> interactors = getDragPainters();\r
189         if (interactors.isEmpty()) {\r
190             dtde.rejectDrop();\r
191             return;\r
192         }\r
193 \r
194         // Try to make sure that all DragItems have a position\r
195         // before invoking IDropTargetParticipant.drop.\r
196         Point mouseLocation = dtde.getLocation();\r
197         Point2D mouseControlPos = new Point2D.Double(mouseLocation.getX(), mouseLocation.getY());\r
198         for (DragPainter interactor : interactors)\r
199             interactor.setMousePos( mouseControlPos, true );\r
200 \r
201         // Remove drag painter before dropping just to prevent it from\r
202         // doing anything with the DNDContext after this point.\r
203         if (currentDragPainter != null) {\r
204             getContext().remove(currentDragPainter);\r
205             currentDragPainter = null;\r
206         }\r
207 \r
208         syncExec(new Runnable() {\r
209             @Override\r
210             public void run() {\r
211 //                DragPainter painter = getDragPainter();\r
212                 if (dropAccepter != null)\r
213                     dropAccepter.drop(dtde, dropCtx);\r
214 //                final Collection<IDropTargetParticipant> participants = getDropParticipants();\r
215 //                for (IDropTargetParticipant p : participants)\r
216 //                    p.drop(dtde, dropCtx);\r
217 \r
218                 endDrag();\r
219             }\r
220         });\r
221         //dtde.acceptDrop(dtde.getDropAction());\r
222 //        task.finish();\r
223     }\r
224 \r
225     @Override\r
226     public void dropActionChanged(DropTargetDragEvent dtde) {\r
227         //System.out.println("dropActionChanged: "+dtde.getDropAction());\r
228         // remove interactor when action is canceled\r
229     }\r
230 \r
231     public void endDrag()\r
232     {\r
233         Collection<DragPainter> dragPainters = getContext().getItemsByClass(DragPainter.class);\r
234         if (dragPainters.isEmpty()) return;\r
235         for (DragPainter dp : dragPainters)\r
236             dp.remove();\r
237         dropAccepter = null;\r
238         setDirty();\r
239     }\r
240 \r
241 }\r