1 /*******************************************************************************
2  * Copyright (c) 2003, 2015 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.ui.navigator;
15 
16 import org.eclipse.core.runtime.IStatus;
17 import org.eclipse.core.runtime.Status;
18 import org.eclipse.jface.util.LocalSelectionTransfer;
19 import org.eclipse.jface.viewers.IStructuredSelection;
20 import org.eclipse.swt.dnd.DragSourceListener;
21 import org.eclipse.swt.dnd.DropTargetEvent;
22 import org.eclipse.swt.dnd.DropTargetListener;
23 import org.eclipse.swt.dnd.TransferData;
24 import org.eclipse.swt.widgets.Shell;
25 import org.eclipse.ui.internal.navigator.NavigatorContentService;
26 
27 /**
28  * <p>
29  * Used by the
30  * <b>org.eclipse.ui.navigator.navigatorContent/navigatorContent/commonDropAdapter</b>
31  * extension point to carry out pluggable drop operations.
32  * </p>
33  * <p>
34  * Each {@link CommonDropAdapterAssistant} is contained by single content
35  * extension. The opportunity for each assistant to handle the drop operation is
36  * determined by the <b>possibleChildren</b> expression of the
37  * <b>org.eclipse.ui.navigator.navigatorContent/navigatorContent</b> extension;
38  * whenever every element in the drag set matches the <b>possibleChildren</b>
39  * expression of an extension, it is eligible to handle the drop operation. This
40  * initial set is further culled using the <b>possibleDropTargets</b> expression
41  * of the <b>commonDropAdapter</b> using the current drop target.
42  * </p>
43  * <p>
44  * If drag operations originate outside of Eclipse, then the set of eligible
45  * drop adapters is determined based on the drop target (using the
46  * <b>possibleDropTargets</b> expression). Each assistant can then indicate
47  * whether {@link #isSupportedType(TransferData) the incoming type is
48  * supported}.
49  * <p>
50  * Whenever a match is found, the assistant will be given an opportunity to
51  * first {@link #validateDrop(Object, int, TransferData)}, and then if the
52  * assistant returns true, the assist must
53  * {@link #handleDrop(CommonDropAdapter, DropTargetEvent, Object)}. If multiple
54  * assistants match the drop target, then the potential assistants are ordered
55  * based on priority and their override relationships and given an opportunity
56  * to validate the drop operation in turn. The first one to validate will have
57  * the opportunty to carry out the drop.
58  * </p>
59  *
60  * <p>
61  * Clients may handle DND operations that begin and end in the current viewer by
62  * overriding the following methods:
63  * </p>
64  * <ul>
65  * <li>{@link #validateDrop(Object, int, TransferData)}: Indicate whether this
66  * assistant can handle a drop onto the current viewer.</li>
67  * <li>{@link #handleDrop(CommonDropAdapter, DropTargetEvent, Object)}: Handle
68  * the drop operation onto the current viewer.</li>
69  * </ul>
70  * <p>
71  * If a user originates a drag operation to another viewer that cannot handle
72  * one of the available drag transfer types, drop assistants may handle the drop
73  * operation for the target viewer. Clients must override :
74  * </p>
75  * <ul>
76  * <li>{@link #validatePluginTransferDrop(IStructuredSelection, Object)}:
77  * Indicate whether this assistant can handle the drop onto another viewer.
78  * <li>{@link #handlePluginTransferDrop(IStructuredSelection, Object)}: Handle
79  * the drop operation onto the other viewer.</li>
80  * </ul>
81  * <p>
82  * Clients may subclass this.
83  * </p>
84  *
85  * @see INavigatorDnDService
86  * @see INavigatorDnDService#findCommonDropAdapterAssistants(Object,
87  *      TransferData)
88  * @since 3.2
89  *
90  */
91 public abstract class CommonDropAdapterAssistant {
92 
93 	private INavigatorContentService contentService;
94 
95 	private DropTargetEvent _currentEvent;
96 
97 	private CommonDropAdapter _dropAdapter;
98 
99 	/**
100 	 * Perform any necessary initialization using the
101 	 * {@link INavigatorContentService}.
102 	 *
103 	 *
104 	 * @param aContentService
105 	 *            The instance of {@link INavigatorContentService} that the
106 	 *            current CommonDropAdapterAssistant will be associated with
107 	 */
init(INavigatorContentService aContentService)108 	public final void init(INavigatorContentService aContentService) {
109 		contentService = aContentService;
110 		doInit();
111 	}
112 
113 
114 	/**
115 	 * Override to perform any one-time initialization.
116 	 */
doInit()117 	protected void doInit() {
118 
119 	}
120 
121 	/**
122 	 * Validates dropping on the given object. This method is called whenever
123 	 * some aspect of the drop operation changes.
124 	 * <p>
125 	 * Subclasses must implement this method to define which drops make sense.
126 	 * If clients return true, then they will be allowed to handle the drop in
127 	 * {@link #handleDrop(CommonDropAdapter, DropTargetEvent, Object) }.
128 	 * </p>
129 	 *
130 	 * @param target
131 	 *            the object that the mouse is currently hovering over, or
132 	 *            <code>null</code> if the mouse is hovering over empty space
133 	 * @param operation
134 	 *            the current drag operation (copy, move, etc.)
135 	 * @param transferType
136 	 *            the current transfer type
137 	 * @return A status indicating whether the drop is valid.
138 	 */
validateDrop(Object target, int operation, TransferData transferType)139 	public abstract IStatus validateDrop(Object target, int operation,
140 			TransferData transferType);
141 
142 	/**
143 	 * Carry out the DND operation.
144 	 *
145 	 * <p>
146 	 * Note: Contrary to the SWT {@link DropTargetListener} specification, you
147 	 * <i>must</i> make sure that the aDropTargetEvent.detail is not set to
148 	 * DND.DROP_MOVE unless actual work is required in the
149 	 * {@link DragSourceListener#dragFinished(org.eclipse.swt.dnd.DragSourceEvent)}
150 	 * to complete the operation (for example removing the moved file). In
151 	 * particular for the LocalSelectionTransfer case, DND.DROP_MOVE cannot be
152 	 * used as it will cause incorrect behavior in some existing drag handlers.
153 	 *
154 	 * In case of move operations where no action is required on the source side
155 	 * (e.g. LocalSelectionTransfer) you must set aDropTargetEvent.detail to
156 	 * DND.DROP_NONE to signal this to the drag source. Even though the SWT
157 	 * specification says this is canceling the drop, it is not really doing so,
158 	 * it is only preventing the DND.DROP_MOVE from being passed through to the
159 	 * dragFinished() method.
160 	 *
161 	 * @param aDropAdapter
162 	 *            The Drop Adapter contains information that has already been
163 	 *            parsed from the drop event.
164 	 * @param aDropTargetEvent
165 	 *            The drop target event.
166 	 * @param aTarget
167 	 *            The object being dragged onto
168 	 * @return A status indicating whether the drop completed OK.
169 	 */
handleDrop(CommonDropAdapter aDropAdapter, DropTargetEvent aDropTargetEvent, Object aTarget)170 	public abstract IStatus handleDrop(CommonDropAdapter aDropAdapter,
171 			DropTargetEvent aDropTargetEvent, Object aTarget);
172 
173 	/**
174 	 * Clients may extend the supported transfer types beyond the default
175 	 * {@link LocalSelectionTransfer#getTransfer()} and
176 	 * {@link org.eclipse.ui.part.PluginTransfer#getInstance()} transfer types. When a transfer type
177 	 * other than one of these is encountered, the DND Service will query the
178 	 * <b>visible</b> and <b>active</b> descriptors that are <b>enabled</b>
179 	 * for the drop target of the current operation.
180 	 *
181 	 * @param aTransferType
182 	 *            The transfer data from the drop operation
183 	 * @return True if the given TransferData can be understood by this
184 	 *         assistant.
185 	 */
isSupportedType(TransferData aTransferType)186 	public boolean isSupportedType(TransferData aTransferType) {
187 		return LocalSelectionTransfer.getTransfer().isSupportedType(
188 				aTransferType);
189 	}
190 
191 	/**
192 	 *
193 	 * Return true if the client can handle the drop onto the target viewer of
194 	 * the drop operation.
195 	 * <p>
196 	 * The default behavior of this method is to return <b>Status.CANCEL_STATUS</b>.
197 	 * </p>
198 	 *
199 	 * @param aDragSelection
200 	 *            The selection dragged from the viewer.
201 	 * @param aDropTarget
202 	 *            The target of the drop operation.
203 	 *
204 	 * @return OK if the plugin transfer can be handled by this assistant.
205 	 */
validatePluginTransferDrop( IStructuredSelection aDragSelection, Object aDropTarget)206 	public IStatus validatePluginTransferDrop(
207 			IStructuredSelection aDragSelection, Object aDropTarget) {
208 		return Status.CANCEL_STATUS;
209 	}
210 
211 	/**
212 	 * Handle the drop operation for the target viewer.
213 	 * <p>
214 	 * The default behavior of this method is to return <b>Status.CANCEL_STATUS</b>.
215 	 * </p>
216 	 *
217 	 * @param aDragSelection
218 	 *            The selection dragged from the viewer.
219 	 * @param aDropTarget
220 	 *            The target of the drop operation.
221 	 *
222 	 * @return OK if the drop operation succeeded.
223 	 */
handlePluginTransferDrop( IStructuredSelection aDragSelection, Object aDropTarget)224 	public IStatus handlePluginTransferDrop(
225 			IStructuredSelection aDragSelection, Object aDropTarget) {
226 		return Status.CANCEL_STATUS;
227 	}
228 
229 	/**
230 	 *
231 	 * @return The associated content service.
232 	 */
getContentService()233 	protected INavigatorContentService getContentService() {
234 		return contentService;
235 	}
236 
237 	/**
238 	 *
239 	 * @return A shell for the viewer currently used by the
240 	 *         {@link INavigatorContentService}.
241 	 */
getShell()242 	protected final Shell getShell() {
243 		return ((NavigatorContentService) contentService).getShell();
244 	}
245 
246 	/**
247 	 * Sets the current {@link DropTargetEvent}.
248 	 *
249 	 * This is used to make the event available to the client methods of this class.
250 	 *
251 	 * @param event
252 	 *            the new event.
253 	 *
254 	 * @since 3.4
255 	 */
setCurrentEvent(DropTargetEvent event)256 	void setCurrentEvent(DropTargetEvent event) {
257 		_currentEvent = event;
258 	}
259 
260 	/**
261 	 * Returns the current {@link DropTargetEvent}.
262 	 *
263 	 * @return event the current DropTargetEvent.
264 	 *
265 	 * @since 3.4
266 	 */
getCurrentEvent()267 	public DropTargetEvent getCurrentEvent() {
268 		return _currentEvent;
269 	}
270 
271 	/**
272 	 * Sets the {@link CommonDropAdapter}.
273 	 *
274 	 * @param dropAdapter the drop adapter
275 	 *
276 	 * @noreference This method is not intended to be referenced by clients.
277 	 * @nooverride This method is not intended to be re-implemented or extended by
278 	 *             clients.
279 	 */
setCommonDropAdapter(CommonDropAdapter dropAdapter)280 	public void setCommonDropAdapter(CommonDropAdapter dropAdapter) {
281 		_dropAdapter = dropAdapter;
282 	}
283 
284 	/**
285 	 * Returns the {@link CommonDropAdapter}.
286 	 *
287 	 * @return the CommonDropAdapter.
288 	 *
289 	 * @since 3.4
290 	 *
291 	 */
getCommonDropAdapter()292 	protected CommonDropAdapter getCommonDropAdapter() {
293 		return _dropAdapter;
294 	}
295 
296 }
297