/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ /* * * @author Toni Kalajainen */ package org.simantics.g2d.dnd; import java.awt.Component; import java.awt.Point; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import org.simantics.g2d.canvas.ICanvasContext; import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant; /** * This participant handles drop operations of a canvas. * * To implement a drop operation add an implementation of {@link IDropTargetParticipant} to the canvas. * * Intantiates DragPainter for the duration of drag operations. * * DropInteractor is added by chassis. */ public class DropInteractor extends AbstractCanvasParticipant implements DropTargetListener { private final Component component; @SuppressWarnings("unused") private DropTarget dropTarget; private DnDContext dropCtx; int allowedOps; /** * Create new abstract drop interactor * @param context * @param component * @param ops see DnDConstants */ public DropInteractor(Component component) { super(); this.component = component; } @Override public void addedToContext(ICanvasContext ctx) { super.addedToContext(ctx); installDropTarget(); } @Override public void removedFromContext(ICanvasContext ctx) { super.removedFromContext(ctx); component.setDropTarget(null); } private int getAllowedOps() { int result = 0; for (IDropTargetParticipant p : getDropParticipants()) result |= p.getAllowedOps(); return result; } void installDropTarget() { allowedOps = getAllowedOps(); dropTarget = new DropTarget(component, allowedOps, this); } protected Collection getDropParticipants() { ArrayList participants = new ArrayList(getContext().getItemsByClass(IDropTargetParticipant.class)); Collections.sort(participants, new Comparator() { @Override public int compare(IDropTargetParticipant o1, IDropTargetParticipant o2) { return Double.compare(o2.getPriority(), o1.getPriority()); } }); return participants; } IDropTargetParticipant dropAccepter = null; private DragPainter currentDragPainter; public Collection getDragPainters() { return getContext().getItemsByClass(DragPainter.class); } @Override public void dragEnter(final DropTargetDragEvent dtde) { dropAccepter = null; final Collection participants = getDropParticipants(); if (participants.isEmpty()) { dtde.rejectDrag(); return; } dropCtx = new DnDContext(); syncExec(new Runnable() { @Override public void run() { for (IDropTargetParticipant p : participants) { p.dragEnter(dtde, dropCtx); if (dropCtx.toArray().length > 0) { dropAccepter = p; break; } } }}); if (dropCtx.toArray().length==0) dtde.rejectDrag(); else dtde.acceptDrag(dtde.getDropAction()); // if drag is accepted, start drag interactor Point mouseLocation = dtde.getLocation(); Point2D mouseControlPos = new Point2D.Double(mouseLocation.getX(), mouseLocation.getY()); currentDragPainter = new DragPainter(dropCtx, mouseControlPos); getContext().add(currentDragPainter); setDirty(); } @Override public void dragExit(final DropTargetEvent dte) { syncExec(new Runnable() { @Override public void run() { if (dropAccepter != null) dropAccepter.dragExit(dte, dropCtx); // final Collection participants = getDropParticipants(); // for (IDropTargetParticipant p : participants) // p.dragExit(dte, dropCtx); endDrag(); } }); } @Override public void dragOver(final DropTargetDragEvent dtde) { final Collection interactors = getDragPainters(); if (interactors.isEmpty()) { dtde.rejectDrag(); return; } syncExec(new Runnable() { @Override public void run() { Point mouseLocation = dtde.getLocation(); Point2D mouseControlPos = new Point2D.Double(mouseLocation.getX(), mouseLocation.getY()); for (DragPainter interactor : interactors) interactor.setMousePos( mouseControlPos ); if (dropAccepter != null) dropAccepter.dragOver(dtde, dropCtx); // final Collection participants = getDropParticipants(); // for (IDropTargetParticipant p : participants) // p.dragOver(dtde, dropCtx); } }); } @Override public void drop(final DropTargetDropEvent dtde) { // ITask task = ThreadLogger.getInstance().begin("Drop"); final Collection interactors = getDragPainters(); if (interactors.isEmpty()) { dtde.rejectDrop(); return; } // Try to make sure that all DragItems have a position // before invoking IDropTargetParticipant.drop. Point mouseLocation = dtde.getLocation(); Point2D mouseControlPos = new Point2D.Double(mouseLocation.getX(), mouseLocation.getY()); for (DragPainter interactor : interactors) interactor.setMousePos( mouseControlPos, true ); // Remove drag painter before dropping just to prevent it from // doing anything with the DNDContext after this point. if (currentDragPainter != null) { getContext().remove(currentDragPainter); currentDragPainter = null; } syncExec(new Runnable() { @Override public void run() { // DragPainter painter = getDragPainter(); if (dropAccepter != null) dropAccepter.drop(dtde, dropCtx); // final Collection participants = getDropParticipants(); // for (IDropTargetParticipant p : participants) // p.drop(dtde, dropCtx); endDrag(); } }); //dtde.acceptDrop(dtde.getDropAction()); // task.finish(); } @Override public void dropActionChanged(DropTargetDragEvent dtde) { //System.out.println("dropActionChanged: "+dtde.getDropAction()); // remove interactor when action is canceled } public void endDrag() { Collection dragPainters = getContext().getItemsByClass(DragPainter.class); if (dragPainters.isEmpty()) return; for (DragPainter dp : dragPainters) dp.remove(); dropAccepter = null; setDirty(); } }