001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.views.navigator;
011:
012: import java.util.ArrayList;
013: import java.util.Iterator;
014: import java.util.List;
015:
016: import org.eclipse.core.resources.IFile;
017: import org.eclipse.core.resources.IFolder;
018: import org.eclipse.core.resources.IResource;
019: import org.eclipse.core.runtime.CoreException;
020: import org.eclipse.core.runtime.IPath;
021: import org.eclipse.jface.viewers.ISelection;
022: import org.eclipse.jface.viewers.ISelectionProvider;
023: import org.eclipse.jface.viewers.IStructuredSelection;
024: import org.eclipse.swt.dnd.DND;
025: import org.eclipse.swt.dnd.DragSource;
026: import org.eclipse.swt.dnd.DragSourceAdapter;
027: import org.eclipse.swt.dnd.DragSourceEvent;
028: import org.eclipse.swt.dnd.DragSourceListener;
029: import org.eclipse.swt.dnd.FileTransfer;
030: import org.eclipse.swt.dnd.TransferData;
031: import org.eclipse.swt.widgets.Control;
032: import org.eclipse.swt.widgets.Shell;
033: import org.eclipse.ui.actions.ReadOnlyStateChecker;
034: import org.eclipse.ui.internal.views.navigator.ResourceNavigatorMessages;
035: import org.eclipse.ui.part.ResourceTransfer;
036:
037: /**
038: * Implements drag behaviour when items are dragged out of the
039: * resource navigator.
040: *
041: * @since 2.0
042: */
043: public class NavigatorDragAdapter extends DragSourceAdapter {
044: private static final String CHECK_MOVE_TITLE = ResourceNavigatorMessages.DragAdapter_title;
045:
046: private static final String CHECK_DELETE_MESSAGE = ResourceNavigatorMessages.DragAdapter_checkDeleteMessage;
047:
048: ISelectionProvider selectionProvider;
049:
050: private TransferData lastDataType;
051:
052: /**
053: * Constructs a new drag adapter.
054: * @param provider The selection provider
055: */
056: public NavigatorDragAdapter(ISelectionProvider provider) {
057: selectionProvider = provider;
058: }
059:
060: /**
061: * This implementation of {@link DragSourceListener#dragFinished(DragSourceEvent)}
062: * responds to a drag that has moved resources outside the Navigator by deleting
063: * the corresponding source resource.
064: */
065: public void dragFinished(DragSourceEvent event) {
066: LocalSelectionTransfer.getInstance().setSelection(null);
067:
068: if (event.doit == false) {
069: return;
070: }
071:
072: final int typeMask = IResource.FOLDER | IResource.FILE;
073: if (event.detail == DND.DROP_MOVE) {
074: //never delete resources when dragging outside Eclipse.
075: //workaround for bug 30543.
076: if (lastDataType != null
077: && FileTransfer.getInstance().isSupportedType(
078: lastDataType)) {
079: return;
080: }
081:
082: IResource[] resources = getSelectedResources(typeMask);
083: DragSource dragSource = (DragSource) event.widget;
084: Control control = dragSource.getControl();
085: Shell shell = control.getShell();
086: ReadOnlyStateChecker checker;
087:
088: if (resources == null || resources.length == 0) {
089: return;
090: }
091:
092: checker = new ReadOnlyStateChecker(shell, CHECK_MOVE_TITLE,
093: CHECK_DELETE_MESSAGE);
094: resources = checker.checkReadOnlyResources(resources);
095: //delete the old elements
096: for (int i = 0; i < resources.length; i++) {
097: try {
098: resources[i].delete(IResource.KEEP_HISTORY
099: | IResource.FORCE, null);
100: } catch (CoreException e) {
101: e.printStackTrace();
102: }
103: }
104: } else if (event.detail == DND.DROP_TARGET_MOVE) {
105: IResource[] resources = getSelectedResources(typeMask);
106:
107: // file moved for us by OS, no need to delete the resources, just
108: // update the view
109: if (resources == null) {
110: return;
111: }
112: for (int i = 0; i < resources.length; i++) {
113: try {
114: resources[i].refreshLocal(IResource.DEPTH_INFINITE,
115: null);
116: } catch (CoreException e) {
117: e.printStackTrace();
118: }
119: }
120: }
121: }
122:
123: /**
124: * This implementation of {@link DragSourceListener#dragSetData(DragSourceEvent)}
125: * sets the drag event data based on the current selection in the Navigator.
126: */
127: public void dragSetData(DragSourceEvent event) {
128: final int typeMask = IResource.FILE | IResource.FOLDER;
129: IResource[] resources = getSelectedResources(typeMask);
130:
131: if (resources == null || resources.length == 0) {
132: return;
133: }
134:
135: lastDataType = event.dataType;
136: //use local selection transfer if possible
137: if (LocalSelectionTransfer.getInstance().isSupportedType(
138: event.dataType)) {
139: event.data = LocalSelectionTransfer.getInstance()
140: .getSelection();
141: return;
142: }
143: //use resource transfer if possible
144: if (ResourceTransfer.getInstance().isSupportedType(
145: event.dataType)) {
146: event.data = resources;
147: return;
148: }
149: //resort to a file transfer
150: if (!FileTransfer.getInstance().isSupportedType(event.dataType)) {
151: return;
152: }
153:
154: // Get the path of each file and set as the drag data
155: final int length = resources.length;
156: int actualLength = 0;
157: String[] fileNames = new String[length];
158: for (int i = 0; i < length; i++) {
159: IPath location = resources[i].getLocation();
160: // location may be null. See bug 29491.
161: if (location != null) {
162: fileNames[actualLength++] = location.toOSString();
163: }
164: }
165: if (actualLength == 0) {
166: return;
167: }
168: // was one or more of the locations null?
169: if (actualLength < length) {
170: String[] tempFileNames = fileNames;
171: fileNames = new String[actualLength];
172: for (int i = 0; i < actualLength; i++) {
173: fileNames[i] = tempFileNames[i];
174: }
175: }
176: event.data = fileNames;
177: }
178:
179: /**
180: * This implementation of {@link DragSourceListener#dragStart(DragSourceEvent)}
181: * allows the drag to start if the current Navigator selection contains resources
182: * that can be dragged.
183: */
184: public void dragStart(DragSourceEvent event) {
185: lastDataType = null;
186: // Workaround for 1GEUS9V
187: DragSource dragSource = (DragSource) event.widget;
188: Control control = dragSource.getControl();
189: if (control != control.getDisplay().getFocusControl()) {
190: event.doit = false;
191: return;
192: }
193:
194: IStructuredSelection selection = (IStructuredSelection) selectionProvider
195: .getSelection();
196: for (Iterator i = selection.iterator(); i.hasNext();) {
197: Object next = i.next();
198: if (!(next instanceof IFile || next instanceof IFolder)) {
199: event.doit = false;
200: return;
201: }
202: }
203: if (selection.isEmpty()) {
204: event.doit = false;
205: return;
206: }
207: LocalSelectionTransfer.getInstance().setSelection(selection);
208: event.doit = true;
209: }
210:
211: private IResource[] getSelectedResources(int resourceTypes) {
212: List resources = new ArrayList();
213: IResource[] result = new IResource[0];
214:
215: ISelection selection = selectionProvider.getSelection();
216: if (!(selection instanceof IStructuredSelection)
217: || selection.isEmpty()) {
218: return null;
219: }
220: IStructuredSelection structuredSelection = (IStructuredSelection) selection;
221:
222: // loop through list and look for matching items
223: Iterator itr = structuredSelection.iterator();
224: while (itr.hasNext()) {
225: Object obj = itr.next();
226: if (obj instanceof IResource) {
227: IResource res = (IResource) obj;
228: if ((res.getType() & resourceTypes) == res.getType()) {
229: resources.add(res);
230: }
231: }
232: }
233: result = new IResource[resources.size()];
234: resources.toArray(result);
235: return result;
236: }
237: }
|