Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-patch] CDT/UI Fix CView Drag&Drop

Index: ChangeLog
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui/ChangeLog,v
retrieving revision 1.152
diff -u -r1.152 ChangeLog
--- ChangeLog	31 Aug 2003 04:46:02 -0000	1.152
+++ ChangeLog	1 Sep 2003 21:46:47 -0000
@@ -1,3 +1,15 @@
+2003-09-01 Alain Magloire
+
+	The Drag&Drop code is revisited with a facelift.
+	The good news much of the code can be removed, the Eclise
+	platform/Worbench folks refactor there code so more can now
+	be shared.  We take adavantage of this.
+	The bad news much of the code will have to be revisited
+	and rewrite again when we will start dealing with refactoring.
+
+	* src/org/eclipse/cdt/internal/ui/cview/CViewDropAdapter.java
+	* src/org/eclipse/cdt/internal/ui/cview/CViewDragAdapter.java
+
 2003-08-31 Alain Magloire
 
 	Added new block ErrorParserBlock, not enable yet.
Index: src/org/eclipse/cdt/internal/ui/cview/CViewDragAdapter.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewDragAdapter.java,v
retrieving revision 1.5
diff -u -r1.5 CViewDragAdapter.java
--- src/org/eclipse/cdt/internal/ui/cview/CViewDragAdapter.java	20 Aug 2003 17:34:33 -0000	1.5
+++ src/org/eclipse/cdt/internal/ui/cview/CViewDragAdapter.java	1 Sep 2003 21:46:50 -0000
@@ -9,9 +9,12 @@
 import java.util.Iterator;
 import java.util.List;
 
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.viewers.ISelectionProvider;
 import org.eclipse.jface.viewers.IStructuredSelection;
@@ -20,7 +23,10 @@
 import org.eclipse.swt.dnd.DragSourceAdapter;
 import org.eclipse.swt.dnd.DragSourceEvent;
 import org.eclipse.swt.dnd.FileTransfer;
+import org.eclipse.swt.dnd.TransferData;
 import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.actions.ReadOnlyStateChecker;
 import org.eclipse.ui.part.ResourceTransfer;
 import org.eclipse.ui.views.navigator.LocalSelectionTransfer;
 
