diff --git a/core/org.eclipse.cdt.ui/ChangeLog b/core/org.eclipse.cdt.ui/ChangeLog index 7d7e52ba95c..3346df3da61 100644 --- a/core/org.eclipse.cdt.ui/ChangeLog +++ b/core/org.eclipse.cdt.ui/ChangeLog @@ -1,3 +1,10 @@ +2005-01-26 Alain Magloire + Part of implementing PR 83112 + * src/org/eclipse/cdt/internal/ui/cview/CView.java + * src/org/eclipse/cdt/internal/ui/cview/SelectionTransferDragAdapter.java + * src/org/eclipse/cdt/internal/ui/cview/SelectionTransferDropAdapter.java + * src/org/eclipse/cdt/internal/ui/dnd/*.java + 2005-01-24 Vladimir Hirsl SCD work for CDT 3.0 Better displaying of error messages in TabFolderOptionBlock. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CView.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CView.java index 86f20a8c92e..dc22d8768be 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CView.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CView.java @@ -26,11 +26,14 @@ import org.eclipse.cdt.core.model.IParent; import org.eclipse.cdt.core.model.ISourceReference; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.internal.ui.actions.SelectionConverter; -import org.eclipse.cdt.internal.ui.drag.DelegatingDragAdapter; -import org.eclipse.cdt.internal.ui.drag.FileTransferDragAdapter; -import org.eclipse.cdt.internal.ui.drag.LocalSelectionTransferDragAdapter; -import org.eclipse.cdt.internal.ui.drag.ResourceTransferDragAdapter; -import org.eclipse.cdt.internal.ui.drag.TransferDragSourceListener; +import org.eclipse.cdt.internal.ui.dnd.CDTViewerDragAdapter; +import org.eclipse.cdt.internal.ui.dnd.DelegatingDropAdapter; +import org.eclipse.cdt.internal.ui.dnd.FileTransferDragAdapter; +import org.eclipse.cdt.internal.ui.dnd.FileTransferDropAdapter; +import org.eclipse.cdt.internal.ui.dnd.ResourceTransferDragAdapter; +import org.eclipse.cdt.internal.ui.dnd.ResourceTransferDropAdapter; +import org.eclipse.cdt.internal.ui.dnd.TransferDragSourceListener; +import org.eclipse.cdt.internal.ui.dnd.TransferDropTargetListener; import org.eclipse.cdt.internal.ui.preferences.CPluginPreferencePage; import org.eclipse.cdt.internal.ui.util.EditorUtility; import org.eclipse.cdt.internal.ui.util.ProblemTreeViewer; @@ -40,7 +43,6 @@ import org.eclipse.cdt.internal.ui.viewsupport.CUILabelProvider; import org.eclipse.cdt.internal.ui.viewsupport.DecoratingCLabelProvider; import org.eclipse.cdt.ui.CElementContentProvider; import org.eclipse.cdt.ui.CElementSorter; -import org.eclipse.cdt.ui.CLocalSelectionTransfer; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.core.resources.IFile; @@ -99,7 +101,6 @@ import org.eclipse.ui.model.IWorkbenchAdapter; import org.eclipse.ui.part.ISetSelectionTarget; import org.eclipse.ui.part.IShowInSource; import org.eclipse.ui.part.IShowInTarget; -import org.eclipse.ui.part.PluginTransfer; import org.eclipse.ui.part.ResourceTransfer; import org.eclipse.ui.part.ShowInContext; import org.eclipse.ui.part.ViewPart; @@ -371,20 +372,9 @@ public class CView extends ViewPart implements ISetSelectionTarget, IPropertyCha * Adds drag and drop support to the navigator. */ void initDragAndDrop() { - int ops = DND.DROP_COPY | DND.DROP_MOVE; + initDrag(); + initDrop(); - Transfer[] dragTransfers = new Transfer[] { ResourceTransfer.getInstance(), FileTransfer.getInstance(), - CLocalSelectionTransfer.getInstance(), PluginTransfer.getInstance()}; - - TransferDragSourceListener[] dragListeners = new TransferDragSourceListener[] { new ResourceTransferDragAdapter(viewer), - new LocalSelectionTransferDragAdapter(viewer), new FileTransferDragAdapter(viewer)}; - - viewer.addDragSupport(ops, dragTransfers, new DelegatingDragAdapter(viewer, dragListeners)); - - Transfer[] dropTransfers = new Transfer[] { ResourceTransfer.getInstance(), FileTransfer.getInstance(), - LocalSelectionTransfer.getInstance(), PluginTransfer.getInstance()}; - - viewer.addDropSupport(ops, dropTransfers, new CViewDropAdapter(viewer)); dragDetectListener = new Listener() { public void handleEvent(Event event) { @@ -395,6 +385,35 @@ public class CView extends ViewPart implements ISetSelectionTarget, IPropertyCha } + private void initDrag() { + int ops= DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK; + Transfer[] transfers= new Transfer[] { + LocalSelectionTransfer.getInstance(), + ResourceTransfer.getInstance(), + FileTransfer.getInstance() + }; + TransferDragSourceListener[] dragListeners= new TransferDragSourceListener[] { + new SelectionTransferDragAdapter(viewer), + new ResourceTransferDragAdapter(viewer), + new FileTransferDragAdapter(viewer) + }; + viewer.addDragSupport(ops, transfers, new CDTViewerDragAdapter(viewer, dragListeners)); + } + + private void initDrop() { + int ops= DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK | DND.DROP_DEFAULT; + Transfer[] transfers= new Transfer[] { + LocalSelectionTransfer.getInstance(), + ResourceTransfer.getInstance(), + FileTransfer.getInstance()}; + TransferDropTargetListener[] dropListeners= new TransferDropTargetListener[] { + new SelectionTransferDropAdapter(viewer), + new ResourceTransferDropAdapter(viewer), + new FileTransferDropAdapter(viewer) + }; + viewer.addDropSupport(ops, transfers, new DelegatingDropAdapter(dropListeners)); + } + /** * Initializes the default preferences */ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewDropAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewDropAdapter.java deleted file mode 100644 index cbe3bba3386..00000000000 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewDropAdapter.java +++ /dev/null @@ -1,538 +0,0 @@ -package org.eclipse.cdt.internal.ui.cview; - -/* - * (c) Copyright IBM Corp. 2000, 2001. - * All Rights Reserved. - */ - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.eclipse.cdt.core.model.ICContainer; -import org.eclipse.cdt.core.model.ICElement; -import org.eclipse.cdt.core.model.ICProject; -import org.eclipse.cdt.ui.CUIPlugin; -import org.eclipse.core.resources.IContainer; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.ResourceAttributes; -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.MultiStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.jface.dialogs.ErrorDialog; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.StructuredSelection; -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.TransferData; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.actions.CopyFilesAndFoldersOperation; -import org.eclipse.ui.actions.MoveFilesAndFoldersOperation; -import org.eclipse.ui.actions.ReadOnlyStateChecker; -import org.eclipse.ui.dialogs.IOverwriteQuery; -import org.eclipse.ui.part.PluginDropAdapter; -import org.eclipse.ui.part.ResourceTransfer; -import org.eclipse.ui.views.navigator.LocalSelectionTransfer; - -/** - * Implements drop behaviour for drag and drop operations - * that land on the resource navigator. - */ -class CViewDropAdapter extends PluginDropAdapter implements IOverwriteQuery { - - /** - * A flag indicating that the drop has been cancelled by the user. - */ - protected boolean isCanceled = false; - /** - * A flag indicating that overwrites should always occur. - */ - protected boolean alwaysOverwrite = false; - - /** - * The last valid operation. - */ - private int lastValidOperation = DND.DROP_NONE; - - /* - * @see org.eclipse.swt.dnd.DropTargetListener#dragEnter(org.eclipse.swt.dnd.DropTargetEvent) - */ - public void dragEnter(DropTargetEvent event) { - - if (FileTransfer.getInstance().isSupportedType(event.currentDataType) && - event.detail == DND.DROP_DEFAULT) { - // default to copy when dragging from outside Eclipse. Fixes bug 16308. - event.detail = DND.DROP_COPY; - } - - super.dragEnter(event); - } - - - public void dropAccept(DropTargetEvent event){ - if (getCurrentOperation() == DND.DROP_MOVE){ - validateMove(event); - } - } - - /** - * @param event - */ - private void validateMove(DropTargetEvent event) { - ICElement currentContainer = null; - - Object currentTarget = getCurrentTarget(); - if (currentTarget instanceof ICElement){ - currentContainer =(ICElement) currentTarget; - } else { - return; - } - - if ((!((currentContainer instanceof ICContainer) || - (currentContainer instanceof ICProject))) || - currentContainer.isReadOnly()){ - event.detail = DND.DROP_NONE; - return; - } - - ISelection sel = this.getViewer().getSelection(); - if (sel instanceof IStructuredSelection){ - StructuredSelection structSel = (StructuredSelection) sel; - Iterator iter=structSel.iterator(); - while (iter.hasNext()){ - Object tempSelection = iter.next(); - if (tempSelection instanceof ICElement){ - - if (tempSelection instanceof ICProject){ - event.detail = DND.DROP_NONE; - break; - } - - ICElement tempElement = (ICElement) tempSelection; - ICElement tempElementParent = tempElement.getParent(); - - if (tempElementParent.equals(currentContainer) || - tempElement.equals(currentContainer) || - tempElement.equals(currentContainer.getParent()) || - tempElement.isReadOnly()){ - event.detail = DND.DROP_NONE; - break; - } - } - else if (tempSelection instanceof IResource){ - - if (tempSelection instanceof IProject){ - event.detail = DND.DROP_NONE; - break; - } - - - IResource tempResource = (IResource) tempSelection; - IResource tempResourceParent = tempResource.getParent(); - //Apples to apples... - IResource resourceCurrentContainer = currentContainer.getResource(); - ResourceAttributes attributes = tempResource.getResourceAttributes(); - boolean isReadOnly = true; - if (attributes != null) { - isReadOnly = attributes.isReadOnly(); - } - if (tempResourceParent.equals(resourceCurrentContainer) || - tempResource.equals(resourceCurrentContainer) || - tempResource.equals(resourceCurrentContainer.getParent()) || - isReadOnly){ - event.detail = DND.DROP_NONE; - break; - } - - } - } - } - - } - - - /** - * Returns an error status with the given info. - */ - protected IStatus error(String message, Throwable exception) { - return new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, message, exception); - } - - /** - * Returns an error status with the given info. - */ - protected IStatus error(String message) { - return error(message, null); - } - - /** - * Returns an error status, indicating why the given source - * could not be copied or moved. - */ - protected IStatus error(IResource source, String message) { - if (getCurrentOperation() == DND.DROP_COPY) { - return error("Can Not Copy", null); //$NON-NLS-1$ - } - return error("Can Not Move", null); //$NON-NLS-1$ - } - - /** - * Returns the actual target of the drop, given the resource - * under the mouse. If the mouse target is a file, then the drop actually - * occurs in its parent. If the drop location is before or after the - * mouse target, the target is also the parent. - */ - protected IContainer getActualTarget(IResource mouseTarget) { - /* if cursor is before or after mouseTarget, set target to parent */ - if (getCurrentLocation() == LOCATION_BEFORE || getCurrentLocation() == LOCATION_AFTER) { - return mouseTarget.getParent(); - } - /* if cursor is on a file, return the parent */ - if (mouseTarget.getType() == IResource.FILE) { - return mouseTarget.getParent(); - } - /* otherwise the mouseTarget is the real target */ - return (IContainer)mouseTarget; - } - - /** - * Returns the display - */ - protected Display getDisplay() { - return getViewer().getControl().getDisplay(); - } - - /** - * Returns the shell - */ - protected Shell getShell() { - return getViewer().getControl().getShell(); - } - - /** - * Returns an error status with the given info. - */ - protected IStatus info(String message) { - return new Status(IStatus.INFO, PlatformUI.PLUGIN_ID, 0, message, null); - } - - /** - * CViewDropAction constructor comment. - */ - public CViewDropAdapter(StructuredViewer viewer) { - super(viewer); - } - - /** - * Adds the given status to the list of problems. Discards - * OK statuses. If the status is a multi-status, only its children - * are added. - */ - protected void mergeStatus(MultiStatus status, IStatus toMerge) { - if (!toMerge.isOK()) { - status.merge(toMerge); - } - } - - /** - * Creates a status object from the given list of problems. - */ - protected IStatus multiStatus(List problems, String message) { - IStatus[] children = new IStatus[problems.size()]; - problems.toArray(children); - if (children.length == 1) { - return children[0]; - } - return new MultiStatus(PlatformUI.PLUGIN_ID, 0, children, message, null); - } - - /** - * Returns an status indicating success. - */ - protected IStatus ok() { - return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, 0, "Ok", null); //$NON-NLS-1$ - } - - /** - * Opens an error dialog if necessary. Takes care of - * complex rules necessary for making the error dialog look nice. - */ - protected void openError(IStatus status) { - if (status == null) - return; - - String genericTitle = "Error"; //$NON-NLS-1$ - int codes = IStatus.ERROR | IStatus.WARNING; - - //simple case: one error, not a multistatus - if (!status.isMultiStatus()) { - ErrorDialog.openError(getShell(), genericTitle, null, status, codes); - return; - } - - //one error, single child of multistatus - IStatus[] children = status.getChildren(); - if (children.length == 1) { - ErrorDialog.openError(getShell(), status.getMessage(), null, children[0], codes); - return; - } - //several problems - ErrorDialog.openError(getShell(), genericTitle, null, status, codes); - } - - /** - * Returns the resource selection from the LocalSelectionTransfer. - * - * @return the resource selection from the LocalSelectionTransfer - */ - private static final int typeMask = IResource.FOLDER | IResource.FILE; - - private IResource[] getSelectedResources() { - ISelection selection = LocalSelectionTransfer.getInstance().getSelection(); - List resources = new ArrayList(); - - // Sanity checks - if (selection == null || !(selection instanceof IStructuredSelection) || selection.isEmpty()) { - return null; - } - - IStructuredSelection structuredSelection = (IStructuredSelection) selection; - - // loop through list and look for matching items - for (Iterator enumarator = structuredSelection.iterator(); enumarator.hasNext();) { - Object object = enumarator.next(); - IResource resource = null; - - if (object instanceof IResource) { - resource = (IResource) object; - } else if (object instanceof IAdaptable) { - resource = (IResource) ((IAdaptable) object).getAdapter(IResource.class); - } - if (resource != null && (resource.getType() & typeMask) != 0) { - resources.add(resource); - } - } - - IResource[] result = new IResource[resources.size()]; - resources.toArray(result); - - return result; - } - - /* (non-Javadoc) - * @see org.eclipse.jface.viewers.ViewerDropAdapter#performDrop(java.lang.Object) - */ - /** - * Invoked when an action occurs. - * Argument context is the Window which contains the UI from which this action was fired. - * This default implementation prints the name of this class and its label. - */ - public boolean performDrop(final Object data) { - isCanceled = false; - alwaysOverwrite = false; - if (getCurrentTarget() == null || data == null) { - return false; - } - boolean result = false; - IStatus status = null; - IResource[] resources = null; - TransferData currentTransfer = getCurrentTransfer(); - if (LocalSelectionTransfer.getInstance().isSupportedType(currentTransfer)) { - resources = getSelectedResources(); - } else if (ResourceTransfer.getInstance().isSupportedType(currentTransfer)) { - resources = (IResource[]) data; - } else if (FileTransfer.getInstance().isSupportedType(currentTransfer)) { - status = performFileDrop(data); - result = status.isOK(); - } else { - result = super.performDrop(data); - } - if (resources != null) { - if (getCurrentOperation() == DND.DROP_COPY) { - status = performResourceCopy(getShell(), resources); - } else { - status = performResourceMove(resources); - } - } - openError(status); - - - return result; - } - - /** - * Performs a drop using the FileTransfer transfer type. - */ - private IStatus performFileDrop(Object data) { - MultiStatus problems = new MultiStatus(PlatformUI.PLUGIN_ID, 0, "ProblemI mporting", null); //$NON-NLS-1$ - mergeStatus(problems, validateTarget(getCurrentTarget(), getCurrentTransfer())); - - Object obj = getCurrentTarget(); - IResource res = null; - if (obj instanceof IAdaptable) { - res = (IResource)((IAdaptable) obj).getAdapter(IResource.class); - } - final IContainer target = getActualTarget(res); - final String[] names = (String[]) data; - // Run the import operation asynchronously. - // Otherwise the drag source (e.g., Windows Explorer) will be blocked - // while the operation executes. Fixes bug 16478. - Display.getCurrent().asyncExec(new Runnable() { - public void run() { - getShell().forceActive(); - CopyFilesAndFoldersOperation operation = new CopyFilesAndFoldersOperation(getShell()); - operation.copyFiles(names, target); - } - }); - return problems; - } - - /** - * Performs a resource copy - */ - private IStatus performResourceCopy(Shell shell, IResource[] sources) { - MultiStatus problems = new MultiStatus(PlatformUI.PLUGIN_ID, 1, "Problems Moving", null); //$NON-NLS-1$ - mergeStatus(problems, validateTarget(getCurrentTarget(), getCurrentTransfer())); - - Object obj = getCurrentTarget(); - IResource res = null; - if (obj instanceof IAdaptable) { - res = (IResource)((IAdaptable) obj).getAdapter(IResource.class); - } - IContainer target = getActualTarget(res); - CopyFilesAndFoldersOperation operation = new CopyFilesAndFoldersOperation(shell); - operation.copyResources(sources, target); - - return problems; - } - - /** - * Performs a resource move - */ - private IStatus performResourceMove(IResource[] sources) { - MultiStatus problems = new MultiStatus(PlatformUI.PLUGIN_ID, 1, "Problems Moving", null); //$NON-NLS-1$ - mergeStatus(problems, validateTarget(getCurrentTarget(), getCurrentTransfer())); - - Object obj = getCurrentTarget(); - IResource res = null; - if (obj instanceof IAdaptable) { - res = (IResource)((IAdaptable) obj).getAdapter(IResource.class); - } - IContainer target = getActualTarget(res); - ReadOnlyStateChecker checker = new ReadOnlyStateChecker( - getShell(), - "Move Resource Action", //$NON-NLS-1$ - "Move Resource Action");//$NON-NLS-1$ - sources = checker.checkReadOnlyResources(sources); - MoveFilesAndFoldersOperation operation = new MoveFilesAndFoldersOperation(getShell()); - operation.copyResources(sources, target); - - return problems; - } - - /* (non-Javadoc) - * Method declared on IOverWriteQuery - */ - public String queryOverwrite(String pathString) { - final String returnCode[] = {CANCEL}; - final String msg = pathString + " " + CUIPlugin.getResourceString("CViewDragNDrop.txt") ; //$NON-NLS-1$ //$NON-NLS-2$ - final String[] options = {IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.YES_TO_ALL_LABEL, IDialogConstants.CANCEL_LABEL}; - getDisplay().syncExec(new Runnable() { - public void run() { - MessageDialog dialog = new MessageDialog(getShell(), "Question", null, msg, MessageDialog.QUESTION, options, 0); //$NON-NLS-1$ - dialog.open(); - int returnVal = dialog.getReturnCode(); - String[] returnCodes = {YES, NO, ALL, CANCEL}; - returnCode[0] = returnVal < 0 ? CANCEL : returnCodes[returnVal]; - } - }); - return returnCode[0]; - } - - /** - * This method is used to notify the action that some aspect of - * the drop operation has changed. - */ - public boolean validateDrop(Object target, int dragOperation, TransferData transferType) { - if (dragOperation != DND.DROP_NONE) { - lastValidOperation = dragOperation; - } - - if (super.validateDrop(target, dragOperation, transferType)) { - return true; - } - return validateTarget(target, transferType).isOK(); - } - - /** - * Ensures that the drop target meets certain criteria - */ - private IStatus validateTarget(Object target, TransferData transferType) { - - if (target instanceof IAdaptable) { - IResource r = (IResource)((IAdaptable) target).getAdapter(IResource.class); - if (r == null) - return info("Target Must Be Resource"); //$NON-NLS-1$ - target = r; - } - - if (!(target instanceof IResource)) { - return info("Target Must Be Resource"); //$NON-NLS-1$ - } - IResource resource = (IResource) target; - if (!resource.isAccessible()) { - return error("Can Not Drop Into Closed Project"); //$NON-NLS-1$ - } - IContainer destination = getActualTarget(resource); - if (destination.getType() == IResource.ROOT) { - return error("Resources Can Not Be Siblings"); //$NON-NLS-1$ - } - - String message = null; - // drag within Eclipse? - if (LocalSelectionTransfer.getInstance().isSupportedType(transferType)) { - IResource[] selectedResources = getSelectedResources(); - - if (selectedResources == null) - message = "Drop Operation Error Other"; //$NON-NLS-1$ - else { - CopyFilesAndFoldersOperation operation; - if (lastValidOperation == DND.DROP_COPY) { - operation = new CopyFilesAndFoldersOperation(getShell()); - } - else { - operation = new MoveFilesAndFoldersOperation(getShell()); - } - message = operation.validateDestination(destination, selectedResources); - - } - } // file import? - else if (FileTransfer.getInstance().isSupportedType(transferType)) { - String[] sourceNames = (String[]) FileTransfer.getInstance().nativeToJava(transferType); - if (sourceNames == null) { - // source names will be null on Linux. Use empty names to do destination validation. - // Fixes bug 29778 - sourceNames = new String[0]; - } - CopyFilesAndFoldersOperation copyOperation = new CopyFilesAndFoldersOperation(getShell()); - message = copyOperation.validateImportDestination(destination, sourceNames); - } - - if (message != null) { - return error(message); - } - - return ok(); - } - - -} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/SelectionTransferDragAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/SelectionTransferDragAdapter.java new file mode 100644 index 00000000000..543bfb157bd --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/SelectionTransferDragAdapter.java @@ -0,0 +1,49 @@ +/********************************************************************** + * Copyright (c) 2002,2003,2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + ***********************************************************************/ + +package org.eclipse.cdt.internal.ui.cview; + +import java.util.Iterator; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ISourceReference; +import org.eclipse.cdt.internal.ui.dnd.BasicSelectionTransferDragAdapter; +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; + +public class SelectionTransferDragAdapter extends BasicSelectionTransferDragAdapter { + + public SelectionTransferDragAdapter(ISelectionProvider provider) { + super(provider); + } + + protected boolean isDragable(ISelection selection) { + if (selection instanceof IStructuredSelection) { + for (Iterator iter= ((IStructuredSelection)selection).iterator(); iter.hasNext();) { + Object element= iter.next(); + if (element instanceof ICElement) { + ICElement celement = (ICElement)element; + IResource res = celement.getResource(); + if (res != null) { + return false; + } + if (!(element instanceof ISourceReference)) { + return false; + } + } + } + return true; + } + return false; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/SelectionTransferDropAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/SelectionTransferDropAdapter.java new file mode 100644 index 00000000000..e4bcac2148c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/SelectionTransferDropAdapter.java @@ -0,0 +1,329 @@ +/********************************************************************** + * Copyright (c) 2002,2003,2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + ***********************************************************************/ + +package org.eclipse.cdt.internal.ui.cview; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.ISourceReference; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.internal.ui.dnd.CDTViewerDropAdapter; +import org.eclipse.cdt.internal.ui.dnd.TransferDropTargetListener; +import org.eclipse.cdt.internal.ui.util.ExceptionHandler; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.operation.IRunnableContext; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DropTargetEvent; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.views.navigator.LocalSelectionTransfer; + +public class SelectionTransferDropAdapter extends CDTViewerDropAdapter implements TransferDropTargetListener { + + private List fElements; + private ICElement[] fMoveData; + private ICElement[] fCopyData; + + private static final long DROP_TIME_DIFF_TRESHOLD= 150; + + public SelectionTransferDropAdapter(StructuredViewer viewer) { + super(viewer, DND.FEEDBACK_SCROLL | DND.FEEDBACK_EXPAND); + } + + //---- TransferDropTargetListener interface --------------------------------------- + + public Transfer getTransfer() { + return LocalSelectionTransfer.getInstance(); + } + + public boolean isEnabled(DropTargetEvent event) { + Object target= event.item != null ? event.item.getData() : null; + if (target == null) { + return false; + } + return target instanceof ISourceReference; + } + + //---- Actual DND ----------------------------------------------------------------- + + public void dragEnter(DropTargetEvent event) { + clear(); + super.dragEnter(event); + } + + public void dragLeave(DropTargetEvent event) { + clear(); + super.dragLeave(event); + } + + private void clear() { + fElements = null; + fMoveData = null; + fCopyData = null; + } + + public void validateDrop(Object target, DropTargetEvent event, int operation) { + event.detail= DND.DROP_NONE; + + if (tooFast(event)) { + return; + } + + initializeSelection(); + + try { + switch(operation) { + case DND.DROP_DEFAULT: + event.detail= handleValidateDefault(target, event); + break; + case DND.DROP_COPY: + event.detail= handleValidateCopy(target, event); + break; + case DND.DROP_MOVE: + event.detail= handleValidateMove(target, event); + break; + case DND.DROP_LINK: + event.detail= handleValidateLink(target, event); + break; + } + } catch (CModelException e){ + ExceptionHandler.handle(e, CViewMessages.getString("SelectionTransferDropAdapter.error.title"), CViewMessages.getString("SelectionTransferDropAdapter.error.message")); //$NON-NLS-1$ //$NON-NLS-2$ + event.detail= DND.DROP_NONE; + } + } + + protected void initializeSelection(){ + if (fElements != null) { + return; + } + ISelection s= LocalSelectionTransfer.getInstance().getSelection(); + if (!(s instanceof IStructuredSelection)) { + return; + } + fElements = ((IStructuredSelection)s).toList(); + } + + private boolean tooFast(DropTargetEvent event) { + return Math.abs(LocalSelectionTransfer.getInstance().getSelectionSetTime() - (event.time & 0xFFFFFFFFL)) < DROP_TIME_DIFF_TRESHOLD; + } + + public void drop(Object target, DropTargetEvent event) { + try { + switch(event.detail) { + case DND.DROP_MOVE: + handleDropMove(target, event); + break; + case DND.DROP_COPY: + handleDropCopy(target, event); + break; + case DND.DROP_LINK: + handleDropLink(target, event); + break; + } + } catch (CModelException e){ + ExceptionHandler.handle(e, CViewMessages.getString("SelectionTransferDropAdapter.error.title"), CViewMessages.getString("SelectionTransferDropAdapter.error.message")); //$NON-NLS-1$ //$NON-NLS-2$ + } catch(InvocationTargetException e) { + ExceptionHandler.handle(e, CViewMessages.getString("OpenRefactoringWizardAction.refactoring"), CViewMessages.getString("OpenRefactoringWizardAction.exception")); //$NON-NLS-1$ //$NON-NLS-2$ + } catch (InterruptedException e) { + //ok + } finally { + // The drag source listener must not perform any operation + // since this drop adapter did the remove of the source even + // if we moved something. + event.detail= DND.DROP_NONE; + } + } + + private int handleValidateDefault(Object target, DropTargetEvent event) throws CModelException { + if (target == null) { + return DND.DROP_NONE; + } + return handleValidateMove(target, event); + } + + private int handleValidateMove(Object target, DropTargetEvent event) throws CModelException { + if (target == null) { + return DND.DROP_NONE; + } + if (fMoveData == null) { + ICElement[] cElements= getCElements(fElements); + if (cElements != null && cElements.length > 0) { + fMoveData = cElements; + } + } + + if (!canMoveElements()) { + return DND.DROP_NONE; + } + + if (target instanceof ISourceReference) { + return DND.DROP_MOVE; + } + return DND.DROP_NONE; + } + + private boolean canMoveElements() { + if (fMoveData != null) { + return hasCommonParent(fMoveData); + } + return false; + } + + private boolean hasCommonParent(ICElement[] elements) { + if (elements.length > 1) { + ICElement parent = elements[0]; + for (int i = 0; i < elements.length; ++i) { + ICElement p = elements[i].getParent(); + if (parent == null && p!= null) { + return false; + } else if (!parent.equals(p)){ + return false; + } + } + } + return true; + } + + private void handleDropLink(Object target, DropTargetEvent event) { + } + + private int handleValidateLink(Object target, DropTargetEvent event) { + return DND.DROP_NONE; + } + + private void handleDropMove(final Object target, DropTargetEvent event) throws CModelException, InvocationTargetException, InterruptedException{ + final ICElement[] cElements= getCElements(fElements); + + if (target instanceof ICElement) { + ICElement cTarget = (ICElement)target; + ICElement parent = cTarget; + boolean isTargetTranslationUnit = cTarget instanceof ITranslationUnit; + if (!isTargetTranslationUnit) { + parent = cTarget.getParent(); + } + final ICElement[] containers = new ICElement[cElements.length]; + for (int i = 0; i < containers.length; ++i) { + containers[i] = parent; + } + ICElement[] neighbours = null; + if (!isTargetTranslationUnit) { + neighbours = new ICElement[cElements.length]; + for (int i = 0; i < neighbours.length; ++i) { + neighbours[i] = cTarget; + } + } + final ICElement[] siblings = neighbours; + IRunnableWithProgress runnable = new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + try { + CoreModel.getDefault().getCModel().move(cElements, containers, siblings, null, false, monitor); + } catch (CModelException e) { + throw new InvocationTargetException(e); + } + } + }; + run(runnable); + } + } + + private int handleValidateCopy(Object target, DropTargetEvent event) throws CModelException{ + + if (fCopyData == null) { + ICElement[] cElements= getCElements(fElements); + ICProject project= null; + if (cElements != null && cElements.length > 0) { + fCopyData= cElements; + } + } + + if (!canCopyElements()) + return DND.DROP_NONE; + + if (target instanceof ISourceReference) { + return DND.DROP_COPY; + } + return DND.DROP_NONE; + } + + private boolean canCopyElements() { + if (fCopyData != null) { + return hasCommonParent(fCopyData); + } + return false; + } + + private void handleDropCopy(final Object target, DropTargetEvent event) throws CModelException, InvocationTargetException, InterruptedException{ + final ICElement[] cElements= getCElements(fElements); + + if (target instanceof ICElement) { + ICElement cTarget = (ICElement)target; + ICElement parent = cTarget; + boolean isTargetTranslationUnit = cTarget instanceof ITranslationUnit; + if (!isTargetTranslationUnit) { + parent = cTarget.getParent(); + } + final ICElement[] containers = new ICElement[cElements.length]; + for (int i = 0; i < containers.length; ++i) { + containers[i] = parent; + } + ICElement[] neighbours = null; + if (!isTargetTranslationUnit) { + neighbours = new ICElement[cElements.length]; + for (int i = 0; i < neighbours.length; ++i) { + neighbours[i] = cTarget; + } + } + final ICElement[] siblings = neighbours; + IRunnableWithProgress runnable = new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + try { + CoreModel.getDefault().getCModel().copy(cElements, containers, siblings, null, false, monitor); + } catch (CModelException e) { + throw new InvocationTargetException(e); + } + } + }; + run(runnable); + } + } + + private Shell getShell() { + return getViewer().getControl().getShell(); + } + + public void run(IRunnableWithProgress runnable) throws InterruptedException, InvocationTargetException { + IRunnableContext context= new ProgressMonitorDialog(getShell()); + context.run(true, true, runnable); + } + + public static ICElement[] getCElements(List elements) { + List resources= new ArrayList(elements.size()); + for (Iterator iter= elements.iterator(); iter.hasNext();) { + Object element= iter.next(); + if (element instanceof ICElement) + resources.add(element); + } + return (ICElement[]) resources.toArray(new ICElement[resources.size()]); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/BasicSelectionTransferDragAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/BasicSelectionTransferDragAdapter.java new file mode 100644 index 00000000000..ea66ffc2fbe --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/BasicSelectionTransferDragAdapter.java @@ -0,0 +1,83 @@ +/********************************************************************** + * Copyright (c) 2002,2003,2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + ***********************************************************************/ + +package org.eclipse.cdt.internal.ui.dnd; + +import org.eclipse.jface.util.Assert; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DragSourceAdapter; +import org.eclipse.swt.dnd.DragSourceEvent; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.ui.views.navigator.LocalSelectionTransfer; + +public class BasicSelectionTransferDragAdapter extends DragSourceAdapter implements TransferDragSourceListener { + + private ISelectionProvider fProvider; + + public BasicSelectionTransferDragAdapter(ISelectionProvider provider) { + Assert.isNotNull(provider); + fProvider= provider; + } + + /** + * @see TransferDragSourceListener#getTransfer + */ + public Transfer getTransfer() { + return LocalSelectionTransfer.getInstance(); + } + + /* non Java-doc + * @see org.eclipse.swt.dnd.DragSourceListener#dragStart + */ + public void dragStart(DragSourceEvent event) { + ISelection selection= fProvider.getSelection(); + LocalSelectionTransfer.getInstance().setSelection(selection); + LocalSelectionTransfer.getInstance().setSelectionSetTime(event.time & 0xFFFFFFFFL); + event.doit= isDragable(selection); + } + + /** + * Checks if the elements contained in the given selection can + * be dragged. + *
+ * Subclasses may override.
+ *
+ * @param selection containing the elements to be dragged
+ */
+ protected boolean isDragable(ISelection selection) {
+ return true;
+ }
+
+
+ /* non Java-doc
+ * @see org.eclipse.swt.dnd.DragSourceListener#dragSetData
+ */
+ public void dragSetData(DragSourceEvent event) {
+ // For consistency set the data to the selection even though
+ // the selection is provided by the LocalSelectionTransfer
+ // to the drop target adapter.
+ event.data= LocalSelectionTransfer.getInstance().getSelection();
+ }
+
+
+ /* non Java-doc
+ * @see org.eclipse.swt.dnd.DragSourceListener#dragFinished
+ */
+ public void dragFinished(DragSourceEvent event) {
+ // We assume that the drop target listener has done all
+ // the work.
+ Assert.isTrue(event.detail == DND.DROP_NONE);
+ LocalSelectionTransfer.getInstance().setSelection(null);
+ LocalSelectionTransfer.getInstance().setSelectionSetTime(0);
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/CDTViewerDragAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/CDTViewerDragAdapter.java
new file mode 100644
index 00000000000..f03dc555145
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/CDTViewerDragAdapter.java
@@ -0,0 +1,41 @@
+/**********************************************************************
+ * Copyright (c) 2002,2003,2004 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ ***********************************************************************/
+
+package org.eclipse.cdt.internal.ui.dnd;
+
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.dnd.DragSourceEvent;
+
+/**
+ * CDTViewerDragAdapter
+ */
+public class CDTViewerDragAdapter extends DelegatingDragAdapter {
+
+ private StructuredViewer fViewer;
+
+ public CDTViewerDragAdapter(StructuredViewer viewer, TransferDragSourceListener[] listeners) {
+ super(listeners);
+ Assert.isNotNull(viewer);
+ fViewer= viewer;
+ }
+
+ public void dragStart(DragSourceEvent event) {
+ IStructuredSelection selection= (IStructuredSelection)fViewer.getSelection();
+ if (selection.isEmpty()) {
+ event.doit= false;
+ return;
+ }
+ super.dragStart(event);
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/CDTViewerDropAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/CDTViewerDropAdapter.java
new file mode 100644
index 00000000000..2c13cf132bd
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/CDTViewerDropAdapter.java
@@ -0,0 +1,268 @@
+/**********************************************************************
+ * Copyright (c) 2002,2003,2004 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ ***********************************************************************/
+
+package org.eclipse.cdt.internal.ui.dnd;
+
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.DropTargetListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.TreeItem;
+
+/**
+ * A drag and drop adapter to be used together with structured viewers.
+ * The adapater delegates the dragEnter
, dragOperationChanged
+ *
, dragOver
and dropAccept
method to the
+ * validateDrop
method. Furthermore it adds location feedback.
+ */
+public class CDTViewerDropAdapter implements DropTargetListener {
+
+ /**
+ * Constant describing the position of the mouse cursor relative
+ * to the target object. This means the mouse is not positioned
+ * over or near any valid target.
+ */
+ public static final int LOCATION_NONE= DND.FEEDBACK_NONE;
+
+ /**
+ * Constant describing the position of the mouse cursor relative
+ * to the target object. This means the mouse is positioned
+ * directly on the target.
+ */
+ public static final int LOCATION_ON= DND.FEEDBACK_SELECT;
+
+ /**
+ * Constant describing the position of the mouse cursor relative
+ * to the target object. This means the mouse is positioned
+ * slightly before the target.
+ */
+ public static final int LOCATION_BEFORE= DND.FEEDBACK_INSERT_BEFORE;
+
+ /**
+ * Constant describing the position of the mouse cursor relative
+ * to the target object. This means the mouse is positioned
+ * slightly after the target.
+ */
+ public static final int LOCATION_AFTER= DND.FEEDBACK_INSERT_AFTER;
+
+ /**
+ * The threshold used to determine if the mouse is before or after
+ * an item.
+ */
+ private static final int LOCATION_EPSILON= 5;
+
+ /**
+ * Style to enable location feedback.
+ */
+ public static final int INSERTION_FEEDBACK= 1 << 1;
+
+ private StructuredViewer fViewer;
+ private int fFeedback;
+ private boolean fShowInsertionFeedback;
+ private int fRequestedOperation;
+ private int fLastOperation;
+ protected int fLocation;
+ protected Object fTarget;
+
+ public CDTViewerDropAdapter(StructuredViewer viewer, int feedback) {
+ Assert.isNotNull(viewer);
+ fViewer= viewer;
+ fFeedback= feedback;
+ fLastOperation= -1;
+ }
+
+ /**
+ * Controls whether the drop adapter shows insertion feedback or not.
+ *
+ * @param showInsertionFeedback true
if the drop adapter is supposed
+ * to show insertion feedback. Otherwise false
+ */
+ public void showInsertionFeedback(boolean showInsertionFeedback) {
+ fShowInsertionFeedback= showInsertionFeedback;
+ }
+
+ /**
+ * Returns the viewer this adapter is working on.
+ */
+ protected StructuredViewer getViewer() {
+ return fViewer;
+ }
+
+ //---- Hooks to override -----------------------------------------------------
+
+ /**
+ * The actual drop has occurred. Calls drop(Object target, DropTargetEvent event)
+ *
.
+ * @see DropTargetListener#drop(org.eclipse.swt.dnd.DropTargetEvent)
+ */
+ public void drop(DropTargetEvent event) {
+ drop(fTarget, event);
+ }
+
+ /**
+ * The actual drop has occurred.
+ * @param target the drop target in form of a domain element.
+ * @param event the drop traget event
+ */
+ public void drop(Object target, DropTargetEvent event) {
+ }
+
+ /**
+ * Checks if the drop is valid. The method calls validateDrop
+ * (Object target, DropTargetEvent event). Implementors can alter the
+ *
DROP_NODEcurrentDataType
field and the detail
field
+ * to give feedback about drop acceptence.
+ */
+ public void validateDrop(DropTargetEvent event) {
+ validateDrop(fTarget, event, fRequestedOperation);
+ }
+
+ /**
+ * Checks if the drop on the current target is valid. The method
+ * can alter the currentDataType
field and the
+ * detail
field to give feedback about drop acceptence.
+ * @param target the drop target in form of a domain element.
+ * @param event the drop traget event
+ * @param operation the operation requested by the user.
+ */
+ public void validateDrop(Object target, DropTargetEvent event, int operation) {
+ }
+
+ public void dragEnter(DropTargetEvent event) {
+ dragOperationChanged(event);
+ }
+
+ public void dragLeave(DropTargetEvent event) {
+ fTarget= null;
+ fLocation= LOCATION_NONE;
+ }
+
+ public void dragOperationChanged(DropTargetEvent event) {
+ fRequestedOperation= event.detail;
+ fTarget= computeTarget(event);
+ fLocation= computeLocation(event);
+ validateDrop(event);
+ fLastOperation= event.detail;
+ computeFeedback(event);
+ }
+
+ public void dragOver(DropTargetEvent event) {
+ Object oldTarget= fTarget;
+ fTarget= computeTarget(event);
+
+ //set the location feedback
+ int oldLocation= fLocation;
+ fLocation= computeLocation(event);
+ if (oldLocation != fLocation || oldTarget != fTarget || fLastOperation != event.detail) {
+ validateDrop(event);
+ fLastOperation= event.detail;
+ } else {
+ event.detail= fLastOperation;
+ }
+ computeFeedback(event);
+ }
+
+ public void dropAccept(DropTargetEvent event) {
+ fTarget= computeTarget(event);
+ validateDrop(event);
+ fLastOperation= event.detail;
+ }
+
+ /**
+ * Returns the data held by event.item
. Inside a viewer
+ * this corresponds to the items data model element.
+ */
+ protected Object computeTarget(DropTargetEvent event) {
+ return event.item == null ? null : event.item.getData();
+ }
+
+ /**
+ * Returns the position of the given coordinates relative to the given target.
+ * The position is determined to be before, after, or on the item, based on
+ * some threshold value. The return value is one of the LOCATION_* constants
+ * defined in this class.
+ */
+ final protected int computeLocation(DropTargetEvent event) {
+ if (!(event.item instanceof Item))
+ return LOCATION_NONE;
+
+ Item item= (Item) event.item;
+ Point coordinates= fViewer.getControl().toControl(new Point(event.x, event.y));
+ Rectangle bounds= getBounds(item);
+ if (bounds == null) {
+ return LOCATION_NONE;
+ }
+ if ((coordinates.y - bounds.y) < LOCATION_EPSILON) {
+ return LOCATION_BEFORE;
+ }
+ if ((bounds.y + bounds.height - coordinates.y) < LOCATION_EPSILON) {
+ return LOCATION_AFTER;
+ }
+ return LOCATION_ON;
+ }
+
+ /**
+ * Returns the bounds of the given item, or null
if it is not a
+ * valid type of item.
+ */
+ private Rectangle getBounds(Item item) {
+ if (item instanceof TreeItem)
+ return ((TreeItem) item).getBounds();
+
+ if (item instanceof TableItem)
+ return ((TableItem) item).getBounds(0);
+
+ return null;
+ }
+
+ /**
+ * Sets the drag under feedback corresponding to the value of fLocation
+ * and the INSERTION_FEEDBACK
style bit.
+ */
+ protected void computeFeedback(DropTargetEvent event) {
+ if (!fShowInsertionFeedback && fLocation != LOCATION_NONE) {
+ event.feedback= DND.FEEDBACK_SELECT;
+ } else {
+ event.feedback= fLocation;
+ }
+ event.feedback|= fFeedback;
+ }
+
+ /**
+ * Sets the drop operation to .
+ */
+ protected void clearDropOperation(DropTargetEvent event) {
+ event.detail= DND.DROP_NONE;
+ }
+
+ /**
+ * Returns the requested drop operation.
+ */
+ protected int getRequestedOperation() {
+ return fRequestedOperation;
+ }
+
+ protected void setDefaultFeedback(int feedback) {
+ fFeedback= feedback;
+ }
+
+ //---- helper methods to test DnD
+
+ public void internalTestSetLocation(int location) {
+ fLocation= location;
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/DelegatingDragAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/DelegatingDragAdapter.java
new file mode 100644
index 00000000000..f88c8267567
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/DelegatingDragAdapter.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.dnd;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.util.Assert;
+import org.eclipse.swt.dnd.DragSource;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.DragSourceListener;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.TransferData;
+
+/**
+ * A delegating drag adapter negotiates between a set of
TransferDragSourceListener
s
+ * On dragStart
the adapter determines the listener to be used for any further
+ * drag*
callbacks.
+ */
+public class DelegatingDragAdapter implements DragSourceListener {
+ private TransferDragSourceListener[] fPossibleListeners;
+ private List fActiveListeners;
+ private TransferDragSourceListener fFinishListener;
+
+ public DelegatingDragAdapter(TransferDragSourceListener[] listeners) {
+ setPossibleListeners(listeners);
+ }
+
+ protected void setPossibleListeners(TransferDragSourceListener[] listeners) {
+ Assert.isNotNull(listeners);
+ Assert.isTrue(fActiveListeners == null, "Can only set possible listeners before drag operation has started"); //$NON-NLS-1$
+ fPossibleListeners= listeners;
+ }
+
+ /* non Java-doc
+ * @see DragSourceListener
+ */
+ public void dragStart(DragSourceEvent event) {
+ fFinishListener= null;
+ boolean saveDoit= event.doit;
+ Object saveData= event.data;
+ boolean doIt= false;
+ List transfers= new ArrayList(fPossibleListeners.length);
+ fActiveListeners= new ArrayList(fPossibleListeners.length);
+
+ for (int i= 0; i < fPossibleListeners.length; i++) {
+ TransferDragSourceListener listener= fPossibleListeners[i];
+ event.doit= saveDoit;
+ listener.dragStart(event);
+ if (event.doit) {
+ transfers.add(listener.getTransfer());
+ fActiveListeners.add(listener);
+ }
+ doIt= doIt || event.doit;
+ }
+ if (doIt) {
+ ((DragSource)event.widget).setTransfer((Transfer[])transfers.toArray(new Transfer[transfers.size()]));
+ }
+ event.data= saveData;
+ event.doit= doIt;
+ }
+
+ /* non Java-doc
+ * @see DragSourceListener
+ */
+ public void dragSetData(DragSourceEvent event) {
+ fFinishListener= getListener(event.dataType);
+ if (fFinishListener != null)
+ fFinishListener.dragSetData(event);
+ }
+
+ /* non Java-doc
+ * @see DragSourceListener
+ */
+ public void dragFinished(DragSourceEvent event) {
+ try{
+ if (fFinishListener != null) {
+ fFinishListener.dragFinished(event);
+ } else {
+ // If the user presses Escape then we get a dragFinished without
+ // getting a dragSetData before.
+ fFinishListener= getListener(event.dataType);
+ if (fFinishListener != null)
+ fFinishListener.dragFinished(event);
+ }
+ } finally{
+ fFinishListener= null;
+ fActiveListeners= null;
+ }
+ }
+
+ private TransferDragSourceListener getListener(TransferData type) {
+ if (type == null)
+ return null;
+
+ for (Iterator iter= fActiveListeners.iterator(); iter.hasNext();) {
+ TransferDragSourceListener listener= (TransferDragSourceListener)iter.next();
+ if (listener.getTransfer().isSupportedType(type)) {
+ return listener;
+ }
+ }
+ return null;
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/DelegatingDropAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/DelegatingDropAdapter.java
new file mode 100644
index 00000000000..d0897a5fed3
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/DelegatingDropAdapter.java
@@ -0,0 +1,264 @@
+/**********************************************************************
+ * Copyright (c) 2002,2003,2004 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ ***********************************************************************/
+
+package org.eclipse.cdt.internal.ui.dnd;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.util.SafeRunnable;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.DropTargetListener;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.TransferData;
+
+/**
+ * DelegatingDropAdapter
+ */
+public class DelegatingDropAdapter implements DropTargetListener {
+ private TransferDropTargetListener[] fListeners;
+ TransferDropTargetListener fCurrentListener;
+ private int fOriginalDropType;
+
+ /**
+ * Creates a new delegating drop adapter.
+ *
+ * @param listeners an array of potential listeners
+ */
+ public DelegatingDropAdapter(TransferDropTargetListener[] listeners) {
+ Assert.isNotNull(listeners);
+ fListeners= listeners;
+ }
+
+ /**
+ * The cursor has entered the drop target boundaries. The current listener
+ * is updated, and #dragEnter()
is forwarded to the current
+ * listener.
+ *
+ * @param event the drop target event
+ * @see DropTargetListener#dragEnter(DropTargetEvent)
+ */
+ public void dragEnter(DropTargetEvent event) {
+ fOriginalDropType= event.detail;
+ updateCurrentListener(event);
+ }
+
+ /**
+ * The cursor has left the drop target boundaries. The event is forwarded to
+ * the current listener.
+ *
+ * @param event the drop target event
+ * @see DropTargetListener#dragLeave(DropTargetEvent)
+ */
+ public void dragLeave(final DropTargetEvent event) {
+ setCurrentListener(null, event);
+ }
+
+ /**
+ * The operation being performed has changed (usually due to the user
+ * changing a drag modifier key while dragging). Updates the current
+ * listener and forwards this event to that listener.
+ *
+ * @param event the drop target event
+ * @see DropTargetListener#dragOperationChanged(DropTargetEvent)
+ */
+ public void dragOperationChanged(final DropTargetEvent event) {
+ fOriginalDropType= event.detail;
+ TransferDropTargetListener oldListener= getCurrentListener();
+ updateCurrentListener(event);
+ final TransferDropTargetListener newListener= getCurrentListener();
+ // only notify the current listener if it hasn't changed based on the
+ // operation change. otherwise the new listener would get a dragEnter
+ // followed by a dragOperationChanged with the exact same event.
+ if (newListener != null && newListener == oldListener) {
+ Platform.run(new SafeRunnable() {
+ public void run() throws Exception {
+ newListener.dragOperationChanged(event);
+ }
+ });
+ }
+ }
+
+ /**
+ * The cursor is moving over the drop target. Updates the current listener
+ * and forwards this event to that listener. If no listener can handle the
+ * drag operation the event.detail
field is set to
+ * DND.DROP_NONE
to indicate an invalid drop.
+ *
+ * @param event the drop target event
+ * @see DropTargetListener#dragOver(DropTargetEvent)
+ */
+ public void dragOver(final DropTargetEvent event) {
+ TransferDropTargetListener oldListener= getCurrentListener();
+ updateCurrentListener(event);
+ final TransferDropTargetListener newListener= getCurrentListener();
+
+ // only notify the current listener if it hasn't changed based on the
+ // drag over. otherwise the new listener would get a dragEnter
+ // followed by a dragOver with the exact same event.
+ if (newListener != null && newListener == oldListener) {
+ Platform.run(new SafeRunnable() {
+ public void run() throws Exception {
+ newListener.dragOver(event);
+ }
+ });
+ }
+ }
+
+ /**
+ * Forwards this event to the current listener, if there is one. Sets the
+ * current listener to null
afterwards.
+ *
+ * @param event the drop target event
+ * @see DropTargetListener#drop(DropTargetEvent)
+ */
+ public void drop(final DropTargetEvent event) {
+ updateCurrentListener(event);
+ if (getCurrentListener() != null) {
+ Platform.run(new SafeRunnable() {
+ public void run() throws Exception {
+ getCurrentListener().drop(event);
+ }
+ });
+ }
+ setCurrentListener(null, event);
+ }
+
+ /**
+ * Forwards this event to the current listener if there is one.
+ *
+ * @param event the drop target event
+ * @see DropTargetListener#dropAccept(DropTargetEvent)
+ */
+ public void dropAccept(final DropTargetEvent event) {
+ if (getCurrentListener() != null) {
+ Platform.run(new SafeRunnable() {
+ public void run() throws Exception {
+ getCurrentListener().dropAccept(event);
+ }
+ });
+ }
+ }
+
+ /**
+ * Returns the listener which currently handles drop events.
+ *
+ * @return the TransferDropTargetListener
which currently
+ * handles drop events.
+ */
+ TransferDropTargetListener getCurrentListener() {
+ return fCurrentListener;
+ }
+
+ /**
+ * Returns the transfer data type supported by the given listener. Returns
+ * null
if the listener does not support any of the specified
+ * data types.
+ *
+ * @param dataTypes available data types
+ * @param listener TransferDropTargetListener
to use for
+ * testing supported data types.
+ * @return the transfer data type supported by the given listener or
+ * null
.
+ */
+ private TransferData getSupportedTransferType(TransferData[] dataTypes, TransferDropTargetListener listener) {
+ for (int i= 0; i < dataTypes.length; i++) {
+ if (listener.getTransfer().isSupportedType(dataTypes[i])) {
+ return dataTypes[i];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the combined set of Transfer
types of all
+ * TransferDropTargetListeners
.
+ *
+ * @return the combined set of Transfer
types
+ */
+ public Transfer[] getTransfers() {
+ Transfer[] types= new Transfer[fListeners.length];
+ for (int i= 0; i < fListeners.length; i++) {
+ types[i]= fListeners[i].getTransfer();
+ }
+ return types;
+ }
+
+ /**
+ * Sets the current listener to listener
. Sends the given
+ * DropTargetEvent
if the current listener changes.
+ *
+ * @return true
if the new listener is different than the
+ * previous false
otherwise
+ */
+ private boolean setCurrentListener(TransferDropTargetListener listener, final DropTargetEvent event) {
+ if (fCurrentListener == listener)
+ return false;
+ if (fCurrentListener != null) {
+ Platform.run(new SafeRunnable() {
+ public void run() throws Exception {
+ fCurrentListener.dragLeave(event);
+ }
+ });
+ }
+ fCurrentListener= listener;
+ if (fCurrentListener != null) {
+ Platform.run(new SafeRunnable() {
+ public void run() throws Exception {
+ fCurrentListener.dragEnter(event);
+ }
+ });
+ }
+ return true;
+ }
+
+ /**
+ * Updates the current listener to one that can handle the drop. There can
+ * be many listeners and each listener may be able to handle many
+ * TransferData
types. The first listener found that can
+ * handle a drop of one of the given TransferData
types will
+ * be selected. If no listener can handle the drag operation the
+ * event.detail
field is set to DND.DROP_NONE
+ * to indicate an invalid drop.
+ *
+ * @param event the drop target event
+ */
+ private void updateCurrentListener(DropTargetEvent event) {
+ int originalDetail= event.detail;
+ // Revert the detail to the "original" drop type that the User
+ // indicated. This is necessary because the previous listener
+ // may have changed the detail to something other than what the
+ // user indicated.
+ event.detail= fOriginalDropType;
+
+ for (int i= 0; i < fListeners.length; i++) {
+ TransferDropTargetListener listener= fListeners[i];
+ TransferData dataType= getSupportedTransferType(event.dataTypes, listener);
+ if (dataType != null) {
+ TransferData originalDataType= event.currentDataType;
+ // set the data type supported by the drop listener
+ event.currentDataType= dataType;
+ if (listener.isEnabled(event)) {
+ // if the listener stays the same, set its previously
+ // determined
+ // event detail
+ if (!setCurrentListener(listener, event))
+ event.detail= originalDetail;
+ return;
+ }
+ event.currentDataType= originalDataType;
+ }
+ }
+ setCurrentListener(null, event);
+ event.detail= DND.DROP_NONE;
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/FileTransferDragAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/FileTransferDragAdapter.java
similarity index 88%
rename from core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/FileTransferDragAdapter.java
rename to core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/FileTransferDragAdapter.java
index 83c559bcc65..642d3007946 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/FileTransferDragAdapter.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/FileTransferDragAdapter.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.cdt.internal.ui.drag;
+package org.eclipse.cdt.internal.ui.dnd;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
@@ -62,9 +62,7 @@ public class FileTransferDragAdapter implements TransferDragSourceListener {
}
public void dragSetData(DragSourceEvent event) {
- String[] locations = getResourceLocations(getResources());
-
- event.data = locations.length != 0 ? locations : null;
+ event.data = getResourceLocations(getResources());
}
public void dragFinished(DragSourceEvent event) {
@@ -132,10 +130,11 @@ public class FileTransferDragAdapter implements TransferDragSourceListener {
Object object = iterator.next();
IResource resource = null;
- if (object instanceof IResource)
+ if (object instanceof IResource) {
resource = (IResource) object;
- else if (object instanceof IAdaptable)
+ } else if (object instanceof IAdaptable) {
resource = (IResource) ((IAdaptable) object).getAdapter(IResource.class);
+ }
if (resource != null)
result.add(resource);
@@ -146,22 +145,26 @@ public class FileTransferDragAdapter implements TransferDragSourceListener {
}
private static String[] getResourceLocations(List resources) {
- final int count = resources.size();
- final List locations = new ArrayList(count);
-
- for (Iterator iterator = resources.iterator(); iterator.hasNext();) {
- IResource resource = (IResource) iterator.next();
- IPath location = resource.getLocation();
-
- if (location != null)
- locations.add(location.toOSString());
+ if (!resources.isEmpty()) {
+ int count = resources.size();
+ List locations = new ArrayList(count);
+
+ for (Iterator iterator = resources.iterator(); iterator.hasNext();) {
+ IResource resource = (IResource) iterator.next();
+ IPath location = resource.getLocation();
+
+ if (location != null) {
+ locations.add(location.toOSString());
+ }
+ }
+
+ String[] result = new String[locations.size()];
+
+ locations.toArray(result);
+
+ return result;
}
-
- String[] result = new String[locations.size()];
-
- locations.toArray(result);
-
- return result;
+ return null;
}
private static void runOperation(
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/FileTransferDropAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/FileTransferDropAdapter.java
new file mode 100644
index 00000000000..59d87342ab7
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/FileTransferDropAdapter.java
@@ -0,0 +1,111 @@
+/**********************************************************************
+ * Copyright (c) 2002,2003,2004 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ ***********************************************************************/
+
+package org.eclipse.cdt.internal.ui.dnd;
+
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourceAttributes;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.viewers.AbstractTreeViewer;
+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.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.actions.CopyFilesAndFoldersOperation;
+
+/**
+ * FileTransferDropAdapter
+ */
+public class FileTransferDropAdapter extends CDTViewerDropAdapter implements TransferDropTargetListener {
+
+ public FileTransferDropAdapter(AbstractTreeViewer viewer) {
+ super(viewer, DND.FEEDBACK_SCROLL | DND.FEEDBACK_EXPAND);
+ }
+
+ //---- TransferDropTargetListener interface ---------------------------------------
+
+ public Transfer getTransfer() {
+ return FileTransfer.getInstance();
+ }
+
+ public boolean isEnabled(DropTargetEvent event) {
+ Object target= event.item != null ? event.item.getData() : null;
+ if (target == null) {
+ return false;
+ }
+ return target instanceof ICElement || target instanceof IResource;
+ }
+
+ //---- Actual DND -----------------------------------------------------------------
+
+ public void validateDrop(Object target, DropTargetEvent event, int operation) {
+ event.detail= DND.DROP_NONE;
+ boolean isContainer = false;
+ if (target instanceof IContainer) {
+ isContainer = true;
+ } else if (target instanceof IAdaptable) {
+ target = ((IAdaptable)target).getAdapter(IResource.class);
+ isContainer = target instanceof IContainer;
+ }
+ if (isContainer) {
+ IContainer container= (IContainer)target;
+ if (container.isAccessible()) {
+ ResourceAttributes attributes = container.getResourceAttributes();
+ if (attributes != null && !attributes.isReadOnly()) {
+ event.detail= DND.DROP_COPY;
+ }
+ }
+ }
+ }
+
+ public void drop(Object dropTarget, final DropTargetEvent event) {
+ int operation= event.detail;
+
+ event.detail= DND.DROP_NONE;
+ final Object data= event.data;
+ if (data == null || !(data instanceof String[]) || operation != DND.DROP_COPY)
+ return;
+
+ final IContainer target= getActualTarget(dropTarget);
+ if (target == null)
+ return;
+
+ // Run the import operation asynchronously.
+ // Otherwise the drag source (e.g., Windows Explorer) will be blocked
+ // while the operation executes. Fixes bug 35796.
+ Display.getCurrent().asyncExec(new Runnable() {
+ public void run() {
+ getShell().forceActive();
+ new CopyFilesAndFoldersOperation(getShell()).copyFiles((String[]) data, target);
+ // Import always performs a copy.
+ event.detail= DND.DROP_COPY;
+ }
+ });
+ }
+
+ private IContainer getActualTarget(Object dropTarget) {
+ if (dropTarget instanceof IContainer) {
+ return (IContainer)dropTarget;
+ } else if (dropTarget instanceof ICElement) {
+ return getActualTarget(((ICElement)dropTarget).getResource());
+ }
+ return null;
+ }
+
+ Shell getShell() {
+ return getViewer().getControl().getShell();
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/ResourceTransferDragAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/ResourceTransferDragAdapter.java
similarity index 80%
rename from core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/ResourceTransferDragAdapter.java
rename to core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/ResourceTransferDragAdapter.java
index a1a95d710f6..14b6ca7f7f8 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/ResourceTransferDragAdapter.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/ResourceTransferDragAdapter.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.cdt.internal.ui.drag;
+package org.eclipse.cdt.internal.ui.dnd;
import java.util.ArrayList;
import java.util.Collections;
@@ -57,31 +57,7 @@ public class ResourceTransferDragAdapter implements TransferDragSourceListener {
}
public void dragStart(DragSourceEvent event) {
- event.doit = false;
-
- ISelection selection = provider.getSelection();
-
- if (selection instanceof IStructuredSelection) {
- IStructuredSelection structured = (IStructuredSelection) selection;
-
- for (Iterator iterator = structured.iterator(); iterator.hasNext();) {
- Object element = iterator.next();
-
- if (element instanceof IAdaptable) {
- IAdaptable adaptable = (IAdaptable) element;
- IResource resource = (IResource) adaptable.getAdapter(IResource.class);
-
- if (resource == null) {
- event.doit = false;
- break;
- }
-
- // this will stick unless a later part of the
- // selection isn't adaptable into a resource
- event.doit = true;
- }
- }
- }
+ event.doit = getSelectedResources().length > 0;
}
public void dragSetData(DragSourceEvent event) {
@@ -127,13 +103,15 @@ public class ResourceTransferDragAdapter implements TransferDragSourceListener {
for (Iterator iterator = structured.iterator(); iterator.hasNext();) {
Object element = iterator.next();
-
- if (element instanceof IAdaptable) {
+ IResource resource = null;
+ if (element instanceof IResource) {
+ resource = (IResource)element;
+ } else if (element instanceof IAdaptable) {
IAdaptable adaptable = (IAdaptable) element;
- IResource resource = (IResource) adaptable.getAdapter(IResource.class);
-
- if (resource != null)
- resources.add(resource);
+ resource = (IResource) adaptable.getAdapter(IResource.class);
+ }
+ if (resource != null) {
+ resources.add(resource);
}
}
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/ResourceTransferDropAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/ResourceTransferDropAdapter.java
new file mode 100644
index 00000000000..f407fcf4839
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/ResourceTransferDropAdapter.java
@@ -0,0 +1,160 @@
+/**********************************************************************
+ * Copyright (c) 2002,2003,2004 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ ***********************************************************************/
+
+package org.eclipse.cdt.internal.ui.dnd;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.actions.CopyFilesAndFoldersOperation;
+import org.eclipse.ui.actions.MoveFilesAndFoldersOperation;
+import org.eclipse.ui.actions.ReadOnlyStateChecker;
+import org.eclipse.ui.part.ResourceTransfer;
+import org.eclipse.ui.views.navigator.LocalSelectionTransfer;
+
+/**
+ * ResourceTransferDropAdapter
+ */
+public class ResourceTransferDropAdapter extends CDTViewerDropAdapter implements TransferDropTargetListener {
+
+ /**
+ * @param viewer
+ */
+ public ResourceTransferDropAdapter(StructuredViewer viewer) {
+ super(viewer, DND.FEEDBACK_SCROLL | DND.FEEDBACK_EXPAND);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.internal.ui.drag.TransferDropTargetListener#getTransfer()
+ */
+ public Transfer getTransfer() {
+ return ResourceTransfer.getInstance();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.internal.ui.drag.TransferDropTargetListener#isEnabled(org.eclipse.swt.dnd.DropTargetEvent)
+ */
+ public boolean isEnabled(DropTargetEvent event) {
+ Object target= event.item != null ? event.item.getData() : null;
+ if (target == null) {
+ return false;
+ }
+ return target instanceof ICElement || target instanceof IResource;
+ }
+
+ public void validateDrop(Object target, DropTargetEvent event, int op) {
+ IContainer destination = getDestination(target);
+ if (destination == null) {
+ event.detail = DND.DROP_NONE;
+ } else {
+ IResource[] selectedResources = getSelectedResources();
+ if (selectedResources.length == 0) {
+ event.detail = DND.DROP_NONE;
+ } else {
+ if (op == DND.DROP_COPY) {
+ CopyFilesAndFoldersOperation operation = new CopyFilesAndFoldersOperation(getShell());
+ if (operation.validateDestination(destination, selectedResources) == null) {
+ event.detail = op;
+ }
+ } else {
+ MoveFilesAndFoldersOperation operation = new MoveFilesAndFoldersOperation(getShell());
+ if (operation.validateDestination(destination, selectedResources) == null) {
+ event.detail = op;
+ }
+ }
+ }
+ }
+ }
+
+ public void drop(Object dropTarget, final DropTargetEvent event) {
+ int op= event.detail;
+
+ event.detail= DND.DROP_NONE;
+ final Object data= event.data;
+ if (data == null || !(data instanceof IResource[]))
+ return;
+
+ final IContainer target= getDestination(dropTarget);
+ if (target == null) {
+ return;
+ }
+ IResource[] sources = (IResource[])data;
+ if (op == DND.DROP_COPY) {
+ CopyFilesAndFoldersOperation operation = new CopyFilesAndFoldersOperation(getShell());
+ operation.copyResources(sources, target);
+ } else {
+ ReadOnlyStateChecker checker = new ReadOnlyStateChecker(
+ getShell(),
+ "Move Resource Action", //$NON-NLS-1$
+ "Move Resource Action");//$NON-NLS-1$
+ sources = checker.checkReadOnlyResources(sources);
+ MoveFilesAndFoldersOperation operation = new MoveFilesAndFoldersOperation(getShell());
+ operation.copyResources(sources, target);
+ }
+ }
+
+ private IContainer getDestination(Object dropTarget) {
+ if (dropTarget instanceof IContainer) {
+ return (IContainer)dropTarget;
+ } else if (dropTarget instanceof ICElement) {
+ return getDestination(((ICElement)dropTarget).getResource());
+ }
+ return null;
+ }
+
+ /**
+ * Returns the resource selection from the LocalSelectionTransfer.
+ *
+ * @return the resource selection from the LocalSelectionTransfer
+ */
+ private IResource[] getSelectedResources() {
+ ArrayList selectedResources = new ArrayList();
+
+ ISelection selection = LocalSelectionTransfer.getInstance()
+ .getSelection();
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection ssel = (IStructuredSelection) selection;
+ for (Iterator i = ssel.iterator(); i.hasNext();) {
+ Object o = i.next();
+ if (o instanceof IResource) {
+ selectedResources.add(o);
+ }
+ else if (o instanceof IAdaptable) {
+ IAdaptable a = (IAdaptable) o;
+ IResource r = (IResource) a.getAdapter(IResource.class);
+ if (r != null) {
+ selectedResources.add(r);
+ }
+ }
+ }
+ }
+ return (IResource[]) selectedResources.toArray(new IResource[selectedResources.size()]);
+ }
+
+ /**
+ * Returns the shell
+ */
+ protected Shell getShell() {
+ return getViewer().getControl().getShell();
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/TransferDragSourceListener.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/TransferDragSourceListener.java
similarity index 95%
rename from core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/TransferDragSourceListener.java
rename to core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/TransferDragSourceListener.java
index 0c21d10c152..a1d1e5c9b8b 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/TransferDragSourceListener.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/TransferDragSourceListener.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.cdt.internal.ui.drag;
+package org.eclipse.cdt.internal.ui.dnd;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.Transfer;
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/TransferDropTargetListener.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/TransferDropTargetListener.java
new file mode 100644
index 00000000000..da0808d2817
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dnd/TransferDropTargetListener.java
@@ -0,0 +1,38 @@
+/**********************************************************************
+ * Copyright (c) 2002,2003,2004 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ ***********************************************************************/
+
+package org.eclipse.cdt.internal.ui.dnd;
+
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.DropTargetListener;
+import org.eclipse.swt.dnd.Transfer;
+
+/**
+ * TransferDropTargetListener
+ */
+public interface TransferDropTargetListener extends DropTargetListener {
+
+ /**
+ * Returns the transfer used by this drop target.
+ */
+ public Transfer getTransfer();
+
+ /**
+ * Returns whether the listener is able to handle the given
+ * drop traget event.
+ *
+ * @param event the drop target event
+ *
+ * @return true
if the listener can handle the event;
+ * otherwise false
+ */
+ public boolean isEnabled(DropTargetEvent event);
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/DelegatingDragAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/DelegatingDragAdapter.java
deleted file mode 100644
index 42fd8686d85..00000000000
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/DelegatingDragAdapter.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.cdt.internal.ui.drag;
-
-import java.util.Arrays;
-
-import org.eclipse.jface.util.Assert;
-import org.eclipse.jface.viewers.ISelectionProvider;
-import org.eclipse.swt.dnd.DragSource;
-import org.eclipse.swt.dnd.DragSourceEvent;
-import org.eclipse.swt.dnd.DragSourceListener;
-import org.eclipse.swt.dnd.Transfer;
-import org.eclipse.swt.dnd.TransferData;
-import org.eclipse.swt.widgets.Control;
-
-/**
- * A delegating drag adapter negotiates between a set of TransferDragSourceListener
s
- * On dragStart
the adapter determines the listener to be used for any further
- * drag*
callbacks.
- */
-public class DelegatingDragAdapter implements DragSourceListener {
- private final ISelectionProvider provider;
- private final TransferDragSourceListener[] listeners;
- private final boolean[] actives;
- private TransferDragSourceListener selected;
-
- public DelegatingDragAdapter(
- ISelectionProvider provider,
- TransferDragSourceListener[] listeners) {
- super();
- Assert.isNotNull(provider);
- Assert.isNotNull(listeners);
- this.provider = provider;
- this.listeners = listeners;
- this.actives = new boolean[listeners.length];
- this.selected = null;
- }
-
- /* non Java-doc
- * @see DragSourceListener
- */
- public void dragStart(DragSourceEvent event) {
- selected = null;
-
- if (provider.getSelection().isEmpty()) {
- event.doit = false;
- return;
- }
-
- // Workaround for 1GEUS9V
- final DragSource dragSource = (DragSource) event.widget;
- final Control control = dragSource.getControl();
-
- if (control != control.getDisplay().getFocusControl()) {
- event.doit = false;
- return;
- }
-
- final Object saveData = event.data;
- final boolean saveDoit = event.doit;
- final int listenerCount = listeners.length;
-
- int transferCount = 0;
-
- for (int i = 0; i < listenerCount; ++i) {
- TransferDragSourceListener listener = listeners[i];
-
- event.data = saveData;
- event.doit = saveDoit;
-
- listener.dragStart(event);
-
- if (actives[i] = event.doit)
- ++transferCount;
- }
-
- event.data = saveData;
-
- if (event.doit = (transferCount != 0)) {
- Transfer[] transferArray = new Transfer[transferCount];
-
- for (int i = listenerCount; --i >= 0;)
- if (actives[i])
- transferArray[--transferCount] = listeners[i].getTransfer();
-
- dragSource.setTransfer(transferArray);
- }
- }
-
- /* non Java-doc
- * @see DragSourceListener
- */
- public void dragSetData(DragSourceEvent event) {
- selected = getListener(event.dataType);
-
- if (selected != null)
- selected.dragSetData(event);
- }
-
- /* non Java-doc
- * @see DragSourceListener
- */
- public void dragFinished(DragSourceEvent event) {
- try {
- // If the user presses Escape then we get a dragFinished
- // without getting a dragSetData before.
- if (selected == null)
- selected = getListener(event.dataType);
-
- if (selected != null)
- selected.dragFinished(event);
- } finally {
- Arrays.fill(actives, false);
- selected = null;
- }
- }
-
- private TransferDragSourceListener getListener(TransferData type) {
- if (type != null) {
- for (int i = 0; i < actives.length; ++i) {
- if (actives[i]) {
- TransferDragSourceListener listener = listeners[i];
-
- if (listener.getTransfer().isSupportedType(type))
- return listener;
- }
- }
- }
-
- return null;
- }
-}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/LocalSelectionTransferDragAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/LocalSelectionTransferDragAdapter.java
deleted file mode 100644
index ebaadff9067..00000000000
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/LocalSelectionTransferDragAdapter.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.cdt.internal.ui.drag;
-
-import org.eclipse.cdt.ui.CLocalSelectionTransfer;
-import org.eclipse.jface.util.Assert;
-import org.eclipse.jface.viewers.ISelectionProvider;
-import org.eclipse.swt.dnd.DragSourceEvent;
-import org.eclipse.swt.dnd.Transfer;
-
-public class LocalSelectionTransferDragAdapter implements TransferDragSourceListener {
- private final ISelectionProvider provider;
- private final CLocalSelectionTransfer transfer;
-
- public LocalSelectionTransferDragAdapter(ISelectionProvider provider) {
- super();
- this.provider = provider;
- this.transfer = CLocalSelectionTransfer.getInstance();
- Assert.isNotNull(provider);
- Assert.isNotNull(transfer);
- }
-
- /* (non-Javadoc)
- * @see DragSourceListener#dragStart
- */
- public void dragStart(DragSourceEvent event) {
- transfer.setSelection(provider.getSelection());
-
- event.doit = true;
- }
-
- /* (non-Javadoc)
- * @see DragSourceListener#dragSetData
- */
- public void dragSetData(DragSourceEvent event) {
- event.data = transfer.isSupportedType(event.dataType) ? transfer.getSelection() : null;
- }
-
- /* (non-Javadoc)
- * @see DragSourceListener#dragFinished
- */
- public void dragFinished(DragSourceEvent event) {
- transfer.setSelection(null);
- }
-
- /* (non-Javadoc)
- * @see TransferDragSourceListener#getTransfer
- */
- public Transfer getTransfer() {
- return transfer;
- }
-}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CLocalSelectionTransfer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CLocalSelectionTransfer.java
deleted file mode 100644
index 8c63a76d712..00000000000
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CLocalSelectionTransfer.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.eclipse.cdt.ui;
-
-import java.util.Arrays;
-
-import org.eclipse.jface.util.Assert;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.swt.dnd.ByteArrayTransfer;
-import org.eclipse.swt.dnd.TransferData;
-
-/**
- * @author kcampbell
- */
-public class CLocalSelectionTransfer extends ByteArrayTransfer {
- private static final CLocalSelectionTransfer INSTANCE = new CLocalSelectionTransfer();
-
- private final String typeName;
- private final int typeId;
- private ISelection selection;
-
- private CLocalSelectionTransfer() {
- super();
- // Try to ensure that different Eclipse applications use different "types" of CLocalSelectionTransfer
- typeName = "cdt-local-selection-transfer-format" + System.currentTimeMillis(); //$NON-NLS-1$;
- typeId = registerType(typeName);
- selection = null;
- }
-
- /**
- * Returns the singleton.
- */
- public static CLocalSelectionTransfer getInstance() {
- return INSTANCE;
- }
-
- /**
- * Sets the transfer data for local use.
- */
- public void setSelection(ISelection selection) {
- this.selection = selection;
- }
-
- /**
- * Returns the local transfer data.
- */
- public ISelection getSelection() {
- return selection;
- }
-
- public void javaToNative(Object object, TransferData transferData) {
- // No encoding needed since this is a hardcoded string read and written in the same process.
- // See nativeToJava below
- super.javaToNative(typeName.getBytes(), transferData);
- }
-
- public Object nativeToJava(TransferData transferData) {
- Object result = super.nativeToJava(transferData);
-
- // No decoding needed: see javaToNative above.
- Assert.isTrue(result instanceof byte[] && Arrays.equals(typeName.getBytes(), (byte[]) result));
-
- return selection;
- }
-
- /**
- * The type id used to identify this transfer.
- */
- protected int[] getTypeIds() {
- return new int[] { typeId };
- }
-
- protected String[] getTypeNames() {
- return new String[] { typeName };
- }
-}
\ No newline at end of file