KickJava   Java API By Example, From Geeks To Geeks.

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


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 import org.eclipse.core.runtime.SafeRunner;
15
16 import org.eclipse.swt.dnd.DND;
17 import org.eclipse.swt.dnd.DropTargetEvent;
18 import org.eclipse.swt.dnd.DropTargetListener;
19 import org.eclipse.swt.dnd.Transfer;
20 import org.eclipse.swt.dnd.TransferData;
21
22 import org.eclipse.jface.util.SafeRunnable;
23 import org.eclipse.jface.util.TransferDropTargetListener;
24
25 /**
26  * A delegating drop adapter negotiates between a set of
27  * <code>TransferDropTargetListener</code> s On <code>dragEnter</code> the
28  * adapter determines the listener to be used for any further <code>drag*</code>
29  * callback.
30  */

31 public class DelegatingDropAdapter implements DropTargetListener {
32
33     private TransferDropTargetListener[] fListeners;
34     private TransferDropTargetListener fCurrentListener;
35     private int fOriginalDropType;
36
37     /**
38      * Creates a new delegating drop adapter.
39      *
40      * @param listeners an array of potential listeners
41      */

42     public DelegatingDropAdapter(TransferDropTargetListener[] listeners) {
43         Assert.isNotNull(listeners);
44         fListeners= listeners;
45     }
46
47     /**
48      * The cursor has entered the drop target boundaries. The current listener
49      * is updated, and <code>#dragEnter()</code> is forwarded to the current
50      * listener.
51      *
52      * @param event the drop target event
53      * @see DropTargetListener#dragEnter(DropTargetEvent)
54      */

55     public void dragEnter(DropTargetEvent event) {
56         fOriginalDropType= event.detail;
57         updateCurrentListener(event);
58     }
59
60     /**
61      * The cursor has left the drop target boundaries. The event is forwarded to
62      * the current listener.
63      *
64      * @param event the drop target event
65      * @see DropTargetListener#dragLeave(DropTargetEvent)
66      */

67     public void dragLeave(final DropTargetEvent event) {
68         setCurrentListener(null, event);
69     }
70
71     /**
72      * The operation being performed has changed (usually due to the user
73      * changing a drag modifier key while dragging). Updates the current
74      * listener and forwards this event to that listener.
75      *
76      * @param event the drop target event
77      * @see DropTargetListener#dragOperationChanged(DropTargetEvent)
78      */

79     public void dragOperationChanged(final DropTargetEvent event) {
80         fOriginalDropType= event.detail;
81         TransferDropTargetListener oldListener= getCurrentListener();
82         updateCurrentListener(event);
83         final TransferDropTargetListener newListener= getCurrentListener();
84         // only notify the current listener if it hasn't changed based on the
85
// operation change. otherwise the new listener would get a dragEnter
86
// followed by a dragOperationChanged with the exact same event.
87
if (newListener != null && newListener == oldListener) {
88             SafeRunner.run(new SafeRunnable() {
89                 public void run() throws Exception JavaDoc {
90                     newListener.dragOperationChanged(event);
91                 }
92             });
93         }
94     }
95
96     /**
97      * The cursor is moving over the drop target. Updates the current listener
98      * and forwards this event to that listener. If no listener can handle the
99      * drag operation the <code>event.detail</code> field is set to
100      * <code>DND.DROP_NONE</code> to indicate an invalid drop.
101      *
102      * @param event the drop target event
103      * @see DropTargetListener#dragOver(DropTargetEvent)
104      */

105     public void dragOver(final DropTargetEvent event) {
106         TransferDropTargetListener oldListener= getCurrentListener();
107         updateCurrentListener(event);
108         final TransferDropTargetListener newListener= getCurrentListener();
109
110         // only notify the current listener if it hasn't changed based on the
111
// drag over. otherwise the new listener would get a dragEnter
112
// followed by a dragOver with the exact same event.
113
if (newListener != null && newListener == oldListener) {
114             SafeRunner.run(new SafeRunnable() {
115                 public void run() throws Exception JavaDoc {
116                     newListener.dragOver(event);
117                 }
118             });
119         }
120     }
121
122     /**
123      * Forwards this event to the current listener, if there is one. Sets the
124      * current listener to <code>null</code> afterwards.
125      *
126      * @param event the drop target event
127      * @see DropTargetListener#drop(DropTargetEvent)
128      */

129     public void drop(final DropTargetEvent event) {
130         updateCurrentListener(event);
131         if (getCurrentListener() != null) {
132             SafeRunner.run(new SafeRunnable() {
133                 public void run() throws Exception JavaDoc {
134                     getCurrentListener().drop(event);
135                 }
136             });
137         }
138         setCurrentListener(null, event);
139     }
140
141     /**
142      * Forwards this event to the current listener if there is one.
143      *
144      * @param event the drop target event
145      * @see DropTargetListener#dropAccept(DropTargetEvent)
146      */

147     public void dropAccept(final DropTargetEvent event) {
148         if (getCurrentListener() != null) {
149             SafeRunner.run(new SafeRunnable() {
150                 public void run() throws Exception JavaDoc {
151                     getCurrentListener().dropAccept(event);
152                 }
153             });
154         }
155     }
156
157     /**
158      * Returns the listener which currently handles drop events.
159      *
160      * @return the <code>TransferDropTargetListener</code> which currently
161      * handles drop events.
162      */

163     private TransferDropTargetListener getCurrentListener() {
164         return fCurrentListener;
165     }
166
167     /**
168      * Returns the transfer data type supported by the given listener. Returns
169      * <code>null</code> if the listener does not support any of the specified
170      * data types.
171      *
172      * @param dataTypes available data types
173      * @param listener <code>TransferDropTargetListener</code> to use for
174      * testing supported data types.
175      * @return the transfer data type supported by the given listener or
176      * <code>null</code>.
177      */

178     private TransferData getSupportedTransferType(TransferData[] dataTypes, TransferDropTargetListener listener) {
179         for (int i= 0; i < dataTypes.length; i++) {
180             if (listener.getTransfer().isSupportedType(dataTypes[i])) {
181                 return dataTypes[i];
182             }
183         }
184         return null;
185     }
186
187     /**
188      * Returns the combined set of <code>Transfer</code> types of all
189      * <code>TransferDropTargetListeners</code>.
190      *
191      * @return the combined set of <code>Transfer</code> types
192      */

193     public Transfer[] getTransfers() {
194         Transfer[] types= new Transfer[fListeners.length];
195         for (int i= 0; i < fListeners.length; i++) {
196             types[i]= fListeners[i].getTransfer();
197         }
198         return types;
199     }
200
201     /**
202      * Sets the current listener to <code>listener</code>. Sends the given
203      * <code>DropTargetEvent</code> if the current listener changes.
204      *
205      * @return <code>true</code> if the new listener is different than the
206      * previous <code>false</code> otherwise
207      */

208     private boolean setCurrentListener(TransferDropTargetListener listener, final DropTargetEvent event) {
209         if (fCurrentListener == listener)
210             return false;
211         if (fCurrentListener != null) {
212             SafeRunner.run(new SafeRunnable() {
213                 public void run() throws Exception JavaDoc {
214                     fCurrentListener.dragLeave(event);
215                 }
216             });
217         }
218         fCurrentListener= listener;
219         if (fCurrentListener != null) {
220             SafeRunner.run(new SafeRunnable() {
221                 public void run() throws Exception JavaDoc {
222                     fCurrentListener.dragEnter(event);
223                 }
224             });
225         }
226         return true;
227     }
228
229     /**
230      * Updates the current listener to one that can handle the drop. There can
231      * be many listeners and each listener may be able to handle many
232      * <code>TransferData</code> types. The first listener found that can
233      * handle a drop of one of the given <code>TransferData</code> types will
234      * be selected. If no listener can handle the drag operation the
235      * <code>event.detail</code> field is set to <code>DND.DROP_NONE</code>
236      * to indicate an invalid drop.
237      *
238      * @param event the drop target event
239      */

240     private void updateCurrentListener(DropTargetEvent event) {
241         int originalDetail= event.detail;
242         // Revert the detail to the "original" drop type that the User
243
// indicated. This is necessary because the previous listener
244
// may have changed the detail to something other than what the
245
// user indicated.
246
event.detail= fOriginalDropType;
247
248         for (int i= 0; i < fListeners.length; i++) {
249             TransferDropTargetListener listener= fListeners[i];
250             TransferData dataType= getSupportedTransferType(event.dataTypes, listener);
251             if (dataType != null) {
252                 TransferData originalDataType= event.currentDataType;
253                 // set the data type supported by the drop listener
254
event.currentDataType= dataType;
255                 if (listener.isEnabled(event)) {
256                     // if the listener stays the same, set its previously
257
// determined
258
// event detail
259
if (!setCurrentListener(listener, event))
260                         event.detail= originalDetail;
261                     return;
262                 } else {
263                     event.currentDataType= originalDataType;
264                 }
265             }
266         }
267         setCurrentListener(null, event);
268         event.detail= DND.DROP_NONE;
269     }
270 }
271
Popular Tags