KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > EditorSiteDragAndDropServiceImpl


1 /*******************************************************************************
2  * Copyright (c) 2006, 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  *******************************************************************************/

11
12 package org.eclipse.ui.internal;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.List JavaDoc;
17
18 import org.eclipse.swt.dnd.DND;
19 import org.eclipse.swt.dnd.DropTarget;
20 import org.eclipse.swt.dnd.DropTargetEvent;
21 import org.eclipse.swt.dnd.DropTargetListener;
22 import org.eclipse.swt.dnd.Transfer;
23 import org.eclipse.swt.dnd.TransferData;
24 import org.eclipse.swt.widgets.Control;
25 import org.eclipse.ui.PlatformUI;
26 import org.eclipse.ui.dnd.IDragAndDropService;
27 import org.eclipse.ui.services.IDisposable;
28
29 /**
30  * Implementation for the <code>IDragAndDropService</code> to be used from
31  * <code>EditorSite</code>'s.
32  * </p><p>
33  * Adds a drop target to the given control that merges the site's
34  * drop behaviour with that specified by the <code>addMergedDropTarget</code> call.
35  * </p><p>
36  * The current implementation is only defined for EditorSite's and merges the
37  * given drop handling with the existing EditorSashContainer's behaviour.
38  * </p><p>
39  * NOTE: There is no cleanup (i.e. 'dispose') handling necessary for merged
40  * Drop Targets but the hooks are put into place to maintain the consistency
41  * of the implementation pattern.
42  * </p>
43  * @since 3.3
44  *
45  */

