KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > dnd > JdtViewerDropAdapter


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.ui.dnd;
12
13 import org.eclipse.core.runtime.Assert;
14
15 import org.eclipse.swt.dnd.DND;
16 import org.eclipse.swt.dnd.DropTargetEvent;
17 import org.eclipse.swt.dnd.DropTargetListener;
18 import org.eclipse.swt.graphics.Point;
19 import org.eclipse.swt.graphics.Rectangle;
20 import org.eclipse.swt.widgets.Item;
21 import org.eclipse.swt.widgets.TableItem;
22 import org.eclipse.swt.widgets.TreeItem;
23
24 import org.eclipse.jface.viewers.StructuredViewer;
25
26 /**
27  * A drag and drop adapter to be used together with structured viewers.
28  * The adapater delegates the <code>dragEnter</code>, <code>dragOperationChanged
29  * </code>, <code>dragOver</code> and <code>dropAccept</code> method to the
30  * <code>validateDrop</code> method. Furthermore it adds location feedback.
31  */

32 public class JdtViewerDropAdapter implements DropTargetListener {
33
34     /**
35      * Constant describing the position of the mouse cursor relative
36      * to the target object. This means the mouse is not positioned
37      * over or near any valid target.
38      */

39     public static final int LOCATION_NONE= DND.FEEDBACK_NONE;
40     
41     /**
42      * Constant describing the position of the mouse cursor relative
43      * to the target object. This means the mouse is positioned
44      * directly on the target.
45      */

46     public static final int LOCATION_ON= DND.FEEDBACK_SELECT;
47     
48     /**
49      * Constant describing the position of the mouse cursor relative
50      * to the target object. This means the mouse is positioned
51      * slightly before the target.
52      */

53     public static final int LOCATION_BEFORE= DND.FEEDBACK_INSERT_BEFORE;
54     
55     /**
56      * Constant describing the position of the mouse cursor relative
57      * to the target object. This means the mouse is positioned
58      * slightly after the target.
59      */

60     public static final int LOCATION_AFTER= DND.FEEDBACK_INSERT_AFTER;
61     
62     /**
63      * The threshold used to determine if the mouse is before or after
64      * an item.
65      */

66     private static final int LOCATION_EPSILON= 5;
67     
68
69     private static final int ITEM_MARGIN_LEFT= 40;
70     private static final int ITEM_MARGIN_RIGTH= 10;
71     
72     /**
73      * Style to enable location feedback.
74      */

75     public static final int INSERTION_FEEDBACK= 1 << 1;
76
77     private StructuredViewer fViewer;
78     private int fFeedback;
79     private boolean fShowInsertionFeedback;
80     private boolean fFullWidthMatchesItem;
81     private int fRequestedOperation;
82     private int fLastOperation;
83     protected int fLocation;
84     protected Object JavaDoc fTarget;
85
86
87
88     public JdtViewerDropAdapter(StructuredViewer viewer, int feedback) {
89         Assert.isNotNull(viewer);
90         fViewer= viewer;
91         fFeedback= feedback;
92         fLastOperation= -1;
93         fFullWidthMatchesItem= true;
94     }
95
96     /**
97      * Controls whether the drop adapter shows insertion feedback or not.
98      *
99      * @param showInsertionFeedback <code>true</code> if the drop adapter is supposed
100      * to show insertion feedback. Otherwise <code>false</code>
101      */

102     public void showInsertionFeedback(boolean showInsertionFeedback) {
103         fShowInsertionFeedback= showInsertionFeedback;
104     }
105     
106     /**
107      * Controls whether the drop adapter matches an tree or table item on the full width of the viewer.
108      *
109      * @param enable <code>true</code> if the drop adapter is supposed
110      * to test the horizontal distance
111      */

112     protected void setFullWidthMatchesItem(boolean enable) {
113         fFullWidthMatchesItem= enable;
114     }
115     
116     /**
117      * Returns the viewer this adapter is working on.
118      */

119     protected StructuredViewer getViewer() {
120         return fViewer;
121     }
122     
123     //---- Hooks to override -----------------------------------------------------
124

125     /**
126      * The actual drop has occurred. Calls <code>drop(Object target, DropTargetEvent event)
127      * </code>.
128      * @see DropTargetListener#drop(org.eclipse.swt.dnd.DropTargetEvent)
129      */

130     public void drop(DropTargetEvent event) {
131         drop(fTarget, event);
132     }
133     
134     /**
135      * The actual drop has occurred.
136      * @param target the drop target in form of a domain element.
137      * @param event the drop traget event
138      */

139     public void drop(Object JavaDoc target, DropTargetEvent event) {
140     }
141     
142     /**
143      * Checks if the drop is valid. The method calls <code>validateDrop
144      * (Object target, DropTargetEvent event). Implementors can alter the
145      * <code>currentDataType</code> field and the <code>detail</code> field
146      * to give feedback about drop acceptence.
147      */

148     public void validateDrop(DropTargetEvent event) {
149         validateDrop(fTarget, event, fRequestedOperation);
150     }
151     
152     /**
153      * Checks if the drop on the current target is valid. The method
154      * can alter the <code>currentDataType</code> field and the <code>
155      * detail</code> field to give feedback about drop acceptence.
156      * @param target the drop target in form of a domain element.
157      * @param event the drop traget event
158      * @param operation the operation requested by the user.
159      */

160     public void validateDrop(Object JavaDoc target, DropTargetEvent event, int operation) {
161     }
162     
163     public void dragEnter(DropTargetEvent event) {
164         dragOperationChanged(event);
165     }
166     
167     public void dragLeave(DropTargetEvent event) {
168         fTarget= null;
169         fLocation= LOCATION_NONE;
170     }
171     
172     public void dragOperationChanged(DropTargetEvent event) {
173         fRequestedOperation= event.detail;
174         fTarget= computeTarget(event);
175         fLocation= computeLocation(event);
176         validateDrop(event);
177         fLastOperation= event.detail;
178         computeFeedback(event);
179     }
180     
181     public void dragOver(DropTargetEvent event) {
182         Object JavaDoc oldTarget= fTarget;
183         fTarget= computeTarget(event);
184         
185         //set the location feedback
186
int oldLocation= fLocation;
187         fLocation= computeLocation(event);
188         if (oldLocation != fLocation || oldTarget != fTarget || fLastOperation != event.detail) {
189             validateDrop(event);
190             fLastOperation= event.detail;
191         } else {
192             event.detail= fLastOperation;
193         }
194         computeFeedback(event);
195     }
196     
197     public void dropAccept(DropTargetEvent event) {
198         fTarget= computeTarget(event);
199         validateDrop(event);
200         fLastOperation= event.detail;
201     }
202     
203     /**
204      * Returns the data held by <code>event.item</code>. Inside a viewer
205      * this corresponds to the items data model element.
206      */

207     protected Object JavaDoc computeTarget(DropTargetEvent event) {
208         if (event.item == null) {
209             return null;
210         }
211         if (!fFullWidthMatchesItem) {
212             Point coordinates= fViewer.getControl().toControl(new Point(event.x, event.y));
213             Rectangle bounds= getBounds((Item) event.item);
214             if (coordinates.x < bounds.x - ITEM_MARGIN_LEFT || coordinates.x >= bounds.x + bounds.width + ITEM_MARGIN_RIGTH) {
215                 event.item= null; // too far away
216
return null;
217             }
218         }
219         return event.item.getData();
220     }
221     
222     /**
223      * Returns the position of the given coordinates relative to the given target.
224      * The position is determined to be before, after, or on the item, based on
225      * some threshold value. The return value is one of the LOCATION_* constants
226      * defined in this class.
227      */

228     protected int computeLocation(DropTargetEvent event) {
229         if (!(event.item instanceof Item))
230             return LOCATION_NONE;
231         
232         Item item= (Item) event.item;
233         Point coordinates= fViewer.getControl().toControl(new Point(event.x, event.y));
234         Rectangle bounds= getBounds(item);
235         if (bounds == null) {
236             return LOCATION_NONE;
237         }
238         if ((coordinates.y - bounds.y) < LOCATION_EPSILON) {
239             return LOCATION_BEFORE;
240         }
241         if ((bounds.y + bounds.height - coordinates.y) < LOCATION_EPSILON) {
242             return LOCATION_AFTER;
243         }
244         return LOCATION_ON;
245     }
246
247     /**
248      * Returns the bounds of the given item, or <code>null</code> if it is not a
249      * valid type of item.
250      */

251     private Rectangle getBounds(Item item) {
252         if (item instanceof TreeItem)
253             return ((TreeItem) item).getBounds();
254             
255         if (item instanceof TableItem)
256             return ((TableItem) item).getBounds(0);
257             
258         return null;
259     }
260
261     /**
262      * Sets the drag under feedback corresponding to the value of <code>fLocation</code>
263      * and the <code>INSERTION_FEEDBACK</code> style bit.
264      */

265     protected void computeFeedback(DropTargetEvent event) {
266         if (!fShowInsertionFeedback && fLocation != LOCATION_NONE) {
267             event.feedback= DND.FEEDBACK_SELECT;
268         } else {
269             event.feedback= fLocation;
270         }
271         event.feedback|= fFeedback;
272     }
273     
274     /**
275      * Sets the drop operation to </code>DROP_NODE<code>.
276      */

277     protected void clearDropOperation(DropTargetEvent event) {
278         event.detail= DND.DROP_NONE;
279     }
280     
281     /**
282      * Returns the requested drop operation.
283      */

284     protected int getRequestedOperation() {
285         return fRequestedOperation;
286     }
287     
288     protected void setDefaultFeedback(int feedback) {
289         fFeedback= feedback;
290     }
291     
292     //---- helper methods to test DnD
293

294     public void internalTestSetLocation(int location) {
295         fLocation= location;
296     }
297 }
298
Popular Tags