001 /*
002 * Copyright 1998-2006 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.event.InputEvent;
029 import java.awt.Component;
030 import java.awt.Point;
031
032 import java.util.TooManyListenersException;
033 import java.util.ArrayList;
034
035 import java.io.IOException;
036 import java.io.ObjectInputStream;
037 import java.io.ObjectOutputStream;
038 import java.io.Serializable;
039
040 /**
041 * The <code>DragGestureRecognizer</code> is an
042 * abstract base class for the specification
043 * of a platform-dependent listener that can be associated with a particular
044 * <code>Component</code> in order to
045 * identify platform-dependent drag initiating gestures.
046 * <p>
047 * The appropriate <code>DragGestureRecognizer</code>
048 * subclass instance is obtained from the
049 * {@link DragSource} asssociated with
050 * a particular <code>Component</code>, or from the <code>Toolkit</code> object via its
051 * {@link java.awt.Toolkit#createDragGestureRecognizer createDragGestureRecognizer()}
052 * method.
053 * <p>
054 * Once the <code>DragGestureRecognizer</code>
055 * is associated with a particular <code>Component</code>
056 * it will register the appropriate listener interfaces on that
057 * <code>Component</code>
058 * in order to track the input events delivered to the <code>Component</code>.
059 * <p>
060 * Once the <code>DragGestureRecognizer</code> identifies a sequence of events
061 * on the <code>Component</code> as a drag initiating gesture, it will notify
062 * its unicast <code>DragGestureListener</code> by
063 * invoking its
064 * {@link java.awt.dnd.DragGestureListener#dragGestureRecognized gestureRecognized()}
065 * method.
066 * <P>
067 * When a concrete <code>DragGestureRecognizer</code>
068 * instance detects a drag initiating
069 * gesture on the <code>Component</code> it is associated with,
070 * it fires a {@link DragGestureEvent} to
071 * the <code>DragGestureListener</code> registered on
072 * its unicast event source for <code>DragGestureListener</code>
073 * events. This <code>DragGestureListener</code> is responsible
074 * for causing the associated
075 * <code>DragSource</code> to start the Drag and Drop operation (if
076 * appropriate).
077 * <P>
078 * @author Laurence P. G. Cable
079 * @version 1.28
080 * @see java.awt.dnd.DragGestureListener
081 * @see java.awt.dnd.DragGestureEvent
082 * @see java.awt.dnd.DragSource
083 */
084
085 public abstract class DragGestureRecognizer implements Serializable {
086
087 private static final long serialVersionUID = 8996673345831063337L;
088
089 /**
090 * Construct a new <code>DragGestureRecognizer</code>
091 * given the <code>DragSource</code> to be used
092 * in this Drag and Drop operation, the <code>Component</code>
093 * this <code>DragGestureRecognizer</code> should "observe"
094 * for drag initiating gestures, the action(s) supported
095 * for this Drag and Drop operation, and the
096 * <code>DragGestureListener</code> to notify
097 * once a drag initiating gesture has been detected.
098 * <P>
099 * @param ds the <code>DragSource</code> this
100 * <code>DragGestureRecognizer</code>
101 * will use to process the Drag and Drop operation
102 *
103 * @param c the <code>Component</code>
104 * this <code>DragGestureRecognizer</code>
105 * should "observe" the event stream to,
106 * in order to detect a drag initiating gesture.
107 * If this value is <code>null</code>, the
108 * <code>DragGestureRecognizer</code>
109 * is not associated with any <code>Component</code>.
110 *
111 * @param sa the set (logical OR) of the
112 * <code>DnDConstants</code>
113 * that this Drag and Drop operation will support
114 *
115 * @param dgl the <code>DragGestureRecognizer</code>
116 * to notify when a drag gesture is detected
117 * <P>
118 * @throws <code>IllegalArgumentException</code>
119 * if ds is <code>null</code>.
120 */
121
122 protected DragGestureRecognizer(DragSource ds, Component c, int sa,
123 DragGestureListener dgl) {
124 super ();
125
126 if (ds == null)
127 throw new IllegalArgumentException("null DragSource");
128
129 dragSource = ds;
130 component = c;
131 sourceActions = sa
132 & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK);
133
134 try {
135 if (dgl != null)
136 addDragGestureListener(dgl);
137 } catch (TooManyListenersException tmle) {
138 // cant happen ...
139 }
140 }
141
142 /**
143 * Construct a new <code>DragGestureRecognizer</code>
144 * given the <code>DragSource</code> to be used in this
145 * Drag and Drop
146 * operation, the <code>Component</code> this
147 * <code>DragGestureRecognizer</code> should "observe"
148 * for drag initiating gestures, and the action(s)
149 * supported for this Drag and Drop operation.
150 * <P>
151 * @param ds the <code>DragSource</code> this
152 * <code>DragGestureRecognizer</code> will use to
153 * process the Drag and Drop operation
154 *
155 * @param c the <code>Component</code> this
156 * <code>DragGestureRecognizer</code> should "observe" the event
157 * stream to, in order to detect a drag initiating gesture.
158 * If this value is <code>null</code>, the
159 * <code>DragGestureRecognizer</code>
160 * is not associated with any <code>Component</code>.
161 *
162 * @param sa the set (logical OR) of the <code>DnDConstants</code>
163 * that this Drag and Drop operation will support
164 * <P>
165 * @throws <code>IllegalArgumentException</code>
166 * if ds is <code>null</code>.
167 */
168
169 protected DragGestureRecognizer(DragSource ds, Component c, int sa) {
170 this (ds, c, sa, null);
171 }
172
173 /**
174 * Construct a new <code>DragGestureRecognizer</code>
175 * given the <code>DragSource</code> to be used
176 * in this Drag and Drop operation, and
177 * the <code>Component</code> this
178 * <code>DragGestureRecognizer</code>
179 * should "observe" for drag initiating gestures.
180 * <P>
181 * @param ds the <code>DragSource</code> this
182 * <code>DragGestureRecognizer</code>
183 * will use to process the Drag and Drop operation
184 *
185 * @param c the <code>Component</code>
186 * this <code>DragGestureRecognizer</code>
187 * should "observe" the event stream to,
188 * in order to detect a drag initiating gesture.
189 * If this value is <code>null</code>,
190 * the <code>DragGestureRecognizer</code>
191 * is not associated with any <code>Component</code>.
192 * <P>
193 * @throws <code>IllegalArgumentException</code>
194 * if ds is <code>null</code>.
195 */
196
197 protected DragGestureRecognizer(DragSource ds, Component c) {
198 this (ds, c, DnDConstants.ACTION_NONE);
199 }
200
201 /**
202 * Construct a new <code>DragGestureRecognizer</code>
203 * given the <code>DragSource</code> to be used in this
204 * Drag and Drop operation.
205 * <P>
206 * @param ds the <code>DragSource</code> this
207 * <code>DragGestureRecognizer</code> will
208 * use to process the Drag and Drop operation
209 * <P>
210 * @throws <code>IllegalArgumentException</code>
211 * if ds is <code>null</code>.
212 */
213
214 protected DragGestureRecognizer(DragSource ds) {
215 this (ds, null);
216 }
217
218 /**
219 * register this DragGestureRecognizer's Listeners with the Component
220 *
221 * subclasses must override this method
222 */
223
224 protected abstract void registerListeners();
225
226 /**
227 * unregister this DragGestureRecognizer's Listeners with the Component
228 *
229 * subclasses must override this method
230 */
231
232 protected abstract void unregisterListeners();
233
234 /**
235 * This method returns the <code>DragSource</code>
236 * this <code>DragGestureRecognizer</code>
237 * will use in order to process the Drag and Drop
238 * operation.
239 * <P>
240 * @return the DragSource
241 */
242
243 public DragSource getDragSource() {
244 return dragSource;
245 }
246
247 /**
248 * This method returns the <code>Component</code>
249 * that is to be "observed" by the
250 * <code>DragGestureRecognizer</code>
251 * for drag initiating gestures.
252 * <P>
253 * @return The Component this DragGestureRecognizer
254 * is associated with
255 */
256
257 public synchronized Component getComponent() {
258 return component;
259 }
260
261 /**
262 * set the Component that the DragGestureRecognizer is associated with
263 *
264 * registerListeners() and unregisterListeners() are called as a side
265 * effect as appropriate.
266 * <P>
267 * @param c The <code>Component</code> or <code>null</code>
268 */
269
270 public synchronized void setComponent(Component c) {
271 if (component != null && dragGestureListener != null)
272 unregisterListeners();
273
274 component = c;
275
276 if (component != null && dragGestureListener != null)
277 registerListeners();
278 }
279
280 /**
281 * This method returns an int representing the
282 * type of action(s) this Drag and Drop
283 * operation will support.
284 * <P>
285 * @return the currently permitted source action(s)
286 */
287
288 public synchronized int getSourceActions() {
289 return sourceActions;
290 }
291
292 /**
293 * This method sets the permitted source drag action(s)
294 * for this Drag and Drop operation.
295 * <P>
296 * @param actions the permitted source drag action(s)
297 */
298
299 public synchronized void setSourceActions(int actions) {
300 sourceActions = actions
301 & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK);
302 }
303
304 /**
305 * This method returns the first event in the
306 * series of events that initiated
307 * the Drag and Drop operation.
308 * <P>
309 * @return the initial event that triggered the drag gesture
310 */
311
312 public InputEvent getTriggerEvent() {
313 return events.isEmpty() ? null : (InputEvent) events.get(0);
314 }
315
316 /**
317 * Reset the Recognizer, if its currently recognizing a gesture, ignore
318 * it.
319 */
320
321 public void resetRecognizer() {
322 events.clear();
323 }
324
325 /**
326 * Register a new <code>DragGestureListener</code>.
327 * <P>
328 * @param dgl the <code>DragGestureListener</code> to register
329 * with this <code>DragGestureRecognizer</code>.
330 * <P>
331 * @throws java.util.TooManyListenersException if a
332 * <code>DragGestureListener</code> has already been added.
333 */
334
335 public synchronized void addDragGestureListener(
336 DragGestureListener dgl) throws TooManyListenersException {
337 if (dragGestureListener != null)
338 throw new TooManyListenersException();
339 else {
340 dragGestureListener = dgl;
341
342 if (component != null)
343 registerListeners();
344 }
345 }
346
347 /**
348 * unregister the current DragGestureListener
349 * <P>
350 * @param dgl the <code>DragGestureListener</code> to unregister
351 * from this <code>DragGestureRecognizer</code>
352 * <P>
353 * @throws <code>IllegalArgumentException</code> if
354 * dgl is not (equal to) the currently registered <code>DragGestureListener</code>.
355 */
356
357 public synchronized void removeDragGestureListener(
358 DragGestureListener dgl) {
359 if (dragGestureListener == null
360 || !dragGestureListener.equals(dgl))
361 throw new IllegalArgumentException();
362 else {
363 dragGestureListener = null;
364
365 if (component != null)
366 unregisterListeners();
367 }
368 }
369
370 /**
371 * Notify the DragGestureListener that a Drag and Drop initiating
372 * gesture has occurred. Then reset the state of the Recognizer.
373 * <P>
374 * @param dragAction The action initially selected by the users gesture
375 * @param p The point (in Component coords) where the gesture originated
376 */
377 protected synchronized void fireDragGestureRecognized(
378 int dragAction, Point p) {
379 try {
380 if (dragGestureListener != null) {
381 dragGestureListener
382 .dragGestureRecognized(new DragGestureEvent(
383 this , dragAction, p, events));
384 }
385 } finally {
386 events.clear();
387 }
388 }
389
390 /**
391 * Listeners registered on the Component by this Recognizer shall record
392 * all Events that are recognized as part of the series of Events that go
393 * to comprise a Drag and Drop initiating gesture via this API.
394 *<P>
395 * This method is used by a <code>DragGestureRecognizer</code>
396 * implementation to add an <code>InputEvent</code>
397 * subclass (that it believes is one in a series
398 * of events that comprise a Drag and Drop operation)
399 * to the array of events that this
400 * <code>DragGestureRecognizer</code> maintains internally.
401 * <P>
402 * @param awtie the <code>InputEvent</code>
403 * to add to this <code>DragGestureRecognizer</code>'s
404 * internal array of events. Note that <code>null</code>
405 * is not a valid value, and will be ignored.
406 */
407
408 protected synchronized void appendEvent(InputEvent awtie) {
409 events.add(awtie);
410 }
411
412 /**
413 * Serializes this <code>DragGestureRecognizer</code>. This method first
414 * performs default serialization. Then, this object's
415 * <code>DragGestureListener</code> is written out if and only if it can be
416 * serialized. If not, <code>null</code> is written instead.
417 *
418 * @serialData The default serializable fields, in alphabetical order,
419 * followed by either a <code>DragGestureListener</code>, or
420 * <code>null</code>.
421 * @since 1.4
422 */
423 private void writeObject(ObjectOutputStream s) throws IOException {
424 s.defaultWriteObject();
425
426 s
427 .writeObject(SerializationTester
428 .test(dragGestureListener) ? dragGestureListener
429 : null);
430 }
431
432 /**
433 * Deserializes this <code>DragGestureRecognizer</code>. This method first
434 * performs default deserialization for all non-<code>transient</code>
435 * fields. This object's <code>DragGestureListener</code> is then
436 * deserialized as well by using the next object in the stream.
437 *
438 * @since 1.4
439 */
440 private void readObject(ObjectInputStream s)
441 throws ClassNotFoundException, IOException {
442 s.defaultReadObject();
443
444 dragGestureListener = (DragGestureListener) s.readObject();
445 }
446
447 /*
448 * fields
449 */
450
451 /**
452 * The <code>DragSource</code>
453 * associated with this
454 * <code>DragGestureRecognizer</code>.
455 *
456 * @serial
457 */
458 protected DragSource dragSource;
459
460 /**
461 * The <code>Component</code>
462 * associated with this <code>DragGestureRecognizer</code>.
463 *
464 * @serial
465 */
466 protected Component component;
467
468 /**
469 * The <code>DragGestureListener</code>
470 * associated with this <code>DragGestureRecognizer</code>.
471 */
472 protected transient DragGestureListener dragGestureListener;
473
474 /**
475 * An <code>int</code> representing
476 * the type(s) of action(s) used
477 * in this Drag and Drop operation.
478 *
479 * @serial
480 */
481 protected int sourceActions;
482
483 /**
484 * The list of events (in order) that
485 * the <code>DragGestureRecognizer</code>
486 * "recognized" as a "gesture" that triggers a drag.
487 *
488 * @serial
489 */
490 protected ArrayList<InputEvent> events = new ArrayList<InputEvent>(
491 1);
492 }
|