### Eclipse Workspace Patch 1.0 #P org.eclipse.ui.navigator Index: src/org/eclipse/ui/navigator/CommonDragAdapter.java =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/navigator/CommonDragAdapter.java,v retrieving revision 1.1 diff -u -r1.1 CommonDragAdapter.java --- src/org/eclipse/ui/navigator/CommonDragAdapter.java 9 Feb 2006 21:32:09 -0000 1.1 +++ src/org/eclipse/ui/navigator/CommonDragAdapter.java 22 Feb 2006 04:32:48 -0000 @@ -10,6 +10,9 @@ *******************************************************************************/ package org.eclipse.ui.navigator; +import java.util.LinkedHashSet; +import java.util.Set; + import org.eclipse.jface.util.LocalSelectionTransfer; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; @@ -50,6 +53,8 @@ */ public final class CommonDragAdapter extends DragSourceAdapter { + private static final boolean DEBUG = false; + private final INavigatorContentService contentService; private final ISelectionProvider provider; @@ -70,30 +75,67 @@ provider = aProvider; } + /** + * + * @return An array of supported Drag Transfer types. The list contains [ + * {@link LocalSelectionTransfer#getTransfer()}, + * {@link PluginTransfer#getInstance()}] in addition to any + * supported types contributed by the + * {@link CommonDragAdapterAssistant assistants}. + * @see CommonDragAdapterAssistant + * @see LocalSelectionTransfer + * @see PluginTransfer + */ + public Transfer[] getSupportDragTransfers() { + CommonDragAdapterAssistant[] assistants = contentService + .getDnDService().getCommonDragAssistants(); + + Set supportedTypes = new LinkedHashSet(); + supportedTypes.add(PluginTransfer.getInstance()); + supportedTypes.add(LocalSelectionTransfer.getTransfer()); + Transfer[] transferTypes = null; + for (int i = 0; i < assistants.length; i++) { + transferTypes = assistants[i].getSupportedTransferTypes(); + for (int j = 0; j < transferTypes.length; j++) { + if (transferTypes[j] != null) + supportedTypes.add(transferTypes[j]); + } + } + + Transfer[] transfers = (Transfer[]) supportedTypes + .toArray(new Transfer[supportedTypes.size()]); + return transfers; + } + /* * (non-Javadoc) * * @see org.eclipse.swt.dnd.DragSourceAdapter#dragStart(org.eclipse.swt.dnd.DragSourceEvent) */ public void dragStart(DragSourceEvent event) { + if (DEBUG) + System.out.println("CommonDragAdapter.dragStart (begin): " + event); //$NON-NLS-1$ try { // Workaround for 1GEUS9V DragSource dragSource = (DragSource) event.widget; Control control = dragSource.getControl(); - if (control != control.getDisplay().getFocusControl()) { - event.doit = false; - return; - } - ISelection selection = provider.getSelection(); - if (selection.isEmpty()) { + if (control == control.getDisplay().getFocusControl()) { + ISelection selection = provider.getSelection(); + if (!selection.isEmpty()) { + LocalSelectionTransfer.getTransfer() + .setSelection(selection); + event.doit = true; + } else + event.doit = false; + } else event.doit = false; - return; - } - LocalSelectionTransfer.getTransfer().setSelection(selection); - event.doit = true; } catch (RuntimeException e) { NavigatorPlugin.logError(0, e.getMessage(), e); } + + if (DEBUG) + System.out + .println("CommonDragAdapter.dragStart (end): doit=" + event.doit); //$NON-NLS-1$ } /* @@ -105,13 +147,29 @@ ISelection selection = LocalSelectionTransfer.getTransfer() .getSelection(); + + if (DEBUG) + System.out + .println("CommonDragAdapter.dragSetData (begin): event" + event + " selection=" + selection); //$NON-NLS-1$ //$NON-NLS-2$ + if (LocalSelectionTransfer.getTransfer() - .isSupportedType(event.dataType)) + .isSupportedType(event.dataType)) { event.data = selection; - else if (PluginTransfer.getInstance().isSupportedType(event.dataType)) + + if (DEBUG) + System.out + .println("CommonDragAdapter.dragSetData set LocalSelectionTransfer"); //$NON-NLS-1$ + } else if (PluginTransfer.getInstance().isSupportedType(event.dataType)) { event.data = NavigatorPluginDropAction .createTransferData(contentService); - else if (selection instanceof IStructuredSelection) { + if (DEBUG) + System.out + .println("CommonDragAdapter.dragSetData set PluginTransfer"); //$NON-NLS-1$ + } else if (selection instanceof IStructuredSelection) { + if (DEBUG) + System.out + .println("CommonDragAdapter.dragSetData looking for assistants"); //$NON-NLS-1$ + INavigatorDnDService dndService = contentService.getDnDService(); CommonDragAdapterAssistant[] assistants = dndService .getCommonDragAssistants(); @@ -123,6 +181,9 @@ if (supportedTransferTypes[j] .isSupportedType(event.dataType)) try { + if (DEBUG) + System.out + .println("CommonDragAdapter.dragSetData set assistant transfer type"); //$NON-NLS-1$ assistants[i].setDragData(event, (IStructuredSelection) selection); } catch (RuntimeException re) { @@ -132,7 +193,11 @@ } } - } + } else + event.doit = false; + + if (DEBUG) + System.out.println("CommonDragAdapter.dragSetData (end): " + event); //$NON-NLS-1$ } /* @@ -141,9 +206,16 @@ * @see org.eclipse.swt.dnd.DragSourceAdapter#dragFinished(org.eclipse.swt.dnd.DragSourceEvent) */ public void dragFinished(DragSourceEvent event) { + + if (DEBUG) + System.out.println("CommonDragAdapter.dragFinished()."); //$NON-NLS-1$ + LocalSelectionTransfer.getTransfer().setSelection(null); - if (event.doit == false) - return; + + // TODO Handle clean up if drop target was outside of workbench + // if (event.doit != false) { + // + // } } } Index: src/org/eclipse/ui/navigator/INavigatorDnDService.java =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/navigator/INavigatorDnDService.java,v retrieving revision 1.1 diff -u -r1.1 INavigatorDnDService.java --- src/org/eclipse/ui/navigator/INavigatorDnDService.java 9 Feb 2006 21:32:09 -0000 1.1 +++ src/org/eclipse/ui/navigator/INavigatorDnDService.java 22 Feb 2006 04:32:51 -0000 @@ -11,6 +11,9 @@ package org.eclipse.ui.navigator; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.dnd.TransferData; + /** * @@ -66,24 +69,48 @@ * content extensions that are visible and active for the * associated {@link INavigatorContentService}. The array is sorted by * priority, with overrides taken into account. - * + * *

