History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/awt/dnd/DragSource.java (1 of 18352 files). Show all

Unified · Split

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