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