1 /*******************************************************************************
2  * Copyright (c) 2000, 2017 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.ui.views.navigator;
15 
16 import java.util.ArrayList;
17 import java.util.List;
18 
19 import org.eclipse.core.resources.IFile;
20 import org.eclipse.core.resources.IFolder;
21 import org.eclipse.core.resources.IResource;
22 import org.eclipse.core.runtime.CoreException;
23 import org.eclipse.core.runtime.IPath;
24 import org.eclipse.jface.viewers.ISelection;
25 import org.eclipse.jface.viewers.ISelectionProvider;
26 import org.eclipse.jface.viewers.IStructuredSelection;
27 import org.eclipse.swt.dnd.DND;
28 import org.eclipse.swt.dnd.DragSource;
29 import org.eclipse.swt.dnd.DragSourceAdapter;
30 import org.eclipse.swt.dnd.DragSourceEvent;
31 import org.eclipse.swt.dnd.DragSourceListener;
32 import org.eclipse.swt.dnd.FileTransfer;
33 import org.eclipse.swt.dnd.TransferData;
34 import org.eclipse.swt.widgets.Control;
35 import org.eclipse.swt.widgets.Shell;
36 import org.eclipse.ui.actions.ReadOnlyStateChecker;
37 import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
38 import org.eclipse.ui.internal.views.navigator.ResourceNavigatorMessages;
39 import org.eclipse.ui.part.ResourceTransfer;
40 import org.eclipse.ui.statushandlers.StatusManager;
41 
42 /**
43  * Implements drag behaviour when items are dragged out of the resource
44  * navigator.
45  *
46  * @since 2.0
47  * @deprecated as of 3.5, use the Common Navigator Framework classes instead
48  */
49 @Deprecated
50 public class NavigatorDragAdapter extends DragSourceAdapter {
51 	private static final String CHECK_MOVE_TITLE = ResourceNavigatorMessages.DragAdapter_title;
52 
53 	private static final String CHECK_DELETE_MESSAGE = ResourceNavigatorMessages.DragAdapter_checkDeleteMessage;
54 
55 	ISelectionProvider selectionProvider;
56 
57 	private TransferData lastDataType;
58 
59 	/**
60 	 * Constructs a new drag adapter.
61 	 *
62 	 * @param provider The selection provider
63 	 */
NavigatorDragAdapter(ISelectionProvider provider)64 	public NavigatorDragAdapter(ISelectionProvider provider) {
65 		selectionProvider = provider;
66 	}
67 
68 	/**
69 	 * This implementation of
70 	 * {@link DragSourceListener#dragFinished(DragSourceEvent)} responds to a drag
71 	 * that has moved resources outside the Navigator by deleting the corresponding
72 	 * source resource.
73 	 */
74 	@Override
dragFinished(DragSourceEvent event)75 	public void dragFinished(DragSourceEvent event) {
76 		LocalSelectionTransfer.getInstance().setSelection(null);
77 
78 		if (event.doit == false) {
79 			return;
80 		}
81 
82 		final int typeMask = IResource.FOLDER | IResource.FILE;
83 		if (event.detail == DND.DROP_MOVE) {
84 			// never delete resources when dragging outside Eclipse.
85 			// workaround for bug 30543.
86 			if (lastDataType != null && FileTransfer.getInstance().isSupportedType(lastDataType)) {
87 				return;
88 			}
89 
90 			IResource[] resources = getSelectedResources(typeMask);
91 			DragSource dragSource = (DragSource) event.widget;
92 			Control control = dragSource.getControl();
93 			Shell shell = control.getShell();
94 			ReadOnlyStateChecker checker;
95 
96 			if (resources == null || resources.length == 0) {
97 				return;
98 			}
99 
100 			checker = new ReadOnlyStateChecker(shell, CHECK_MOVE_TITLE, CHECK_DELETE_MESSAGE);
101 			resources = checker.checkReadOnlyResources(resources);
102 			// delete the old elements
103 			for (IResource resource : resources) {
104 				try {
105 					resource.delete(IResource.KEEP_HISTORY | IResource.FORCE, null);
106 				} catch (CoreException e) {
107 					StatusManager.getManager().handle(e, IDEWorkbenchPlugin.IDE_WORKBENCH);
108 				}
109 			}
110 		} else if (event.detail == DND.DROP_TARGET_MOVE) {
111 			IResource[] resources = getSelectedResources(typeMask);
112 
113 			// file moved for us by OS, no need to delete the resources, just
114 			// update the view
115 			if (resources == null) {
116 				return;
117 			}
118 			for (IResource resource : resources) {
119 				try {
120 					resource.refreshLocal(IResource.DEPTH_INFINITE, null);
121 				} catch (CoreException e) {
122 					StatusManager.getManager().handle(e, IDEWorkbenchPlugin.IDE_WORKBENCH);
123 				}
124 			}
125 		}
126 	}
127 
128 	/**
129 	 * This implementation of
130 	 * {@link DragSourceListener#dragSetData(DragSourceEvent)} sets the drag event
131 	 * data based on the current selection in the Navigator.
132 	 */
133 	@Override
dragSetData(DragSourceEvent event)134 	public void dragSetData(DragSourceEvent event) {
135 		final int typeMask = IResource.FILE | IResource.FOLDER;
136 		IResource[] resources = getSelectedResources(typeMask);
137 
138 		if (resources == null || resources.length == 0) {
139 			return;
140 		}
141 
142 		lastDataType = event.dataType;
143 		// use local selection transfer if possible
144 		if (LocalSelectionTransfer.getInstance().isSupportedType(event.dataType)) {
145 			event.data = LocalSelectionTransfer.getInstance().getSelection();
146 			return;
147 		}
148 		// use resource transfer if possible
149 		if (ResourceTransfer.getInstance().isSupportedType(event.dataType)) {
150 			event.data = resources;
151 			return;
152 		}
153 		// resort to a file transfer
154 		if (!FileTransfer.getInstance().isSupportedType(event.dataType)) {
155 			return;
156 		}
157 
158 		// Get the path of each file and set as the drag data
159 		final int length = resources.length;
160 		int actualLength = 0;
161 		String[] fileNames = new String[length];
162 		for (int i = 0; i < length; i++) {
163 			IPath location = resources[i].getLocation();
164 			// location may be null. See bug 29491.
165 			if (location != null) {
166 				fileNames[actualLength++] = location.toOSString();
167 			}
168 		}
169 		if (actualLength == 0) {
170 			return;
171 		}
172 		// was one or more of the locations null?
173 		if (actualLength < length) {
174 			String[] tempFileNames = fileNames;
175 			fileNames = new String[actualLength];
176 			System.arraycopy(tempFileNames, 0, fileNames, 0, actualLength);
177 		}
178 		event.data = fileNames;
179 	}
180 
181 	/**
182 	 * This implementation of {@link DragSourceListener#dragStart(DragSourceEvent)}
183 	 * allows the drag to start if the current Navigator selection contains
184 	 * resources that can be dragged.
185 	 */
186 	@Override
dragStart(DragSourceEvent event)187 	public void dragStart(DragSourceEvent event) {
188 		lastDataType = null;
189 		// Workaround for 1GEUS9V
190 		DragSource dragSource = (DragSource) event.widget;
191 		Control control = dragSource.getControl();
192 		if (control != control.getDisplay().getFocusControl()) {
193 			event.doit = false;
194 			return;
195 		}
196 
197 		IStructuredSelection selection = (IStructuredSelection) selectionProvider.getSelection();
198 		for (Object next : selection) {
199 			if (!(next instanceof IFile || next instanceof IFolder)) {
200 				event.doit = false;
201 				return;
202 			}
203 		}
204 		if (selection.isEmpty()) {
205 			event.doit = false;
206 			return;
207 		}
208 		LocalSelectionTransfer.getInstance().setSelection(selection);
209 		event.doit = true;
210 	}
211 
getSelectedResources(int resourceTypes)212 	private IResource[] getSelectedResources(int resourceTypes) {
213 		List<IResource> resources = new ArrayList<>();
214 
215 		ISelection selection = selectionProvider.getSelection();
216 		if (!(selection instanceof IStructuredSelection) || selection.isEmpty()) {
217 			return null;
218 		}
219 		IStructuredSelection structuredSelection = (IStructuredSelection) selection;
220 
221 		// loop through list and look for matching items
222 		for (Object obj : structuredSelection) {
223 			if (obj instanceof IResource) {
224 				IResource res = (IResource) obj;
225 				if ((res.getType() & resourceTypes) == res.getType()) {
226 					resources.add(res);
227 				}
228 			}
229 		}
230 		IResource[] result = new IResource[resources.size()];
231 		resources.toArray(result);
232 		return result;
233 	}
234 }
235