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