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