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
14 * @author Toni Kalajainen
\r
16 package org.simantics.g2d.dnd;
\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
31 import org.simantics.g2d.canvas.ICanvasContext;
\r
32 import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;
\r
36 * This participant handles drop operations of a canvas.
\r
38 * To implement a drop operation add an implementation of {@link IDropTargetParticipant} to the canvas.
\r
40 * Intantiates DragPainter for the duration of drag operations.
\r
42 * DropInteractor is added by chassis.
\r
44 public class DropInteractor extends AbstractCanvasParticipant implements DropTargetListener {
\r
46 private final Component component;
\r
47 @SuppressWarnings("unused")
\r
48 private DropTarget dropTarget;
\r
49 private DnDContext dropCtx;
\r
53 * Create new abstract drop interactor
\r
56 * @param ops see DnDConstants
\r
58 public DropInteractor(Component component) {
\r
60 this.component = component;
\r
64 public void addedToContext(ICanvasContext ctx) {
\r
65 super.addedToContext(ctx);
\r
66 installDropTarget();
\r
70 public void removedFromContext(ICanvasContext ctx) {
\r
71 super.removedFromContext(ctx);
\r
72 component.setDropTarget(null);
\r
75 private int getAllowedOps() {
\r
77 for (IDropTargetParticipant p : getDropParticipants())
\r
78 result |= p.getAllowedOps();
\r
82 void installDropTarget() {
\r
83 allowedOps = getAllowedOps();
\r
84 dropTarget = new DropTarget(component, allowedOps, this);
\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
91 public int compare(IDropTargetParticipant o1, IDropTargetParticipant o2) {
\r
92 return Double.compare(o2.getPriority(), o1.getPriority());
\r
95 return participants;
\r
98 IDropTargetParticipant dropAccepter = null;
\r
99 private DragPainter currentDragPainter;
\r
101 public Collection<DragPainter> getDragPainters() {
\r
102 return getContext().getItemsByClass(DragPainter.class);
\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
113 dropCtx = new DnDContext();
\r
114 syncExec(new Runnable() {
\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
127 if (dropCtx.toArray().length==0)
\r
130 dtde.acceptDrag(dtde.getDropAction());
\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
142 public void dragExit(final DropTargetEvent dte) {
\r
143 syncExec(new Runnable() {
\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
160 public void dragOver(final DropTargetDragEvent dtde) {
\r
161 final Collection<DragPainter> interactors = getDragPainters();
\r
162 if (interactors.isEmpty()) {
\r
167 syncExec(new Runnable() {
\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
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
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
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
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
208 syncExec(new Runnable() {
\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
221 //dtde.acceptDrop(dtde.getDropAction());
\r
226 public void dropActionChanged(DropTargetDragEvent dtde) {
\r
227 //System.out.println("dropActionChanged: "+dtde.getDropAction());
\r
228 // remove interactor when action is canceled
\r
231 public void endDrag()
\r
233 Collection<DragPainter> dragPainters = getContext().getItemsByClass(DragPainter.class);
\r
234 if (dragPainters.isEmpty()) return;
\r
235 for (DragPainter dp : dragPainters)
\r
237 dropAccepter = null;
\r