blob: e9f1d9a1422b581ebe580f85e293e8a7092ac29b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2010 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
* ken.ryall@nokia.com - 157506 drop from external sources does not work on Linux/Mac
*******************************************************************************/
package org.eclipse.ui.navigator;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Item;
import org.eclipse.ui.internal.navigator.NavigatorSafeRunnable;
import org.eclipse.ui.internal.navigator.Policy;
import org.eclipse.ui.internal.navigator.dnd.NavigatorPluginDropAction;
import org.eclipse.ui.part.PluginDropAdapter;
import org.eclipse.ui.part.PluginTransfer;
/**
* Provides an implementation of {@link PluginDropAdapter} which uses the
* extensions provided by the associated {@link INavigatorContentService}.
*
* <p>
* Clients should not need to create an instance of this class unless they are
* creating their own custom viewer. Otherwise, {@link CommonViewer} configures
* its drop adapter automatically.
* </p>
*
*
* @see INavigatorDnDService
* @see CommonDragAdapter
* @see CommonDragAdapterAssistant
* @see CommonDropAdapterAssistant
* @see CommonViewer
* @since 3.2
*/
public final class CommonDropAdapter extends PluginDropAdapter {
private static final Transfer[] SUPPORTED_DROP_TRANSFERS = new Transfer[] {
LocalSelectionTransfer.getTransfer(), FileTransfer.getInstance(),
PluginTransfer.getInstance() };
private final INavigatorContentService contentService;
private final INavigatorDnDService dndService;
/**
* Create a DropAdapter that handles a drop based on the given content
* service and selection provider.
*
* @param aContentService
* The content service this Drop Adapter is associated with
* @param aStructuredViewer
* The viewer this DropAdapter is associated with.
*/
public CommonDropAdapter(INavigatorContentService aContentService,
StructuredViewer aStructuredViewer) {
super(aStructuredViewer);
contentService = aContentService;
dndService = contentService.getDnDService();
setFeedbackEnabled(false);
}
/**
*
* @return An array of Transfers allowed by the CommonDropAdapter. Includes
* {@link LocalSelectionTransfer#getTransfer()},
* {@link FileTransfer#getInstance()},
* {@link PluginTransfer#getInstance()}.
* @see LocalSelectionTransfer
* @see FileTransfer
* @see PluginTransfer
*/
public Transfer[] getSupportedDropTransfers() {
return SUPPORTED_DROP_TRANSFERS;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ViewerDropAdapter#dragEnter(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void dragEnter(DropTargetEvent event) {
if (event.detail == DND.DROP_NONE)
return;
if (Policy.DEBUG_DND) {
System.out.println("CommonDropAdapter.dragEnter: " + event); //$NON-NLS-1$
}
for (int i = 0; i < event.dataTypes.length; i++) {
if (LocalSelectionTransfer.getTransfer().isSupportedType(
event.dataTypes[i])) {
event.currentDataType = event.dataTypes[i];
if (Policy.DEBUG_DND) {
System.out.println("CommonDropAdapter.dragEnter: local selection: " + event.currentDataType); //$NON-NLS-1$
}
super.dragEnter(event);
return;
}
}
for (int i = 0; i < event.dataTypes.length; i++) {
if (FileTransfer.getInstance().isSupportedType(event.dataTypes[i])) {
event.currentDataType = event.dataTypes[i];
event.detail = DND.DROP_COPY;
if (Policy.DEBUG_DND) {
System.out.println("CommonDropAdapter.dragEnter: file: " + event.currentDataType); //$NON-NLS-1$
}
super.dragEnter(event);
return;
}
}
for (int i = 0; i < event.dataTypes.length; i++) {
if (PluginTransfer.getInstance()
.isSupportedType(event.dataTypes[i])) {
event.currentDataType = event.dataTypes[i];
if (Policy.DEBUG_DND) {
System.out.println("CommonDropAdapter.dragEnter: plugin: " + event.currentDataType); //$NON-NLS-1$
}
super.dragEnter(event);
return;
}
}
event.detail = DND.DROP_NONE;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.dnd.DropTargetAdapter#dragLeave(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void dragLeave(DropTargetEvent event) {
super.dragLeave(event);
if (LocalSelectionTransfer.getTransfer().isSupportedType(
event.currentDataType)) {
event.data = NavigatorPluginDropAction
.createTransferData(contentService);
}
}
public boolean performDrop(Object data) {
final DropTargetEvent event = getCurrentEvent();
if (Policy.DEBUG_DND) {
System.out.println("CommonDropAdapter.drop (begin): " + event); //$NON-NLS-1$
}
final Object target = getCurrentTarget() != null ?
getCurrentTarget() : getViewer().getInput();
// Must validate the drop here because on some platforms (Linux, Mac) the event
// is not populated with the correct currentDataType until the drop actually
// happens, and validateDrop sets the currentTransfer based on that. The
// call to validateDrop in dragAccept is too early.
validateDrop(target, getCurrentOperation(), event.currentDataType);
if (PluginTransfer.getInstance().isSupportedType(event.currentDataType)) {
super.drop(event);
return true;
}
if (Policy.DEBUG_DND) {
System.out.println("CommonDropAdapter.drop target: " + target + " op: " + getCurrentOperation()); //$NON-NLS-1$ //$NON-NLS-2$
}
final CommonDropAdapterAssistant[] assistants = dndService.findCommonDropAdapterAssistants(target,
getCurrentTransfer());
final boolean[] retValue = new boolean[1];
for (int i = 0; i < assistants.length; i++) {
final CommonDropAdapterAssistant localAssistant = assistants[i];
SafeRunner.run(new NavigatorSafeRunnable() {
public void run() throws Exception {
localAssistant.setCurrentEvent(event);
IStatus valid = localAssistant.validateDrop(target, getCurrentOperation(),
getCurrentTransfer());
if (valid != null && valid.isOK()) {
if (Policy.DEBUG_DND) {
System.out
.println("CommonDropAdapter.drop assistant selected: " + localAssistant + " op: " + event.detail); //$NON-NLS-1$ //$NON-NLS-2$
}
localAssistant.handleDrop(CommonDropAdapter.this, event, target);
retValue[0] = true;
}
}
});
if (retValue[0])
return true;
}
return false;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ViewerDropAdapter#validateDrop(java.lang.Object,
* int, org.eclipse.swt.dnd.TransferData)
*/
public boolean validateDrop(final Object aDropTarget, final int theDropOperation,
final TransferData theTransferData) {
if (Policy.DEBUG_DND) {
System.out.println("CommonDropAdapter.validateDrop (begin) operation: " + theDropOperation + " target: " + aDropTarget /*+ " transferType: " + theTransferData.type*/); //$NON-NLS-1$ //$NON-NLS-2$
//new Exception().printStackTrace(System.out);
}
boolean result = false;
final IStatus[] valid = new IStatus[1];
if (super.validateDrop(aDropTarget, theDropOperation, theTransferData)) {
result = true;
if (Policy.DEBUG_DND) {
System.out.println("CommonDropAdapter.validateDrop valid for plugin transfer"); //$NON-NLS-1$
}
} else {
final Object target = aDropTarget != null ? aDropTarget : getViewer().getInput();
if (Policy.DEBUG_DND) {
System.out.println("CommonDropAdapter.validateDrop target: " + target); //$NON-NLS-1$
System.out.println("CommonDropAdapter.validateDrop local selection: " + //$NON-NLS-1$
LocalSelectionTransfer.getTransfer().getSelection());
}
CommonDropAdapterAssistant[] assistants = dndService.findCommonDropAdapterAssistants(
target, theTransferData);
for (int i = 0; i < assistants.length; i++) {
if (Policy.DEBUG_DND) {
System.out
.println("CommonDropAdapter.validateDrop checking assistant: \"" + assistants[i]); //$NON-NLS-1$
}
final CommonDropAdapterAssistant assistantLocal = assistants[i];
SafeRunner.run(new NavigatorSafeRunnable() {
public void run() throws Exception {
assistantLocal.setCurrentEvent(getCurrentEvent());
valid[0] = assistantLocal.validateDrop(target, theDropOperation,
theTransferData);
}
});
if (valid[0] != null && valid[0].isOK()) {
result = true;
if (Policy.DEBUG_DND) {
System.out.println("CommonDropAdapter.validateDrop VALID"); //$NON-NLS-1$
}
break;
}
if (Policy.DEBUG_DND) {
System.out
.println("CommonDropAdapter.validateDrop NOT valid: " + (valid[0] != null ? (valid[0].getSeverity() + ": " + valid[0].getMessage()) : "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
}
if (Policy.DEBUG_DND) {
System.out
.println("CommonDropAdapter.validateDrop (returning " + (valid[0] != null ? valid[0].getSeverity() + ": " + valid[0].getMessage() : "" + result) + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
setScrollExpandEnabled(true);
return result;
}
/*
* The visibility of the following methods is raised for downstream clients
* (assistants).
*/
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ViewerDropAdapter#getBounds(org.eclipse.swt.widgets.Item)
*/
public Rectangle getBounds(Item item) {
return super.getBounds(item);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ViewerDropAdapter#getCurrentLocation()
*/
public int getCurrentLocation() {
return super.getCurrentLocation();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ViewerDropAdapter#getCurrentOperation()
*/
public int getCurrentOperation() {
return super.getCurrentOperation();
}
/**
* @see org.eclipse.jface.viewers.ViewerDropAdapter#overrideOperation(int)
* @since 3.4
*/
public void overrideOperation(int operation) {
if (Policy.DEBUG_DND) {
System.out.println("CommonDropAdapter.overrideOperation: " + operation); //$NON-NLS-1$
}
super.overrideOperation(operation);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ViewerDropAdapter#getCurrentTarget()
*/
public Object getCurrentTarget() {
return super.getCurrentTarget();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.PluginDropAdapter#getCurrentTransfer()
*/
public TransferData getCurrentTransfer() {
return super.getCurrentTransfer();
}
}