1. /*
  2. * @(#)DragSource.java 1.42 03/01/23
  3. *
  4. * Copyright 2003 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.AWTError;
  9. import java.awt.AWTException;
  10. import java.awt.event.InputEvent;
  11. import java.awt.AWTPermission;
  12. import java.awt.Component;
  13. import java.awt.Cursor;
  14. import java.awt.GraphicsEnvironment;
  15. import java.awt.HeadlessException;
  16. import java.awt.Image;
  17. import java.awt.Point;
  18. import java.awt.Toolkit;
  19. import java.awt.datatransfer.FlavorMap;
  20. import java.awt.datatransfer.SystemFlavorMap;
  21. import java.awt.datatransfer.Transferable;
  22. import java.awt.dnd.peer.DragSourceContextPeer;
  23. import java.io.Serializable;
  24. import java.io.IOException;
  25. import java.io.ObjectInputStream;
  26. import java.io.ObjectOutputStream;
  27. import java.io.Serializable;
  28. import java.security.AccessController;
  29. import java.util.EventListener;
  30. import sun.awt.dnd.SunDragSourceContextPeer;
  31. /**
  32. * The <code>DragSource</code> is the entity responsible
  33. * for the initiation of the Drag
  34. * and Drop operation, and may be used in a number of scenarios:
  35. * <UL>
  36. * <LI>1 default instance per JVM for the lifetime of that JVM.
  37. * <LI>1 instance per class of potential Drag Initiator object (e.g
  38. * TextField). [implementation dependent]
  39. * <LI>1 per instance of a particular
  40. * <code>Component</code>, or application specific
  41. * object associated with a <code>Component</code>
  42. * instance in the GUI. [implementation dependent]
  43. * <LI>Some other arbitrary association. [implementation dependent]
  44. *</UL>
  45. *
  46. * Once the <code>DragSource</code> is
  47. * obtained, a <code>DragGestureRecognizer</code> should
  48. * also be obtained to associate the <code>DragSource</code>
  49. * with a particular
  50. * <code>Component</code>.
  51. * <P>
  52. * The initial interpretation of the user's gesture,
  53. * and the subsequent starting of the drag operation
  54. * are the responsibility of the implementing
  55. * <code>Component</code>, which is usually
  56. * implemented by a <code>DragGestureRecognizer</code>.
  57. *<P>
  58. * When a drag gesture occurs, the
  59. * <code>DragSource</code>'s
  60. * startDrag() method shall be
  61. * invoked in order to cause processing
  62. * of the user's navigational
  63. * gestures and delivery of Drag and Drop
  64. * protocol notifications. A
  65. * <code>DragSource</code> shall only
  66. * permit a single Drag and Drop operation to be
  67. * current at any one time, and shall
  68. * reject any further startDrag() requests
  69. * by throwing an <code>IllegalDnDOperationException</code>
  70. * until such time as the extant operation is complete.
  71. * <P>
  72. * The startDrag() method invokes the
  73. * createDragSourceContext() method to
  74. * instantiate an appropriate
  75. * <code>DragSourceContext</code>
  76. * and associate the <code>DragSourceContextPeer</code>
  77. * with that.
  78. * <P>
  79. * If the Drag and Drop System is
  80. * unable to initiate a drag operation for
  81. * some reason, the startDrag() method throws
  82. * a <code>java.awt.dnd.InvalidDnDOperationException</code>
  83. * to signal such a condition. Typically this
  84. * exception is thrown when the underlying platform
  85. * system is either not in a state to
  86. * initiate a drag, or the parameters specified are invalid.
  87. * <P>
  88. * Note that during the drag, the
  89. * set of operations exposed by the source
  90. * at the start of the drag operation may not change
  91. * until the operation is complete.
  92. * The operation(s) are constant for the
  93. * duration of the operation with respect to the
  94. * <code>DragSource</code>.
  95. *
  96. * @version 1.42, 01/23/03
  97. * @since 1.2
  98. */
  99. public class DragSource implements Serializable {
  100. private static final long serialVersionUID = 6236096958971414066L;
  101. /*
  102. * load a system default cursor
  103. */
  104. private static Cursor load(String name) {
  105. if (GraphicsEnvironment.isHeadless()) {
  106. return null;
  107. }
  108. try {
  109. return (Cursor)Toolkit.getDefaultToolkit().getDesktopProperty(name);
  110. } catch (Exception e) {
  111. e.printStackTrace();
  112. throw new RuntimeException("failed to load system cursor: " + name + " : " + e.getMessage());
  113. }
  114. }
  115. /**
  116. * The default <code>Cursor</code> to use with a copy operation indicating
  117. * that a drop is currently allowed. <code>null</code> if
  118. * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>.
  119. *
  120. * @see java.awt.GraphicsEnvironment#isHeadless
  121. */
  122. public static final Cursor DefaultCopyDrop =
  123. load("DnD.Cursor.CopyDrop");
  124. /**
  125. * The default <code>Cursor</code> to use with a move operation indicating
  126. * that a drop is currently allowed. <code>null</code> if
  127. * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>.
  128. *
  129. * @see java.awt.GraphicsEnvironment#isHeadless
  130. */
  131. public static final Cursor DefaultMoveDrop =
  132. load("DnD.Cursor.MoveDrop");
  133. /**
  134. * The default <code>Cursor</code> to use with a link operation indicating
  135. * that a drop is currently allowed. <code>null</code> if
  136. * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>.
  137. *
  138. * @see java.awt.GraphicsEnvironment#isHeadless
  139. */
  140. public static final Cursor DefaultLinkDrop =
  141. load("DnD.Cursor.LinkDrop");
  142. /**
  143. * The default <code>Cursor</code> to use with a copy operation indicating
  144. * that a drop is currently not allowed. <code>null</code> if
  145. * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>.
  146. *
  147. * @see java.awt.GraphicsEnvironment#isHeadless
  148. */
  149. public static final Cursor DefaultCopyNoDrop =
  150. load("DnD.Cursor.CopyNoDrop");
  151. /**
  152. * The default <code>Cursor</code> to use with a move operation indicating
  153. * that a drop is currently not allowed. <code>null</code> if
  154. * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>.
  155. *
  156. * @see java.awt.GraphicsEnvironment#isHeadless
  157. */
  158. public static final Cursor DefaultMoveNoDrop =
  159. load("DnD.Cursor.MoveNoDrop");
  160. /**
  161. * The default <code>Cursor</code> to use with a link operation indicating
  162. * that a drop is currently not allowed. <code>null</code> if
  163. * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>.
  164. *
  165. * @see java.awt.GraphicsEnvironment#isHeadless
  166. */
  167. public static final Cursor DefaultLinkNoDrop =
  168. load("DnD.Cursor.LinkNoDrop");
  169. private static final DragSource dflt =
  170. (GraphicsEnvironment.isHeadless()) ? null : new DragSource();
  171. /**
  172. * Internal constants for serialization.
  173. */
  174. static final String dragSourceListenerK = "dragSourceL";
  175. static final String dragSourceMotionListenerK = "dragSourceMotionL";
  176. /**
  177. * Gets the <code>DragSource</code> object associated with
  178. * the underlying platform.
  179. *
  180. * @return the platform DragSource
  181. * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  182. * returns true
  183. * @see java.awt.GraphicsEnvironment#isHeadless
  184. */
  185. public static DragSource getDefaultDragSource() {
  186. if (GraphicsEnvironment.isHeadless()) {
  187. throw new HeadlessException();
  188. } else {
  189. return dflt;
  190. }
  191. }
  192. /**
  193. * Reports
  194. * whether or not drag
  195. * <code>Image</code> support
  196. * is available on the underlying platform.
  197. * <P>
  198. * @return if the Drag Image support is available on this platform
  199. */
  200. public static boolean isDragImageSupported() {
  201. Toolkit t = Toolkit.getDefaultToolkit();
  202. Boolean supported;
  203. try {
  204. supported = (Boolean)Toolkit.getDefaultToolkit().getDesktopProperty("DnD.isDragImageSupported");
  205. return supported.booleanValue();
  206. } catch (Exception e) {
  207. return false;
  208. }
  209. }
  210. /**
  211. * Creates a new <code>DragSource</code>.
  212. *
  213. * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  214. * returns true
  215. * @see java.awt.GraphicsEnvironment#isHeadless
  216. */
  217. public DragSource() throws HeadlessException {
  218. if (GraphicsEnvironment.isHeadless()) {
  219. throw new HeadlessException();
  220. }
  221. }
  222. /**
  223. * Start a drag, given the <code>DragGestureEvent</code>
  224. * that initiated the drag, the initial
  225. * <code>Cursor</code> to use,
  226. * the <code>Image</code> to drag,
  227. * the offset of the <code>Image</code> origin
  228. * from the hotspot of the <code>Cursor</code> at
  229. * the instant of the trigger,
  230. * the <code>Transferable</code> subject data
  231. * of the drag, the <code>DragSourceListener</code>,
  232. * and the <code>FlavorMap</code>.
  233. * <P>
  234. * @param trigger the <code>DragGestureEvent</code> that initiated the drag
  235. * @param dragCursor the initial <code>Cursor</code> or <code>null</code> for defaults
  236. * @param dragImage the image to drag or null,
  237. * @param imageOffset the offset of the <code>Image</code> origin from the hotspot
  238. * of the <code>Cursor</code> at the instant of the trigger
  239. * @param transferable the subject data of the drag
  240. * @param dsl the <code>DragSourceListener</code>
  241. * @param flavorMap the <code>FlavorMap</code> to use, or <code>null</code>
  242. * <P>
  243. * @throws <code>java.awt.dnd.InvalidDnDOperationException</code>
  244. * if the Drag and Drop
  245. * system is unable to initiate a drag operation, or if the user
  246. * attempts to start a drag while an existing drag operation
  247. * is still executing
  248. */
  249. public void startDrag(DragGestureEvent trigger,
  250. Cursor dragCursor,
  251. Image dragImage,
  252. Point imageOffset,
  253. Transferable transferable,
  254. DragSourceListener dsl,
  255. FlavorMap flavorMap) throws InvalidDnDOperationException {
  256. SunDragSourceContextPeer.setDragDropInProgress(true);
  257. try {
  258. if (flavorMap != null) this.flavorMap = flavorMap;
  259. DragSourceContextPeer dscp = Toolkit.getDefaultToolkit().createDragSourceContextPeer(trigger);
  260. DragSourceContext dsc = createDragSourceContext(dscp,
  261. trigger,
  262. dragCursor,
  263. dragImage,
  264. imageOffset,
  265. transferable,
  266. dsl
  267. );
  268. if (dsc == null) {
  269. throw new InvalidDnDOperationException();
  270. }
  271. dscp.startDrag(dsc, dsc.getCursor(), dragImage, imageOffset); // may throw
  272. } catch (RuntimeException e) {
  273. SunDragSourceContextPeer.setDragDropInProgress(false);
  274. throw e;
  275. }
  276. }
  277. /**
  278. * Start a drag, given the <code>DragGestureEvent</code>
  279. * that initiated the drag, the initial
  280. * <code>Cursor</code> to use,
  281. * the <code>Transferable</code> subject data
  282. * of the drag, the <code>DragSourceListener</code>,
  283. * and the <code>FlavorMap</code>.
  284. * <P>
  285. * @param trigger the <code>DragGestureEvent</code> that
  286. * initiated the drag
  287. * @param dragCursor the initial <code>Cursor</code> or
  288. * <code>null</code> for defaults
  289. * @param transferable the subject data of the drag
  290. * @param dsl the <code>DragSourceListener</code>
  291. * @param flavorMap the <code>FlavorMap to use or <code>null</code>
  292. * <P>
  293. * @throws <code>java.awt.dnd.InvalidDnDOperationException</code>
  294. * if the Drag and Drop
  295. * system is unable to initiate a drag operation, or if the user
  296. * attempts to start a drag while an existing drag operation
  297. * is still executing
  298. */
  299. public void startDrag(DragGestureEvent trigger,
  300. Cursor dragCursor,
  301. Transferable transferable,
  302. DragSourceListener dsl,
  303. FlavorMap flavorMap) throws InvalidDnDOperationException {
  304. startDrag(trigger, dragCursor, null, null, transferable, dsl, flavorMap);
  305. }
  306. /**
  307. * Start a drag, given the <code>DragGestureEvent</code>
  308. * that initiated the drag, the initial <code>Cursor</code>
  309. * to use,
  310. * the <code>Image</code> to drag,
  311. * the offset of the <code>Image</code> origin
  312. * from the hotspot of the <code>Cursor</code>
  313. * at the instant of the trigger,
  314. * the subject data of the drag, and
  315. * the <code>DragSourceListener</code>.
  316. * <P>
  317. * @param trigger the <code>DragGestureEvent</code> that initiated the drag
  318. * @param dragCursor the initial <code>Cursor</code> or <code>null</code> for defaults
  319. * @param dragImage the <code>Image</code> to drag or <code>null</code>
  320. * @param dragOffset the offset of the <code>Image</code> origin from the hotspot
  321. * of the <code>Cursor</code> at the instant of the trigger
  322. * @param transferable the subject data of the drag
  323. * @param dsl the <code>DragSourceListener</code>
  324. * <P>
  325. * @throws <code>java.awt.dnd.InvalidDnDOperationException</code>
  326. * if the Drag and Drop
  327. * system is unable to initiate a drag operation, or if the user
  328. * attempts to start a drag while an existing drag operation
  329. * is still executing
  330. */
  331. public void startDrag(DragGestureEvent trigger,
  332. Cursor dragCursor,
  333. Image dragImage,
  334. Point dragOffset,
  335. Transferable transferable,
  336. DragSourceListener dsl) throws InvalidDnDOperationException {
  337. startDrag(trigger, dragCursor, dragImage, dragOffset, transferable, dsl, null);
  338. }
  339. /**
  340. * Start a drag, given the <code>DragGestureEvent</code>
  341. * that initiated the drag, the initial
  342. * <code>Cursor</code> to
  343. * use,
  344. * the <code>Transferable</code> subject data
  345. * of the drag, and the <code>DragSourceListener</code>.
  346. * <P>
  347. * @param trigger the <code>DragGestureEvent</code> that initiated the drag
  348. * @param dragCursor the initial <code>Cursor</code> or <code>null</code> for defaults
  349. * @param transferable the subject data of the drag
  350. * @param dsl the <code>DragSourceListener</code>
  351. * <P>
  352. * @throws <code>java.awt.dnd.InvalidDnDOperationException</code>
  353. * if the Drag and Drop
  354. * system is unable to initiate a drag operation, or if the user
  355. * attempts to start a drag while an existing drag operation
  356. * is still executing
  357. */
  358. public void startDrag(DragGestureEvent trigger,
  359. Cursor dragCursor,
  360. Transferable transferable,
  361. DragSourceListener dsl) throws InvalidDnDOperationException {
  362. startDrag(trigger, dragCursor, null, null, transferable, dsl, null);
  363. }
  364. /**
  365. * Creates the <code>DragSourceContext</code> to handle this drag.
  366. * <p>
  367. * To incorporate a new <code>DragSourceContext</code>
  368. * subclass, subclass <code>DragSource</code> and
  369. * override this method.
  370. * <p>
  371. * If <code>dragImage</code> is <code>null</code>, no image is used
  372. * to represent the drag over feedback for this drag operation, but
  373. * <code>NullPointerException</code> is not thrown.
  374. * <p>
  375. * If <code>dsl</code> is <code>null</code>, no drag source listener
  376. * is registered with the created <code>DragSourceContext</code>,
  377. * but <code>NullPointerException</code> is not thrown.
  378. * <p>
  379. * If <code>dragCursor</code> is <code>null</code>, the default drag
  380. * cursors are used for this drag operation.
  381. * <code>NullPointerException</code> is not thrown.
  382. *
  383. * @param dscp The <code>DragSourceContextPeer</code> for this drag
  384. * @param dgl The <code>DragGestureEvent</code> that triggered the
  385. * drag
  386. * @param dragCursor The initial <code>Cursor</code> to display
  387. * @param dragImage The <code>Image</code> to drag or <code>null</code>
  388. * @param imageOffset The offset of the <code>Image</code> origin from the
  389. * hotspot of the cursor at the instant of the trigger
  390. * @param t The subject data of the drag
  391. * @param dsl The <code>DragSourceListener</code>
  392. *
  393. * @return the <code>DragSourceContext</code>
  394. *
  395. * @throws NullPointerException if <code>dscp</code> is <code>null</code>
  396. * @throws NullPointerException if <code>dgl</code> is <code>null</code>
  397. * @throws NullPointerException if <code>dragImage</code> is not
  398. * <code>null</code> and <code>imageOffset</code> is <code>null</code>
  399. * @throws NullPointerException if <code>t</code> is <code>null</code>
  400. * @throws IllegalArgumentException if the <code>Component</code>
  401. * associated with the trigger event is <code>null</code>.
  402. * @throws IllegalArgumentException if the <code>DragSource</code> for the
  403. * trigger event is <code>null</code>.
  404. * @throws IllegalArgumentException if the drag action for the
  405. * trigger event is <code>DnDConstants.ACTION_NONE</code>.
  406. * @throws IllegalArgumentException if the source actions for the
  407. * <code>DragGestureRecognizer</code> associated with the trigger
  408. * event are equal to <code>DnDConstants.ACTION_NONE</code>.
  409. */
  410. protected DragSourceContext createDragSourceContext(DragSourceContextPeer dscp, DragGestureEvent dgl, Cursor dragCursor, Image dragImage, Point imageOffset, Transferable t, DragSourceListener dsl) {
  411. return new DragSourceContext(dscp, dgl, dragCursor, dragImage, imageOffset, t, dsl);
  412. }
  413. /**
  414. * This method returns the
  415. * <code>FlavorMap</code> for this <code>DragSource</code>.
  416. * <P>
  417. * @return the <code>FlavorMap</code> for this <code>DragSource</code>
  418. */
  419. public FlavorMap getFlavorMap() { return flavorMap; }
  420. /**
  421. * Creates a new <code>DragGestureRecognizer</code>
  422. * that implements the specified
  423. * abstract subclass of
  424. * <code>DragGestureRecognizer</code>, and
  425. * sets the specified <code>Component</code>
  426. * and <code>DragGestureListener</code> on
  427. * the newly created object.
  428. * <P>
  429. * @param recognizerAbstractClass the requested abstract type
  430. * @param actions the permitted source drag actions
  431. * @param c the <code>Component</code> target
  432. * @param dgl the <code>DragGestureListener</code> to notify
  433. * <P>
  434. * @return the new <code>DragGestureRecognizer</code> or <code>null</code>
  435. * if the <code>Toolkit.createDragGestureRecognizer</code> method
  436. * has no implementation available for
  437. * the requested <code>DragGestureRecognizer</code>
  438. * subclass and returns <code>null</code>
  439. */
  440. public DragGestureRecognizer createDragGestureRecognizer(Class recognizerAbstractClass, Component c, int actions, DragGestureListener dgl) {
  441. return Toolkit.getDefaultToolkit().createDragGestureRecognizer(recognizerAbstractClass, this, c, actions, dgl);
  442. }
  443. /**
  444. * Creates a new <code>DragGestureRecognizer</code>
  445. * that implements the default
  446. * abstract subclass of <code>DragGestureRecognizer</code>
  447. * for this <code>DragSource</code>,
  448. * and sets the specified <code>Component</code>
  449. * and <code>DragGestureListener</code> on the
  450. * newly created object.
  451. *
  452. * For this <code>DragSource</code>
  453. * the default is <code>MouseDragGestureRecognizer</code>.
  454. * <P>
  455. * @param c the <code>Component</code> target for the recognizer
  456. * @param actions the permitted source actions
  457. * @param dgl the <code>DragGestureListener</code> to notify
  458. * <P>
  459. * @return the new <code>DragGestureRecognizer</code> or <code>null</code>
  460. * if the <code>Toolkit.createDragGestureRecognizer</code> method
  461. * has no implementation available for
  462. * the requested <code>DragGestureRecognizer</code>
  463. * subclass and returns <code>null</code>
  464. */
  465. public DragGestureRecognizer createDefaultDragGestureRecognizer(Component c, int actions, DragGestureListener dgl) {
  466. return Toolkit.getDefaultToolkit().createDragGestureRecognizer(MouseDragGestureRecognizer.class, this, c, actions, dgl);
  467. }
  468. /**
  469. * Adds the specified <code>DragSourceListener</code> to this
  470. * <code>DragSource</code> to receive drag source events during drag
  471. * operations intiated with this <code>DragSource</code>.
  472. * If a <code>null</code> listener is specified, no action is taken and no
  473. * exception is thrown.
  474. *
  475. * @param dsl the <code>DragSourceListener</code> to add
  476. *
  477. * @see #removeDragSourceListener
  478. * @see #getDragSourceListeners
  479. * @since 1.4
  480. */
  481. public void addDragSourceListener(DragSourceListener dsl) {
  482. if (dsl != null) {
  483. synchronized (this) {
  484. listener = DnDEventMulticaster.add(listener, dsl);
  485. }
  486. }
  487. }
  488. /**
  489. * Removes the specified <code>DragSourceListener</code> from this
  490. * <code>DragSource</code>.
  491. * If a <code>null</code> listener is specified, no action is taken and no
  492. * exception is thrown.
  493. * If the listener specified by the argument was not previously added to
  494. * this <code>DragSource</code>, no action is taken and no exception
  495. * is thrown.
  496. *
  497. * @param dsl the <code>DragSourceListener</code> to remove
  498. *
  499. * @see #addDragSourceListener
  500. * @see #getDragSourceListeners
  501. * @since 1.4
  502. */
  503. public void removeDragSourceListener(DragSourceListener dsl) {
  504. if (dsl != null) {
  505. synchronized (this) {
  506. listener = DnDEventMulticaster.remove(listener, dsl);
  507. }
  508. }
  509. }
  510. /**
  511. * Gets all the <code>DragSourceListener</code>s
  512. * registered with this <code>DragSource</code>.
  513. *
  514. * @return all of this <code>DragSource</code>'s
  515. * <code>DragSourceListener</code>s or an empty array if no
  516. * such listeners are currently registered
  517. *
  518. * @see #addDragSourceListener
  519. * @see #removeDragSourceListener
  520. * @since 1.4
  521. */
  522. public DragSourceListener[] getDragSourceListeners() {
  523. return (DragSourceListener[])getListeners(DragSourceListener.class);
  524. }
  525. /**
  526. * Adds the specified <code>DragSourceMotionListener</code> to this
  527. * <code>DragSource</code> to receive drag motion events during drag
  528. * operations intiated with this <code>DragSource</code>.
  529. * If a <code>null</code> listener is specified, no action is taken and no
  530. * exception is thrown.
  531. *
  532. * @param dsml the <code>DragSourceMotionListener</code> to add
  533. *
  534. * @see #removeDragSourceMotionListener
  535. * @see #getDragSourceMotionListeners
  536. * @since 1.4
  537. */
  538. public void addDragSourceMotionListener(DragSourceMotionListener dsml) {
  539. if (dsml != null) {
  540. synchronized (this) {
  541. motionListener = DnDEventMulticaster.add(motionListener, dsml);
  542. }
  543. }
  544. }
  545. /**
  546. * Removes the specified <code>DragSourceMotionListener</code> from this
  547. * <code>DragSource</code>.
  548. * If a <code>null</code> listener is specified, no action is taken and no
  549. * exception is thrown.
  550. * If the listener specified by the argument was not previously added to
  551. * this <code>DragSource</code>, no action is taken and no exception
  552. * is thrown.
  553. *
  554. * @param dsml the <code>DragSourceMotionListener</code> to remove
  555. *
  556. * @see #addDragSourceMotionListener
  557. * @see #getDragSourceMotionListeners
  558. * @since 1.4
  559. */
  560. public void removeDragSourceMotionListener(DragSourceMotionListener dsml) {
  561. if (dsml != null) {
  562. synchronized (this) {
  563. motionListener = DnDEventMulticaster.remove(motionListener, dsml);
  564. }
  565. }
  566. }
  567. /**
  568. * Gets all of the <code>DragSourceMotionListener</code>s
  569. * registered with this <code>DragSource</code>.
  570. *
  571. * @return all of this <code>DragSource</code>'s
  572. * <code>DragSourceMotionListener</code>s or an empty array if no
  573. * such listeners are currently registered
  574. *
  575. * @see #addDragSourceMotionListener
  576. * @see #removeDragSourceMotionListener
  577. * @since 1.4
  578. */
  579. public DragSourceMotionListener[] getDragSourceMotionListeners() {
  580. return (DragSourceMotionListener[])
  581. getListeners(DragSourceMotionListener.class);
  582. }
  583. /**
  584. * Gets all the objects currently registered as
  585. * <code><em>Foo</em>Listener</code>s upon this <code>DragSource</code>.
  586. * <code><em>Foo</em>Listener</code>s are registered using the
  587. * <code>add<em>Foo</em>Listener</code> method.
  588. *
  589. * @param listenerType the type of listeners requested; this parameter
  590. * should specify an interface that descends from
  591. * <code>java.util.EventListener</code>
  592. * @return an array of all objects registered as
  593. * <code><em>Foo</em>Listener</code>s on this
  594. * <code>DragSource</code>, or an empty array if no such listeners
  595. * have been added
  596. * @exception <code>ClassCastException</code> if <code>listenerType</code>
  597. * doesn't specify a class or interface that implements
  598. * <code>java.util.EventListener</code>
  599. *
  600. * @see #getDragSourceListeners
  601. * @see #getDragSourceMotionListeners
  602. * @since 1.4
  603. */
  604. public EventListener[] getListeners(Class listenerType) {
  605. EventListener l = null;
  606. if (listenerType == DragSourceListener.class) {
  607. l = listener;
  608. } else if (listenerType == DragSourceMotionListener.class) {
  609. l = motionListener;
  610. }
  611. return DnDEventMulticaster.getListeners(l, listenerType);
  612. }
  613. /**
  614. * This method calls <code>dragEnter</code> on the
  615. * <code>DragSourceListener</code>s registered with this
  616. * <code>DragSource</code>, and passes them the specified
  617. * <code>DragSourceDragEvent</code>.
  618. *
  619. * @param dsde the <code>DragSourceDragEvent</code>
  620. */
  621. void processDragEnter(DragSourceDragEvent dsde) {
  622. DragSourceListener dsl = listener;
  623. if (dsl != null) {
  624. dsl.dragEnter(dsde);
  625. }
  626. }
  627. /**
  628. * This method calls <code>dragOver</code> on the
  629. * <code>DragSourceListener</code>s registered with this
  630. * <code>DragSource</code>, and passes them the specified
  631. * <code>DragSourceDragEvent</code>.
  632. *
  633. * @param dsde the <code>DragSourceDragEvent</code>
  634. */
  635. void processDragOver(DragSourceDragEvent dsde) {
  636. DragSourceListener dsl = listener;
  637. if (dsl != null) {
  638. dsl.dragOver(dsde);
  639. }
  640. }
  641. /**
  642. * This method calls <code>dropActionChanged</code> on the
  643. * <code>DragSourceListener</code>s registered with this
  644. * <code>DragSource</code>, and passes them the specified
  645. * <code>DragSourceDragEvent</code>.
  646. *
  647. * @param dsde the <code>DragSourceDragEvent</code>
  648. */
  649. void processDropActionChanged(DragSourceDragEvent dsde) {
  650. DragSourceListener dsl = listener;
  651. if (dsl != null) {
  652. dsl.dropActionChanged(dsde);
  653. }
  654. }
  655. /**
  656. * This method calls <code>dragExit</code> on the
  657. * <code>DragSourceListener</code>s registered with this
  658. * <code>DragSource</code>, and passes them the specified
  659. * <code>DragSourceEvent</code>.
  660. *
  661. * @param dse the <code>DragSourceEvent</code>
  662. */
  663. void processDragExit(DragSourceEvent dse) {
  664. DragSourceListener dsl = listener;
  665. if (dsl != null) {
  666. dsl.dragExit(dse);
  667. }
  668. }
  669. /**
  670. * This method calls <code>dragDropEnd</code> on the
  671. * <code>DragSourceListener</code>s registered with this
  672. * <code>DragSource</code>, and passes them the specified
  673. * <code>DragSourceDropEvent</code>.
  674. *
  675. * @param dsde the <code>DragSourceEvent</code>
  676. */
  677. void processDragDropEnd(DragSourceDropEvent dsde) {
  678. DragSourceListener dsl = listener;
  679. if (dsl != null) {
  680. dsl.dragDropEnd(dsde);
  681. }
  682. }
  683. /**
  684. * This method calls <code>dragMouseMoved</code> on the
  685. * <code>DragSourceMotionListener</code>s registered with this
  686. * <code>DragSource</code>, and passes them the specified
  687. * <code>DragSourceDragEvent</code>.
  688. *
  689. * @param dsde the <code>DragSourceEvent</code>
  690. */
  691. void processDragMouseMoved(DragSourceDragEvent dsde) {
  692. DragSourceMotionListener dsml = motionListener;
  693. if (dsml != null) {
  694. dsml.dragMouseMoved(dsde);
  695. }
  696. }
  697. /**
  698. * Serializes this <code>DragSource</code>. This method first performs
  699. * default serialization. Next, it writes out this object's
  700. * <code>FlavorMap</code> if and only if it can be serialized. If not,
  701. * <code>null</code> is written instead. Next, it writes out
  702. * <code>Serializable</code> listeners registered with this
  703. * object. Listeners are written in a <code>null</code>-terminated sequence
  704. * of 0 or more pairs. The pair consists of a <code>String</code> and an
  705. * <code>Object</code> the <code>String</code> indicates the type of the
  706. * <code>Object</code> and is one of the following:
  707. * <ul>
  708. * <li><code>dragSourceListenerK</code> indicating a
  709. * <code>DragSourceListener</code> object;
  710. * <li><code>dragSourceMotionListenerK</code> indicating a
  711. * <code>DragSourceMotionListener</code> object.
  712. * </ul>
  713. *
  714. * @serialData Either a <code>FlavorMap</code> instance, or
  715. * <code>null</code>, followed by a <code>null</code>-terminated
  716. * sequence of 0 or more pairs; the pair consists of a
  717. * <code>String</code> and an <code>Object</code> the
  718. * <code>String</code> indicates the type of the <code>Object</code>
  719. * and is one of the following:
  720. * <ul>
  721. * <li><code>dragSourceListenerK</code> indicating a
  722. * <code>DragSourceListener</code> object;
  723. * <li><code>dragSourceMotionListenerK</code> indicating a
  724. * <code>DragSourceMotionListener</code> object.
  725. * </ul>.
  726. * @since 1.4
  727. */
  728. private void writeObject(ObjectOutputStream s) throws IOException {
  729. s.defaultWriteObject();
  730. s.writeObject(SerializationTester.test(flavorMap) ? flavorMap : null);
  731. DnDEventMulticaster.save(s, dragSourceListenerK, listener);
  732. DnDEventMulticaster.save(s, dragSourceMotionListenerK, motionListener);
  733. s.writeObject(null);
  734. }
  735. /**
  736. * Deserializes this <code>DragSource</code>. This method first performs
  737. * default deserialization. Next, this object's <code>FlavorMap</code> is
  738. * deserialized by using the next object in the stream.
  739. * If the resulting <code>FlavorMap</code> is <code>null</code>, this
  740. * object's <code>FlavorMap</code> is set to the default FlavorMap for
  741. * this thread's <code>ClassLoader</code>.
  742. * Next, this object's listeners are deserialized by reading a
  743. * <code>null</code>-terminated sequence of 0 or more key/value pairs
  744. * from the stream:
  745. * <ul>
  746. * <li>If a key object is a <code>String</code> equal to
  747. * <code>dragSourceListenerK</code>, a <code>DragSourceListener</code> is
  748. * deserialized using the corresponding value object and added to this
  749. * <code>DragSource</code>.
  750. * <li>If a key object is a <code>String</code> equal to
  751. * <code>dragSourceMotionListenerK</code>, a
  752. * <code>DragSourceMotionListener</code> is deserialized using the
  753. * corresponding value object and added to this <code>DragSource</code>.
  754. * <li>Otherwise, the key/value pair is skipped.
  755. * </ul>
  756. *
  757. * @see java.awt.datatransfer.SystemFlavorMap#getDefaultFlavorMap
  758. * @since 1.4
  759. */
  760. private void readObject(ObjectInputStream s)
  761. throws ClassNotFoundException, IOException {
  762. s.defaultReadObject();
  763. // 'flavorMap' was written explicitly
  764. flavorMap = (FlavorMap)s.readObject();
  765. // Implementation assumes 'flavorMap' is never null.
  766. if (flavorMap == null) {
  767. flavorMap = SystemFlavorMap.getDefaultFlavorMap();
  768. }
  769. Object keyOrNull;
  770. while (null != (keyOrNull = s.readObject())) {
  771. String key = ((String)keyOrNull).intern();
  772. if (dragSourceListenerK == key) {
  773. addDragSourceListener((DragSourceListener)(s.readObject()));
  774. } else if (dragSourceMotionListenerK == key) {
  775. addDragSourceMotionListener(
  776. (DragSourceMotionListener)(s.readObject()));
  777. } else {
  778. // skip value for unrecognized key
  779. s.readObject();
  780. }
  781. }
  782. }
  783. /*
  784. * fields
  785. */
  786. private transient FlavorMap flavorMap = SystemFlavorMap.getDefaultFlavorMap();
  787. private transient DragSourceListener listener;
  788. private transient DragSourceMotionListener motionListener;
  789. }