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.jdt.internal.ui.packageview;
011:
012: import java.util.ArrayList;
013: import java.util.Arrays;
014: import java.util.HashMap;
015: import java.util.HashSet;
016: import java.util.Iterator;
017: import java.util.List;
018: import java.util.Map;
019: import java.util.Set;
020:
021: import org.eclipse.core.runtime.IAdaptable;
022:
023: import org.eclipse.core.resources.IResource;
024:
025: import org.eclipse.swt.dnd.DND;
026: import org.eclipse.swt.dnd.DropTargetEvent;
027: import org.eclipse.swt.dnd.Transfer;
028: import org.eclipse.swt.dnd.TransferData;
029:
030: import org.eclipse.jface.util.TransferDropTargetListener;
031: import org.eclipse.jface.viewers.ISelection;
032: import org.eclipse.jface.viewers.IStructuredSelection;
033: import org.eclipse.jface.viewers.ITreeSelection;
034: import org.eclipse.jface.viewers.TreePath;
035:
036: import org.eclipse.ui.IWorkingSet;
037:
038: import org.eclipse.ui.views.navigator.LocalSelectionTransfer;
039:
040: import org.eclipse.jdt.core.IJavaElement;
041:
042: import org.eclipse.jdt.internal.corext.refactoring.reorg.ReorgUtils;
043:
044: import org.eclipse.jdt.internal.ui.dnd.JdtViewerDropAdapter;
045: import org.eclipse.jdt.internal.ui.workingsets.OthersWorkingSetUpdater;
046: import org.eclipse.jdt.internal.ui.workingsets.WorkingSetModel;
047:
048: public class WorkingSetDropAdapter extends JdtViewerDropAdapter
049: implements TransferDropTargetListener {
050:
051: private PackageExplorerPart fPackageExplorer;
052:
053: private IStructuredSelection fSelection;
054: private Object[] fElementsToAdds;
055: private Set fCurrentElements;
056: private IWorkingSet fWorkingSet;
057:
058: private int fLocation;
059:
060: public WorkingSetDropAdapter(PackageExplorerPart part) {
061: super (part.getTreeViewer());
062: fPackageExplorer = part;
063:
064: fLocation = -1;
065:
066: setScrollEnabled(true);
067: setExpandEnabled(true);
068: setFeedbackEnabled(false);
069: }
070:
071: //---- TransferDropTargetListener interface ---------------------------------------
072:
073: /**
074: * {@inheritDoc}
075: */
076: public Transfer getTransfer() {
077: return LocalSelectionTransfer.getInstance();
078: }
079:
080: /**
081: * {@inheritDoc}
082: */
083: public boolean isEnabled(DropTargetEvent event) {
084: Object target = event.item != null ? event.item.getData()
085: : null;
086: if (target == null)
087: return false;
088: ISelection selection = LocalSelectionTransfer.getInstance()
089: .getSelection();
090: if (!isValidSelection(selection)) {
091: return false;
092: }
093: if (!isValidTarget(target))
094: return false;
095:
096: initializeState(target, selection);
097: return true;
098: }
099:
100: //---- Actual DND -----------------------------------------------------------------
101:
102: /**
103: * {@inheritDoc}
104: */
105: public boolean validateDrop(Object target, int operation,
106: TransferData transferType) {
107: return determineOperation(target, operation, transferType,
108: DND.DROP_MOVE | DND.DROP_LINK | DND.DROP_COPY) != DND.DROP_NONE;
109: }
110:
111: /**
112: * {@inheritDoc}
113: */
114: protected int determineOperation(Object target, int operation,
115: TransferData transferType, int operations) {
116: switch (operation) {
117: case DND.DROP_DEFAULT:
118: case DND.DROP_COPY:
119: case DND.DROP_MOVE:
120: return validateTarget(target, operation);
121: default:
122: return DND.DROP_NONE;
123: }
124:
125: }
126:
127: private int validateTarget(Object target, int operation) {
128: setFeedbackEnabled(false);
129: setScrollEnabled(true);
130: setExpandEnabled(true);
131: if (!isValidTarget(target))
132: return DND.DROP_NONE;
133: ISelection s = LocalSelectionTransfer.getInstance()
134: .getSelection();
135: if (!isValidSelection(s)) {
136: return DND.DROP_NONE;
137: }
138:
139: initializeState(target, s);
140:
141: if (isWorkingSetSelection()) {
142: setExpandEnabled(false);
143: if (getCurrentLocation() == LOCATION_BEFORE
144: || getCurrentLocation() == LOCATION_AFTER) {
145: setFeedbackEnabled(true);
146: return DND.DROP_MOVE;
147: }
148: return DND.DROP_NONE;
149: } else {
150: if (isOthersWorkingSet(fWorkingSet)
151: && operation == DND.DROP_COPY)
152: return DND.DROP_NONE;
153:
154: List realJavaElements = new ArrayList();
155: List realResource = new ArrayList();
156: ReorgUtils.splitIntoJavaElementsAndResources(
157: fElementsToAdds, realJavaElements, realResource);
158: if (fElementsToAdds.length != realJavaElements.size()
159: + realResource.size())
160: return DND.DROP_NONE;
161: for (Iterator iter = realJavaElements.iterator(); iter
162: .hasNext();) {
163: IJavaElement element = (IJavaElement) iter.next();
164: if (ReorgUtils.containsElementOrParent(
165: fCurrentElements, element))
166: return DND.DROP_NONE;
167: }
168: for (Iterator iter = realResource.iterator(); iter
169: .hasNext();) {
170: IResource element = (IResource) iter.next();
171: if (ReorgUtils.containsElementOrParent(
172: fCurrentElements, element))
173: return DND.DROP_NONE;
174: }
175: if (!(fSelection instanceof ITreeSelection)) {
176: return DND.DROP_COPY;
177: }
178: ITreeSelection treeSelection = (ITreeSelection) fSelection;
179: TreePath[] paths = treeSelection.getPaths();
180: for (int i = 0; i < paths.length; i++) {
181: TreePath path = paths[i];
182: if (path.getSegmentCount() != 2)
183: return DND.DROP_COPY;
184: if (!(path.getSegment(0) instanceof IWorkingSet))
185: return DND.DROP_COPY;
186: if (paths.length == 1) {
187: IWorkingSet ws = (IWorkingSet) path.getSegment(0);
188: if (OthersWorkingSetUpdater.ID.equals(ws.getId()))
189: return DND.DROP_MOVE;
190: }
191: }
192: }
193: if (operation == DND.DROP_DEFAULT)
194: return DND.DROP_MOVE;
195: return operation;
196: }
197:
198: private boolean isValidTarget(Object target) {
199: return target instanceof IWorkingSet;
200: }
201:
202: private boolean isValidSelection(ISelection selection) {
203: return selection instanceof IStructuredSelection;
204: }
205:
206: private boolean isOthersWorkingSet(IWorkingSet ws) {
207: return OthersWorkingSetUpdater.ID.equals(ws.getId());
208: }
209:
210: private void initializeState(Object target, ISelection s) {
211: fWorkingSet = (IWorkingSet) target;
212: fSelection = (IStructuredSelection) s;
213: fElementsToAdds = fSelection.toArray();
214: fCurrentElements = new HashSet(Arrays.asList(fWorkingSet
215: .getElements()));
216: }
217:
218: private boolean isWorkingSetSelection() {
219: for (int i = 0; i < fElementsToAdds.length; i++) {
220: if (!(fElementsToAdds[i] instanceof IWorkingSet))
221: return false;
222: }
223: return true;
224: }
225:
226: /**
227: * {@inheritDoc}
228: */
229: public boolean performDrop(Object data) {
230: if (isWorkingSetSelection()) {
231: performWorkingSetReordering();
232: } else {
233: performElementRearrange(getCurrentOperation());
234: }
235: // drag adapter has nothing to do, even on move.
236: return false;
237: }
238:
239: private void performWorkingSetReordering() {
240: WorkingSetModel model = fPackageExplorer.getWorkingSetModel();
241: List activeWorkingSets = new ArrayList(Arrays.asList(model
242: .getActiveWorkingSets()));
243: int index = activeWorkingSets.indexOf(fWorkingSet);
244: if (index != -1) {
245: if (getCurrentLocation() == LOCATION_AFTER)
246: index++;
247: List result = new ArrayList(activeWorkingSets.size());
248: List selected = new ArrayList(Arrays
249: .asList(fElementsToAdds));
250: for (int i = 0; i < activeWorkingSets.size(); i++) {
251: if (i == index) {
252: result.addAll(selected);
253: }
254: Object element = activeWorkingSets.get(i);
255: if (!selected.contains(element)) {
256: result.add(element);
257: }
258: }
259: if (index == activeWorkingSets.size())
260: result.addAll(selected);
261: model.setActiveWorkingSets((IWorkingSet[]) result
262: .toArray(new IWorkingSet[result.size()]));
263: }
264: }
265:
266: private void performElementRearrange(int eventDetail) {
267: // only move if target isn't the other working set. If this is the case
268: // the move will happenn automatically by refreshing the other working set
269: if (!isOthersWorkingSet(fWorkingSet)) {
270: List elements = new ArrayList(Arrays.asList(fWorkingSet
271: .getElements()));
272: elements.addAll(Arrays.asList(fElementsToAdds));
273: fWorkingSet.setElements((IAdaptable[]) elements
274: .toArray(new IAdaptable[elements.size()]));
275: }
276: if (eventDetail == DND.DROP_MOVE) {
277: ITreeSelection treeSelection = (ITreeSelection) fSelection;
278: Map workingSets = groupByWorkingSets(treeSelection
279: .getPaths());
280: for (Iterator iter = workingSets.keySet().iterator(); iter
281: .hasNext();) {
282: IWorkingSet ws = (IWorkingSet) iter.next();
283: List toRemove = (List) workingSets.get(ws);
284: List currentElements = new ArrayList(Arrays.asList(ws
285: .getElements()));
286: currentElements.removeAll(toRemove);
287: ws
288: .setElements((IAdaptable[]) currentElements
289: .toArray(new IAdaptable[currentElements
290: .size()]));
291: }
292: }
293: }
294:
295: private Map/*<List<IWorkingSet>>*/groupByWorkingSets(
296: TreePath[] paths) {
297: Map result = new HashMap();
298: for (int i = 0; i < paths.length; i++) {
299: TreePath path = paths[i];
300: IWorkingSet ws = (IWorkingSet) path.getSegment(0);
301: List l = (List) result.get(ws);
302: if (l == null) {
303: l = new ArrayList();
304: result.put(ws, l);
305: }
306: l.add(path.getSegment(1));
307: }
308: return result;
309: }
310:
311: //---- test methods for JUnit test since DnD is hard to simulate
312:
313: public int internalTestValidateTarget(Object target, int operation) {
314: return validateTarget(target, operation);
315: }
316:
317: public void internalTestDrop(Object target, int eventDetail) {
318: if (isWorkingSetSelection()) {
319: performWorkingSetReordering();
320: } else {
321: performElementRearrange(eventDetail);
322: }
323: }
324:
325: public void internalTestSetLocation(int location) {
326: fLocation = location;
327: }
328:
329: /**
330: * {@inheritDoc}
331: */
332: protected int getCurrentLocation() {
333: if (fLocation == -1)
334: return super.getCurrentLocation();
335:
336: return fLocation;
337: }
338: }
|