1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.dnd;
14 //import org.eclipse.jface.text.Assert;
15 import org.eclipse.core.runtime.Assert;
16 import org.eclipse.jface.viewers.StructuredViewer;
17 import org.eclipse.swt.dnd.DND;
18 import org.eclipse.swt.dnd.DropTargetEvent;
19 import org.eclipse.swt.dnd.DropTargetListener;
20 import org.eclipse.swt.graphics.Point;
21 import org.eclipse.swt.graphics.Rectangle;
22 import org.eclipse.swt.widgets.Item;
23 import org.eclipse.swt.widgets.TableItem;
24 import org.eclipse.swt.widgets.TreeItem;
27 * A drag and drop adapter to be used together with structured viewers. The
28 * adapater delegates the <code>dragEnter</code>, <code>dragOperationChanged
30 * <code>dragOver</code> and <code>dropAccept</code> method to the
31 * <code>validateDrop</code> method. Furthermore it adds location feedback.
33 public class JdtViewerDropAdapter implements DropTargetListener {
36 * Constant describing the position of the mouse cursor relative to the
37 * target object. This means the mouse is positioned slightly before the
40 protected static final int LOCATION_BEFORE = 1;
43 * Constant describing the position of the mouse cursor relative to the
44 * target object. This means the mouse is positioned slightly after the
47 protected static final int LOCATION_AFTER = 2;
50 * Constant describing the position of the mouse cursor relative to the
51 * target object. This means the mouse is positioned directly on the target.
53 protected static final int LOCATION_ON = 3;
56 * Constant describing the position of the mouse cursor relative to the
57 * target object. This means the mouse is not positioned over or near any
60 protected static final int LOCATION_NONE = 4;
63 * The threshold used to determine if the mouse is before or after an item.
65 private static final int LOCATION_EPSILON = 5;
68 * Style to enable location feedback.
70 public static final int INSERTION_FEEDBACK = 1 << 1;
72 private StructuredViewer fViewer;
74 private int fFeedback;
76 private boolean fShowInsertionFeedback;
78 private int fRequestedOperation;
80 private int fLastOperation;
82 protected int fLocation;
84 protected Object fTarget;
86 public JdtViewerDropAdapter(StructuredViewer viewer, int feedback) {
88 Assert.isNotNull(fViewer);
94 * Controls whether the drop adapter shows insertion feedback or not.
96 * @param showInsertionFeedback
97 * <code>true</code> if the drop adapter is supposed to show
98 * insertion feedback. Otherwise <code>false</code>
100 // public void showInsertionFeedback(boolean showInsertionFeedback) {
101 // fShowInsertionFeedback = showInsertionFeedback;
105 * Returns the viewer this adapter is working on.
107 // protected StructuredViewer getViewer() {
111 // ---- Hooks to override
112 // -----------------------------------------------------
115 * The actual drop has occurred. Calls
116 * <code>drop(Object target, DropTargetEvent event)
119 * @see DropTargetListener#drop(org.eclipse.swt.dnd.DropTargetEvent)
121 public void drop(DropTargetEvent event) {
122 drop(fTarget, event);
126 * The actual drop has occurred.
129 * the drop target in form of a domain element.
131 * the drop traget event
133 public void drop(Object target, DropTargetEvent event) {
137 * Checks if the drop is valid. The method calls <code>validateDrop
138 * (Object target, DropTargetEvent event). Implementors can alter the
139 * <code>currentDataType</code> field and the <code>detail</code> field
140 * to give feedback about drop acceptence.
142 public void validateDrop(DropTargetEvent event) {
143 validateDrop(fTarget, event, fRequestedOperation);
147 * Checks if the drop on the current target is valid. The method can alter
148 * the <code>currentDataType</code> field and the <code>
150 * field to give feedback about drop acceptence.
153 * the drop target in form of a domain element.
155 * the drop traget event
157 * the operation requested by the user.
159 public void validateDrop(Object target, DropTargetEvent event, int operation) {
162 public void dragEnter(DropTargetEvent event) {
163 dragOperationChanged(event);
166 public void dragLeave(DropTargetEvent event) {
168 fLocation = LOCATION_NONE;
171 public void dragOperationChanged(DropTargetEvent event) {
172 fRequestedOperation = event.detail;
173 fTarget = computeTarget(event);
174 fLocation = computeLocation(event);
176 fLastOperation = event.detail;
177 computeFeedback(event);
180 public void dragOver(DropTargetEvent event) {
181 Object oldTarget = fTarget;
182 fTarget = computeTarget(event);
184 // set the location feedback
185 int oldLocation = fLocation;
186 fLocation = computeLocation(event);
187 if (oldLocation != fLocation || oldTarget != fTarget
188 || fLastOperation != event.detail) {
190 fLastOperation = event.detail;
192 event.detail = fLastOperation;
194 computeFeedback(event);
197 public void dropAccept(DropTargetEvent event) {
198 fTarget = computeTarget(event);
200 fLastOperation = event.detail;
204 * Returns the data held by <code>event.item</code>. Inside a viewer this
205 * corresponds to the items data model element.
207 protected Object computeTarget(DropTargetEvent event) {
208 return event.item == null ? null : event.item.getData();
212 * Returns the position of the given coordinates relative to the given
213 * target. The position is determined to be before, after, or on the item,
214 * based on some threshold value. The return value is one of the LOCATION_*
215 * constants defined in this class.
217 final protected int computeLocation(DropTargetEvent event) {
218 if (!(event.item instanceof Item))
219 return LOCATION_NONE;
221 Item item = (Item) event.item;
222 Point coordinates = fViewer.getControl().toControl(
223 new Point(event.x, event.y));
224 Rectangle bounds = getBounds(item);
225 if (bounds == null) {
226 return LOCATION_NONE;
228 if ((coordinates.y - bounds.y) < LOCATION_EPSILON) {
229 return LOCATION_BEFORE;
231 if ((bounds.y + bounds.height - coordinates.y) < LOCATION_EPSILON) {
232 return LOCATION_AFTER;
238 * Returns the bounds of the given item, or <code>null</code> if it is not
239 * a valid type of item.
241 private Rectangle getBounds(Item item) {
242 if (item instanceof TreeItem)
243 return ((TreeItem) item).getBounds();
245 if (item instanceof TableItem)
246 return ((TableItem) item).getBounds(0);
252 * Sets the drag under feedback corresponding to the value of
253 * <code>fLocation</code> and the <code>INSERTION_FEEDBACK</code> style
256 protected void computeFeedback(DropTargetEvent event) {
257 if (!fShowInsertionFeedback && fLocation != LOCATION_NONE) {
258 event.feedback = DND.FEEDBACK_SELECT;
260 if (fLocation == LOCATION_BEFORE) {
261 event.feedback = DND.FEEDBACK_INSERT_BEFORE;
262 } else if (fLocation == LOCATION_AFTER) {
263 event.feedback = DND.FEEDBACK_INSERT_AFTER;
266 event.feedback |= fFeedback;
270 * Sets the drop operation to </code>DROP_NODE<code>.
272 protected void clearDropOperation(DropTargetEvent event) {
273 event.detail = DND.DROP_NONE;
277 * Returns the requested drop operation.
279 protected int getRequestedOperation() {
280 return fRequestedOperation;