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 + * currentDataType 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 DROP_NODE. + */ + 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 TransferDragSourceListeners + * 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 TransferDragSourceListeners - * 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