1. /*
  2. * @(#)DropTargetContext.java 1.37 04/05/05
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt.dnd;
  8. import java.awt.Component;
  9. import java.awt.datatransfer.DataFlavor;
  10. import java.awt.datatransfer.Transferable;
  11. import java.awt.datatransfer.UnsupportedFlavorException;
  12. import java.awt.dnd.peer.DropTargetContextPeer;
  13. import java.io.IOException;
  14. import java.io.Serializable;
  15. import java.util.Arrays;
  16. import java.util.List;
  17. /**
  18. * A <code>DropTargetContext</code> is created
  19. * whenever the logical cursor associated
  20. * with a Drag and Drop operation coincides with the visible geometry of
  21. * a <code>Component</code> associated with a <code>DropTarget</code>.
  22. * The <code>DropTargetContext</code> provides
  23. * the mechanism for a potential receiver
  24. * of a drop operation to both provide the end user with the appropriate
  25. * drag under feedback, but also to effect the subsequent data transfer
  26. * if appropriate.
  27. *
  28. * @version 1.37, 05/05/04
  29. * @since 1.2
  30. */
  31. public class DropTargetContext implements Serializable {
  32. private static final long serialVersionUID = -634158968993743371L;
  33. /**
  34. * Construct a <code>DropTargetContext</code>
  35. * given a specified <code>DropTarget</code>.
  36. * <P>
  37. * @param dt the DropTarget to associate with
  38. */
  39. DropTargetContext(DropTarget dt) {
  40. super();
  41. dropTarget = dt;
  42. }
  43. /**
  44. * This method returns the <code>DropTarget</code> associated with this
  45. * <code>DropTargetContext</code>.
  46. * <P>
  47. * @return the <code>DropTarget</code> associated with this <code>DropTargetContext</code>
  48. */
  49. public DropTarget getDropTarget() { return dropTarget; }
  50. /**
  51. * This method returns the <code>Component</code> associated with
  52. * this <code>DropTargetContext</code>.
  53. * <P>
  54. * @return the Component associated with this Context
  55. */
  56. public Component getComponent() { return dropTarget.getComponent(); }
  57. /**
  58. * Called when associated with the <code>DropTargetContextPeer</code>.
  59. * <P>
  60. * @param dtcp the <code>DropTargetContextPeer</code>
  61. */
  62. public void addNotify(DropTargetContextPeer dtcp) {
  63. dropTargetContextPeer = dtcp;
  64. }
  65. /**
  66. * Called when disassociated with the <code>DropTargetContextPeer</code>.
  67. */
  68. public void removeNotify() {
  69. dropTargetContextPeer = null;
  70. transferable = null;
  71. }
  72. /**
  73. * This method sets the current actions acceptable to
  74. * this <code>DropTarget</code>.
  75. * <P>
  76. * @param actions an <code>int</code> representing the supported action(s)
  77. */
  78. protected void setTargetActions(int actions) {
  79. DropTargetContextPeer peer = getDropTargetContextPeer();
  80. if (peer != null) {
  81. synchronized (peer) {
  82. peer.setTargetActions(actions);
  83. getDropTarget().doSetDefaultActions(actions);
  84. }
  85. } else {
  86. getDropTarget().doSetDefaultActions(actions);
  87. }
  88. }
  89. /**
  90. * This method returns an <code>int</code> representing the
  91. * current actions this <code>DropTarget</code> will accept.
  92. * <P>
  93. * @return the current actions acceptable to this <code>DropTarget</code>
  94. */
  95. protected int getTargetActions() {
  96. DropTargetContextPeer peer = getDropTargetContextPeer();
  97. return ((peer != null)
  98. ? peer.getTargetActions()
  99. : dropTarget.getDefaultActions()
  100. );
  101. }
  102. /**
  103. * This method signals that the drop is completed and
  104. * if it was successful or not.
  105. * <P>
  106. * @param success true for success, false if not
  107. * <P>
  108. * @throws InvalidDnDOperationException if a drop is not outstanding/extant
  109. */
  110. public void dropComplete(boolean success) throws InvalidDnDOperationException{
  111. DropTargetContextPeer peer = getDropTargetContextPeer();
  112. if (peer != null) {
  113. peer.dropComplete(success);
  114. }
  115. }
  116. /**
  117. * accept the Drag.
  118. * <P>
  119. * @param dragOperation the supported action(s)
  120. */
  121. protected void acceptDrag(int dragOperation) {
  122. DropTargetContextPeer peer = getDropTargetContextPeer();
  123. if (peer != null) {
  124. peer.acceptDrag(dragOperation);
  125. }
  126. }
  127. /**
  128. * reject the Drag.
  129. */
  130. protected void rejectDrag() {
  131. DropTargetContextPeer peer = getDropTargetContextPeer();
  132. if (peer != null) {
  133. peer.rejectDrag();
  134. }
  135. }
  136. /**
  137. * called to signal that the drop is acceptable
  138. * using the specified operation.
  139. * must be called during DropTargetListener.drop method invocation.
  140. * <P>
  141. * @param dropOperation the supported action(s)
  142. */
  143. protected void acceptDrop(int dropOperation) {
  144. DropTargetContextPeer peer = getDropTargetContextPeer();
  145. if (peer != null) {
  146. peer.acceptDrop(dropOperation);
  147. }
  148. }
  149. /**
  150. * called to signal that the drop is unacceptable.
  151. * must be called during DropTargetListener.drop method invocation.
  152. */
  153. protected void rejectDrop() {
  154. DropTargetContextPeer peer = getDropTargetContextPeer();
  155. if (peer != null) {
  156. peer.rejectDrop();
  157. }
  158. }
  159. /**
  160. * get the available DataFlavors of the
  161. * <code>Transferable</code> operand of this operation.
  162. * <P>
  163. * @return a <code>DataFlavor[]</code> containing the
  164. * supported <code>DataFlavor</code>s of the
  165. * <code>Transferable</code> operand.
  166. */
  167. protected DataFlavor[] getCurrentDataFlavors() {
  168. DropTargetContextPeer peer = getDropTargetContextPeer();
  169. return peer != null ? peer.getTransferDataFlavors() : new DataFlavor[0];
  170. }
  171. /**
  172. * This method returns a the currently available DataFlavors
  173. * of the <code>Transferable</code> operand
  174. * as a <code>java.util.List</code>.
  175. * <P>
  176. * @return the currently available
  177. * DataFlavors as a <code>java.util.List</code>
  178. */
  179. protected List<DataFlavor> getCurrentDataFlavorsAsList() {
  180. return Arrays.asList(getCurrentDataFlavors());
  181. }
  182. /**
  183. * This method returns a <code>boolean</code>
  184. * indicating if the given <code>DataFlavor</code> is
  185. * supported by this <code>DropTargetContext</code>.
  186. * <P>
  187. * @param df the <code>DataFlavor</code>
  188. * <P>
  189. * @return if the <code>DataFlavor</code> specified is supported
  190. */
  191. protected boolean isDataFlavorSupported(DataFlavor df) {
  192. return getCurrentDataFlavorsAsList().contains(df);
  193. }
  194. /**
  195. * get the Transferable (proxy) operand of this operation
  196. * <P>
  197. * @throws InvalidDnDOperationException if a drag is not outstanding/extant
  198. * <P>
  199. * @return the <code>Transferable</code>
  200. */
  201. protected Transferable getTransferable() throws InvalidDnDOperationException {
  202. DropTargetContextPeer peer = getDropTargetContextPeer();
  203. if (peer == null) {
  204. throw new InvalidDnDOperationException();
  205. } else {
  206. if (transferable == null) {
  207. Transferable t = peer.getTransferable();
  208. boolean isLocal = peer.isTransferableJVMLocal();
  209. synchronized (this) {
  210. if (transferable == null) {
  211. transferable = createTransferableProxy(t, isLocal);
  212. }
  213. }
  214. }
  215. return transferable;
  216. }
  217. }
  218. /**
  219. * Get the <code>DropTargetContextPeer</code>
  220. * <P>
  221. * @return the platform peer
  222. */
  223. DropTargetContextPeer getDropTargetContextPeer() {
  224. return dropTargetContextPeer;
  225. }
  226. /**
  227. * Creates a TransferableProxy to proxy for the specified
  228. * Transferable.
  229. *
  230. * @param t the <tt>Transferable</tt> to be proxied
  231. * @param local <tt>true</tt> if <tt>t</tt> represents
  232. * the result of a local drag-n-drop operation.
  233. * @return the new <tt>TransferableProxy</tt> instance.
  234. */
  235. protected Transferable createTransferableProxy(Transferable t, boolean local) {
  236. return new TransferableProxy(t, local);
  237. }
  238. /****************************************************************************/
  239. /**
  240. * <code>TransferableProxy</code> is a helper inner class that implements
  241. * <code>Transferable</code> interface and serves as a proxy for another
  242. * <code>Transferable</code> object which represents data transfer for
  243. * a particular drag-n-drop operation.
  244. * <p>
  245. * The proxy forwards all requests to the encapsulated transferable
  246. * and automatically performs additional conversion on the data
  247. * returned by the encapsulated transferable in case of local transfer.
  248. */
  249. protected class TransferableProxy implements Transferable {
  250. /**
  251. * Constructs a <code>TransferableProxy</code> given
  252. * a specified <code>Transferable</code> object representing
  253. * data transfer for a particular drag-n-drop operation and
  254. * a <code>boolean</code> which indicates whether the
  255. * drag-n-drop operation is local (within the same JVM).
  256. * <p>
  257. * @param t the <code>Transferable</code> object
  258. * @param local <code>true</code>, if <code>t</code> represents
  259. * the result of local drag-n-drop operation
  260. */
  261. TransferableProxy(Transferable t, boolean local) {
  262. proxy = new sun.awt.datatransfer.TransferableProxy(t, local);
  263. transferable = t;
  264. isLocal = local;
  265. }
  266. /**
  267. * Returns an array of DataFlavor objects indicating the flavors
  268. * the data can be provided in by the encapsulated transferable.
  269. * <p>
  270. * @return an array of data flavors in which the data can be
  271. * provided by the encapsulated transferable
  272. */
  273. public DataFlavor[] getTransferDataFlavors() {
  274. return proxy.getTransferDataFlavors();
  275. }
  276. /**
  277. * Returns whether or not the specified data flavor is supported by
  278. * the encapsulated transferable.
  279. * @param flavor the requested flavor for the data
  280. * @return <code>true</code> if the data flavor is supported,
  281. * <code>false</code> otherwise
  282. */
  283. public boolean isDataFlavorSupported(DataFlavor flavor) {
  284. return proxy.isDataFlavorSupported(flavor);
  285. }
  286. /**
  287. * Returns an object which represents the data provided by
  288. * the encapsulated transferable for the requested data flavor.
  289. * <p>
  290. * In case of local transfer a serialized copy of the object
  291. * returned by the encapsulated transferable is provided when
  292. * the data is requested in application/x-java-serialized-object
  293. * data flavor.
  294. *
  295. * @param df the requested flavor for the data
  296. * @throws IOException if the data is no longer available
  297. * in the requested flavor.
  298. * @throws UnsupportedFlavorException if the requested data flavor is
  299. * not supported.
  300. */
  301. public Object getTransferData(DataFlavor df)
  302. throws UnsupportedFlavorException, IOException
  303. {
  304. return proxy.getTransferData(df);
  305. }
  306. /*
  307. * fields
  308. */
  309. // We don't need to worry about client code changing the values of
  310. // these variables. Since TransferableProxy is a protected class, only
  311. // subclasses of DropTargetContext can access it. And DropTargetContext
  312. // cannot be subclassed by client code because it does not have a
  313. // public constructor.
  314. /**
  315. * The encapsulated <code>Transferable</code> object.
  316. */
  317. protected Transferable transferable;
  318. /**
  319. * A <code>boolean</code> indicating if the encapsulated
  320. * <code>Transferable</code> object represents the result
  321. * of local drag-n-drop operation (within the same JVM).
  322. */
  323. protected boolean isLocal;
  324. private sun.awt.datatransfer.TransferableProxy proxy;
  325. }
  326. /****************************************************************************/
  327. /*
  328. * fields
  329. */
  330. /**
  331. * The DropTarget associated with this DropTargetContext.
  332. *
  333. * @serial
  334. */
  335. private DropTarget dropTarget;
  336. private transient DropTargetContextPeer dropTargetContextPeer;
  337. private transient Transferable transferable;
  338. }