@@ -30,22 +36,59 @@
  */
 class CViewDragAdapter extends DragSourceAdapter {
 	private final ISelectionProvider selectionProvider;
+	private static final int typeMask = IResource.FOLDER | IResource.FILE;
+	private TransferData lastDataType; 	
+	private static final String CHECK_MOVE_TITLE = "Drag and Drop Problem"; //$NON-NLS-1$
+	private static final String CHECK_DELETE_MESSAGE = "{0} is read only. Do you still wish to delete it?"; //$NON-NLS-1$
+
 
 	/**
 	 * 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.
-	 * @see IAction#run
+	 * @see DragSourceListener#dragFinished(org.eclipse.swt.dnd.DragSourceEvent)
 	 */
 	public void dragFinished(DragSourceEvent event) {
-		if (event.doit && event.detail == DND.DROP_MOVE) {
-			// delete the old elements
+		LocalSelectionTransfer.getInstance().setSelection(null);
 
+		if (event.doit == false)
+			return;
+
+		if (event.detail == DND.DROP_MOVE) {
+			//never delete resources when dragging outside Eclipse. 
+			//workaround for bug 30543.
+			if (lastDataType != null && FileTransfer.getInstance().isSupportedType(lastDataType))
+				return;
+			
+			IResource[] resources = getSelectedResources();	
+			DragSource dragSource = (DragSource) event.widget;
+			Control control = dragSource.getControl();
+			Shell shell = control.getShell();
+			ReadOnlyStateChecker checker;
+			
+			if (resources == null || resources.length == 0)
+				return;
+			
+			checker = new ReadOnlyStateChecker(shell, CHECK_MOVE_TITLE, CHECK_DELETE_MESSAGE);
+			resources = checker.checkReadOnlyResources(resources);		
+			//delete the old elements
+			for (int i = 0; i < resources.length; i++) {
+				try {
+					resources[i].delete(IResource.KEEP_HISTORY | IResource.FORCE, null);
+				} catch (CoreException e) {
+					e.printStackTrace();
+				}
+			}
+		} else if (event.detail == DND.DROP_TARGET_MOVE) {
 			IResource[] resources = getSelectedResources();
 
-			for (int i = 0; i < resources.length; ++i) {
+			// file moved for us by OS, no need to delete the resources, just
+			// update the view
+			if (resources == null)
+				return;
+			for (int i = 0; i < resources.length; i++) {
 				try {
-					resources[i].delete(true, null);
+					resources[i].refreshLocal(IResource.DEPTH_INFINITE, null);
 				} catch (CoreException e) {
 					e.printStackTrace();
 				}
@@ -53,63 +96,110 @@
 		}
 	}
 
-	/**
-	 * Returns the data to be transferred in a drag and drop
-	 * operation.
+	/*
+	 * @see DragSourceListener#dragSetData(org.eclipse.swt.dnd.DragSourceEvent)
 	 */
 	public void dragSetData(DragSourceEvent event) {
-		if (ResourceTransfer.getInstance().isSupportedType(event.dataType)) {
-			event.data = getSelectedResources();
-		} else if (FileTransfer.getInstance().isSupportedType(event.dataType)) {
-			// get the path of each file and set as the drag data
-			IResource[] resources = getSelectedResources();
-			int length = resources.length;
-			String[] fileNames = new String[length];
-
-			for (int i = 0; i < length; ++i)
-				fileNames[i] = resources[i].getLocation().toOSString();
-
-			event.data = fileNames;
-		} else if (LocalSelectionTransfer.getInstance().isSupportedType(event.dataType)) {
+		IResource[] resources = getSelectedResources();
+		
+		if (resources == null || resources.length == 0)
+			return;
+
+		lastDataType = event.dataType;
+		//use local selection transfer if possible
+		if (LocalSelectionTransfer.getInstance().isSupportedType(event.dataType)) {
 			event.data = LocalSelectionTransfer.getInstance().getSelection();
+			return;
 		}
+		//use resource transfer if possible
+		if (ResourceTransfer.getInstance().isSupportedType(event.dataType)) {
+			event.data = resources;
+			return;
+		}
+		//resort to a file transfer
+		if (!FileTransfer.getInstance().isSupportedType(event.dataType))
+			return;
+
+		// Get the path of each file and set as the drag data
+		final int length = resources.length;
+		int actualLength = 0; 
+		String[] fileNames = new String[length];
+		for (int i = 0; i < length; i++) {
+			IPath location = resources[i].getLocation();
+			// location may be null. See bug 29491.
+			if (location != null) 
+				fileNames[actualLength++] = location.toOSString();
+		}
+		if (actualLength == 0)
+			return;
+		// was one or more of the locations null?
+		if (actualLength < length) {
+			String[] tempFileNames = fileNames;
+			fileNames = new String[actualLength];
+			for (int i = 0; i < actualLength; i++)
+				fileNames[i] = tempFileNames[i];
+		}
+		event.data = fileNames;
 	}
 
-	/**
-	 * All selection must be files or folders.
+	/*
+	 * @see DragSourceListener#dragStart(org.eclipse.swt.dnd.DragSourceEvent)
 	 */
 	public void dragStart(DragSourceEvent event) {
+		lastDataType = null;
 		// Workaround for 1GEUS9V
 		DragSource dragSource = (DragSource) event.widget;
 		Control control = dragSource.getControl();
+		if (control != control.getDisplay().getFocusControl()) {
+			event.doit = false;
+			return;
+		}
 
-		if (control != control.getDisplay().getFocusControl())
+		IStructuredSelection selection =
+			(IStructuredSelection) selectionProvider.getSelection();
+		for (Iterator i = selection.iterator(); i.hasNext();) {
+			Object next = i.next();
+			if (next instanceof IAdaptable) {
+				next = ((IAdaptable) next).getAdapter(IResource.class);
+			}
+			if (!(next instanceof IFile || next instanceof IFolder)) {
+				event.doit = false;
+				return;
+			}
+		}
+		if (selection.isEmpty()) {
 			event.doit = false;
-		else
-			LocalSelectionTransfer.getInstance().setSelection(selectionProvider.getSelection());
+			return;
+		}
+		LocalSelectionTransfer.getInstance().setSelection(selection);
+		event.doit = true;
 	}
+	
 
-	private static final int typeMask = IResource.FOLDER | IResource.FILE;
 
 	private IResource[] getSelectedResources() {
 		ISelection selection = selectionProvider.getSelection();
 		List resources = new ArrayList();
 
-		if (selection instanceof IStructuredSelection) {
-			IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+		// Sanity checks
+		if (selection == null || !(selection instanceof IStructuredSelection) || selection.isEmpty()) {
+			return null;
+		}
 
-			// loop through list and look for matching items
-			for (Iterator enum = structuredSelection.iterator(); enum.hasNext();) {
-				Object object = enum.next();
-				IResource resource = null;
-
-				if (object instanceof IResource)
-					resource = (IResource) object;
-				else if (object instanceof IAdaptable)
-					resource = (IResource) ((IAdaptable) object).getAdapter(IResource.class);
+		IStructuredSelection structuredSelection = (IStructuredSelection) selection;
 
-				if (resource != null && (resource.getType() & typeMask) != 0)
-					resources.add(resource);
+		// loop through list and look for matching items
+		for (Iterator enum = structuredSelection.iterator(); enum.hasNext();) {
+			Object object = enum.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);
 			}
 		}
 
Index: src/org/eclipse/cdt/internal/ui/cview/CViewDropAdapter.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewDropAdapter.java,v
retrieving revision 1.4
diff -u -r1.4 CViewDropAdapter.java
--- src/org/eclipse/cdt/internal/ui/cview/CViewDropAdapter.java	28 May 2003 18:10:13 -0000	1.4
+++ src/org/eclipse/cdt/internal/ui/cview/CViewDropAdapter.java	1 Sep 2003 21:46:51 -0000
@@ -5,43 +5,37 @@
  * All Rights Reserved.
  */
  
-import java.io.File;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
-import org.eclipse.cdt.core.model.ICElement;
 import org.eclipse.cdt.ui.CUIPlugin;
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IResourceStatus;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
+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.dialogs.ProgressMonitorDialog;
-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.jface.viewers.TreeViewer;
 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.swt.widgets.TreeItem;
 import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.actions.CopyResourceAction;
+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.wizards.datatransfer.FileSystemStructureProvider;
-import org.eclipse.ui.wizards.datatransfer.ImportOperation;
+import org.eclipse.ui.views.navigator.LocalSelectionTransfer;
 ;
 
 /**
@@ -49,14 +43,6 @@
  * that land on the resource navigator.
  */
 class CViewDropAdapter extends PluginDropAdapter implements IOverwriteQuery {
-	/**
-	 * The time the mouse first started hovering over the current target
-	 */
-	protected long hoverStart = 0;
-	/**
-	 * The amount of time to hover over a tree item before expanding it
-	 */
-	protected static final long hoverThreshold = 1500;
 
 	/**
 	 * A flag indicating that the drop has been cancelled by the user.
@@ -68,132 +54,20 @@
 	protected boolean alwaysOverwrite = false;
 
 	/**
-	 * Copies or moves the <code>source</code> file to the given <code>
-	 * destination</code>.  If overwrite is true, any resource that
-	 * already exists at the destination will be deleted before the
-	 * copy/move occurs.
-	 */
-	protected IStatus doCopy(final IResource source, final IPath destination, final boolean overwrite) {
-		final boolean copy = getCurrentOperation() == DND.DROP_COPY;
-		final IStatus[] result = new IStatus[] { ok()};
-		try {
-			new ProgressMonitorDialog(getShell()).run(true, true, new IRunnableWithProgress() {
-				public void run(IProgressMonitor monitor) {
-					try {
-						if (overwrite) {
-							//delete the destination
-							IResource oldResource = source.getWorkspace().getRoot().findMember(destination);
-							if (oldResource.exists()) {
-								oldResource.delete(true, null);
-							}
-						}
-						if (copy) {
-							IPath newName = destination;
-							if (source.getWorkspace().getRoot().exists(destination))
-								newName = CopyResourceAction.getNewNameFor(destination, source.getWorkspace());
-							if (newName != null) {
-								source.copy(newName, false, monitor);
-							}
-						} else {
-							source.move(destination, false, monitor);
-						}
-					} catch (CoreException e) {
-						result[0] = e.getStatus();
-					}
-				}
-			});
-		} catch (InvocationTargetException e) {
-			//implementation doesn't throw this
-		} catch (InterruptedException e) {
-		}
-		return result[0];
-	}
-
-	/**
-	 * Copies the source into the target container.  Returns a status object
-	 * indicating success or failure.
+	 * The last valid operation.
 	 */
-	protected IStatus dragAndDropCopy(IContainer target, IResource source) {
-		if (isCanceled) {
-			return ok();
-		}
-		if (getCurrentOperation() != DND.DROP_COPY && (source.equals(target) || source.getParent().equals(target))) {
-			return info("Same Source And Destination"); //$NON-NLS-1$
-		}
-		if (source.getFullPath().isPrefixOf(target.getFullPath())) {
-			return error(source, "destination A SubFolder"); //$NON-NLS-1$
-		}
-		IPath destination = target.getFullPath().append(source.getName());
-
-		IStatus result = doCopy(source, destination, false);
-		if (result.getCode() == IResourceStatus.PATH_OCCUPIED) {
-			if (alwaysOverwrite) {
-				return doCopy(source, destination, true);
-			}
-			String query = queryOverwrite(destination.toString());
-			if (query == YES) {
-			   return doCopy(source, destination, true);
-			}
-			if (query == CANCEL) {
-				isCanceled = true;
-				return ok();
-			}
-			if (query == ALL) {
-				alwaysOverwrite = true;
-				return doCopy(source, destination, true);
-			}
-			if (query == NO) {
-				return ok();
-			}
-		}
-		return result;
-	}
+	private int lastValidOperation = DND.DROP_NONE;
 
-	/**
-	 * Performs an import of the given file into the provided
-	 * container.  Returns a status indicating if the import was successful.
+	/*
+	 * @see org.eclipse.swt.dnd.DropTargetListener#dragEnter(org.eclipse.swt.dnd.DropTargetEvent)
 	 */
-	protected IStatus dragAndDropImport(IContainer target, String filePath) {
-		File toImport = new File(filePath);
-		if (target.getLocation().equals(toImport)) {
-			return info(("DropAdapter.canNotDropOntoSelf")); //$NON-NLS-1$
-		}
-		ImportOperation op = 
-			new ImportOperation(target.getFullPath(), new File(toImport.getParent()), FileSystemStructureProvider.INSTANCE, this, Arrays.asList(new File[] {toImport})); 
-		op.setCreateContainerStructure(false);
-		try {
-			new ProgressMonitorDialog(getShell()).run(true, true, op);
-		} catch (InterruptedException e) {
-			return info("Cancelled"); //$NON-NLS-1$
-		} catch (InvocationTargetException e) {
-			return error("Drop Operation Error", e.getTargetException());  //$NON-NLS-1$
-		}
-		return op.getStatus();
-	}
-
-	/**
-	 * The mouse has moved over the drop target.  If the
-	 * target item has changed, notify the action and check
-	 * that it is still enabled.
-	 */
-	public void dragOver(DropTargetEvent event) {
-		try {
-			//this method implements the UI behaviour that when the user hovers 
-			//over an unexpanded tree item long enough, it will auto-expand.
-			Object oldTarget = getCurrentTarget();
-			super.dragOver(event);
-			if (oldTarget != getCurrentTarget()) {
-				hoverStart = System.currentTimeMillis();
-			} else {
-				//if we've been hovering over this item awhile, expand it.
-				if (hoverStart > 0 && (System.currentTimeMillis() - hoverStart) > hoverThreshold) {
-					expandSelection((TreeItem) event.item);
-					hoverStart = 0;
-				}
-			}
-		} catch (Throwable t) {
-			handleException(t, event);
-		}
+	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);
 	}
 
 	/**
@@ -223,18 +97,6 @@
 	}
 
 	/**
-	 * Expands the selection of the given tree viewer.
-	 */
-	protected void expandSelection(TreeItem selection) {
-		if (selection == null)
-			return;
-		if (!selection.getExpanded()) {
-			TreeViewer treeViewer = (TreeViewer) getViewer();
-			treeViewer.expandToLevel(selection.getData(), 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
@@ -317,6 +179,9 @@
 	 * 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;
 	
@@ -337,69 +202,149 @@
 	}
 
 	/**
+	 * 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 enum = structuredSelection.iterator(); enum.hasNext();) {
+			Object object = enum.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;
+	}
+
+	/**
 	 * 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.
 	 * @see IAction#run
 	 */
-	public boolean performDrop(Object data) {
+	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 (ResourceTransfer.getInstance().isSupportedType(currentTransfer)) {
-			return performResourceDrop(data);
+		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 (FileTransfer.getInstance().isSupportedType(currentTransfer)) {
-			return performFileDrop(data);
+		if (resources != null) {
+			if (getCurrentOperation() == DND.DROP_COPY) {
+				status = performResourceCopy(getShell(), resources);
+			} else {
+				status = performResourceMove(resources);
+			}
 		}
-		return super.performDrop(data);
+		openError(status);
+		return result;
 	}
 
 	/**
 	 * Performs a drop using the FileTransfer transfer type.
 	 */
-	protected boolean performFileDrop(Object data) {
-		MultiStatus problems = new MultiStatus(PlatformUI.PLUGIN_ID, 0, "Problem Importing", null); //$NON-NLS-1$
-		mergeStatus(problems, validateTarget(getCurrentTarget()));
+	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 ICElement) {
-			res = ((ICElement)obj).getUnderlyingResource();
-		}
-		IContainer targetResource = getActualTarget(res);
-		String[] names = (String[]) data;
-		for (int i = 0; i < names.length; i++) {
-			mergeStatus(problems, dragAndDropImport(targetResource, names[i]));
+		if (obj instanceof IAdaptable) {
+			res = (IResource)((IAdaptable) obj).getAdapter(IResource.class);
 		}
-		openError(problems);
-		return problems.isOK();
+		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 drop using the ResourceTransfer transfer type.
+	 * Performs a resource copy
 	 */
-	protected boolean performResourceDrop(Object data) {
+	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()));
+		mergeStatus(problems, validateTarget(getCurrentTarget(), getCurrentTransfer()));
 
 		Object obj = getCurrentTarget();
 		IResource res = null;
-		if (obj instanceof ICElement) {
-			res = ((ICElement)obj).getUnderlyingResource();
-		}
-		IContainer targetResource = getActualTarget(res);
-		IResource[] sources = (IResource[]) data;
-		for (int i = 0; i < sources.length; i++) {
-			mergeStatus(problems, dragAndDropCopy(targetResource, sources[i]));
+		if (obj instanceof IAdaptable) {
+			res = (IResource)((IAdaptable) obj).getAdapter(IResource.class);
 		}
-		openError(problems);
+		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()));
 
-		//always return false because we don't want the source to clean up
-		return false;
+		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)
@@ -425,34 +370,77 @@
 	 * This method is used to notify the action that some aspect of
 	 * the drop operation has changed.
 	 */
-	public boolean validateDrop(Object target, int operation, TransferData transferType) {
-		if (super.validateDrop(target, operation, transferType)) {
+	public boolean validateDrop(Object target, int dragOperation, TransferData transferType) {
+		if (dragOperation != DND.DROP_NONE) {
+			lastValidOperation = dragOperation;
+		}
+		if (FileTransfer.getInstance().isSupportedType(transferType) &&
+			lastValidOperation != DND.DROP_COPY) {
+			// only allow copying when dragging from outside Eclipse
+			return false;
+		}
+
+		if (super.validateDrop(target, dragOperation, transferType)) {
 			return true;
 		}
-		return validateTarget(target).isOK();
+		return validateTarget(target, transferType).isOK();
 	}
 
 	/**
 	 * Ensures that the drop target meets certain criteria
 	 */
-	protected IStatus validateTarget(Object target) {
-		if (target instanceof ICElement) {
-			IResource r = ((ICElement)target).getUnderlyingResource();
+	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;
+		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-2$
+			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();
 	}
+
+
 }



Back to the top