- * That is, if an extension X overrides extension Y (see - * org.eclipse.ui.navigator.navigatorContent/override), then X will - * occur before Y in the array. If X and Y override Z, but X has higher - * priority than Y, then X will occur before Y, and Y will occur before Z. + * The array should be processed from the first element to the last, asking + * each extension to + * {@link CommonDropAdapterAssistant#validateDrop(Object, int, org.eclipse.swt.dnd.TransferData)}. + * The first to successfully validate the drop operation will have the + * opportunity to + * {@link CommonDropAdapterAssistant#handleDrop(CommonDropAdapter, org.eclipse.swt.dnd.DropTargetEvent, Object) handle the drop} *

+ * + * @param aDropTarget + * The target element in the viewer of the drop operation. + * @param theTransferType + * The transfer type of the current drop operation. + * @return An array of {@link CommonDropAdapterAssistant}s that are defined + * by the set of + * org.eclipse.ui.navigator.navigatorContent/navigatorContent + * extensions that provide a possibleChildren expression + * that matches the given drop target. + */ + CommonDropAdapterAssistant[] findCommonDropAdapterAssistants( + Object aDropTarget, TransferData theTransferType); + + /** + * + * This method returns an array of {@link CommonDropAdapterAssistant} from + * content extensions that are visible and active for the + * associated {@link INavigatorContentService}. + * *

* The array should be processed from the first element to the last, asking * each extension to * {@link CommonDropAdapterAssistant#validateDrop(Object, int, org.eclipse.swt.dnd.TransferData)}. * The first to successfully validate the drop operation will have the * opportunity to - * {@link CommonDropAdapterAssistant#handleDrop(org.eclipse.swt.dnd.DropTargetEvent, Object)}. + * {@link CommonDropAdapterAssistant#handleDrop(CommonDropAdapter, org.eclipse.swt.dnd.DropTargetEvent, Object) handle the drop} *

* * @param aDropTarget - * The target element in the viewer of the drop operation + * The target element in the viewer of the drop operation. + * @param theDragSelection + * The drag selection of the current drop operation. * @return An array of {@link CommonDropAdapterAssistant}s that are defined * by the set of * org.eclipse.ui.navigator.navigatorContent/navigatorContent @@ -91,5 +118,5 @@ * that matches the given drop target. */ CommonDropAdapterAssistant[] findCommonDropAdapterAssistants( - Object aDropTarget); + Object aDropTarget, IStructuredSelection theDragSelection); } Index: src/org/eclipse/ui/navigator/INavigatorContentDescriptor.java =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/navigator/INavigatorContentDescriptor.java,v retrieving revision 1.5 diff -u -r1.5 INavigatorContentDescriptor.java --- src/org/eclipse/ui/navigator/INavigatorContentDescriptor.java 6 Feb 2006 22:24:45 -0000 1.5 +++ src/org/eclipse/ui/navigator/INavigatorContentDescriptor.java 22 Feb 2006 04:32:51 -0000 @@ -12,6 +12,7 @@ import java.util.Set; +import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.internal.navigator.extensions.OverridePolicy; @@ -100,6 +101,14 @@ boolean isPossibleChild(Object anElement); /** + * A convenience method to check all elements in a selection. + * + * @param aSelection A non-null selection + * @return True if and only if every element in the selection is a possible child. + */ + boolean arePossibleChildren(IStructuredSelection aSelection); + + /** * @return Returns the suppressedExtensionId or null if none specified. */ String getSuppressedExtensionId(); Index: src/org/eclipse/ui/navigator/CommonDropAdapterAssistant.java =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/navigator/CommonDropAdapterAssistant.java,v retrieving revision 1.1 diff -u -r1.1 CommonDropAdapterAssistant.java --- src/org/eclipse/ui/navigator/CommonDropAdapterAssistant.java 9 Feb 2006 21:32:09 -0000 1.1 +++ src/org/eclipse/ui/navigator/CommonDropAdapterAssistant.java 22 Feb 2006 04:32:49 -0000 @@ -10,9 +10,14 @@ *******************************************************************************/ package org.eclipse.ui.navigator; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.jface.util.LocalSelectionTransfer; +import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.dnd.TransferData; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.internal.navigator.NavigatorContentService; import org.eclipse.ui.part.PluginTransfer; /** @@ -29,11 +34,11 @@ * Whenever a match is found, the assistant will be given an opportunity to * first {@link #validateDrop(Object, int, TransferData) }, and then if the * assistant returns true, the assist must - * {@link #handleDrop(DropTargetEvent, Object) }. If multiple assistants match - * the drop target, then the potential assistants are ordered based on priority - * and their override relationships and given an opportunity to validate the - * drop operation in turn. The first one to validate will have the opportunty to - * carry out the drop. + * {@link #handleDrop(CommonDropAdapter, DropTargetEvent, Object) }. If + * multiple assistants match the drop target, then the potential assistants are + * ordered based on priority and their override relationships and given an + * opportunity to validate the drop operation in turn. The first one to validate + * will have the opportunty to carry out the drop. *

*

* That is, if a content extension X overrides content extension Y (see @@ -42,6 +47,28 @@ * than Y, then X will have an opportunity before Y, and Y will have an * opportunity before Z. *

+ * + *

+ * Clients may handle DND operations that begin and end in the current viewer by + * overriding the following methods: + *

+ *

+ *

+ * If a user originates a drag operation to another viewer that cannot handle + * one of the available drag transfer types, drop assistants may handle the drop + * operation for the target viewer. Clients must override : + *

+ *

*

* EXPERIMENTAL. This class or interface has been added as * part of a work in progress. There is a guarantee neither that this API will @@ -53,7 +80,8 @@ *

* * @see INavigatorDnDService - * @see INavigatorDnDService#findCommonDropAdapterAssistants(Object) + * @see INavigatorDnDService#findCommonDropAdapterAssistants(Object, + * TransferData) * @since 3.2 * */ @@ -76,7 +104,7 @@ } /** - * Override to perform any one-time intialization. + * Override to perform any one-time initialization. */ protected void doInit() { @@ -88,7 +116,7 @@ *

* Subclasses must implement this method to define which drops make sense. * If clients return true, then they will be allowed to handle the drop in - * {@link #handleDrop(DropTargetEvent, Object) }. + * {@link #handleDrop(CommonDropAdapter, DropTargetEvent, Object) }. *

* * @param target @@ -98,41 +126,81 @@ * the current drag operation (copy, move, etc.) * @param transferType * the current transfer type - * @return true if the drop is valid, and false - * otherwise + * @return A status indicating whether the drop is valid. */ - public abstract boolean validateDrop(Object target, int operation, + public abstract IStatus validateDrop(Object target, int operation, TransferData transferType); /** - * Carry out the DND operation + * Carry out the DND operation. * + * @param aDropAdapter + * The Drop Adapter contains information that has already been + * parsed from the drop event. * @param aDropTargetEvent * The drop target event. * @param aTarget * The object being dragged onto - * @return True if the operation completed. + * @return A status indicating whether the drop completed OK. */ - public abstract boolean handleDrop(DropTargetEvent aDropTargetEvent, - Object aTarget); + public abstract IStatus handleDrop(CommonDropAdapter aDropAdapter, + DropTargetEvent aDropTargetEvent, Object aTarget); + + /** + * Clients may extend the supported transfer types beyond the default + * {@link LocalSelectionTransfer#getTransfer()} and + * {@link PluginTransfer#getInstance()} transfer types. When a transfer type + * other than one of these is encountered, the DND Service will query the + * visible and active descriptors that are enabled + * for the drop target of the current operation. + * + * @param aTransferType + * The transfer data from the drop operation + * @return True if the given TransferData can be understood by this + * assistant. + */ + public boolean isSupportedType(TransferData aTransferType) { + return LocalSelectionTransfer.getTransfer().isSupportedType( + aTransferType); + } /** - * When a drop opportunity presents itself, the available TransferData types - * will be supplied in the event. The DropAdapter must select one of these - * TransferData types for the DragAdapter to provide. By default the Common - * Navigator supports {@link LocalSelectionTransfer} and - * {@link PluginTransfer}. Clients are required to indicate if they support - * other TransferData types using this method. * + * Return true if the client can handle the drop onto the target viewer of + * the drop operation. *

- * If none of the given TransferData types are supported, return null. + * The default behavior of this method is to return Status.CANCEL_STATUS. *

* - * @param theAvailableTransferData - * @return The supported TransferData from the set. - */ - public abstract TransferData findSupportedTransferData( - TransferData[] theAvailableTransferData); + * @param aDragSelection + * The selection dragged from the viewer. + * @param aDropTarget + * The target of the drop operation. + * + * @return OK if the plugin transfer can be handled by this assistant. + */ + public IStatus validatePluginTransferDrop( + IStructuredSelection aDragSelection, Object aDropTarget) { + return Status.CANCEL_STATUS; + } + + /** + * Handle the drop operation for the target viewer. + *

+ * The default behavior of this method is to return Status.CANCEL_STATUS. + *

+ * + * @param aDragSelection + * The selection dragged from the viewer. + * @param aDropTarget + * The target of the drop operation. + * + * @return OK if the drop operation succeeded. + */ + public IStatus handlePluginTransferDrop( + IStructuredSelection aDragSelection, Object aDropTarget) { + return Status.CANCEL_STATUS; + } /** * @@ -142,4 +210,13 @@ return contentService; } + /** + * + * @return A shell for the viewer currently used by the + * {@link INavigatorContentService}. + */ + protected final Shell getShell() { + return ((NavigatorContentService) contentService).getShell(); + } + } Index: src/org/eclipse/ui/navigator/CommonDragAdapterAssistant.java =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/navigator/CommonDragAdapterAssistant.java,v retrieving revision 1.1 diff -u -r1.1 CommonDragAdapterAssistant.java --- src/org/eclipse/ui/navigator/CommonDragAdapterAssistant.java 9 Feb 2006 21:32:09 -0000 1.1 +++ src/org/eclipse/ui/navigator/CommonDragAdapterAssistant.java 22 Feb 2006 04:32:48 -0000 @@ -17,6 +17,9 @@ import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.dnd.TransferData; import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.internal.navigator.NavigatorContentService; import org.eclipse.ui.part.PluginTransfer; /** @@ -31,7 +34,7 @@ *

* * @see INavigatorDnDService - * @see CommonDragAdapter + * @see CommonDragAdapter * @see CommonDropAdapter * @see CommonDropAdapterAssistant * @see CommonViewer#initDragAndDrop() @@ -47,6 +50,8 @@ */ public abstract class CommonDragAdapterAssistant { + private INavigatorContentService contentService; + /** * Extra TransferTypes allow the Navigator to generate different kinds of * payloads for DND clients. By default, the {@link CommonDragAdapter} @@ -81,4 +86,33 @@ public abstract void setDragData(DragSourceEvent anEvent, IStructuredSelection aSelection); + /** + * Accept and remember the content service this assistant is associated + * with. + * + * @param aContentService + */ + public final void setContentService(INavigatorContentService aContentService) { + contentService = aContentService; + } + + /** + * + * @return The associated content service. + */ + public INavigatorContentService getContentService() { + return contentService; + } + + /** + * + * @return The shell for the viewer this assistant is associated with or the + * shell of the active workbench window. + */ + public final Shell getShell() { + if (contentService != null) + ((NavigatorContentService) contentService).getShell(); + return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + } + } Index: src/org/eclipse/ui/navigator/CommonDropAdapter.java =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/navigator/CommonDropAdapter.java,v retrieving revision 1.1 diff -u -r1.1 CommonDropAdapter.java --- src/org/eclipse/ui/navigator/CommonDropAdapter.java 9 Feb 2006 21:32:10 -0000 1.1 +++ src/org/eclipse/ui/navigator/CommonDropAdapter.java 22 Feb 2006 04:32:49 -0000 @@ -10,12 +10,18 @@ *******************************************************************************/ package org.eclipse.ui.navigator; +import org.eclipse.core.runtime.IStatus; 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.NavigatorPlugin; +import org.eclipse.ui.internal.navigator.dnd.NavigatorDnDService; import org.eclipse.ui.internal.navigator.dnd.NavigatorPluginDropAction; import org.eclipse.ui.part.PluginDropAdapter; import org.eclipse.ui.part.PluginTransfer; @@ -46,10 +52,16 @@ */ public final class CommonDropAdapter extends PluginDropAdapter { - // private final StructuredViewer viewer; + private static final Transfer[] SUPPORTED_DROP_TRANSFERS = new Transfer[] { + LocalSelectionTransfer.getTransfer(), FileTransfer.getInstance(), + PluginTransfer.getInstance() }; + + private static final boolean DEBUG = false; private final INavigatorContentService contentService; + private final NavigatorDnDService dndService; + /** * Create a DropAdapter that handles a drop based on the given content * service and selection provider. @@ -62,8 +74,22 @@ public CommonDropAdapter(INavigatorContentService aContentService, StructuredViewer aStructuredViewer) { super(aStructuredViewer); - // viewer = aStructuredViewer; contentService = aContentService; + dndService = (NavigatorDnDService) contentService.getDnDService(); + } + + /** + * + * @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; } /* @@ -74,22 +100,28 @@ public void dragEnter(DropTargetEvent event) { super.dragEnter(event); - for (int i = 0; i < event.dataTypes.length; i++) { + for (int i = 0; i < event.dataTypes.length; i++) if (LocalSelectionTransfer.getTransfer().isSupportedType( event.dataTypes[i])) { event.currentDataType = event.dataTypes[i]; return; - } else if (FileTransfer.getInstance().isSupportedType( - event.dataTypes[i])) { + } + + 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; return; - } else if (PluginTransfer.getInstance().isSupportedType( - event.dataTypes[i])) { + } + + for (int i = 0; i < event.dataTypes.length; i++) + + if (PluginTransfer.getInstance() + .isSupportedType(event.dataTypes[i])) { event.currentDataType = event.dataTypes[i]; return; } - } + event.detail = DND.DROP_NONE; } @@ -116,8 +148,27 @@ public void drop(DropTargetEvent event) { if (PluginTransfer.getInstance().isSupportedType(event.currentDataType)) super.drop(event); + else { - // TODO Use the CommonDropAssistants to validate the drop. + CommonDropAdapterAssistant[] assistants = dndService + .findCommonDropAdapterAssistants(getCurrentTarget(), + getCurrentTransfer()); + + IStatus valid = null; + for (int i = 0; i < assistants.length; i++) { + try { + valid = assistants[i].validateDrop(getCurrentTarget(), + getCurrentOperation(), getCurrentTransfer()); + if (valid != null && valid.isOK()) { + assistants[i].handleDrop(this, event, + getCurrentTarget()); + return; + } + } catch (Throwable t) { + NavigatorPlugin.logError(0, t.getMessage(), t); + } + } + } } /* @@ -126,20 +177,97 @@ * @see org.eclipse.jface.viewers.ViewerDropAdapter#validateDrop(java.lang.Object, * int, org.eclipse.swt.dnd.TransferData) */ - public boolean validateDrop(Object target, int operation, - TransferData transferType) { - /* - * should be called first sense the currentTransfer field is set in the - * parent in this method - */ - if (super.validateDrop(target, operation, transferType)) { - return true; - } + public boolean validateDrop(Object aDropTarget, int theDropOperation, + TransferData theTransferData) { + + if (DEBUG) + System.out.println("CommonDropAdapter.validateDrop (begin)"); //$NON-NLS-1$ + boolean result = false; - // TODO Use the CommonDropAssistants to validate the drop. + IStatus valid = null; + + if (super.validateDrop(aDropTarget, theDropOperation, theTransferData)) + result = true; + else if (FileTransfer.getInstance().isSupportedType(theTransferData)) + // only allow copying when dragging from outside Eclipse + // result = theDropOperation != DND.DROP_COPY; + result = true; + else { + CommonDropAdapterAssistant[] assistants = dndService + .findCommonDropAdapterAssistants(aDropTarget, + theTransferData); + + for (int i = 0; i < assistants.length; i++) { + try { + valid = assistants[i].validateDrop(aDropTarget, + theDropOperation, theTransferData); + } catch (Throwable t) { + NavigatorPlugin.logError(0, t.getMessage(), t); + } + if (valid != null && valid.isOK()) { + result = true; + break; + } + } + } + + if (DEBUG) + System.out + .println("CommonDropAdapter.validateDrop (returning " + (valid != null ? valid.getSeverity() + ": " + valid.getMessage() : "" + result) + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ 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(); + } + + /* + * (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(); } } Index: src/org/eclipse/ui/navigator/CommonViewer.java =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/navigator/CommonViewer.java,v retrieving revision 1.11 diff -u -r1.11 CommonViewer.java --- src/org/eclipse/ui/navigator/CommonViewer.java 9 Feb 2006 21:32:09 -0000 1.11 +++ src/org/eclipse/ui/navigator/CommonViewer.java 22 Feb 2006 04:32:51 -0000 @@ -21,6 +21,7 @@ import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.DND; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Item; @@ -304,9 +305,7 @@ * By default, the following Transfer types are supported: * *

* @@ -314,35 +313,19 @@ * @see CommonDropAdapter */ protected void initDragAndDrop() { - - // TODO initDragAndDrop is in progress. - -// /* Handle Drag and Drop */ -// int operations = DND.DROP_COPY | DND.DROP_MOVE; -// -// CommonDragAdapterAssistant[] assistants = contentService -// .getDnDService().getCommonDragAssistants(); -// -// Set supportedTypes = new HashSet(); -// supportedTypes.add(PluginTransfer.getInstance()); -// supportedTypes.add(LocalSelectionTransfer.getInstance()); -// Transfer[] transferTypes = null; -// for (int i = 0; i < assistants.length; i++) { -// transferTypes = assistants[i].getSupportedTransferTypes(); -// for (int j = 0; j < transferTypes.length; j++) { -// if (transferTypes[j] != null) -// supportedTypes.add(transferTypes[j]); -// } -// } -// -// Transfer[] transfers = (Transfer[]) supportedTypes -// .toArray(new Transfer[supportedTypes.size()]); -// -// addDragSupport(operations, transfers, new CommonDragAdapter( -// contentService, this)); -// // TODO Should the Transfers be the same here? -// addDropSupport(operations, transfers, new CommonDropAdapter( -// contentService, this)); + + /* Handle Drag and Drop */ + int operations = DND.DROP_COPY | DND.DROP_MOVE; + + CommonDragAdapter dragAdapter = new CommonDragAdapter(contentService, + this); + addDragSupport(operations, dragAdapter.getSupportDragTransfers(), + dragAdapter); + + CommonDropAdapter dropAdapter = new CommonDropAdapter(contentService, + this); + addDropSupport(operations, dropAdapter.getSupportedDropTransfers(), + dropAdapter); } Index: schema/navigatorContent.exsd =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/schema/navigatorContent.exsd,v retrieving revision 1.22 diff -u -r1.22 navigatorContent.exsd --- schema/navigatorContent.exsd 9 Feb 2006 21:32:11 -0000 1.22 +++ schema/navigatorContent.exsd 22 Feb 2006 04:32:41 -0000 @@ -86,7 +86,7 @@ - + @@ -518,10 +518,19 @@ - Provides a subclass of <code>org.eclipse.ui.navigator.CommonDropAdapterAssistant</code> which can provide programatic validation for a drop operation, request additional transfer types, and handle the drop. + Provides a subclass of <code>org.eclipse.ui.navigator.CommonDropAdapterAssistant</code> which can provide programatic validation for a drop operation, request additional transfer types, and handle the drop operation. +<br><br> +A <b>commonDropAdapter</b> will be invoked whenever elements that are dragged match the <b>possibleChildren</b> expression of the containing <b>navigatorContent</b> extension <i>and</i> the drop target of the operation is described by the <b>possibleDropTargets</b> expression of the <b>commonDropAdapter</b> element. +<br><br> +An extension may have multiple drop adapters with mutually exclusive <b>possibleDropTargets</b> expressions. The first drop adapter found that matches the given drop target and returns an OK status for <code>CommonDropAdapterAssistant.validateDrop(...)</code> will be given an opportunity to handle the drop. +<br><br> + + + + @@ -542,6 +551,30 @@ + + + + Describe the possible drop targets that a particular <b>commonDropAdapter</b> can handle. + + + + + + + + + + + + + + + + + + + + Index: src/org/eclipse/ui/internal/navigator/dnd/NavigatorDnDService.java =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/internal/navigator/dnd/NavigatorDnDService.java,v retrieving revision 1.1 diff -u -r1.1 NavigatorDnDService.java --- src/org/eclipse/ui/internal/navigator/dnd/NavigatorDnDService.java 9 Feb 2006 21:32:08 -0000 1.1 +++ src/org/eclipse/ui/internal/navigator/dnd/NavigatorDnDService.java 22 Feb 2006 04:32:45 -0000 @@ -11,9 +11,15 @@ package org.eclipse.ui.internal.navigator.dnd; +import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Map; import java.util.Set; +import org.eclipse.jface.util.LocalSelectionTransfer; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.dnd.TransferData; import org.eclipse.ui.internal.navigator.NavigatorContentService; import org.eclipse.ui.internal.navigator.extensions.CommonDragAssistantDescriptor; import org.eclipse.ui.internal.navigator.extensions.NavigatorViewerDescriptor; @@ -28,18 +34,27 @@ * {@link CommonDropAdapterAssistant} for the associated * {@link INavigatorContentService}. * + *

+ * Clients may not extend, instantiate or directly reference this class. + *

+ * * @since 3.2 * */ public class NavigatorDnDService implements INavigatorDnDService { + private static final CommonDropAdapterAssistant[] NO_ASSISTANTS = new CommonDropAdapterAssistant[0]; + private NavigatorContentService contentService; private CommonDragAdapterAssistant[] dragAssistants; + private final Map dropAssistants = new HashMap(); + /** * - * @param aContentService The associated content service + * @param aContentService + * The associated content service */ public NavigatorDnDService(NavigatorContentService aContentService) { contentService = aContentService; @@ -62,12 +77,81 @@ return dragAssistants; } - /* (non-Javadoc) - * @see org.eclipse.ui.navigator.INavigatorDnDService#findCommonDropAdapterAssistants(java.lang.Object) - */ - public CommonDropAdapterAssistant[] findCommonDropAdapterAssistants(Object aDropTarget) { - // TODO Implement the search routine - return null; + public CommonDropAdapterAssistant[] findCommonDropAdapterAssistants( + Object aDropTarget, TransferData aTransferType) { + + // TODO Make sure descriptors are sorted by priority + CommonDropAdapterDescriptor[] descriptors = CommonDropDescriptorManager + .getInstance().findCommonDropAdapterAssistants(aDropTarget, + contentService); + + if (descriptors.length == 0) + return NO_ASSISTANTS; + + if (LocalSelectionTransfer.getTransfer().isSupportedType(aTransferType) + && LocalSelectionTransfer.getTransfer().getSelection() instanceof IStructuredSelection) + return getAssistantsBySelection(descriptors, (IStructuredSelection) LocalSelectionTransfer.getTransfer().getSelection()); + return getAssistantsByTransferData(descriptors, aTransferType); + } + + + public CommonDropAdapterAssistant[] findCommonDropAdapterAssistants( + Object aDropTarget, IStructuredSelection theDragSelection) { + + // TODO Make sure descriptors are sorted by priority + CommonDropAdapterDescriptor[] descriptors = CommonDropDescriptorManager + .getInstance().findCommonDropAdapterAssistants(aDropTarget, + contentService); + + if (descriptors.length == 0) + return NO_ASSISTANTS; + + return getAssistantsBySelection(descriptors, theDragSelection); + } + + private CommonDropAdapterAssistant[] getAssistantsByTransferData( + CommonDropAdapterDescriptor[] descriptors, + TransferData aTransferType) { + + Set assistants = new LinkedHashSet(); + for (int i = 0; i < descriptors.length; i++) { + CommonDropAdapterAssistant asst = getAssistant(descriptors[i]); + if (asst.isSupportedType(aTransferType)) + assistants.add(asst); + } + return (CommonDropAdapterAssistant[]) assistants + .toArray(new CommonDropAdapterAssistant[assistants.size()]); + + } + + private CommonDropAdapterAssistant[] getAssistantsBySelection( + CommonDropAdapterDescriptor[] descriptors, IStructuredSelection aSelection) { + + Set assistants = new LinkedHashSet(); + + for (int i = 0; i < descriptors.length; i++) + if(descriptors[i].areDragElementsSupported(aSelection)) + assistants.add(getAssistant(descriptors[i])); + + return (CommonDropAdapterAssistant[]) assistants + .toArray(new CommonDropAdapterAssistant[assistants.size()]); + } + + private CommonDropAdapterAssistant getAssistant( + CommonDropAdapterDescriptor descriptor) { + CommonDropAdapterAssistant asst = (CommonDropAdapterAssistant) dropAssistants + .get(descriptor); + if (asst != null) + return asst; + synchronized (dropAssistants) { + asst = (CommonDropAdapterAssistant) dropAssistants.get(descriptor); + if (asst == null) { + dropAssistants.put(descriptor, (asst = descriptor + .createDropAssistant())); + asst.init(contentService); + } + } + return asst; } } Index: src/org/eclipse/ui/internal/navigator/dnd/NavigatorPluginDropAction.java =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/internal/navigator/dnd/NavigatorPluginDropAction.java,v retrieving revision 1.1 diff -u -r1.1 NavigatorPluginDropAction.java --- src/org/eclipse/ui/internal/navigator/dnd/NavigatorPluginDropAction.java 9 Feb 2006 21:32:08 -0000 1.1 +++ src/org/eclipse/ui/internal/navigator/dnd/NavigatorPluginDropAction.java 22 Feb 2006 04:32:45 -0000 @@ -10,28 +10,29 @@ *******************************************************************************/ package org.eclipse.ui.internal.navigator.dnd; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.util.LocalSelectionTransfer; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.navigator.CommonDropAdapterAssistant; import org.eclipse.ui.navigator.INavigatorContentService; import org.eclipse.ui.part.IDropActionDelegate; import org.eclipse.ui.part.PluginTransferData; /** * - *

- * EXPERIMENTAL. This class or interface has been added as - * part of a work in progress. There is a guarantee neither that this API will - * work nor that it will remain the same. Please do not use this API without - * consulting with the Platform/UI team. - *

* * @since 3.2 * */ public class NavigatorPluginDropAction implements IDropActionDelegate { + private static final boolean DEBUG = false; + private static final String CN_PLUGIN_ACTION_ID = "org.eclipse.ui.navigator.PluginDropAction"; //$NON-NLS-1$ /** - * + * A default no-args constructor is required by the + * org.eclipse.ui.dropAdapters extension point */ public NavigatorPluginDropAction() { super(); @@ -45,7 +46,39 @@ */ public boolean run(Object sourceData, Object target) { - // TODO Handle the callback for drop targets that cannot handle the drop + if (DEBUG) + System.out.println("NavigatorPluginDropAction.run (begin)"); //$NON-NLS-1$ + + String sourceViewerId = new String((byte[]) sourceData); + + IStructuredSelection selection = (IStructuredSelection) LocalSelectionTransfer + .getTransfer().getSelection(); + + INavigatorContentService contentService = NavigatorContentServiceTransfer + .getInstance().findService(sourceViewerId); + + if (contentService == null) + return false; + try { + CommonDropAdapterAssistant[] assistants = contentService + .getDnDService().findCommonDropAdapterAssistants(target, + selection); + + IStatus valid = null; + for (int i = 0; i < assistants.length; i++) { + valid = assistants[i].validatePluginTransferDrop(selection, target); + if (valid != null && valid.isOK()) { + valid = assistants[i].handlePluginTransferDrop(selection, target); + return valid != null && valid.isOK(); + } + } + } finally { + NavigatorContentServiceTransfer.getInstance() + .unregisterContentService(contentService); + } + + if (DEBUG) + System.out.println("NavigatorPluginDropAction.run (exit)"); //$NON-NLS-1$ return false; } @@ -59,6 +92,8 @@ */ public static PluginTransferData createTransferData( INavigatorContentService aContentService) { + NavigatorContentServiceTransfer.getInstance().registerContentService( + aContentService); return new PluginTransferData(CN_PLUGIN_ACTION_ID, aContentService .getViewerId().getBytes()); } Index: src/org/eclipse/ui/internal/navigator/dnd/CommonDropAdapterDescriptor.java =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/internal/navigator/dnd/CommonDropAdapterDescriptor.java,v retrieving revision 1.1 diff -u -r1.1 CommonDropAdapterDescriptor.java --- src/org/eclipse/ui/internal/navigator/dnd/CommonDropAdapterDescriptor.java 9 Feb 2006 21:32:08 -0000 1.1 +++ src/org/eclipse/ui/internal/navigator/dnd/CommonDropAdapterDescriptor.java 22 Feb 2006 04:32:44 -0000 @@ -16,10 +16,12 @@ import org.eclipse.core.expressions.Expression; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.internal.navigator.CustomAndExpression; import org.eclipse.ui.internal.navigator.NavigatorPlugin; import org.eclipse.ui.internal.navigator.extensions.INavigatorContentExtPtConstants; import org.eclipse.ui.navigator.CommonDropAdapterAssistant; +import org.eclipse.ui.navigator.INavigatorContentDescriptor; /** * @since 3.2 @@ -28,29 +30,24 @@ public final class CommonDropAdapterDescriptor implements INavigatorContentExtPtConstants { - private IConfigurationElement element; + private final IConfigurationElement element; - private Expression dragExpr; + private final INavigatorContentDescriptor contentDescriptor; private Expression dropExpr; /* package */CommonDropAdapterDescriptor( - IConfigurationElement aConfigElement) { + IConfigurationElement aConfigElement, + INavigatorContentDescriptor aContentDescriptor) { element = aConfigElement; + contentDescriptor = aContentDescriptor; init(); } private void init() { - - IConfigurationElement[] children = element - .getChildren(TAG_DRAG_EXPRESSION); - if (children.length == 1) - dragExpr = new CustomAndExpression(children[0]); - - children = element.getChildren(TAG_DROP_EXPRESSION); + IConfigurationElement[] children = element.getChildren(TAG_POSSIBLE_DROP_TARGETS); if (children.length == 1) dropExpr = new CustomAndExpression(children[0]); - } /** @@ -60,15 +57,21 @@ * @return True if the element matches the drag expression from the * extension. */ - public boolean isDragElementSupported(Object anElement) { - if (dragExpr != null) - try { - return dragExpr - .evaluate(new EvaluationContext(null, anElement)) == EvaluationResult.TRUE; - } catch (CoreException e) { - NavigatorPlugin.logError(0, e.getMessage(), e); - } - return false; + public boolean isDragElementSupported(Object anElement) { + return contentDescriptor.isPossibleChild(anElement); + } + + /** + * + * @param aSelection + * The set of elements being dragged. + * @return True if the element matches the drag expression from the + * extension. + */ + public boolean areDragElementsSupported(IStructuredSelection aSelection) { + if (aSelection.isEmpty()) + return false; + return contentDescriptor.arePossibleChildren(aSelection); } /** @@ -79,7 +82,7 @@ * extension. */ public boolean isDropElementSupported(Object anElement) { - if (dropExpr != null) + if (dropExpr != null && anElement != null) try { return dropExpr .evaluate(new EvaluationContext(null, anElement)) == EvaluationResult.TRUE; @@ -105,7 +108,14 @@ NavigatorPlugin.logError(0, re.getMessage(), re); } return SkeletonCommonDropAssistant.INSTANCE; + } + /** + * + * @return The content descriptor that contains this drop descriptor. + */ + public INavigatorContentDescriptor getContentDescriptor() { + return contentDescriptor; } } Index: src/org/eclipse/ui/internal/navigator/dnd/CommonDropDescriptorManager.java =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/internal/navigator/dnd/CommonDropDescriptorManager.java,v retrieving revision 1.1 diff -u -r1.1 CommonDropDescriptorManager.java --- src/org/eclipse/ui/internal/navigator/dnd/CommonDropDescriptorManager.java 9 Feb 2006 21:32:08 -0000 1.1 +++ src/org/eclipse/ui/internal/navigator/dnd/CommonDropDescriptorManager.java 22 Feb 2006 04:32:44 -0000 @@ -11,13 +11,20 @@ package org.eclipse.ui.internal.navigator.dnd; -import java.util.HashMap; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.TreeMap; import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.ui.internal.navigator.extensions.ExtensionPriorityComparator; import org.eclipse.ui.internal.navigator.extensions.INavigatorContentExtPtConstants; import org.eclipse.ui.internal.navigator.extensions.NavigatorContentRegistryReader; import org.eclipse.ui.navigator.INavigatorContentDescriptor; +import org.eclipse.ui.navigator.INavigatorContentService; /** * @since 3.2 @@ -27,37 +34,89 @@ private static final CommonDropDescriptorManager INSTANCE = new CommonDropDescriptorManager(); + private static final CommonDropAdapterDescriptor[] NO_DESCRIPTORS = new CommonDropAdapterDescriptor[0]; + /** * A map of (INavigatorContentDescriptor, * CommonDropAdapterDescriptor)-pairs. */ - private final Map dropDescriptors = new HashMap(); + private final Map dropDescriptors = new TreeMap(ExtensionPriorityComparator.INSTANCE); /** * * @return An initialized singleton instance of the * CommonDropDescriptorManager. */ - public CommonDropDescriptorManager getInstance() { + public static CommonDropDescriptorManager getInstance() { return INSTANCE; } private CommonDropDescriptorManager() { new CommonDropAdapterRegistry().readRegistry(); } - - // TODO Add fetch Drop Adapters by match method. + + /** + * + * @param aDropTarget + * The drop target of the operation + * @param aContentService + * The associated content service to filter results by. + * @return An array of drop descriptors that can handle the given drop + * target and are visible and active for the given + * service and enabled for the given drop target.. + */ + public CommonDropAdapterDescriptor[] findCommonDropAdapterAssistants(Object aDropTarget, INavigatorContentService aContentService) { + + Set foundDescriptors = new LinkedHashSet(); + for (Iterator iter = dropDescriptors.keySet().iterator(); iter + .hasNext();) { + INavigatorContentDescriptor contentDescriptor = (INavigatorContentDescriptor) iter + .next(); + if (aContentService.isVisible(contentDescriptor.getId()) + && aContentService.isActive(contentDescriptor.getId())) { + List dropDescriptors = getDropDescriptors(contentDescriptor); + for (Iterator iterator = dropDescriptors.iterator(); iterator + .hasNext();) { + CommonDropAdapterDescriptor dropDescriptor = (CommonDropAdapterDescriptor) iterator + .next(); + if (dropDescriptor.isDropElementSupported(aDropTarget)) + foundDescriptors.add(dropDescriptor); + } + } + } + + if (foundDescriptors.isEmpty()) + return NO_DESCRIPTORS; + return (CommonDropAdapterDescriptor[]) foundDescriptors + .toArray(new CommonDropAdapterDescriptor[foundDescriptors + .size()]); + } + + private List getDropDescriptors( + INavigatorContentDescriptor aContentDescriptor) { + List descriptors = (List) dropDescriptors.get(aContentDescriptor); + if (descriptors != null) + return descriptors; + synchronized (dropDescriptors) { + descriptors = (List) dropDescriptors.get(aContentDescriptor); + if (descriptors == null) + dropDescriptors.put(aContentDescriptor, + (descriptors = new ArrayList())); + + } + return descriptors; + } /** * @param aContentDescriptor - * A non-null content descriptor. + * A non-null content descriptor. * @param aDropDescriptor * A non-null drop descriptor. */ private void addCommonDropAdapter( INavigatorContentDescriptor aContentDescriptor, - CommonDropAdapterDescriptor aDropDescriptor) { - dropDescriptors.put(aContentDescriptor, aDropDescriptor); + CommonDropAdapterDescriptor aDropDescriptor) { + getDropDescriptors(aContentDescriptor).add(aDropDescriptor); } private class CommonDropAdapterRegistry extends @@ -82,13 +141,13 @@ .getContentDescriptor(id); if (contentDescriptor != null) { - IConfigurationElement[] commonDropAdapter = element + IConfigurationElement[] commonDropAdapters = element .getChildren(TAG_COMMON_DROP_ADAPTER); - if (commonDropAdapter.length == 1) { + for (int i = 0; i < commonDropAdapters.length; i++) { addCommonDropAdapter(contentDescriptor, - new CommonDropAdapterDescriptor(element)); - } + new CommonDropAdapterDescriptor(commonDropAdapters[i], contentDescriptor)); + } } } Index: src/org/eclipse/ui/internal/navigator/dnd/SkeletonCommonDropAssistant.java =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/internal/navigator/dnd/SkeletonCommonDropAssistant.java,v retrieving revision 1.1 diff -u -r1.1 SkeletonCommonDropAssistant.java --- src/org/eclipse/ui/internal/navigator/dnd/SkeletonCommonDropAssistant.java 9 Feb 2006 21:32:08 -0000 1.1 +++ src/org/eclipse/ui/internal/navigator/dnd/SkeletonCommonDropAssistant.java 22 Feb 2006 04:32:45 -0000 @@ -11,8 +11,11 @@ package org.eclipse.ui.internal.navigator.dnd; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.dnd.TransferData; +import org.eclipse.ui.navigator.CommonDropAdapter; import org.eclipse.ui.navigator.CommonDropAdapterAssistant; /** @@ -34,11 +37,12 @@ /* * (non-Javadoc) * - * @see org.eclipse.ui.navigator.CommonDropAdapterAssistant#handleDrop(org.eclipse.swt.dnd.DropTargetEvent, - * java.lang.Object) + * @see org.eclipse.ui.navigator.CommonDropAdapterAssistant#handleDrop(org.eclipse.ui.navigator.CommonDropAdapter, + * org.eclipse.swt.dnd.DropTargetEvent, java.lang.Object) */ - public boolean handleDrop(DropTargetEvent aDropTargetEvent, Object aTarget) { - return false; + public IStatus handleDrop(CommonDropAdapter aDropAdapter, + DropTargetEvent aDropTargetEvent, Object aTarget) { + return Status.CANCEL_STATUS; } /* @@ -47,21 +51,21 @@ * @see org.eclipse.ui.navigator.CommonDropAdapterAssistant#validateDrop(java.lang.Object, * int, org.eclipse.swt.dnd.TransferData) */ - public boolean validateDrop(Object target, int operation, + public IStatus validateDrop(Object target, int operation, TransferData transferType) { - - return false; + return Status.CANCEL_STATUS; } - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.navigator.CommonDropAdapterAssistant#findSupportedTransferData(org.eclipse.swt.dnd.TransferData[]) - */ - public TransferData findSupportedTransferData( - TransferData[] theAvailableTransferData) { - - return null; - } + // /* + // * (non-Javadoc) + // * + // * @see + // org.eclipse.ui.navigator.CommonDropAdapterAssistant#findSupportedTransferData(org.eclipse.swt.dnd.TransferData[]) + // */ + // public TransferData findSupportedTransferData( + // TransferData[] theAvailableTransferData) { + // + // return null; + // } } Index: src/org/eclipse/ui/internal/navigator/extensions/NavigatorContentDescriptor.java =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/internal/navigator/extensions/NavigatorContentDescriptor.java,v retrieving revision 1.3 diff -u -r1.3 NavigatorContentDescriptor.java --- src/org/eclipse/ui/internal/navigator/extensions/NavigatorContentDescriptor.java 9 Feb 2006 21:32:09 -0000 1.3 +++ src/org/eclipse/ui/internal/navigator/extensions/NavigatorContentDescriptor.java 22 Feb 2006 04:32:46 -0000 @@ -11,6 +11,7 @@ package org.eclipse.ui.internal.navigator.extensions; import java.util.HashSet; +import java.util.Iterator; import java.util.Set; import org.eclipse.core.expressions.ElementHandler; @@ -22,6 +23,7 @@ import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.osgi.util.NLS; import org.eclipse.ui.IPluginContribution; @@ -347,6 +349,8 @@ if ((enablement == null && possibleChildren == null) || anElement == null) return false; + else if(anElement instanceof IStructuredSelection) + return arePossibleChildren((IStructuredSelection) anElement); try { if (possibleChildren != null) @@ -360,6 +364,23 @@ } return false; } + + /** + * A convenience method to check all elements in a selection. + * + * @param aSelection A non-null selection + * @return True if and only if every element in the selection is a possible child. + */ + public boolean arePossibleChildren(IStructuredSelection aSelection) { + if(aSelection.isEmpty()) + return false; + for (Iterator iter = aSelection.iterator(); iter.hasNext();) { + Object element = iter.next(); + if(!isPossibleChild(element)) + return false; + } + return true; + } /** * Index: src/org/eclipse/ui/internal/navigator/extensions/NavigatorContentExtension.java =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/internal/navigator/extensions/NavigatorContentExtension.java,v retrieving revision 1.3 diff -u -r1.3 NavigatorContentExtension.java --- src/org/eclipse/ui/internal/navigator/extensions/NavigatorContentExtension.java 9 Feb 2006 22:38:02 -0000 1.3 +++ src/org/eclipse/ui/internal/navigator/extensions/NavigatorContentExtension.java 22 Feb 2006 04:32:47 -0000 @@ -120,10 +120,9 @@ return provider; } - /* - * (non-Javadoc) + /** * - * @see org.eclipse.ui.internal.navigator.extensions.INavigatorContentExtension#getContentProvider() + * @return The internal content provider that is wrapped by this extension. */ public ITreeContentProvider internalGetContentProvider() { if (contentProvider != null || contentProviderInitializationFailed) Index: src/org/eclipse/ui/internal/navigator/extensions/INavigatorContentExtPtConstants.java =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/internal/navigator/extensions/INavigatorContentExtPtConstants.java,v retrieving revision 1.2 diff -u -r1.2 INavigatorContentExtPtConstants.java --- src/org/eclipse/ui/internal/navigator/extensions/INavigatorContentExtPtConstants.java 9 Feb 2006 21:32:09 -0000 1.2 +++ src/org/eclipse/ui/internal/navigator/extensions/INavigatorContentExtPtConstants.java 22 Feb 2006 04:32:45 -0000 @@ -34,13 +34,10 @@ String TAG_COMMON_SORTER = "commonSorter"; //$NON-NLS-1$ /** */ - String TAG_COMMON_DROP_ADAPTER = "commonDropAdapter"; //$NON-NLS-1$ + String TAG_COMMON_DROP_ADAPTER = "commonDropAdapter"; //$NON-NLS-1$ /** */ - String TAG_DRAG_EXPRESSION = "dragExpression"; //$NON-NLS-1$ - - /** */ - String TAG_DROP_EXPRESSION = "dropExpression"; //$NON-NLS-1$ + String TAG_POSSIBLE_DROP_TARGETS = "possibleDropTargets"; //$NON-NLS-1$ /** */ String TAG_OVERRIDE = "override"; //$NON-NLS-1$ Index: plugin.xml =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/plugin.xml,v retrieving revision 1.9 diff -u -r1.9 plugin.xml --- plugin.xml 9 Feb 2006 21:32:08 -0000 1.9 +++ plugin.xml 22 Feb 2006 04:32:37 -0000 @@ -11,7 +11,7 @@ point="org.eclipse.ui.dropActions"> + id="org.eclipse.ui.navigator.PluginDropAction"> Index: src/org/eclipse/ui/internal/navigator/NavigatorContentService.java =================================================================== RCS file: /home/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/internal/navigator/NavigatorContentService.java,v retrieving revision 1.4 diff -u -r1.4 NavigatorContentService.java --- src/org/eclipse/ui/internal/navigator/NavigatorContentService.java 9 Feb 2006 22:38:02 -0000 1.4 +++ src/org/eclipse/ui/internal/navigator/NavigatorContentService.java 22 Feb 2006 04:32:43 -0000 @@ -30,6 +30,7 @@ import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IMemento; import org.eclipse.ui.internal.navigator.dnd.NavigatorDnDService; import org.eclipse.ui.internal.navigator.extensions.ExtensionPriorityComparator; @@ -914,9 +915,15 @@ navigatorDnDService = new NavigatorDnDService(this); return navigatorDnDService; } - - protected boolean isRootExtension(String anExtensionId) { - return assistant.isRootExtension(anExtensionId); + + /** + * Non-API method to return a shell. + * @return A shell associated with the current viewer (if any) or null. + */ + public Shell getShell() { + if(structuredViewerManager != null && structuredViewerManager.getViewer() != null) + return structuredViewerManager.getViewer().getControl().getShell(); + return null; } /* @@ -935,8 +942,12 @@ */ public String toString() { return "ContentService[" + viewerDescriptor.getViewerId() + "]"; //$NON-NLS-1$//$NON-NLS-2$ + } + + protected boolean isRootExtension(String anExtensionId) { + return assistant.isRootExtension(anExtensionId); } - + private void notifyListeners(NavigatorContentExtension aDescriptorInstance) { if (listeners.size() == 0) Index: src/org/eclipse/ui/internal/navigator/dnd/NavigatorContentServiceTransfer.java =================================================================== RCS file: src/org/eclipse/ui/internal/navigator/dnd/NavigatorContentServiceTransfer.java diff -N src/org/eclipse/ui/internal/navigator/dnd/NavigatorContentServiceTransfer.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/navigator/dnd/NavigatorContentServiceTransfer.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2006 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.ui.internal.navigator.dnd; + +import java.lang.ref.WeakReference; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.ui.navigator.INavigatorContentService; + +/** + * Caches instances of {@link INavigatorContentService} to facilitate the + * handling of drop operations in other viewers. + * + * @since 3.2 + * + */ +public class NavigatorContentServiceTransfer { + + private static final NavigatorContentServiceTransfer instance = new NavigatorContentServiceTransfer(); + + /** + * + * @return The singleton instance of the transfer service. + */ + public static NavigatorContentServiceTransfer getInstance() { + return instance; + } + + private final Set registeredContentServices = new HashSet(); + + /** + * + * @param aContentService The Content Service to register. + */ + public synchronized void registerContentService(INavigatorContentService aContentService) { + if(findService(aContentService.getViewerId()) == null) + registeredContentServices.add(new WeakReference(aContentService)); + } + + /** + * + * @param aContentService The Content Service to unregister. + */ + public synchronized void unregisterContentService(INavigatorContentService aContentService) { + + for (Iterator iter = registeredContentServices.iterator(); iter.hasNext();) { + WeakReference ref = (WeakReference) iter.next(); + if(ref.get() == null) + iter.remove(); + else { + if(ref.get() == aContentService) { + iter.remove(); + return; + } + } + } + } + + /** + * + * @param aViewerId A viewer id that should have previously been registered with the service. + * @return The registered content service for the given viewer id. + */ + public synchronized INavigatorContentService findService(String aViewerId) { + if(aViewerId == null || aViewerId.length() == 0) + return null; + INavigatorContentService contentService; + for (Iterator iter = registeredContentServices.iterator(); iter.hasNext();) { + WeakReference ref = (WeakReference) iter.next(); + if(ref.get() == null) + iter.remove(); + else { + contentService = (INavigatorContentService)ref.get(); + if(aViewerId.equals(contentService.getViewerId())) + return contentService; + } + } + return null; + } + + +}