1. /*
  2. * @(#)DragGestureRecognizer.java 1.12 01/11/29
  3. *
  4. * Copyright 2002 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.event.InputEvent;
  9. import java.awt.Component;
  10. import java.awt.Point;
  11. import java.util.TooManyListenersException;
  12. import java.util.ArrayList;
  13. /**
  14. * The <code>DragGestureRecognizer</code> is an
  15. * abstract base class for the specification
  16. * of a platform-dependent listener that can be associated with a particular
  17. * <code>Component</code> in order to
  18. * identify platform-dependent drag initiating gestures.
  19. * <p>
  20. * The appropriate <code>DragGestureRecognizer</code>
  21. * subclass is obtained from the
  22. * <code>DragSource</code> asssociated with
  23. * a particular <code>Component</code>, or from the <code>Toolkit</code>
  24. * object via its createDragGestureRecognizer() method.
  25. * <p>
  26. * Once the <code>DragGestureRecognizer</code>
  27. * is associated with a particular <code>Component</code>
  28. * it will register the appropriate listener interfaces on that
  29. * <code>Component</code>
  30. * in order to track the input events delivered to the <code>Component</code>.
  31. * <p>
  32. * Once the <code>DragGestureRecognizer</code> identifies a sequence of events
  33. * on the <code>Component</code> as a drag initiating gesture, it will notify
  34. * its unicast <code>DragGestureListener</code> by
  35. * invoking its gestureRecognized() method.
  36. * <P>
  37. * When a concrete <code>DragGestureRecognizer</code>
  38. * instance detects a drag initiating
  39. * gesture on the <code>Component</code> it is associated with,
  40. * it will fire a <code>DragGestureEvent</code> to
  41. * the <code>DragGestureListener</code> registered on
  42. * its unicast event source for <code>DragGestureListener</code>
  43. * events. This <code>DragGestureListener</code> is responsible
  44. * for causing the associated
  45. * <code>DragSource</code> to start the Drag and Drop operation (if
  46. * appropriate).
  47. * <P>
  48. * @author Laurence P. G. Cable
  49. * @version 1.12
  50. * @see java.awt.dnd.DragGestureListener
  51. * @see java.awt.dnd.DragGestureEvent
  52. * @see java.awt.dnd.DragSource
  53. */
  54. public abstract class DragGestureRecognizer {
  55. /**
  56. * Construct a new <code>DragGestureRecognizer</code>
  57. * given the <code>DragSource</code> to be used
  58. * in this Drag and Drop operation, the <code>Component</code>
  59. * this <code>DragGestureRecognizer</code> should "observe"
  60. * for drag initiating gestures, the action(s) supported
  61. * for this Drag and Drop operation, and the
  62. * <code>DragGestureListener</code> to notify
  63. * once a drag initiating gesture has been detected.
  64. * <P>
  65. * @param ds the <code>DragSource</code> this
  66. * <code>DragGestureRecognizer</code>
  67. * will use to process the Drag and Drop operation
  68. *
  69. * @param c the <code>Component</code>
  70. * this <code>DragGestureRecognizer</code>
  71. * should "observe" the event stream to,
  72. * in order to detect a drag initiating gesture.
  73. * If this value is <code>null</code>, the
  74. * <code>DragGestureRecognizer</code>
  75. * is not associated with any <code>Component</code>.
  76. *
  77. * @param sa the set (logical OR) of the
  78. * <code>DnDConstants</code>
  79. * that this Drag and Drop operation will support
  80. *
  81. * @param dgl the <code>DragGestureRecognizer</code>
  82. * to notify when a drag gesture is detected
  83. * <P>
  84. * @throws <code>IllegalArgumentException</code>
  85. * if ds is <code>null</code>.
  86. */
  87. protected DragGestureRecognizer(DragSource ds, Component c, int sa, DragGestureListener dgl) {
  88. super();
  89. if (ds == null) throw new IllegalArgumentException("null DragSource");
  90. dragSource = ds;
  91. component = c;
  92. sourceActions = sa & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK);
  93. try {
  94. if (dgl != null) addDragGestureListener(dgl);
  95. } catch (TooManyListenersException tmle) {
  96. // cant happen ...
  97. }
  98. }
  99. /**
  100. * Construct a new <code>DragGestureRecognizer</code>
  101. * given the <code>DragSource</code> to be used in this
  102. * Drag and Drop
  103. * operation, the <code>Component</code> this
  104. * <code>DragGestureRecognizer</code> should "observe"
  105. * for drag initiating gestures, and the action(s)
  106. * supported for this Drag and Drop operation.
  107. * <P>
  108. * @param ds the <code>DragSource</code> this
  109. * <code>DragGestureRecognizer</code> will use to
  110. * process the Drag and Drop operation
  111. *
  112. * @param c the <code>Component</code> this
  113. * <code>DragGestureRecognizer</code> should "observe" the event
  114. * stream to, in order to detect a drag initiating gesture.
  115. * If this value is <code>null</code>, the
  116. * <code>DragGestureRecognizer</code>
  117. * is not associated with any <code>Component</code>.
  118. *
  119. * @param sa the set (logical OR) of the <code>DnDConstants</code>
  120. * that this Drag and Drop operation will support
  121. * <P>
  122. * @throws <code>IllegalArgumentException</code>
  123. * if ds is <code>null</code>.
  124. */
  125. protected DragGestureRecognizer(DragSource ds, Component c, int sa) {
  126. this(ds, c, sa, null);
  127. }
  128. /**
  129. * Construct a new <code>DragGestureRecognizer</code>
  130. * given the <code>DragSource</code> to be used
  131. * in this Drag and Drop operation, and
  132. * the <code>Component</code> this
  133. * <code>DragGestureRecognizer</code>
  134. * should "observe" for drag initiating gestures.
  135. * <P>
  136. * @param ds the <code>DragSource</code> this
  137. * <code>DragGestureRecognizer</code>
  138. * will use to process the Drag and Drop operation
  139. *
  140. * @param c the <code>Component</code>
  141. * this <code>DragGestureRecognizer</code>
  142. * should "observe" the event stream to,
  143. * in order to detect a drag initiating gesture.
  144. * If this value is <code>null</code>,
  145. * the <code>DragGestureRecognizer</code>
  146. * is not associated with any <code>Component</code>.
  147. * <P>
  148. * @throws <code>IllegalArgumentException</code>
  149. * if ds is <code>null</code>.
  150. */
  151. protected DragGestureRecognizer(DragSource ds, Component c) {
  152. this(ds, c, DnDConstants.ACTION_NONE);
  153. }
  154. /**
  155. * Construct a new <code>DragGestureRecognizer</code>
  156. * given the <code>DragSource</code> to be used in this
  157. * Drag and Drop operation.
  158. * <P>
  159. * @param ds the <code>DragSource</code> this
  160. * <code>DragGestureRecognizer</code> will
  161. * use to process the Drag and Drop operation
  162. * <P>
  163. * @throws <code>IllegalArgumentException</code>
  164. * if ds is <code>null</code>.
  165. */
  166. protected DragGestureRecognizer(DragSource ds) {
  167. this(ds, null);
  168. }
  169. /**
  170. * register this DragGestureRecognizer's Listeners with the Component
  171. *
  172. * subclasses must override this method
  173. */
  174. protected abstract void registerListeners();
  175. /**
  176. * unregister this DragGestureRecognizer's Listeners with the Component
  177. *
  178. * subclasses must override this method
  179. */
  180. protected abstract void unregisterListeners();
  181. /**
  182. * This method returns the <code>DragSource</code>
  183. * this <code>DragGestureRecognizer</code>
  184. * will use in order to process the Drag and Drop
  185. * operation.
  186. * <P>
  187. * @return the DragSource
  188. */
  189. public DragSource getDragSource() { return dragSource; }
  190. /**
  191. * This method returns the <code>Component</code>
  192. * that is to be "observed" by the
  193. * <code>DragGestureRecognizer</code>
  194. * for drag initiating gestures.
  195. * <P>
  196. * @return The Component this DragGestureRecognizer
  197. * is associated with
  198. */
  199. public synchronized Component getComponent() { return component; }
  200. /**
  201. * set the Component that the DragGestureRecognizer is associated with
  202. *
  203. * registerListeners() and unregisterListeners() are called as a side
  204. * effect as appropriate.
  205. * <P>
  206. * @param c The <code>Component</code> or <code>null</code>
  207. */
  208. public synchronized void setComponent(Component c) {
  209. if (component != null && dragGestureListener != null)
  210. unregisterListeners();
  211. component = c;
  212. if (component != null && dragGestureListener != null)
  213. registerListeners();
  214. }
  215. /**
  216. * This method returns an int representing the
  217. * type of action(s) this Drag and Drop
  218. * operation will support.
  219. * <P>
  220. * @return the currently permitted source action(s)
  221. */
  222. public synchronized int getSourceActions() { return sourceActions; }
  223. /**
  224. * This method sets the permitted source drag action(s)
  225. * for this Drag and Drop operation.
  226. * <P>
  227. * @param actions the permitted source drag action(s)
  228. */
  229. public synchronized void setSourceActions(int actions) {
  230. sourceActions = actions & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK);
  231. }
  232. /**
  233. * This method returns the first event in the
  234. * series of events that initiated
  235. * the Drag and Drop operation.
  236. * <P>
  237. * @return the initial event that triggered the drag gesture
  238. */
  239. public InputEvent getTriggerEvent() { return events.isEmpty() ? null : (InputEvent)events.get(0); }
  240. /**
  241. * Reset the Recognizer, if its currently recognizing a gesture, ignore
  242. * it.
  243. */
  244. public void resetRecognizer() { events.clear(); }
  245. /**
  246. * Register a new <code>DragGestureListener</code>.
  247. * <P>
  248. * @param dgl the <code>DragGestureListener</code> to register
  249. * with this <code>DragGestureRecognizer</code>.
  250. * <P>
  251. * @throws java.util.TooManyListenersException if a
  252. * <code>DragGestureListener</code> has already been added.
  253. */
  254. public synchronized void addDragGestureListener(DragGestureListener dgl) throws TooManyListenersException {
  255. if (dragGestureListener != null)
  256. throw new TooManyListenersException();
  257. else {
  258. dragGestureListener = dgl;
  259. if (component != null) registerListeners();
  260. }
  261. }
  262. /**
  263. * unregister the current DragGestureListener
  264. * <P>
  265. * @param dgl the <code>DragGestureListener</code> to unregister
  266. * from this <code>DragGestureRecognizer</code>
  267. * <P>
  268. * @throws <code>IllegalArgumentException</code> if
  269. * dgl is not (equal to) the currently registered <code>DragGestureListener</code>.
  270. */
  271. public synchronized void removeDragGestureListener(DragGestureListener dgl) {
  272. if (dragGestureListener == null || !dragGestureListener.equals(dgl))
  273. throw new IllegalArgumentException();
  274. else {
  275. dragGestureListener = null;
  276. if (component != null) unregisterListeners();
  277. }
  278. }
  279. /**
  280. * Notify the DragGestureListener that a Drag and Drop initiating
  281. * gesture has occurred. Then reset the state of the Recognizer.
  282. * <P>
  283. * @param dragAction The action initially selected by the users gesture
  284. * @param p The point (in Component coords) where the gesture originated
  285. */
  286. protected synchronized void fireDragGestureRecognized(int dragAction, Point p) {
  287. if (dragGestureListener != null) {
  288. dragGestureListener.dragGestureRecognized(new DragGestureEvent(this, dragAction, p, events));
  289. }
  290. events.clear();
  291. }
  292. /**
  293. * Listeners registered on the Component by this Recognizer shall record
  294. * all Events that are recognized as part of the series of Events that go
  295. * to comprise a Drag and Drop initiating gesture via this API.
  296. *<P>
  297. * This method is used by a <code>DragGestureRecognizer</code>
  298. * implementation to add an <code>InputEvent</code>
  299. * subclass (that it believes is one in a series
  300. * of events that comprise a Drag and Drop operation)
  301. * to the array of events that this
  302. * <code>DragGestureRecognizer</code> maintains internally.
  303. * <P>
  304. * @param awtie the <code>InputEvent</code>
  305. * to add to this <code>DragGestureRecognizer</code>'s
  306. * internal array of events. Note that <code>null</code>
  307. * is not a valid value, and will be ignored.
  308. */
  309. protected synchronized void appendEvent(InputEvent awtie) {
  310. events.add(awtie);
  311. }
  312. /*
  313. * fields
  314. */
  315. /**
  316. * The <code>DragSource</code>
  317. * associated with this
  318. * <code>DragGestureRecognizer</code>.
  319. */
  320. protected DragSource dragSource;
  321. /**
  322. * The <code>Component</code>
  323. * associated with this <code>DragGestureRecognizer</code>.
  324. */
  325. protected Component component;
  326. /**
  327. * The <code>DragGestureListener</code>
  328. * associated with this <code>DragGestureRecognizer</code>.
  329. */
  330. protected DragGestureListener dragGestureListener;
  331. /**
  332. * An <code>int</code> representing
  333. * the type(s) of action(s) used
  334. * in this Drag and Drop operation.
  335. */
  336. protected int sourceActions;
  337. /**
  338. * The list of events (in order) that
  339. * the <code>DragGestureRecognizer</code>
  340. * "recognized" as a "gesture" that triggers a drag.
  341. */
  342. protected ArrayList events = new ArrayList(1);
  343. }