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 *******************************************************************************/
14 * @author Toni Kalajainen
16 package org.simantics.g2d.dnd;
18 import java.awt.Component;
19 import java.awt.Point;
20 import java.awt.dnd.DropTarget;
21 import java.awt.dnd.DropTargetDragEvent;
22 import java.awt.dnd.DropTargetDropEvent;
23 import java.awt.dnd.DropTargetEvent;
24 import java.awt.dnd.DropTargetListener;
25 import java.awt.geom.Point2D;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.Collections;
29 import java.util.Comparator;
31 import org.simantics.g2d.canvas.ICanvasContext;
32 import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;
36 * This participant handles drop operations of a canvas.
38 * To implement a drop operation add an implementation of {@link IDropTargetParticipant} to the canvas.
40 * Intantiates DragPainter for the duration of drag operations.
42 * DropInteractor is added by chassis.
44 public class DropInteractor extends AbstractCanvasParticipant implements DropTargetListener {
46 private final Component component;
47 @SuppressWarnings("unused")
48 private DropTarget dropTarget;
49 private DnDContext dropCtx;
53 * Create new abstract drop interactor
56 * @param ops see DnDConstants
58 public DropInteractor(Component component) {
60 this.component = component;
64 public void addedToContext(ICanvasContext ctx) {
65 super.addedToContext(ctx);
70 public void removedFromContext(ICanvasContext ctx) {
71 super.removedFromContext(ctx);
72 component.setDropTarget(null);
75 private int getAllowedOps() {
77 for (IDropTargetParticipant p : getDropParticipants())
78 result |= p.getAllowedOps();
82 void installDropTarget() {
83 allowedOps = getAllowedOps();
84 dropTarget = new DropTarget(component, allowedOps, this);
87 protected Collection<IDropTargetParticipant> getDropParticipants() {
88 ArrayList<IDropTargetParticipant> participants = new ArrayList<IDropTargetParticipant>(getContext().getItemsByClass(IDropTargetParticipant.class));
89 Collections.sort(participants, new Comparator<IDropTargetParticipant>() {
91 public int compare(IDropTargetParticipant o1, IDropTargetParticipant o2) {
92 return Double.compare(o2.getPriority(), o1.getPriority());
98 IDropTargetParticipant dropAccepter = null;
99 private DragPainter currentDragPainter;
101 public Collection<DragPainter> getDragPainters() {
102 return getContext().getItemsByClass(DragPainter.class);
106 public void dragEnter(final DropTargetDragEvent dtde) {
108 final Collection<IDropTargetParticipant> participants = getDropParticipants();
109 if (participants.isEmpty()) {
113 dropCtx = new DnDContext();
114 syncExec(new Runnable() {
117 for (IDropTargetParticipant p : participants) {
118 p.dragEnter(dtde, dropCtx);
119 if (dropCtx.toArray().length > 0) {
127 if (dropCtx.toArray().length==0)
130 dtde.acceptDrag(dtde.getDropAction());
132 // if drag is accepted, start drag interactor
133 Point mouseLocation = dtde.getLocation();
134 Point2D mouseControlPos = new Point2D.Double(mouseLocation.getX(), mouseLocation.getY());
135 currentDragPainter = new DragPainter(dropCtx, mouseControlPos);
136 getContext().add(currentDragPainter);
142 public void dragExit(final DropTargetEvent dte) {
143 syncExec(new Runnable() {
146 if (dropAccepter != null)
147 dropAccepter.dragExit(dte, dropCtx);
148 // final Collection<IDropTargetParticipant> participants = getDropParticipants();
149 // for (IDropTargetParticipant p : participants)
150 // p.dragExit(dte, dropCtx);
160 public void dragOver(final DropTargetDragEvent dtde) {
161 final Collection<DragPainter> interactors = getDragPainters();
162 if (interactors.isEmpty()) {
167 syncExec(new Runnable() {
170 Point mouseLocation = dtde.getLocation();
171 Point2D mouseControlPos = new Point2D.Double(mouseLocation.getX(), mouseLocation.getY());
172 for (DragPainter interactor : interactors)
173 interactor.setMousePos( mouseControlPos );
175 if (dropAccepter != null)
176 dropAccepter.dragOver(dtde, dropCtx);
177 // final Collection<IDropTargetParticipant> participants = getDropParticipants();
178 // for (IDropTargetParticipant p : participants)
179 // p.dragOver(dtde, dropCtx);
186 public void drop(final DropTargetDropEvent dtde) {
187 // ITask task = ThreadLogger.getInstance().begin("Drop");
188 final Collection<DragPainter> interactors = getDragPainters();
189 if (interactors.isEmpty()) {
194 // Try to make sure that all DragItems have a position
195 // before invoking IDropTargetParticipant.drop.
196 Point mouseLocation = dtde.getLocation();
197 Point2D mouseControlPos = new Point2D.Double(mouseLocation.getX(), mouseLocation.getY());
198 for (DragPainter interactor : interactors)
199 interactor.setMousePos( mouseControlPos, true );
201 // Remove drag painter before dropping just to prevent it from
202 // doing anything with the DNDContext after this point.
203 if (currentDragPainter != null) {
204 getContext().remove(currentDragPainter);
205 currentDragPainter = null;
208 syncExec(new Runnable() {
211 // DragPainter painter = getDragPainter();
212 if (dropAccepter != null)
213 dropAccepter.drop(dtde, dropCtx);
214 // final Collection<IDropTargetParticipant> participants = getDropParticipants();
215 // for (IDropTargetParticipant p : participants)
216 // p.drop(dtde, dropCtx);
221 //dtde.acceptDrop(dtde.getDropAction());
226 public void dropActionChanged(DropTargetDragEvent dtde) {
227 //System.out.println("dropActionChanged: "+dtde.getDropAction());
228 // remove interactor when action is canceled
231 public void endDrag()
233 Collection<DragPainter> dragPainters = getContext().getItemsByClass(DragPainter.class);
234 if (dragPainters.isEmpty()) return;
235 for (DragPainter dp : dragPainters)