diff --git a/core/org.eclipse.cdt.ui/ChangeLog b/core/org.eclipse.cdt.ui/ChangeLog index f1964ccc733..e1aef8c875e 100644 --- a/core/org.eclipse.cdt.ui/ChangeLog +++ b/core/org.eclipse.cdt.ui/ChangeLog @@ -1,3 +1,25 @@ +2003-09-21 Alain Magloire + + Patch contributed by Keith Campbell. + + Patch to enable dragging non-resource selections from + the C/C++ Projects view. + + The code has been reorganized to use the delegation pattern found in the + JDT and a new LocalSelectionTransfer specific to the CDT has been + introduced to avoid potential incompatibilities of using + org.eclipse.ui.views.navigator.LocalSelectionTransfer. + + * src/org/eclipse/cdt/internal/ui/drag/DelegatingDraAdapter.java + * src/org/eclipse/cdt/internal/ui/drag/FileTransferDragAdapter.java + * src/org/eclipse/cdt/internal/ui/drag/LocalSelectionTransferDragAdapter.java + * src/org/eclipse/cdt/internal/ui/drag/ResourceTransferDragAdapter.java + * src/org/eclipse/cdt/internal/ui/drag/TransferDragSourceListener.java + + * src/org/eclipse/cdt/internal/ui/cview/CView.java + + * src/org/eclipse/cdt/ui/LocalSelectionTransfer.java + 2003-09-21 Alain Magloire Bug #41960, The asm editor did not know about '#' comment style diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CUIMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CUIMessages.properties index 814d9ececdf..e7ae383959b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CUIMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CUIMessages.properties @@ -9,4 +9,6 @@ # Rational Software - Initial API and implementation ############################################################################### -ExceptionDialog.seeErrorLogMessage= See error log for more details. \ No newline at end of file +Drag.move.problem.title=Drag and Drop Problem +Drag.move.problem.message={0} is read only. Do you still wish to delete it? +ExceptionDialog.seeErrorLogMessage=See error log for more details. 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 37a16eba39a..0d668bf2298 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 @@ -24,6 +24,10 @@ import org.eclipse.cdt.internal.core.model.CProject; import org.eclipse.cdt.internal.core.model.TranslationUnit; import org.eclipse.cdt.internal.ui.IContextMenuConstants; import org.eclipse.cdt.internal.ui.StandardCElementLabelProvider; +import org.eclipse.cdt.internal.ui.drag.DelegatingDragAdapter; +import org.eclipse.cdt.internal.ui.drag.FileTransferDragAdapter; +import org.eclipse.cdt.internal.ui.drag.ResourceTransferDragAdapter; +import org.eclipse.cdt.internal.ui.drag.TransferDragSourceListener; import org.eclipse.cdt.internal.ui.editor.FileSearchAction; import org.eclipse.cdt.internal.ui.editor.FileSearchActionInWorkingSet; import org.eclipse.cdt.internal.ui.editor.OpenIncludeAction; @@ -33,6 +37,7 @@ import org.eclipse.cdt.internal.ui.util.EditorUtility; import org.eclipse.cdt.internal.ui.util.ProblemTreeViewer; import org.eclipse.cdt.ui.CElementContentProvider; import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.LocalSelectionTransfer; import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.core.resources.ICommand; import org.eclipse.core.resources.IContainer; @@ -123,7 +128,6 @@ import org.eclipse.ui.views.framelist.ForwardAction; import org.eclipse.ui.views.framelist.FrameList; import org.eclipse.ui.views.framelist.GoIntoAction; import org.eclipse.ui.views.framelist.UpAction; -import org.eclipse.ui.views.navigator.LocalSelectionTransfer; @@ -365,14 +369,31 @@ public class CView extends ViewPart implements IMenuListener, ISetSelectionTarge */ void initDragAndDrop() { int ops = DND.DROP_COPY | DND.DROP_MOVE; - Transfer[] transfers = new Transfer[] { - ResourceTransfer.getInstance(), - FileTransfer.getInstance(), - LocalSelectionTransfer.getInstance(), - PluginTransfer.getInstance() }; - viewer.addDragSupport(ops, transfers, new CViewDragAdapter((ISelectionProvider)viewer)); - viewer.addDropSupport(ops, transfers, new CViewDropAdapter(viewer)); + Transfer[] dragTransfers = + new Transfer[] { + ResourceTransfer.getInstance(), + FileTransfer.getInstance(), + LocalSelectionTransfer.getInstance(), + PluginTransfer.getInstance()}; + + TransferDragSourceListener[] dragListeners = + new TransferDragSourceListener[] { + new ResourceTransferDragAdapter(viewer), + new org.eclipse.cdt.internal.ui.drag.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)); + } /** diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewDragAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewDragAdapter.java deleted file mode 100644 index 485fc9a36ef..00000000000 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewDragAdapter.java +++ /dev/null @@ -1,219 +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.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; -import org.eclipse.swt.dnd.DND; -import org.eclipse.swt.dnd.DragSource; -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; - -/** - * Implements drag behaviour when items are dragged out of the - * resource navigator. - */ -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 DragSourceListener#dragFinished(org.eclipse.swt.dnd.DragSourceEvent) - */ - public void dragFinished(DragSourceEvent event) { - 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(); - - // 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].refreshLocal(IResource.DEPTH_INFINITE, null); - } catch (CoreException e) { - e.printStackTrace(); - } - } - } - } - - /* - * @see DragSourceListener#dragSetData(org.eclipse.swt.dnd.DragSourceEvent) - */ - public void dragSetData(DragSourceEvent event) { - 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; - } - - /* - * @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; - } - - 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; - return; - } - LocalSelectionTransfer.getInstance().setSelection(selection); - event.doit = true; - } - - - - private IResource[] getSelectedResources() { - ISelection selection = selectionProvider.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; - } - - /** - * CViewDragAction constructor. - */ - public CViewDragAdapter(ISelectionProvider provider) { - super(); - selectionProvider = provider; - } -} 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 new file mode 100644 index 00000000000..42fd8686d85 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/DelegatingDragAdapter.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * 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/FileTransferDragAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/FileTransferDragAdapter.java new file mode 100644 index 00000000000..83c559bcc65 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/FileTransferDragAdapter.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * 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.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.eclipse.cdt.internal.ui.CUIMessages; +import org.eclipse.cdt.internal.ui.util.ExceptionHandler; +import org.eclipse.cdt.ui.CUIPlugin; +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.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.util.Assert; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DragSourceEvent; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.actions.WorkspaceModifyOperation; + +public class FileTransferDragAdapter implements TransferDragSourceListener { + private final ISelectionProvider provider; + + public FileTransferDragAdapter(ISelectionProvider provider) { + super(); + this.provider = provider; + Assert.isNotNull(provider); + } + + public Transfer getTransfer() { + return FileTransfer.getInstance(); + } + + public void dragStart(DragSourceEvent event) { + event.doit = !getResources().isEmpty(); + } + + public void dragSetData(DragSourceEvent event) { + String[] locations = getResourceLocations(getResources()); + + event.data = locations.length != 0 ? locations : null; + } + + public void dragFinished(DragSourceEvent event) { + if (event.doit) { + if (event.detail == DND.DROP_MOVE) { + // Never delete resources when dragging outside Eclipse. + // See: http://bugs.eclipse.org/bugs/show_bug.cgi?id=30543 + } else if (event.detail == DND.DROP_NONE || event.detail == DND.DROP_TARGET_MOVE) { + runOperation(new RefreshOperation(getResources()), true, false); + } + } + } + + private static class RefreshOperation extends WorkspaceModifyOperation { + private final Set roots; + + public RefreshOperation(List resources) { + super(); + + roots = new HashSet(resources.size()); + + for (Iterator iterator = resources.iterator(); iterator.hasNext();) { + IResource resource = (IResource) iterator.next(); + IResource parent = resource.getParent(); + + roots.add(parent != null ? parent : resource); + } + } + + public void execute(IProgressMonitor monitor) throws CoreException { + try { + monitor.beginTask(CUIMessages.getString("DragAdapter.refreshing"), roots.size()); //$NON-NLS-1$ + MultiStatus status = new MultiStatus(CUIPlugin.getPluginId(), IStatus.OK, CUIMessages.getString("DragAdapter.problem"), null); //$NON-NLS-1$ + + for (Iterator iterator = roots.iterator(); iterator.hasNext();) { + IResource resource = (IResource) iterator.next(); + + try { + resource.refreshLocal( + IResource.DEPTH_ONE, + new SubProgressMonitor(monitor, 1)); + } catch (CoreException e) { + status.add(e.getStatus()); + } + } + + if (!status.isOK()) + throw new CoreException(status); + } finally { + monitor.done(); + } + } + } + + private List getResources() { + List result = Collections.EMPTY_LIST; + ISelection selection = provider.getSelection(); + + if (selection instanceof IStructuredSelection) { + IStructuredSelection structured = (IStructuredSelection) selection; + + result = new ArrayList(structured.size()); + + for (Iterator iterator = structured.iterator(); iterator.hasNext();) { + Object object = iterator.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) + result.add(resource); + } + } + + return result; + } + + 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()); + } + + String[] result = new String[locations.size()]; + + locations.toArray(result); + + return result; + } + + private static void runOperation( + IRunnableWithProgress operation, + boolean fork, + boolean cancelable) { + try { + IWorkbench workbench = CUIPlugin.getDefault().getWorkbench(); + IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); + Shell parent = window.getShell(); + + new ProgressMonitorDialog(parent).run(fork, cancelable, operation); + } catch (InterruptedException e) { + // Do nothing. Operation has been canceled by user. + } catch (InvocationTargetException e) { + String message = CUIMessages.getString("Problem while moving or copying files."); //$NON-NLS-1$ + String title = CUIMessages.getString("Drag & Drop"); //$NON-NLS-1$ + + ExceptionHandler.handle(e, title, message); + } + } +} 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 new file mode 100644 index 00000000000..72ddce731ae --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/LocalSelectionTransferDragAdapter.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * 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.LocalSelectionTransfer; +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 LocalSelectionTransfer transfer; + + public LocalSelectionTransferDragAdapter(ISelectionProvider provider) { + super(); + this.provider = provider; + this.transfer = LocalSelectionTransfer.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/internal/ui/drag/ResourceTransferDragAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/ResourceTransferDragAdapter.java new file mode 100644 index 00000000000..a1a95d710f6 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/ResourceTransferDragAdapter.java @@ -0,0 +1,147 @@ +/******************************************************************************* + * 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.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.cdt.internal.ui.CUIMessages; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.jface.util.Assert; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DragSource; +import org.eclipse.swt.dnd.DragSourceEvent; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.actions.ReadOnlyStateChecker; +import org.eclipse.ui.part.ResourceTransfer; + +/** + * A drag adapter that transfers the current selection as + * IResource. Only those elements in the selection are part + * of the transfer which can be converted into an IResource + * . + */ +public class ResourceTransferDragAdapter implements TransferDragSourceListener { + private final ISelectionProvider provider; + + /** + * Creates a new ResourceTransferDragAdapter for the given selection provider. + * + * @param provider the selection provider to access the viewer's selection + */ + public ResourceTransferDragAdapter(ISelectionProvider provider) { + super(); + this.provider = provider; + Assert.isNotNull(provider); + } + + public Transfer getTransfer() { + return ResourceTransfer.getInstance(); + } + + 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; + } + } + } + } + + public void dragSetData(DragSourceEvent event) { + event.data = getSelectedResources(); + } + + public void dragFinished(DragSourceEvent event) { + if (event.doit && event.detail == DND.DROP_MOVE) { + IResource[] resources = getSelectedResources(); + + if (resources.length == 0) + return; + + DragSource dragSource = (DragSource) event.widget; + Control control = dragSource.getControl(); + Shell shell = control.getShell(); + String title = CUIMessages.getString("Drag.move.problem.title"); //$NON-NLS-1$ + String message = CUIMessages.getString("Drag.move.problem.message"); //$NON-NLS-1$ + + ReadOnlyStateChecker checker = new ReadOnlyStateChecker(shell, title, 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(); + } + } + } + } + + private IResource[] getSelectedResources() { + List resources = Collections.EMPTY_LIST; + ISelection selection = provider.getSelection(); + + if (selection instanceof IStructuredSelection) { + IStructuredSelection structured = (IStructuredSelection) selection; + + resources = new ArrayList(structured.size()); + + 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) + resources.add(resource); + } + } + } + + IResource[] result = new IResource[resources.size()]; + resources.toArray(result); + + return result; + } + +} 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/drag/TransferDragSourceListener.java new file mode 100644 index 00000000000..0c21d10c152 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/drag/TransferDragSourceListener.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * 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.swt.dnd.DragSourceListener; +import org.eclipse.swt.dnd.Transfer; + +/** + * A special drag source listener which is typed with a TransferData. + */ +public interface TransferDragSourceListener extends DragSourceListener { + /** + * Returns the transfer used by this drag source. + */ + public Transfer getTransfer(); +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/LocalSelectionTransfer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/LocalSelectionTransfer.java new file mode 100644 index 00000000000..c69ac1b6c8b --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/LocalSelectionTransfer.java @@ -0,0 +1,74 @@ +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 LocalSelectionTransfer extends ByteArrayTransfer { + private static final LocalSelectionTransfer INSTANCE = new LocalSelectionTransfer(); + + private final String typeName; + private final int typeId; + private ISelection selection; + + private LocalSelectionTransfer() { + super(); + // Try to ensure that different Eclipse applications use different "types" of LocalSelectionTransfer + typeName = "cdt-local-selection-transfer-format" + System.currentTimeMillis(); //$NON-NLS-1$; + typeId = registerType(typeName); + selection = null; + } + + /** + * Returns the singleton. + */ + public static LocalSelectionTransfer 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