KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > util > DelegatingDragAdapter


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.jface.util;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.List JavaDoc;
16
17 import org.eclipse.swt.dnd.DragSource;
18 import org.eclipse.swt.dnd.DragSourceEvent;
19 import org.eclipse.swt.dnd.DragSourceListener;
20 import org.eclipse.swt.dnd.Transfer;
21 import org.eclipse.swt.dnd.TransferData;
22
23 /**
24  * A <code>DelegatingDragAdapter</code> is a <code>DragSourceListener</code> that
25  * maintains and delegates to a set of {@link TransferDragSourceListener}s. Each
26  * TransferDragSourceListener can then be implemented as if it were the
27  * <code>DragSource's</code> only DragSourceListener.
28  * <p>
29  * When a drag is started, a subset of all <code>TransferDragSourceListeners</code>
30  * is generated and stored in a list of <i>active</i> listeners. This subset is
31  * calculated by forwarding {@link DragSourceListener#dragStart(DragSourceEvent)} to
32  * every listener, and checking if the {@link DragSourceEvent#doit doit} field is left
33  * set to <code>true</code>.
34  * </p>
35  * The <code>DragSource</code>'s set of supported Transfer types ({@link
36  * DragSource#setTransfer(Transfer[])}) is updated to reflect the Transfer types
37  * corresponding to the active listener subset.
38  * <p>
39  * If and when {@link #dragSetData(DragSourceEvent)} is called, a single
40  * <code>TransferDragSourceListener</code> is chosen, and only it is allowed to set the
41  * drag data. The chosen listener is the first listener in the subset of active listeners
42  * whose Transfer supports ({@link Transfer#isSupportedType(TransferData)}) the
43  * <code>dataType</code> in the <code>DragSourceEvent</code>.
44  * </p>
45  * <p>
46  * The following example snippet shows a <code>DelegatingDragAdapter</code> with two
47  * <code>TransferDragSourceListeners</code>. One implements drag of text strings,
48  * the other supports file transfer and demonstrates how a listener can be disabled using
49  * the dragStart method.
50  * </p>
51  * <code><pre>
52  * final TreeViewer viewer = new TreeViewer(shell, SWT.NONE);
53  *
54  * DelegatingDragAdapter dragAdapter = new DelegatingDragAdapter();
55  * dragAdapter.addDragSourceListener(new TransferDragSourceListener() {
56  * public Transfer getTransfer() {
57  * return TextTransfer.getInstance();
58  * }
59  * public void dragStart(DragSourceEvent event) {
60  * // always enabled, can control enablement based on selection etc.
61  * }
62  * public void dragSetData(DragSourceEvent event) {
63  * event.data = "Transfer data";
64  * }
65  * public void dragFinished(DragSourceEvent event) {
66  * // no clean-up required
67  * }
68  * });
69  * dragAdapter.addDragSourceListener(new TransferDragSourceListener() {
70  * public Transfer getTransfer() {
71  * return FileTransfer.getInstance();
72  * }
73  * public void dragStart(DragSourceEvent event) {
74  * // enable drag listener if there is a viewer selection
75  * event.doit = !viewer.getSelection().isEmpty();
76  * }
77  * public void dragSetData(DragSourceEvent event) {
78  * File file1 = new File("C:/temp/file1");
79  * File file2 = new File("C:/temp/file2");
80  * event.data = new String[] {file1.getAbsolutePath(), file2.getAbsolutePath()};
81  * }
82  * public void dragFinished(DragSourceEvent event) {
83  * // no clean-up required
84  * }
85  * });
86  * viewer.addDragSupport(DND.DROP_COPY | DND.DROP_MOVE, dragAdapter.getTransfers(), dragAdapter);
87  * </pre></code>
88  * @since 3.0
89  */

