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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.g2d.dnd;
\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
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
46 * This participant handles drop operations.
\r
48 * To implement a drop operation add an implementation of IDragParticipant to the canvas.
\r
50 * Drag interactor is added by chassis.
\r
52 * @author Toni Kalajainen
\r
54 public class DragInteractor extends AbstractCanvasParticipant implements DragSourceListener {
\r
56 private final Component component;
\r
57 private IDragSourceParticipant dragParticipant;
\r
59 MouseUtil mouseUtil;
\r
61 public DragInteractor(Component component) {
\r
63 this.component = component;
\r
67 public void addedToContext(ICanvasContext ctx) {
\r
68 super.addedToContext(ctx);
\r
69 installDragSource();
\r
73 public void removedFromContext(ICanvasContext ctx) {
\r
74 DRAG_SOURCE.removeDragSourceListener(this);
\r
75 super.removedFromContext(ctx);
\r
78 int getAllowedOps() {
\r
80 for (IDragSourceParticipant p : getDragParticipants())
\r
81 result |= p.getAllowedOps();
\r
85 class MyDragGestureRecognizer extends DragGestureRecognizer {
\r
87 private static final long serialVersionUID = 920532285869166322L;
\r
89 protected MyDragGestureRecognizer(DragSource ds, Component c, int actionMask) {
\r
90 super(ds, c, actionMask);
\r
94 protected void registerListeners() {
\r
98 protected void unregisterListeners() {
\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
115 static DragSource DRAG_SOURCE = new DragSource();
\r
116 MyDragGestureRecognizer dgr;
\r
118 @EventHandler(priority = -1000)
\r
119 public boolean handleDrag(MouseDragBegin me) {
\r
120 return dgr.handleDrag(me);
\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
128 dgr = new MyDragGestureRecognizer(DRAG_SOURCE, component, actionMask);
\r
130 dgr.addDragGestureListener(new DragGestureListener() {
\r
132 public void dragGestureRecognized(DragGestureEvent e) {
\r
135 // Create transferable from selection
\r
136 Transferable transferable = null;
\r
137 IDragSourceParticipant activeParticipant = null;
\r
138 for (IDragSourceParticipant p : getDragParticipants())
\r
140 transferable = p.dragStart(e);
\r
141 if (transferable!=null) {
\r
142 activeParticipant = p;
\r
147 if (transferable==null)
\r
150 //initial cursor, transferable, dsource listener
\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
157 DRAG_SOURCE.startDrag(e, null, transferable, DragInteractor.this);
\r
158 DragInteractor.this.dragParticipant = activeParticipant;
\r
160 // synthetisize mouse button release
\r
161 MouseInfo mi = mouseUtil.getMouseInfo(0);
\r
163 long time = System.currentTimeMillis();
\r
164 for (ButtonInfo bi : mi.getButtonInfos())
\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
173 } catch( InvalidDnDOperationException idoe ) {
\r
174 ErrorLogger.defaultLogError(idoe);
\r
177 } catch (TooManyListenersException e) {
\r
178 // Should not happen
\r
179 e.printStackTrace();
\r
181 DRAG_SOURCE.addDragSourceListener(this);
\r
184 protected Collection<IDragSourceParticipant> getDragParticipants() {
\r
185 return getContext().getItemsByClass(IDragSourceParticipant.class);
\r
189 public void dragEnter(final DragSourceDragEvent dsde) {
\r
190 if (dragParticipant==null) return;
\r
191 syncExec(new Runnable() {
\r
193 public void run() {
\r
194 if (dragParticipant==null) return;
\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
201 dragParticipant.dragEnter(dsde);
\r
206 public void dragDropEnd(final DragSourceDropEvent dsde) {
\r
207 if (dragParticipant==null) return;
\r
208 syncExec(new Runnable() {
\r
210 public void run() {
\r
211 if (dragParticipant==null) return;
\r
212 dragParticipant.dragDropEnd(dsde);
\r
219 public void dragExit(final DragSourceEvent dse) {
\r
220 if (dragParticipant==null) return;
\r
221 syncExec(new Runnable() {
\r
223 public void run() {
\r
224 if (dragParticipant==null) return;
\r
225 dragParticipant.dragExit(dse);
\r
232 public void dragOver(final DragSourceDragEvent dsde) {
\r
233 syncExec(new Runnable() {
\r
235 public void run() {
\r
236 if (dragParticipant==null) return;
\r
237 dragParticipant.dragOver(dsde);
\r
242 public static Cursor getCursor(int action, int allowedOps)
\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
255 public void dropActionChanged(final DragSourceDragEvent dsde) {
\r
257 if (dragParticipant==null) return;
\r
258 syncExec(new Runnable() {
\r
260 public void run() {
\r
261 if (dragParticipant==null) return;
\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
268 dragParticipant.dropActionChanged(dsde);
\r
273 public void endDrag()
\r
275 Collection<DragPainter> dragPainters = getContext().getItemsByClass(DragPainter.class);
\r
276 if (dragPainters.size()==0) return;
\r
277 for (DragPainter dp : dragPainters)
\r
279 dragParticipant = null;
\r
280 getContext().getContentContext().setDirty();
\r