blob: 9c185c1046655af169eacdf524ba4a7250c908c1 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2002, 2003 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
****************************************************************************/
package org.eclipse.gmf.runtime.diagram.ui.parts;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.draw2d.Cursors;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.dnd.AbstractTransferDropTargetListener;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.gmf.runtime.diagram.ui.requests.DropObjectsRequest;
import org.eclipse.gmf.runtime.notation.View;
/**
* Performs a drop of one or more semantic elements using a given transfer. The Drop is performed by
* using a {@link DropObjectsRequest} to obtain a <code>Command</code> from the targeted
* <code>EditPart</code>. The target edit part might re-interpret the <code>DropElementsRequest</code>
* to mean another request.
* <P>
* This class is <code>abstract</code>. Subclasses are responsible for providing the
* appropriate <code>Transfer</code> object based on the type of elements that are being dragged.
*
* @author melaasar
*/
public abstract class DiagramDropTargetListener
extends AbstractTransferDropTargetListener {
/**
* Constructor for DiagramDropTargetListener.
* @param viewer
*/
public DiagramDropTargetListener(EditPartViewer viewer) {
super(viewer);
}
/**
* Constructor for DiagramDropTargetListener.
* @param viewer
* @param xfer
*/
public DiagramDropTargetListener(EditPartViewer viewer, Transfer xfer) {
super(viewer, xfer);
}
/**
*
* @see org.eclipse.gef.dnd.AbstractTransferDropTargetListener#createTargetRequest()
*/
protected Request createTargetRequest() {
DropObjectsRequest request = new DropObjectsRequest();
request.setObjects(getObjectsBeingDropped());
request.setAllowedDetail(getCurrentEvent().operations);
return request;
}
/**
* A helper method that casts the target Request to a DropElementsRequest.
* @return DropElementsRequest
*/
protected final DropObjectsRequest getDropObjectsRequest() {
return ((DropObjectsRequest) getTargetRequest());
}
/**
* gets a list of objects being dropped on the diagram
* @return <code>List</code>
*/
protected abstract List getObjectsBeingDropped();
/**
* @see org.eclipse.swt.dnd.DropTargetListener#dragEnter(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void dragEnter(DropTargetEvent event) {
super.dragEnter(event);
handleDragEnter(); // called to properly initialize the effect
}
/**
* Called whenever the User enters the target. By default, the target Request and
* target EditPart are updated, and feedback is
*/
protected void handleDragEnter() {
handleDragOver();
}
/**
* The purpose of a template is to be copied. Therefore, the drop operation can't be
* anything but <code>DND.DROP_COPY</code>.
* @see AbstractTransferDropTargetListener#handleDragOperationChanged()
*/
protected void handleDragOperationChanged() {
super.handleDragOperationChanged();
getCurrentEvent().detail = getDropObjectsRequest().getRequiredDetail();
}
/**
* The purpose of a template is to be copied. Therefore, the Drop operation is set to
* <code>DND.DROP_COPY</code> by default.
* @see org.eclipse.gef.dnd.AbstractTransferDropTargetListener#handleDragOver()
*/
protected void handleDragOver() {
super.handleDragOver();
getCurrentEvent().detail = getDropObjectsRequest().getRequiredDetail();
getCurrentEvent().feedback = DND.FEEDBACK_SCROLL | DND.FEEDBACK_EXPAND;
}
/**
* Overridden to select the request result if any
* @see org.eclipse.gef.dnd.AbstractTransferDropTargetListener#handleDrop()
*/
protected void handleDrop() {
getViewer().setCursor(Cursors.WAIT);
super.handleDrop();
getViewer().setCursor(null);
selectAddedViews();
}
/**
* Selects the created views that could result from the drop request if any
*/
private void selectAddedViews() {
Object result = getDropObjectsRequest().getResult();
if (result == null || !(result instanceof Collection))
return;
EditPartViewer viewer = getViewer();
List editParts = new ArrayList();
Iterator views = ((Collection)result).iterator();
while (views.hasNext()) {
Object view = views.next();
if (view instanceof IAdaptable) {
EditPart editPart = (EditPart) viewer.getEditPartRegistry().get(((IAdaptable)view).getAdapter(View.class));
if (editPart != null)
editParts.add(editPart);
}
}
if (!editParts.isEmpty()) {
//Force a layout first.
viewer.getControl().forceFocus();
getViewer().flush();
viewer.setSelection(new StructuredSelection(editParts));
}
}
/**
* Assumes that the target request is a {@link DropObjectsRequest}.
*/
protected void updateTargetRequest() {
DropObjectsRequest request = getDropObjectsRequest();
request.setLocation(getDropLocation());
}
/**
* Make sure the target can produce a command
*/
public boolean isEnabled(DropTargetEvent event) {
if (super.isEnabled(event)){
boolean result = calculateTargetEditPart() != null;
return result;
}
return false;
}
/**
* @see org.eclipse.gef.dnd.AbstractTransferDropTargetListener#updateTargetEditPart()
*/
protected void updateTargetEditPart() {
setTargetEditPart(calculateTargetEditPart());
}
/**
* @return an edit part that can produce an executable command for the target request
*/
private EditPart calculateTargetEditPart() {
updateTargetRequest();
EditPart ep = getViewer()
.findObjectAtExcluding(
getDropLocation(),
getExclusionSet(),
new EditPartViewer.Conditional() {
public boolean evaluate(EditPart editpart) {
Command command = editpart.getCommand(getTargetRequest());
return command != null && command.canExecute();
}
});
if (ep != null) {
Command command = ep.getCommand(getTargetRequest());
return (command != null && command.canExecute())? ep : null;
}
return ep;
}
}