90 public class DelegatingDragAdapter implements DragSourceListener {
91     private List JavaDoc listeners = new ArrayList JavaDoc();
92
93     private List JavaDoc activeListeners = new ArrayList JavaDoc();
94
95     private TransferDragSourceListener currentListener;
96
97     /**
98      * Adds the given <code>TransferDragSourceListener</code>.
99      *
100      * @param listener the new listener
101      */

102     public void addDragSourceListener(TransferDragSourceListener listener) {
103         listeners.add(listener);
104     }
105
106     /**
107      * The drop has successfully completed. This event is forwarded to the current
108      * drag listener.
109      * Doesn't update the current listener, since the current listener is already the one
110      * that completed the drag operation.
111      *
112      * @param event the drag source event
113      * @see DragSourceListener#dragFinished(DragSourceEvent)
114      */

115     public void dragFinished(final DragSourceEvent event) {
116         // if (Policy.DEBUG_DRAG_DROP)
117
// System.out.println("Drag Finished: " + toString()); //$NON-NLS-1$
118
SafeRunnable.run(new SafeRunnable() {
119             public void run() throws Exception JavaDoc {
120                 if (currentListener != null) {
121                     // there is a listener that can handle the drop, delegate the event
122
currentListener.dragFinished(event);
123                 } else {
124                     // The drag was canceled and currentListener was never set, so send the
125
// dragFinished event to all the active listeners.
126
Iterator JavaDoc iterator = activeListeners.iterator();
127                     while (iterator.hasNext()) {
128                         ((TransferDragSourceListener) iterator.next())
129                                 .dragFinished(event);
130                     }
131                 }
132             }
133         });
134         currentListener = null;
135         activeListeners.clear();
136     }
137
138     /**
139      * The drop data is requested.
140      * Updates the current listener and then forwards the event to it.
141      *
142      * @param event the drag source event
143      * @see DragSourceListener#dragSetData(DragSourceEvent)
144      */

145     public void dragSetData(final DragSourceEvent event) {
146         // if (Policy.DEBUG_DRAG_DROP)
147
// System.out.println("Drag Set Data: " + toString()); //$NON-NLS-1$
148

149         updateCurrentListener(event); // find a listener that can provide the given data type
150
if (currentListener != null) {
151             SafeRunnable.run(new SafeRunnable() {
152                 public void run() throws Exception JavaDoc {
153                     currentListener.dragSetData(event);
154                 }
155             });
156         }
157     }
158
159     /**
160      * A drag operation has started.
161      * Forwards this event to each listener. A listener must set <code>event.doit</code>
162      * to <code>false</code> if it cannot handle the drag operation. If a listener can
163      * handle the drag, it is added to the list of active listeners.
164      * The drag is aborted if there are no listeners that can handle it.
165      *
166      * @param event the drag source event
167      * @see DragSourceListener#dragStart(DragSourceEvent)
168      */

169     public void dragStart(final DragSourceEvent event) {
170         // if (Policy.DEBUG_DRAG_DROP)
171
// System.out.println("Drag Start: " + toString()); //$NON-NLS-1$
172
boolean doit = false; // true if any one of the listeners can handle the drag
173
List JavaDoc transfers = new ArrayList JavaDoc(listeners.size());
174
175         activeListeners.clear();
176         for (int i = 0; i < listeners.size(); i++) {
177             final TransferDragSourceListener listener = (TransferDragSourceListener) listeners
178                     .get(i);
179             event.doit = true; // restore event.doit
180
SafeRunnable.run(new SafeRunnable() {
181                 public void run() throws Exception JavaDoc {
182                     listener.dragStart(event);
183                 }
184             });
185             if (event.doit) { // the listener can handle this drag
186
transfers.add(listener.getTransfer());
187                 activeListeners.add(listener);
188             }
189             doit |= event.doit;
190         }
191
192         if (doit) {
193             ((DragSource) event.widget).setTransfer((Transfer[]) transfers
194                     .toArray(new Transfer[transfers.size()]));
195         }
196
197         event.doit = doit;
198     }
199
200     /**
201      * Returns the <code>Transfer<code>s from every <code>TransferDragSourceListener</code>.
202      *
203      * @return the combined <code>Transfer</code>s
204      */

205     public Transfer[] getTransfers() {
206         Transfer[] types = new Transfer[listeners.size()];
207         for (int i = 0; i < listeners.size(); i++) {
208             TransferDragSourceListener listener = (TransferDragSourceListener) listeners
209                     .get(i);
210             types[i] = listener.getTransfer();
211         }
212         return types;
213     }
214
215     /**
216      * Returns <code>true</code> if there are no listeners to delegate drag events to.
217      *
218      * @return <code>true</code> if there are no <code>TransferDragSourceListeners</code>
219      * <code>false</code> otherwise.
220      */

221     public boolean isEmpty() {
222         return listeners.isEmpty();
223     }
224
225     /**
226      * Removes the given <code>TransferDragSourceListener</code>.
227      * Listeners should not be removed while a drag and drop operation is in progress.
228      *
229      * @param listener the <code>TransferDragSourceListener</code> to remove
230      */

231     public void removeDragSourceListener(TransferDragSourceListener listener) {
232         listeners.remove(listener);
233         if (currentListener == listener) {
234             currentListener = null;
235         }
236         if (activeListeners.contains(listener)) {
237             activeListeners.remove(listener);
238         }
239     }
240
241     /**
242      * Updates the current listener to one that can handle the drag. There can
243      * be many listeners and each listener may be able to handle many <code>TransferData</code>
244      * types. The first listener found that supports one of the <code>TransferData</ode>
245      * types specified in the <code>DragSourceEvent</code> will be selected.
246      *
247      * @param event the drag source event
248      */

249     private void updateCurrentListener(DragSourceEvent event) {
250         currentListener = null;
251         if (event.dataType == null) {
252             return;
253         }
254         Iterator JavaDoc iterator = activeListeners.iterator();
255         while (iterator.hasNext()) {
256             TransferDragSourceListener listener = (TransferDragSourceListener) iterator
257                     .next();
258
259             if (listener.getTransfer().isSupportedType(event.dataType)) {
260                 // if (Policy.DEBUG_DRAG_DROP)
261
// System.out.println("Current drag listener: " + listener); //$NON-NLS-1$
262
currentListener = listener;
263                 return;
264             }
265         }
266     }
267
268 }
269
Popular Tags