1
/*******************************************************************************
2
* Copyright (c) 2002, 2008 QNX Software Systems 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
* QNX Software Systems - Initial API and implementation
10
* Anton Leherbauer (Wind River Systems) - Fixed bug 141484
11
*******************************************************************************/
13
package org.eclipse.cdt.internal.ui.cview;
15
import java.lang.reflect.InvocationTargetException;
16
import java.util.ArrayList;
17
import java.util.Iterator;
18
import java.util.List;
20
import org.eclipse.core.runtime.IProgressMonitor;
21
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
22
import org.eclipse.jface.operation.IRunnableContext;
23
import org.eclipse.jface.operation.IRunnableWithProgress;
24
import org.eclipse.jface.viewers.ISelection;
25
import org.eclipse.jface.viewers.IStructuredSelection;
26
import org.eclipse.jface.viewers.StructuredViewer;
27
import org.eclipse.swt.dnd.DND;
28
import org.eclipse.swt.dnd.DropTargetEvent;
29
import org.eclipse.swt.dnd.Transfer;
30
import org.eclipse.swt.widgets.Shell;
31
import org.eclipse.ui.views.navigator.LocalSelectionTransfer;
33
import org.eclipse.cdt.core.model.CModelException;
34
import org.eclipse.cdt.core.model.CoreModel;
35
import org.eclipse.cdt.core.model.ICElement;
36
import org.eclipse.cdt.core.model.ISourceReference;
37
import org.eclipse.cdt.core.model.ITranslationUnit;
39
import org.eclipse.cdt.internal.ui.dnd.CDTViewerDropAdapter;
40
import org.eclipse.cdt.internal.ui.dnd.TransferDropTargetListener;
41
import org.eclipse.cdt.internal.ui.util.ExceptionHandler;
43
public class SelectionTransferDropAdapter extends CDTViewerDropAdapter implements TransferDropTargetListener {
45
private List<?> fElements;
46
private ICElement[] fMoveData;
47
private ICElement[] fCopyData;
49
private static final long DROP_TIME_DIFF_TRESHOLD= 150;
51
public SelectionTransferDropAdapter(StructuredViewer viewer) {
52
super(viewer, DND.FEEDBACK_SCROLL | DND.FEEDBACK_EXPAND);
55
//---- TransferDropTargetListener interface ---------------------------------------
57
public Transfer getTransfer() {
58
return LocalSelectionTransfer.getInstance();
61
public boolean isEnabled(DropTargetEvent event) {
62
Object target= event.item != null ? event.item.getData() : null;
66
return target instanceof ISourceReference;
69
//---- Actual DND -----------------------------------------------------------------
72
public void dragEnter(DropTargetEvent event) {
74
super.dragEnter(event);
78
public void dragLeave(DropTargetEvent event) {
80
super.dragLeave(event);
83
private void clear() {
90
public void validateDrop(Object target, DropTargetEvent event, int operation) {
91
event.detail= DND.DROP_NONE;
97
initializeSelection();
101
case DND.DROP_DEFAULT:
102
event.detail= handleValidateDefault(target, event);
105
event.detail= handleValidateCopy(target, event);
108
event.detail= handleValidateMove(target, event);
111
event.detail= handleValidateLink(target, event);
114
} catch (CModelException e){
115
ExceptionHandler.handle(e, CViewMessages.SelectionTransferDropAdapter_error_title, CViewMessages.SelectionTransferDropAdapter_error_message);
116
event.detail= DND.DROP_NONE;
120
protected void initializeSelection(){
121
if (fElements != null) {
124
ISelection s= LocalSelectionTransfer.getInstance().getSelection();
125
if (!(s instanceof IStructuredSelection)) {
128
fElements = ((IStructuredSelection)s).toList();
131
private boolean tooFast(DropTargetEvent event) {
132
return Math.abs(LocalSelectionTransfer.getInstance().getSelectionSetTime() - (event.time & 0xFFFFFFFFL)) < DROP_TIME_DIFF_TRESHOLD;
136
public void drop(Object target, DropTargetEvent event) {
138
switch(event.detail) {
140
handleDropMove(target, event);
143
handleDropCopy(target, event);
146
handleDropLink(target, event);
149
} catch (CModelException e){
150
ExceptionHandler.handle(e, CViewMessages.SelectionTransferDropAdapter_error_title, CViewMessages.SelectionTransferDropAdapter_error_message);
151
} catch(InvocationTargetException e) {
152
ExceptionHandler.handle(e, CViewMessages.SelectionTransferDropAdapter_error_title, CViewMessages.SelectionTransferDropAdapter_error_exception);
153
} catch (InterruptedException e) {
156
// The drag source listener must not perform any operation
157
// since this drop adapter did the remove of the source even
158
// if we moved something.
159
event.detail= DND.DROP_NONE;
163
private int handleValidateDefault(Object target, DropTargetEvent event) throws CModelException {
164
if (target == null) {
165
return DND.DROP_NONE;
167
return handleValidateMove(target, event);
170
private int handleValidateMove(Object target, DropTargetEvent event) throws CModelException {
171
if (target == null || fElements.contains(target)) {
172
return DND.DROP_NONE;
174
if (fMoveData == null) {
175
ICElement[] cElements= getCElements(fElements);
176
if (cElements != null && cElements.length > 0) {
177
fMoveData = cElements;
181
if (!canMoveElements()) {
182
return DND.DROP_NONE;
185
if (target instanceof ISourceReference) {
186
return DND.DROP_MOVE;
188
return DND.DROP_NONE;
191
private boolean canMoveElements() {
192
if (fMoveData != null) {
193
return hasCommonParent(fMoveData);
198
private boolean hasCommonParent(ICElement[] elements) {
199
if (elements.length > 1) {
200
ICElement parent = elements[0];
201
for (int i = 0; i < elements.length; ++i) {
202
ICElement p = elements[i].getParent();
203
if (parent == null) {
207
} else if (!parent.equals(p)){
215
private void handleDropLink(Object target, DropTargetEvent event) {
218
private int handleValidateLink(Object target, DropTargetEvent event) {
219
return DND.DROP_NONE;
222
private void handleDropMove(final Object target, DropTargetEvent event) throws CModelException, InvocationTargetException, InterruptedException{
223
final ICElement[] cElements= getCElements(fElements);
225
if (target instanceof ICElement) {
226
ICElement cTarget = (ICElement)target;
227
ICElement parent = cTarget;
228
boolean isTargetTranslationUnit = cTarget instanceof ITranslationUnit;
229
if (!isTargetTranslationUnit) {
230
parent = cTarget.getParent();
232
final ICElement[] containers = new ICElement[cElements.length];
233
for (int i = 0; i < containers.length; ++i) {
234
containers[i] = parent;
236
ICElement[] neighbours = null;
237
if (!isTargetTranslationUnit) {
238
neighbours = new ICElement[cElements.length];
239
for (int i = 0; i < neighbours.length; ++i) {
240
neighbours[i] = cTarget;
243
final ICElement[] siblings = neighbours;
244
IRunnableWithProgress runnable = new IRunnableWithProgress() {
245
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
247
CoreModel.getDefault().getCModel().move(cElements, containers, siblings, null, false, monitor);
248
} catch (CModelException e) {
249
throw new InvocationTargetException(e);
257
private int handleValidateCopy(Object target, DropTargetEvent event) throws CModelException{
258
if (target == null) {
259
return DND.DROP_NONE;
262
if (fCopyData == null) {
263
ICElement[] cElements= getCElements(fElements);
264
if (cElements != null && cElements.length > 0) {
265
fCopyData= cElements;
269
if (!canCopyElements())
270
return DND.DROP_NONE;
272
if (target instanceof ISourceReference) {
273
return DND.DROP_COPY;
275
return DND.DROP_NONE;
278
private boolean canCopyElements() {
279
if (fCopyData != null) {
280
return hasCommonParent(fCopyData);
285
private void handleDropCopy(final Object target, DropTargetEvent event) throws CModelException, InvocationTargetException, InterruptedException{
286
final ICElement[] cElements= getCElements(fElements);
288
if (target instanceof ICElement) {
289
ICElement cTarget = (ICElement)target;
290
ICElement parent = cTarget;
291
boolean isTargetTranslationUnit = cTarget instanceof ITranslationUnit;
292
if (!isTargetTranslationUnit) {
293
parent = cTarget.getParent();
295
final ICElement[] containers = new ICElement[cElements.length];
296
for (int i = 0; i < containers.length; ++i) {
297
containers[i] = parent;
299
ICElement[] neighbours = null;
300
if (!isTargetTranslationUnit) {
301
neighbours = new ICElement[cElements.length];
302
for (int i = 0; i < neighbours.length; ++i) {
303
neighbours[i] = cTarget;
306
final ICElement[] siblings = neighbours;
307
IRunnableWithProgress runnable = new IRunnableWithProgress() {
308
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
310
CoreModel.getDefault().getCModel().copy(cElements, containers, siblings, null, false, monitor);
311
} catch (CModelException e) {
312
throw new InvocationTargetException(e);
320
private Shell getShell() {
321
return getViewer().getControl().getShell();
324
public void run(IRunnableWithProgress runnable) throws InterruptedException, InvocationTargetException {
325
IRunnableContext context= new ProgressMonitorDialog(getShell());
326
context.run(true, true, runnable);
329
public static ICElement[] getCElements(List<?> elements) {
330
List<ICElement> resources= new ArrayList<ICElement>(elements.size());
331
for (Iterator<?> iter= elements.iterator(); iter.hasNext();) {
332
Object element= iter.next();
333
if (element instanceof ITranslationUnit) {
336
if (element instanceof ICElement)
337
resources.add((ICElement) element);
339
return resources.toArray(new ICElement[resources.size()]);