1 /*******************************************************************************
2 * Copyright (c) 2000, 2011 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.ui.packageview;
13 import java.util.ArrayList;
14 import java.util.Arrays;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.Iterator;
18 import java.util.List;
22 import org.eclipse.swt.dnd.DND;
23 import org.eclipse.swt.dnd.DropTargetEvent;
24 import org.eclipse.swt.dnd.Transfer;
25 import org.eclipse.swt.dnd.TransferData;
27 import org.eclipse.core.runtime.IAdaptable;
29 import org.eclipse.core.resources.IResource;
31 import org.eclipse.jface.util.TransferDropTargetListener;
32 import org.eclipse.jface.viewers.ISelection;
33 import org.eclipse.jface.viewers.IStructuredSelection;
34 import org.eclipse.jface.viewers.ITreeSelection;
35 import org.eclipse.jface.viewers.TreePath;
37 import org.eclipse.ui.IWorkingSet;
38 import org.eclipse.ui.views.navigator.LocalSelectionTransfer;
40 import org.eclipse.jdt.core.IJavaElement;
42 import org.eclipse.jdt.internal.corext.refactoring.reorg.ReorgUtils;
44 import org.eclipse.jdt.internal.ui.dnd.JdtViewerDropAdapter;
45 import org.eclipse.jdt.internal.ui.workingsets.IWorkingSetIDs;
46 import org.eclipse.jdt.internal.ui.workingsets.WorkingSetModel;
48 public class WorkingSetDropAdapter extends JdtViewerDropAdapter implements TransferDropTargetListener {
50 private PackageExplorerPart fPackageExplorer;
52 private IStructuredSelection fSelection;
53 private Object[] fElementsToAdds;
54 private Set<IAdaptable> fCurrentElements;
55 private IWorkingSet fWorkingSet;
57 private int fLocation;
59 public WorkingSetDropAdapter(PackageExplorerPart part) {
60 super(part.getTreeViewer());
61 fPackageExplorer= part;
65 setScrollEnabled(true);
66 setExpandEnabled(true);
67 setFeedbackEnabled(false);
70 //---- TransferDropTargetListener interface ---------------------------------------
75 public Transfer getTransfer() {
76 return LocalSelectionTransfer.getInstance();
82 public boolean isEnabled(DropTargetEvent event) {
83 Object target= event.item != null ? event.item.getData() : null;
86 ISelection selection= LocalSelectionTransfer.getInstance().getSelection();
87 if (!isValidSelection(selection)) {
90 if (!isValidTarget(target))
93 initializeState(target, selection);
97 //---- Actual DND -----------------------------------------------------------------
103 public boolean validateDrop(Object target, int operation, TransferData transferType) {
104 return determineOperation(target, operation, transferType, DND.DROP_MOVE | DND.DROP_LINK | DND.DROP_COPY) != DND.DROP_NONE;
111 protected int determineOperation(Object target, int operation, TransferData transferType, int operations) {
113 case DND.DROP_DEFAULT:
116 return validateTarget(target, operation);
118 return DND.DROP_NONE;
123 private int validateTarget(Object target, int operation) {
124 setFeedbackEnabled(false);
125 setScrollEnabled(true);
126 setExpandEnabled(true);
127 if (!isValidTarget(target))
128 return DND.DROP_NONE;
129 ISelection s= LocalSelectionTransfer.getInstance().getSelection();
130 if (!isValidSelection(s)) {
131 return DND.DROP_NONE;
134 initializeState(target, s);
136 if (isWorkingSetSelection()) {
137 setExpandEnabled(false);
138 if ((getCurrentLocation() == LOCATION_BEFORE || getCurrentLocation() == LOCATION_AFTER) &&
139 !fPackageExplorer.getWorkingSetModel().isSortingEnabled()) {
140 setFeedbackEnabled(true);
141 return DND.DROP_MOVE;
143 return DND.DROP_NONE;
145 if (isOthersWorkingSet(fWorkingSet) && operation == DND.DROP_COPY)
146 return DND.DROP_NONE;
148 List<IJavaElement> realJavaElements= new ArrayList<IJavaElement>();
149 List<IResource> realResource= new ArrayList<IResource>();
150 ReorgUtils.splitIntoJavaElementsAndResources(fElementsToAdds, realJavaElements, realResource);
151 if (fElementsToAdds.length != realJavaElements.size() + realResource.size())
152 return DND.DROP_NONE;
153 for (Iterator<IJavaElement> iter= realJavaElements.iterator(); iter.hasNext();) {
154 IJavaElement element= iter.next();
155 if (ReorgUtils.containsElementOrParent(fCurrentElements, element))
156 return DND.DROP_NONE;
158 for (Iterator<IResource> iter= realResource.iterator(); iter.hasNext();) {
159 IResource element= iter.next();
160 if (ReorgUtils.containsElementOrParent(fCurrentElements, element))
161 return DND.DROP_NONE;
163 if (!(fSelection instanceof ITreeSelection)) {
164 return DND.DROP_COPY;
166 ITreeSelection treeSelection= (ITreeSelection)fSelection;
167 TreePath[] paths= treeSelection.getPaths();
168 for (int i= 0; i < paths.length; i++) {
169 TreePath path= paths[i];
170 if (path.getSegmentCount() != 2)
171 return DND.DROP_COPY;
172 if (!(path.getSegment(0) instanceof IWorkingSet))
173 return DND.DROP_COPY;
174 if (paths.length == 1) {
175 IWorkingSet ws= (IWorkingSet)path.getSegment(0);
176 if (isOthersWorkingSet(ws))
177 return DND.DROP_MOVE;
181 if (operation == DND.DROP_DEFAULT)
182 return DND.DROP_MOVE;
186 private boolean isValidTarget(Object target) {
187 return target instanceof IWorkingSet;
190 private boolean isValidSelection(ISelection selection) {
191 return selection instanceof IStructuredSelection;
194 private boolean isOthersWorkingSet(IWorkingSet ws) {
195 return IWorkingSetIDs.OTHERS.equals(ws.getId());
198 private void initializeState(Object target, ISelection s) {
199 fWorkingSet= (IWorkingSet)target;
200 fSelection= (IStructuredSelection)s;
201 fElementsToAdds= fSelection.toArray();
202 fCurrentElements= new HashSet<IAdaptable>(Arrays.asList(fWorkingSet.getElements()));
205 private boolean isWorkingSetSelection() {
206 for (int i= 0; i < fElementsToAdds.length; i++) {
207 if (!(fElementsToAdds[i] instanceof IWorkingSet))
217 public boolean performDrop(Object data) {
218 if (isWorkingSetSelection()) {
219 performWorkingSetReordering();
221 performElementRearrange(getCurrentOperation());
226 private void performWorkingSetReordering() {
227 WorkingSetModel model= fPackageExplorer.getWorkingSetModel();
228 List<IWorkingSet> allWorkingSets= new ArrayList<IWorkingSet>(Arrays.asList(model.getAllWorkingSets()));
229 int index= allWorkingSets.indexOf(fWorkingSet);
231 if (getCurrentLocation() == LOCATION_AFTER)
233 List<IWorkingSet> result= new ArrayList<IWorkingSet>(allWorkingSets.size());
234 @SuppressWarnings("unchecked") // isWorkingSetSelection() ensures that all elements are IWorkingSets
235 List<IWorkingSet> selected= new ArrayList<IWorkingSet>((List<IWorkingSet>) (List<?>) Arrays.asList(fElementsToAdds));
236 model.generated_7210376127521455312(allWorkingSets, index, result, selected);
240 private void performElementRearrange(int eventDetail) {
241 // only move if target isn't the other working set. If this is the case
242 // the move will happenn automatically by refreshing the other working set
243 if (!isOthersWorkingSet(fWorkingSet)) {
244 List<Object> elements= new ArrayList<Object>(Arrays.asList(fWorkingSet.getElements()));
245 elements.addAll(Arrays.asList(fElementsToAdds));
246 fWorkingSet.setElements(elements.toArray(new IAdaptable[elements.size()]));
248 if (eventDetail == DND.DROP_MOVE) {
249 ITreeSelection treeSelection= (ITreeSelection)fSelection;
250 Map<IWorkingSet, List<Object>> workingSets= groupByWorkingSets(treeSelection.getPaths());
251 for (Iterator<IWorkingSet> iter= workingSets.keySet().iterator(); iter.hasNext();) {
252 IWorkingSet ws= iter.next();
253 List<Object> toRemove= workingSets.get(ws);
254 List<IAdaptable> currentElements= new ArrayList<IAdaptable>(Arrays.asList(ws.getElements()));
255 currentElements.removeAll(toRemove);
256 ws.setElements(currentElements.toArray(new IAdaptable[currentElements.size()]));
261 private Map<IWorkingSet, List<Object>> groupByWorkingSets(TreePath[] paths) {
262 Map<IWorkingSet, List<Object>> result= new HashMap<IWorkingSet, List<Object>>();
263 for (int i= 0; i < paths.length; i++) {
264 TreePath path= paths[i];
265 IWorkingSet ws= (IWorkingSet)path.getSegment(0);
266 List<Object> l= result.get(ws);
268 l= new ArrayList<Object>();
271 l.add(path.getSegment(1));
276 //---- test methods for JUnit test since DnD is hard to simulate
278 public int internalTestValidateTarget(Object target, int operation) {
279 return validateTarget(target, operation);
282 public void internalTestDrop(Object target, int eventDetail) {
283 if (isWorkingSetSelection()) {
284 performWorkingSetReordering();
286 performElementRearrange(eventDetail);
290 public void internalTestSetLocation(int location) {
298 protected int getCurrentLocation() {
300 return super.getCurrentLocation();