EMMA Coverage Report (generated Mon Sep 29 15:05:28 EDT 2008)
[all classes][org.eclipse.jface.util]

COVERAGE SUMMARY FOR SOURCE FILE [DelegatingDropAdapter.java]

nameclass, %method, %block, %line, %
DelegatingDropAdapter.java14%  (1/7)7%   (2/27)4%   (14/362)5%   (4/87)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class DelegatingDropAdapter$10%   (0/1)0%   (0/2)0%   (0/18)0%   (0/4)
DelegatingDropAdapter$1 (DelegatingDropAdapter, TransferDropTargetListener, D... 0%   (0/1)0%   (0/12)0%   (0/2)
run (): void 0%   (0/1)0%   (0/6)0%   (0/2)
     
class DelegatingDropAdapter$20%   (0/1)0%   (0/2)0%   (0/18)0%   (0/4)
DelegatingDropAdapter$2 (DelegatingDropAdapter, TransferDropTargetListener, D... 0%   (0/1)0%   (0/12)0%   (0/2)
run (): void 0%   (0/1)0%   (0/6)0%   (0/2)
     
class DelegatingDropAdapter$30%   (0/1)0%   (0/2)0%   (0/16)0%   (0/4)
DelegatingDropAdapter$3 (DelegatingDropAdapter, DropTargetEvent): void 0%   (0/1)0%   (0/9)0%   (0/2)
run (): void 0%   (0/1)0%   (0/7)0%   (0/2)
     
class DelegatingDropAdapter$40%   (0/1)0%   (0/2)0%   (0/16)0%   (0/4)
DelegatingDropAdapter$4 (DelegatingDropAdapter, DropTargetEvent): void 0%   (0/1)0%   (0/9)0%   (0/2)
run (): void 0%   (0/1)0%   (0/7)0%   (0/2)
     
class DelegatingDropAdapter$50%   (0/1)0%   (0/2)0%   (0/16)0%   (0/4)
DelegatingDropAdapter$5 (DelegatingDropAdapter, DropTargetEvent): void 0%   (0/1)0%   (0/9)0%   (0/2)
run (): void 0%   (0/1)0%   (0/7)0%   (0/2)
     
class DelegatingDropAdapter$60%   (0/1)0%   (0/2)0%   (0/16)0%   (0/4)
DelegatingDropAdapter$6 (DelegatingDropAdapter, DropTargetEvent): void 0%   (0/1)0%   (0/9)0%   (0/2)
run (): void 0%   (0/1)0%   (0/7)0%   (0/2)
     
class DelegatingDropAdapter100% (1/1)13%  (2/15)5%   (14/262)5%   (4/74)
dragEnter (DropTargetEvent): void 0%   (0/1)0%   (0/8)0%   (0/3)
dragLeave (DropTargetEvent): void 0%   (0/1)0%   (0/6)0%   (0/2)
dragOperationChanged (DropTargetEvent): void 0%   (0/1)0%   (0/26)0%   (0/7)
dragOver (DropTargetEvent): void 0%   (0/1)0%   (0/22)0%   (0/6)
drop (DropTargetEvent): void 0%   (0/1)0%   (0/18)0%   (0/5)
dropAccept (DropTargetEvent): void 0%   (0/1)0%   (0/10)0%   (0/3)
getCurrentListener (): TransferDropTargetListener 0%   (0/1)0%   (0/3)0%   (0/1)
getSupportedTransferType (TransferData [], TransferDropTargetListener): Trans... 0%   (0/1)0%   (0/21)0%   (0/4)
getTransfers (): Transfer [] 0%   (0/1)0%   (0/27)0%   (0/6)
isEmpty (): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
removeDropTargetListener (TransferDropTargetListener): void 0%   (0/1)0%   (0/13)0%   (0/4)
setCurrentListener (TransferDropTargetListener, DropTargetEvent): boolean 0%   (0/1)0%   (0/29)0%   (0/8)
updateCurrentListener (DropTargetEvent): void 0%   (0/1)0%   (0/61)0%   (0/20)
DelegatingDropAdapter (): void 100% (1/1)100% (8/8)100% (2/2)
addDropTargetListener (TransferDropTargetListener): void 100% (1/1)100% (6/6)100% (2/2)

1/*******************************************************************************
2 * Copyright (c) 2000, 2007 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 *******************************************************************************/
11package org.eclipse.jface.util;
12 
13import java.util.ArrayList;
14import java.util.Iterator;
15import java.util.List;
16 
17import org.eclipse.swt.dnd.DND;
18import org.eclipse.swt.dnd.DropTargetEvent;
19import org.eclipse.swt.dnd.DropTargetListener;
20import org.eclipse.swt.dnd.Transfer;
21import org.eclipse.swt.dnd.TransferData;
22 
23/**
24 * A <code>DelegatingDropAdapter</code> is a <code>DropTargetListener</code> that 
25 * maintains and delegates to a set of {@link TransferDropTargetListener}s. Each 
26 * <code>TransferDropTargetListener</code> can then be implemented as if it were 
27 * the DropTarget's only <code>DropTargetListener</code>.
28 * <p>
29 * On <code>dragEnter</code>, <code>dragOperationChanged</code>, <code>dragOver</code>
30 * and <code>drop</code>, a <i>current</i> listener is obtained from the set of all 
31 * <code>TransferDropTargetListeners</code>. The current listener is the first listener 
32 * to return <code>true</code> for 
33 * {@link TransferDropTargetListener#isEnabled(DropTargetEvent)}.
34 * The current listener is forwarded all <code>DropTargetEvents</code> until some other
35 * listener becomes the current listener, or the drop terminates.
36 * </p>
37 * <p>
38 * After adding all <code>TransferDropTargetListeners</code> to the 
39 * <code>DelegatingDropAdapter</code> the combined set of <code>Transfers</code> should 
40 * be set in the SWT <code>DropTarget</code>. <code>#getTransfers()</code> provides the 
41 * set of <code>Transfer</code> types of all <code>TransferDropTargetListeners</code>. 
42 * </p>
43 * <p>
44 * The following example snippet shows a <code>DelegatingDropAdapter</code> with two
45 * <code>TransferDropTargetListeners</code>. One supports dropping resources and 
46 * demonstrates how a listener can be disabled in the isEnabled method. 
47 * The other listener supports text transfer. 
48 * </p>
49 * <code><pre>
50 *                final TreeViewer viewer = new TreeViewer(shell, SWT.NONE);
51 *                 DelegatingDropAdapter dropAdapter = new DelegatingDropAdapter();
52 *                dropAdapter.addDropTargetListener(new TransferDropTargetListener() {
53 *                        public Transfer getTransfer() {
54 *                                return ResourceTransfer.getInstance();
55 *                        }
56 *                        public boolean isEnabled(DropTargetEvent event) {
57 *                                // disable drop listener if there is no viewer selection
58 *                                if (viewer.getSelection().isEmpty())
59 *                                        return false;
60 *                                return true;
61 *                        }
62 *                        public void dragEnter(DropTargetEvent event) {}
63 *                        public void dragLeave(DropTargetEvent event) {}
64 *                        public void dragOperationChanged(DropTargetEvent event) {}
65 *                        public void dragOver(DropTargetEvent event) {}
66 *                        public void drop(DropTargetEvent event) {
67 *                                if (event.data == null)
68 *                                        return;
69 *                                IResource[] resources = (IResource[]) event.data;
70 *                                if (event.detail == DND.DROP_COPY) {
71 *                                        // copy resources
72 *                                } else {
73 *                                        // move resources
74 *                                }
75 *                                        
76 *                        }
77 *                        public void dropAccept(DropTargetEvent event) {}
78 *                });
79 *                dropAdapter.addDropTargetListener(new TransferDropTargetListener() {
80 *                        public Transfer getTransfer() {
81 *                                return TextTransfer.getInstance();
82 *                        }
83 *                        public boolean isEnabled(DropTargetEvent event) {
84 *                                return true;
85 *                        }
86 *                        public void dragEnter(DropTargetEvent event) {}
87 *                        public void dragLeave(DropTargetEvent event) {}
88 *                        public void dragOperationChanged(DropTargetEvent event) {}
89 *                        public void dragOver(DropTargetEvent event) {}
90 *                        public void drop(DropTargetEvent event) {
91 *                                if (event.data == null)
92 *                                        return;
93 *                                System.out.println(event.data);
94 *                        }
95 *                        public void dropAccept(DropTargetEvent event) {}
96 *                });                
97 *                viewer.addDropSupport(DND.DROP_COPY | DND.DROP_MOVE, dropAdapter.getTransfers(), dropAdapter);
98 * </pre></code>
99 * @since 3.0
100 */
101public class DelegatingDropAdapter implements DropTargetListener {
102    private List listeners = new ArrayList();
103 
104    private TransferDropTargetListener currentListener;
105 
106    private int originalDropType;
107 
108    /**
109     * Adds the given <code>TransferDropTargetListener</code>.
110     * 
111     * @param listener the new listener
112     */
113    public void addDropTargetListener(TransferDropTargetListener listener) {
114        listeners.add(listener);
115    }
116 
117    /**
118     * The cursor has entered the drop target boundaries. The current listener is 
119     * updated, and <code>#dragEnter()</code> is forwarded to the current listener.
120     * 
121     * @param event the drop target event 
122     * @see DropTargetListener#dragEnter(DropTargetEvent)
123     */
124    public void dragEnter(DropTargetEvent event) {
125        //                if (Policy.DEBUG_DRAG_DROP)
126        //                        System.out.println("Drag Enter: " + toString()); //$NON-NLS-1$
127        originalDropType = event.detail;
128        updateCurrentListener(event);
129    }
130 
131    /**
132     * The cursor has left the drop target boundaries. The event is forwarded to the 
133     * current listener.
134     * 
135     * @param event the drop target event
136     * @see DropTargetListener#dragLeave(DropTargetEvent)
137     */
138    public void dragLeave(final DropTargetEvent event) {
139        //                if (Policy.DEBUG_DRAG_DROP)
140        //                        System.out.println("Drag Leave: " + toString()); //$NON-NLS-1$
141        setCurrentListener(null, event);
142    }
143 
144    /**
145     * The operation being performed has changed (usually due to the user changing 
146     * a drag modifier key while dragging). Updates the current listener and forwards 
147     * this event to that listener.
148     * 
149     * @param event the drop target event
150     * @see DropTargetListener#dragOperationChanged(DropTargetEvent)
151     */
152    public void dragOperationChanged(final DropTargetEvent event) {
153        //                if (Policy.DEBUG_DRAG_DROP)
154        //                        System.out.println("Drag Operation Changed to: " + event.detail); //$NON-NLS-1$
155        originalDropType = event.detail;
156        TransferDropTargetListener oldListener = getCurrentListener();
157        updateCurrentListener(event);
158        final TransferDropTargetListener newListener = getCurrentListener();
159        // only notify the current listener if it hasn't changed based on the 
160        // operation change. otherwise the new listener would get a dragEnter 
161        // followed by a dragOperationChanged with the exact same event. 
162        if (newListener != null && newListener == oldListener) {
163            SafeRunnable.run(new SafeRunnable() {
164                public void run() throws Exception {
165                    newListener.dragOperationChanged(event);
166                }
167            });
168        }
169    }
170 
171    /**
172     * The cursor is moving over the drop target. Updates the current listener and 
173     * forwards this event to that listener. If no listener can handle the drag 
174     * operation the <code>event.detail</code> field is set to <code>DND.DROP_NONE</code> 
175     * to indicate an invalid drop.
176     *   
177     * @param event the drop target event
178     * @see DropTargetListener#dragOver(DropTargetEvent)
179     */
180    public void dragOver(final DropTargetEvent event) {
181        TransferDropTargetListener oldListener = getCurrentListener();
182        updateCurrentListener(event);
183        final TransferDropTargetListener newListener = getCurrentListener();
184 
185        // only notify the current listener if it hasn't changed based on the 
186        // drag over. otherwise the new listener would get a dragEnter 
187        // followed by a dragOver with the exact same event. 
188        if (newListener != null && newListener == oldListener) {
189                SafeRunnable.run(new SafeRunnable() {
190                public void run() throws Exception {
191                    newListener.dragOver(event);
192                }
193            });
194        }
195    }
196 
197    /**
198     * Forwards this event to the current listener, if there is one. Sets the
199     * current listener to <code>null</code> afterwards.
200     * 
201     * @param event the drop target event
202     * @see DropTargetListener#drop(DropTargetEvent)
203     */
204    public void drop(final DropTargetEvent event) {
205        //                if (Policy.DEBUG_DRAG_DROP)
206        //                        System.out.println("Drop: " + toString()); //$NON-NLS-1$
207        updateCurrentListener(event);
208        if (getCurrentListener() != null) {
209                SafeRunnable.run(new SafeRunnable() {
210                public void run() throws Exception {
211                    getCurrentListener().drop(event);
212                }
213            });
214        }
215        setCurrentListener(null, event);
216    }
217 
218    /**
219     * Forwards this event to the current listener if there is one.
220     * 
221     * @param event the drop target event
222     * @see DropTargetListener#dropAccept(DropTargetEvent)
223     */
224    public void dropAccept(final DropTargetEvent event) {
225        //                if (Policy.DEBUG_DRAG_DROP)
226        //                        System.out.println("Drop Accept: " + toString()); //$NON-NLS-1$
227        if (getCurrentListener() != null) {
228                SafeRunnable.run(new SafeRunnable() {
229                public void run() throws Exception {
230                    getCurrentListener().dropAccept(event);
231                }
232            });
233        }
234    }
235 
236    /**
237     * Returns the listener which currently handles drop events.
238     * 
239     * @return the <code>TransferDropTargetListener</code> which currently 
240     *         handles drop events.
241     */
242    private TransferDropTargetListener getCurrentListener() {
243        return currentListener;
244    }
245 
246    /**
247     * Returns the transfer data type supported by the given listener.
248     * Returns <code>null</code> if the listener does not support any of the   
249     * specified data types.
250     *  
251     * @param dataTypes available data types
252     * @param listener <code>TransferDropTargetListener</code> to use for testing 
253     *         supported data types.
254     * @return the transfer data type supported by the given listener or 
255     *         <code>null</code>.
256     */
257    private TransferData getSupportedTransferType(TransferData[] dataTypes,
258            TransferDropTargetListener listener) {
259        for (int i = 0; i < dataTypes.length; i++) {
260            if (listener.getTransfer().isSupportedType(dataTypes[i])) {
261                return dataTypes[i];
262            }
263        }
264        return null;
265    }
266 
267    /**
268     * Returns the combined set of <code>Transfer</code> types of all 
269     * <code>TransferDropTargetListeners</code>.
270     * 
271     * @return the combined set of <code>Transfer</code> types
272     */
273    public Transfer[] getTransfers() {
274        Transfer[] types = new Transfer[listeners.size()];
275        for (int i = 0; i < listeners.size(); i++) {
276            TransferDropTargetListener listener = (TransferDropTargetListener) listeners
277                    .get(i);
278            types[i] = listener.getTransfer();
279        }
280        return types;
281    }
282 
283    /**
284     * Returns <code>true</code> if there are no listeners to delegate events to.
285     * 
286     * @return <code>true</code> if there are no <code>TransferDropTargetListeners</code>
287     *        <code>false</code> otherwise
288     */
289    public boolean isEmpty() {
290        return listeners.isEmpty();
291    }
292 
293    /**
294     * Removes the given <code>TransferDropTargetListener</code>.
295     * Listeners should not be removed while a drag and drop operation is in progress.
296     * 
297     * @param listener the listener to remove
298     */
299    public void removeDropTargetListener(TransferDropTargetListener listener) {
300        if (currentListener == listener) {
301                        currentListener = null;
302                }
303        listeners.remove(listener);
304    }
305 
306    /**
307     * Sets the current listener to <code>listener</code>. Sends the given 
308     * <code>DropTargetEvent</code> if the current listener changes.
309     * 
310     * @return <code>true</code> if the new listener is different than the previous
311     *        <code>false</code> otherwise
312     */
313    private boolean setCurrentListener(TransferDropTargetListener listener,
314            final DropTargetEvent event) {
315        if (currentListener == listener) {
316                        return false;
317                }
318        if (currentListener != null) {
319                SafeRunnable.run(new SafeRunnable() {
320                public void run() throws Exception {
321                    currentListener.dragLeave(event);
322                }
323            });
324        }
325        currentListener = listener;
326        //                if (Policy.DEBUG_DRAG_DROP)
327        //                        System.out.println("Current drop listener: " + listener); //$NON-NLS-1$
328        if (currentListener != null) {
329                SafeRunnable.run(new SafeRunnable() {
330                public void run() throws Exception {
331                    currentListener.dragEnter(event);
332                }
333            });
334        }
335        return true;
336    }
337 
338    /**
339     * Updates the current listener to one that can handle the drop. There can be many
340     * listeners and each listener may be able to handle many <code>TransferData</code> 
341     * types. The first listener found that can handle a drop of one of the given 
342     * <code>TransferData</code> types will be selected.
343     * If no listener can handle the drag operation the <code>event.detail</code> field
344     * is set to <code>DND.DROP_NONE</code> to indicate an invalid drop.
345     *
346     * @param event the drop target event
347     */
348    private void updateCurrentListener(DropTargetEvent event) {
349        int originalDetail = event.detail;
350        // revert the detail to the "original" drop type that the User indicated.
351        // this is necessary because the previous listener may have changed the detail 
352        // to something other than what the user indicated.
353        event.detail = originalDropType;
354 
355        Iterator iter = listeners.iterator();
356        while (iter.hasNext()) {
357            TransferDropTargetListener listener = (TransferDropTargetListener) iter
358                    .next();
359            TransferData dataType = getSupportedTransferType(event.dataTypes,
360                    listener);
361            if (dataType != null) {
362                TransferData originalDataType = event.currentDataType;
363                // set the data type supported by the drop listener
364                event.currentDataType = dataType;
365                if (listener.isEnabled(event)) {
366                    // if the listener stays the same, set its previously determined  
367                    // event detail 
368                    if (!setCurrentListener(listener, event)) {
369                                                event.detail = originalDetail;
370                                        }
371                    return;
372                }
373                                event.currentDataType = originalDataType;
374            }
375        }
376        setCurrentListener(null, event);
377        event.detail = DND.DROP_NONE;
378        
379        // -always- ensure that expand/scroll are on...otherwise
380        // if a valid drop target is a child of an invalid one
381        // you can't get there...
382        event.feedback = DND.FEEDBACK_EXPAND | DND.FEEDBACK_SCROLL;
383    }
384}

[all classes][org.eclipse.jface.util]
EMMA 2.0.5312 EclEmma Fix 1 (C) Vladimir Roubtsov