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