46 public class EditorSiteDragAndDropServiceImpl implements IDragAndDropService, IDisposable {
47     /**
48      * Implementation of a DropTarget wrapper that will either delegate to the
49      * <code>primaryListener</code> if the event's <code>currentDataType</code>
50      * can be handled by it; otherwise the event is forwarded on to the
51      * listener specified by <code>secondaryListener</code>.
52      * </p><p>
53      * NOTE: we should perhaps refactor this out into an external class
54      * </p>
55      * @since 3.3
56      *
57      */

58     private static class MergedDropTarget {
59         private DropTarget realDropTarget;
60         
61         private Transfer[] secondaryTransfers;
62         private DropTargetListener secondaryListener;
63         
64         private Transfer[] primaryTransfers;
65         private DropTargetListener primaryListener;
66         
67         public MergedDropTarget(Control control,
68                 int priOps, Transfer[] priTransfers, DropTargetListener priListener,
69                 int secOps, Transfer[] secTransfers, DropTargetListener secListener) {
70             realDropTarget = new DropTarget(control, priOps | secOps);
71             
72             // Cache the editor's transfers and listener
73
primaryTransfers = priTransfers;
74             primaryListener = priListener;
75             
76             // Capture the editor area's current transfers & listener
77
WorkbenchWindow ww = (WorkbenchWindow) PlatformUI.getWorkbench().getActiveWorkbenchWindow();
78             WorkbenchWindowConfigurer winConfigurer = ww.getWindowConfigurer();
79             secondaryTransfers = winConfigurer.getTransfers();
80             secondaryListener = winConfigurer.getDropTargetListener();
81             
82             // Combine the two sets of transfers into one array
83
Transfer[] allTransfers = new Transfer[secondaryTransfers.length+primaryTransfers.length];
84             int curTransfer = 0;
85             for (int i = 0; i < primaryTransfers.length; i++) {
86                 allTransfers[curTransfer++] = primaryTransfers[i];
87             }
88             for (int i = 0; i < secondaryTransfers.length; i++) {
89                 allTransfers[curTransfer++] = secondaryTransfers[i];
90             }
91             realDropTarget.setTransfer(allTransfers);
92             
93             // Create a listener that will delegate to the appropriate listener
94
// NOTE: the -editor- wins (i.e. it can over-ride WB behaviour if it wants
95
realDropTarget.addDropListener(new DropTargetListener() {
96                 public void dragEnter(DropTargetEvent event) {
97                     getAppropriateListener(event).dragEnter(event);
98                 }
99                 public void dragLeave(DropTargetEvent event) {
100                     getAppropriateListener(event).dragLeave(event);
101                 }
102                 public void dragOperationChanged(DropTargetEvent event) {
103                     getAppropriateListener(event).dragOperationChanged(event);
104                 }
105                 public void dragOver(DropTargetEvent event) {
106                     getAppropriateListener(event).dragOver(event);
107                 }
108                 public void drop(DropTargetEvent event) {
109                     getAppropriateListener(event).drop(event);
110                 }
111                 public void dropAccept(DropTargetEvent event) {
112                     getAppropriateListener(event).dropAccept(event);
113                 }
114             });
115         }
116
117         private DropTargetListener getAppropriateListener(DropTargetEvent event) {
118             if (isSupportedType(primaryTransfers, event.currentDataType))
119                 return primaryListener;
120             
121             return secondaryListener;
122         }
123         
124         private boolean isSupportedType(Transfer[] transfers, TransferData transferType) {
125             for (int i = 0; i < transfers.length; i++) {
126                 if (transfers[i].isSupportedType(transferType))
127                     return true;
128             }
129             return false;
130         }
131
132         /**
133          * Clean up...
134          */

135         public void dispose() {
136         }
137     }
138     
139     // Cache any listeners for cleanup
140
List JavaDoc addedListeners = new ArrayList JavaDoc();
141
142     /* (non-Javadoc)
143      * @see org.eclipse.ui.dnd.IEditorDropTargetService#addDropTarget(org.eclipse.swt.widgets.Control, int, org.eclipse.swt.dnd.Transfer[], org.eclipse.swt.dnd.DropTargetListener)
144      */

145     public void addMergedDropTarget(Control control, int ops, Transfer[] transfers,
146             DropTargetListener listener) {
147          // First we have to remove any existing drop target from the control
148
removeMergedDropTarget(control);
149         
150         // Capture the editor area's current ops, transfers & listener
151
int editorSiteOps = DND.DROP_DEFAULT | DND.DROP_COPY | DND.DROP_LINK;
152
153         WorkbenchWindow ww = (WorkbenchWindow) PlatformUI.getWorkbench().getActiveWorkbenchWindow();
154         WorkbenchWindowConfigurer winConfigurer = ww.getWindowConfigurer();
155         Transfer[] editorSiteTransfers = winConfigurer.getTransfers();
156         DropTargetListener editorSiteListener = winConfigurer.getDropTargetListener();
157         
158         // Create a new 'merged' drop Listener using combination of the desired
159
// transfers and the ones used by the EditorArea
160
MergedDropTarget newTarget = new MergedDropTarget(control, ops, transfers, listener,
161                 editorSiteOps, editorSiteTransfers, editorSiteListener);
162         addedListeners.add(newTarget);
163     }
164
165     /**
166      * This method will return the current drop target for the control
167      * (whether or not it was created using this service.
168      * <p>
169      * <b>WARNING:</b> This code uses an SWT internal string to gain
170      * access to the drop target. I've been assured that neither the
171      * value of the string nor the fact that the target is stored in
172      * a property will change for 3.3 and that post-3.3 we will come
173      * up with a more viable DnD SWT story...
174      * </p>
175      * @param control The control to get the drop target for
176      * @return The DropTarget for that control (could be null
177      */

178     private DropTarget getCurrentDropTarget(Control control) {
179         if (control == null)
180             return null;
181         
182         Object JavaDoc curDT = control.getData("DropTarget"); //$NON-NLS-1$
183
return (DropTarget)curDT;
184     }
185     
186     /* (non-Javadoc)
187      * @see org.eclipse.ui.dnd.IDragAndDropService#removeMergedDropTarget(org.eclipse.swt.widgets.Control)
188      */

189     public void removeMergedDropTarget(Control control) {
190         DropTarget targetForControl = getCurrentDropTarget(control);
191         if (targetForControl != null) {
192             targetForControl.dispose();
193             addedListeners.remove(targetForControl);
194         }
195     }
196
197     /* (non-Javadoc)
198      * @see org.eclipse.ui.services.IDisposable#dispose()
199      */

200     public void dispose() {
201         // Clean up the listeners
202
for (Iterator JavaDoc iterator = addedListeners.iterator(); iterator.hasNext();) {
203             MergedDropTarget target = (MergedDropTarget) iterator.next();
204             target.dispose();
205         }
206         addedListeners.clear();
207     }
208
209 }
210
Popular Tags