001 /*
002 * Copyright 1997-2004 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.awt.dnd;
027
028 import java.awt.Component;
029
030 import java.awt.datatransfer.DataFlavor;
031 import java.awt.datatransfer.Transferable;
032 import java.awt.datatransfer.UnsupportedFlavorException;
033
034 import java.awt.dnd.peer.DropTargetContextPeer;
035
036 import java.io.IOException;
037 import java.io.Serializable;
038
039 import java.util.Arrays;
040 import java.util.List;
041
042 /**
043 * A <code>DropTargetContext</code> is created
044 * whenever the logical cursor associated
045 * with a Drag and Drop operation coincides with the visible geometry of
046 * a <code>Component</code> associated with a <code>DropTarget</code>.
047 * The <code>DropTargetContext</code> provides
048 * the mechanism for a potential receiver
049 * of a drop operation to both provide the end user with the appropriate
050 * drag under feedback, but also to effect the subsequent data transfer
051 * if appropriate.
052 *
053 * @version 1.44, 05/05/07
054 * @since 1.2
055 */
056
057 public class DropTargetContext implements Serializable {
058
059 private static final long serialVersionUID = -634158968993743371L;
060
061 /**
062 * Construct a <code>DropTargetContext</code>
063 * given a specified <code>DropTarget</code>.
064 * <P>
065 * @param dt the DropTarget to associate with
066 */
067
068 DropTargetContext(DropTarget dt) {
069 super ();
070
071 dropTarget = dt;
072 }
073
074 /**
075 * This method returns the <code>DropTarget</code> associated with this
076 * <code>DropTargetContext</code>.
077 * <P>
078 * @return the <code>DropTarget</code> associated with this <code>DropTargetContext</code>
079 */
080
081 public DropTarget getDropTarget() {
082 return dropTarget;
083 }
084
085 /**
086 * This method returns the <code>Component</code> associated with
087 * this <code>DropTargetContext</code>.
088 * <P>
089 * @return the Component associated with this Context
090 */
091
092 public Component getComponent() {
093 return dropTarget.getComponent();
094 }
095
096 /**
097 * Called when associated with the <code>DropTargetContextPeer</code>.
098 * <P>
099 * @param dtcp the <code>DropTargetContextPeer</code>
100 */
101
102 public void addNotify(DropTargetContextPeer dtcp) {
103 dropTargetContextPeer = dtcp;
104 }
105
106 /**
107 * Called when disassociated with the <code>DropTargetContextPeer</code>.
108 */
109
110 public void removeNotify() {
111 dropTargetContextPeer = null;
112 transferable = null;
113 }
114
115 /**
116 * This method sets the current actions acceptable to
117 * this <code>DropTarget</code>.
118 * <P>
119 * @param actions an <code>int</code> representing the supported action(s)
120 */
121
122 protected void setTargetActions(int actions) {
123 DropTargetContextPeer peer = getDropTargetContextPeer();
124 if (peer != null) {
125 synchronized (peer) {
126 peer.setTargetActions(actions);
127 getDropTarget().doSetDefaultActions(actions);
128 }
129 } else {
130 getDropTarget().doSetDefaultActions(actions);
131 }
132 }
133
134 /**
135 * This method returns an <code>int</code> representing the
136 * current actions this <code>DropTarget</code> will accept.
137 * <P>
138 * @return the current actions acceptable to this <code>DropTarget</code>
139 */
140
141 protected int getTargetActions() {
142 DropTargetContextPeer peer = getDropTargetContextPeer();
143 return ((peer != null) ? peer.getTargetActions() : dropTarget
144 .getDefaultActions());
145 }
146
147 /**
148 * This method signals that the drop is completed and
149 * if it was successful or not.
150 * <P>
151 * @param success true for success, false if not
152 * <P>
153 * @throws InvalidDnDOperationException if a drop is not outstanding/extant
154 */
155
156 public void dropComplete(boolean success)
157 throws InvalidDnDOperationException {
158 DropTargetContextPeer peer = getDropTargetContextPeer();
159 if (peer != null) {
160 peer.dropComplete(success);
161 }
162 }
163
164 /**
165 * accept the Drag.
166 * <P>
167 * @param dragOperation the supported action(s)
168 */
169
170 protected void acceptDrag(int dragOperation) {
171 DropTargetContextPeer peer = getDropTargetContextPeer();
172 if (peer != null) {
173 peer.acceptDrag(dragOperation);
174 }
175 }
176
177 /**
178 * reject the Drag.
179 */
180
181 protected void rejectDrag() {
182 DropTargetContextPeer peer = getDropTargetContextPeer();
183 if (peer != null) {
184 peer.rejectDrag();
185 }
186 }
187
188 /**
189 * called to signal that the drop is acceptable
190 * using the specified operation.
191 * must be called during DropTargetListener.drop method invocation.
192 * <P>
193 * @param dropOperation the supported action(s)
194 */
195
196 protected void acceptDrop(int dropOperation) {
197 DropTargetContextPeer peer = getDropTargetContextPeer();
198 if (peer != null) {
199 peer.acceptDrop(dropOperation);
200 }
201 }
202
203 /**
204 * called to signal that the drop is unacceptable.
205 * must be called during DropTargetListener.drop method invocation.
206 */
207
208 protected void rejectDrop() {
209 DropTargetContextPeer peer = getDropTargetContextPeer();
210 if (peer != null) {
211 peer.rejectDrop();
212 }
213 }
214
215 /**
216 * get the available DataFlavors of the
217 * <code>Transferable</code> operand of this operation.
218 * <P>
219 * @return a <code>DataFlavor[]</code> containing the
220 * supported <code>DataFlavor</code>s of the
221 * <code>Transferable</code> operand.
222 */
223
224 protected DataFlavor[] getCurrentDataFlavors() {
225 DropTargetContextPeer peer = getDropTargetContextPeer();
226 return peer != null ? peer.getTransferDataFlavors()
227 : new DataFlavor[0];
228 }
229
230 /**
231 * This method returns a the currently available DataFlavors
232 * of the <code>Transferable</code> operand
233 * as a <code>java.util.List</code>.
234 * <P>
235 * @return the currently available
236 * DataFlavors as a <code>java.util.List</code>
237 */
238
239 protected List<DataFlavor> getCurrentDataFlavorsAsList() {
240 return Arrays.asList(getCurrentDataFlavors());
241 }
242
243 /**
244 * This method returns a <code>boolean</code>
245 * indicating if the given <code>DataFlavor</code> is
246 * supported by this <code>DropTargetContext</code>.
247 * <P>
248 * @param df the <code>DataFlavor</code>
249 * <P>
250 * @return if the <code>DataFlavor</code> specified is supported
251 */
252
253 protected boolean isDataFlavorSupported(DataFlavor df) {
254 return getCurrentDataFlavorsAsList().contains(df);
255 }
256
257 /**
258 * get the Transferable (proxy) operand of this operation
259 * <P>
260 * @throws InvalidDnDOperationException if a drag is not outstanding/extant
261 * <P>
262 * @return the <code>Transferable</code>
263 */
264
265 protected Transferable getTransferable()
266 throws InvalidDnDOperationException {
267 DropTargetContextPeer peer = getDropTargetContextPeer();
268 if (peer == null) {
269 throw new InvalidDnDOperationException();
270 } else {
271 if (transferable == null) {
272 Transferable t = peer.getTransferable();
273 boolean isLocal = peer.isTransferableJVMLocal();
274 synchronized (this ) {
275 if (transferable == null) {
276 transferable = createTransferableProxy(t,
277 isLocal);
278 }
279 }
280 }
281
282 return transferable;
283 }
284 }
285
286 /**
287 * Get the <code>DropTargetContextPeer</code>
288 * <P>
289 * @return the platform peer
290 */
291
292 DropTargetContextPeer getDropTargetContextPeer() {
293 return dropTargetContextPeer;
294 }
295
296 /**
297 * Creates a TransferableProxy to proxy for the specified
298 * Transferable.
299 *
300 * @param t the <tt>Transferable</tt> to be proxied
301 * @param local <tt>true</tt> if <tt>t</tt> represents
302 * the result of a local drag-n-drop operation.
303 * @return the new <tt>TransferableProxy</tt> instance.
304 */
305 protected Transferable createTransferableProxy(Transferable t,
306 boolean local) {
307 return new TransferableProxy(t, local);
308 }
309
310 /****************************************************************************/
311
312 /**
313 * <code>TransferableProxy</code> is a helper inner class that implements
314 * <code>Transferable</code> interface and serves as a proxy for another
315 * <code>Transferable</code> object which represents data transfer for
316 * a particular drag-n-drop operation.
317 * <p>
318 * The proxy forwards all requests to the encapsulated transferable
319 * and automatically performs additional conversion on the data
320 * returned by the encapsulated transferable in case of local transfer.
321 */
322
323 protected class TransferableProxy implements Transferable {
324
325 /**
326 * Constructs a <code>TransferableProxy</code> given
327 * a specified <code>Transferable</code> object representing
328 * data transfer for a particular drag-n-drop operation and
329 * a <code>boolean</code> which indicates whether the
330 * drag-n-drop operation is local (within the same JVM).
331 * <p>
332 * @param t the <code>Transferable</code> object
333 * @param local <code>true</code>, if <code>t</code> represents
334 * the result of local drag-n-drop operation
335 */
336 TransferableProxy(Transferable t, boolean local) {
337 proxy = new sun.awt.datatransfer.TransferableProxy(t, local);
338 transferable = t;
339 isLocal = local;
340 }
341
342 /**
343 * Returns an array of DataFlavor objects indicating the flavors
344 * the data can be provided in by the encapsulated transferable.
345 * <p>
346 * @return an array of data flavors in which the data can be
347 * provided by the encapsulated transferable
348 */
349 public DataFlavor[] getTransferDataFlavors() {
350 return proxy.getTransferDataFlavors();
351 }
352
353 /**
354 * Returns whether or not the specified data flavor is supported by
355 * the encapsulated transferable.
356 * @param flavor the requested flavor for the data
357 * @return <code>true</code> if the data flavor is supported,
358 * <code>false</code> otherwise
359 */
360 public boolean isDataFlavorSupported(DataFlavor flavor) {
361 return proxy.isDataFlavorSupported(flavor);
362 }
363
364 /**
365 * Returns an object which represents the data provided by
366 * the encapsulated transferable for the requested data flavor.
367 * <p>
368 * In case of local transfer a serialized copy of the object
369 * returned by the encapsulated transferable is provided when
370 * the data is requested in application/x-java-serialized-object
371 * data flavor.
372 *
373 * @param df the requested flavor for the data
374 * @throws IOException if the data is no longer available
375 * in the requested flavor.
376 * @throws UnsupportedFlavorException if the requested data flavor is
377 * not supported.
378 */
379 public Object getTransferData(DataFlavor df)
380 throws UnsupportedFlavorException, IOException {
381 return proxy.getTransferData(df);
382 }
383
384 /*
385 * fields
386 */
387
388 // We don't need to worry about client code changing the values of
389 // these variables. Since TransferableProxy is a protected class, only
390 // subclasses of DropTargetContext can access it. And DropTargetContext
391 // cannot be subclassed by client code because it does not have a
392 // public constructor.
393 /**
394 * The encapsulated <code>Transferable</code> object.
395 */
396 protected Transferable transferable;
397
398 /**
399 * A <code>boolean</code> indicating if the encapsulated
400 * <code>Transferable</code> object represents the result
401 * of local drag-n-drop operation (within the same JVM).
402 */
403 protected boolean isLocal;
404
405 private sun.awt.datatransfer.TransferableProxy proxy;
406 }
407
408 /****************************************************************************/
409
410 /*
411 * fields
412 */
413
414 /**
415 * The DropTarget associated with this DropTargetContext.
416 *
417 * @serial
418 */
419 private DropTarget dropTarget;
420
421 private transient DropTargetContextPeer dropTargetContextPeer;
422
423 private transient Transferable transferable;
424 }
|