1 /*
2 * Copyright 1997-2008 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package java.awt.dnd;
27
28 import java.util.TooManyListenersException;
29
30 import java.io.IOException;
31 import java.io.ObjectInputStream;
32 import java.io.ObjectOutputStream;
33 import java.io.Serializable;
34
35 import java.awt.Component;
36 import java.awt.Dimension;
37 import java.awt.GraphicsEnvironment;
38 import java.awt.HeadlessException;
39 import java.awt.Insets;
40 import java.awt.Point;
41 import java.awt.Rectangle;
42 import java.awt.Toolkit;
43 import java.awt.event.ActionEvent;
44 import java.awt.event.ActionListener;
45 import java.awt.datatransfer.FlavorMap;
46 import java.awt.datatransfer.SystemFlavorMap;
47 import javax.swing.Timer;
48 import java.awt.peer.ComponentPeer;
49 import java.awt.peer.LightweightPeer;
50 import java.awt.dnd.peer.DropTargetPeer;
51
52
53 /**
54 * The <code>DropTarget</code> is associated
55 * with a <code>Component</code> when that <code>Component</code>
56 * wishes
57 * to accept drops during Drag and Drop operations.
58 * <P>
59 * Each
60 * <code>DropTarget</code> is associated with a <code>FlavorMap</code>.
61 * The default <code>FlavorMap</code> hereafter designates the
62 * <code>FlavorMap</code> returned by <code>SystemFlavorMap.getDefaultFlavorMap()</code>.
63 *
64 * @since 1.2
65 */
66
67 public class DropTarget implements DropTargetListener, Serializable {
68
69 private static final long serialVersionUID = -6283860791671019047L;
70
71 /**
72 * Creates a new DropTarget given the <code>Component</code>
73 * to associate itself with, an <code>int</code> representing
74 * the default acceptable action(s) to
75 * support, a <code>DropTargetListener</code>
76 * to handle event processing, a <code>boolean</code> indicating
77 * if the <code>DropTarget</code> is currently accepting drops, and
78 * a <code>FlavorMap</code> to use (or null for the default <CODE>FlavorMap</CODE>).
79 * <P>
80 * The Component will receive drops only if it is enabled.
81 * @param c The <code>Component</code> with which this <code>DropTarget</code> is associated
82 * @param ops The default acceptable actions for this <code>DropTarget</code>
83 * @param dtl The <code>DropTargetListener</code> for this <code>DropTarget</code>
84 * @param act Is the <code>DropTarget</code> accepting drops.
85 * @param fm The <code>FlavorMap</code> to use, or null for the default <CODE>FlavorMap</CODE>
86 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
87 * returns true
88 * @see java.awt.GraphicsEnvironment#isHeadless
89 */
90 public DropTarget(Component c, int ops, DropTargetListener dtl,
91 boolean act, FlavorMap fm)
92 throws HeadlessException
93 {
94 if (GraphicsEnvironment.isHeadless()) {
95 throw new HeadlessException();
96 }
97
98 component = c;
99
100 setDefaultActions(ops);
101
102 if (dtl != null) try {
103 addDropTargetListener(dtl);
104 } catch (TooManyListenersException tmle) {
105 // do nothing!
106 }
107
108 if (c != null) {
109 c.setDropTarget(this);
110 setActive(act);
111 }
112
113 if (fm != null) {
114 flavorMap = fm;
115 } else {
116 flavorMap = SystemFlavorMap.getDefaultFlavorMap();
117 }
118 }
119
120 /**
121 * Creates a <code>DropTarget</code> given the <code>Component</code>
122 * to associate itself with, an <code>int</code> representing
123 * the default acceptable action(s)
124 * to support, a <code>DropTargetListener</code>
125 * to handle event processing, and a <code>boolean</code> indicating
126 * if the <code>DropTarget</code> is currently accepting drops.
127 * <P>
128 * The Component will receive drops only if it is enabled.
129 * @param c The <code>Component</code> with which this <code>DropTarget</code> is associated
130 * @param ops The default acceptable actions for this <code>DropTarget</code>
131 * @param dtl The <code>DropTargetListener</code> for this <code>DropTarget</code>
132 * @param act Is the <code>DropTarget</code> accepting drops.
133 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
134 * returns true
135 * @see java.awt.GraphicsEnvironment#isHeadless
136 */
137 public DropTarget(Component c, int ops, DropTargetListener dtl,
138 boolean act)
139 throws HeadlessException
140 {
141 this(c, ops, dtl, act, null);
142 }
143
144 /**
145 * Creates a <code>DropTarget</code>.
146 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
147 * returns true
148 * @see java.awt.GraphicsEnvironment#isHeadless
149 */
150 public DropTarget() throws HeadlessException {
151 this(null, DnDConstants.ACTION_COPY_OR_MOVE, null, true, null);
152 }
153
154 /**
155 * Creates a <code>DropTarget</code> given the <code>Component</code>
156 * to associate itself with, and the <code>DropTargetListener</code>
157 * to handle event processing.
158 * <P>
159 * The Component will receive drops only if it is enabled.
160 * @param c The <code>Component</code> with which this <code>DropTarget</code> is associated
161 * @param dtl The <code>DropTargetListener</code> for this <code>DropTarget</code>
162 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
163 * returns true
164 * @see java.awt.GraphicsEnvironment#isHeadless
165 */
166 public DropTarget(Component c, DropTargetListener dtl)
167 throws HeadlessException
168 {
169 this(c, DnDConstants.ACTION_COPY_OR_MOVE, dtl, true, null);
170 }
171
172 /**
173 * Creates a <code>DropTarget</code> given the <code>Component</code>
174 * to associate itself with, an <code>int</code> representing
175 * the default acceptable action(s) to support, and a
176 * <code>DropTargetListener</code> to handle event processing.
177 * <P>
178 * The Component will receive drops only if it is enabled.
179 * @param c The <code>Component</code> with which this <code>DropTarget</code> is associated
180 * @param ops The default acceptable actions for this <code>DropTarget</code>
181 * @param dtl The <code>DropTargetListener</code> for this <code>DropTarget</code>
182 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
183 * returns true
184 * @see java.awt.GraphicsEnvironment#isHeadless
185 */
186 public DropTarget(Component c, int ops, DropTargetListener dtl)
187 throws HeadlessException
188 {
189 this(c, ops, dtl, true);
190 }
191
192 /**
193 * Note: this interface is required to permit the safe association
194 * of a DropTarget with a Component in one of two ways, either:
195 * <code> component.setDropTarget(droptarget); </code>
196 * or <code> droptarget.setComponent(component); </code>
197 * <P>
198 * The Component will receive drops only if it is enabled.
199 * @param c The new <code>Component</code> this <code>DropTarget</code>
200 * is to be associated with.<P>
201 */
202
203 public synchronized void setComponent(Component c) {
204 if (component == c || component != null && component.equals(c))
205 return;
206
207 Component old;
208 ComponentPeer oldPeer = null;
209
210 if ((old = component) != null) {
211 clearAutoscroll();
212
213 component = null;
214
215 if (componentPeer != null) {
216 oldPeer = componentPeer;
217 removeNotify(componentPeer);
218 }
219
220 old.setDropTarget(null);
221
222 }
223
224 if ((component = c) != null) try {
225 c.setDropTarget(this);
226 } catch (Exception e) { // undo the change
227 if (old != null) {
228 old.setDropTarget(this);
229 addNotify(oldPeer);
230 }
231 }
232 }
233
234 /**
235 * Gets the <code>Component</code> associated
236 * with this <code>DropTarget</code>.
237 * <P>
238 * @return the current <code>Component</code>
239 */
240
241 public synchronized Component getComponent() {
242 return component;
243 }
244
245 /**
246 * Sets the default acceptable actions for this <code>DropTarget</code>
247 * <P>
248 * @param ops the default actions
249 * <P>
250 * @see java.awt.dnd.DnDConstants
251 */
252
253 public void setDefaultActions(int ops) {
254 getDropTargetContext().setTargetActions(ops & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_REFERENCE));
255 }
256
257 /*
258 * Called by DropTargetContext.setTargetActions()
259 * with appropriate synchronization.
260 */
261 void doSetDefaultActions(int ops) {
262 actions = ops;
263 }
264
265 /**
266 * Gets an <code>int</code> representing the
267 * current action(s) supported by this <code>DropTarget</code>.
268 * <P>
269 * @return the current default actions
270 */
271
272 public int getDefaultActions() {
273 return actions;
274 }
275
276 /**
277 * Sets the DropTarget active if <code>true</code>,
278 * inactive if <code>false</code>.
279 * <P>
280 * @param isActive sets the <code>DropTarget</code> (in)active.
281 */
282
283 public synchronized void setActive(boolean isActive) {
284 if (isActive != active) {
285 active = isActive;
286 }
287
288 if (!active) clearAutoscroll();
289 }
290
291 /**
292 * Reports whether or not
293 * this <code>DropTarget</code>
294 * is currently active (ready to accept drops).
295 * <P>
296 * @return <CODE>true</CODE> if active, <CODE>false</CODE> if not
297 */
298
299 public boolean isActive() {
300 return active;
301 }
302
303 /**
304 * Adds a new <code>DropTargetListener</code> (UNICAST SOURCE).
305 * <P>
306 * @param dtl The new <code>DropTargetListener</code>
307 * <P>
308 * @throws <code>TooManyListenersException</code> if a
309 * <code>DropTargetListener</code> is already added to this
310 * <code>DropTarget</code>.
311 */
312
313 public synchronized void addDropTargetListener(DropTargetListener dtl) throws TooManyListenersException {
314 if (dtl == null) return;
315
316 if (equals(dtl)) throw new IllegalArgumentException("DropTarget may not be its own Listener");
317
318 if (dtListener == null)
319 dtListener = dtl;
320 else
321 throw new TooManyListenersException();
322 }
323
324 /**
325 * Removes the current <code>DropTargetListener</code> (UNICAST SOURCE).
326 * <P>
327 * @param dtl the DropTargetListener to deregister.
328 */
329
330 public synchronized void removeDropTargetListener(DropTargetListener dtl) {
331 if (dtl != null && dtListener != null) {
332 if(dtListener.equals(dtl))
333 dtListener = null;
334 else
335 throw new IllegalArgumentException("listener mismatch");
336 }
337 }
338
339 /**
340 * Calls <code>dragEnter</code> on the registered
341 * <code>DropTargetListener</code> and passes it
342 * the specified <code>DropTargetDragEvent</code>.
343 * Has no effect if this <code>DropTarget</code>
344 * is not active.
345 *
346 * @param dtde the <code>DropTargetDragEvent</code>
347 *
348 * @throws NullPointerException if this <code>DropTarget</code>
349 * is active and <code>dtde</code> is <code>null</code>
350 *
351 * @see #isActive
352 */
353 public synchronized void dragEnter(DropTargetDragEvent dtde) {
354 if (!active) return;
355
356 if (dtListener != null) {
357 dtListener.dragEnter(dtde);
358 } else
359 dtde.getDropTargetContext().setTargetActions(DnDConstants.ACTION_NONE);
360
361 initializeAutoscrolling(dtde.getLocation());
362 }
363
364 /**
365 * Calls <code>dragOver</code> on the registered
366 * <code>DropTargetListener</code> and passes it
367 * the specified <code>DropTargetDragEvent</code>.
368 * Has no effect if this <code>DropTarget</code>
369 * is not active.
370 *
371 * @param dtde the <code>DropTargetDragEvent</code>
372 *
373 * @throws NullPointerException if this <code>DropTarget</code>
374 * is active and <code>dtde</code> is <code>null</code>
375 *
376 * @see #isActive
377 */
378 public synchronized void dragOver(DropTargetDragEvent dtde) {
379 if (!active) return;
380
381 if (dtListener != null && active) dtListener.dragOver(dtde);
382
383 updateAutoscroll(dtde.getLocation());
384 }
385
386 /**
387 * Calls <code>dropActionChanged</code> on the registered
388 * <code>DropTargetListener</code> and passes it
389 * the specified <code>DropTargetDragEvent</code>.
390 * Has no effect if this <code>DropTarget</code>
391 * is not active.
392 *
393 * @param dtde the <code>DropTargetDragEvent</code>
394 *
395 * @throws NullPointerException if this <code>DropTarget</code>
396 * is active and <code>dtde</code> is <code>null</code>
397 *
398 * @see #isActive
399 */
400 public synchronized void dropActionChanged(DropTargetDragEvent dtde) {
401 if (!active) return;
402
403 if (dtListener != null) dtListener.dropActionChanged(dtde);
404
405 updateAutoscroll(dtde.getLocation());
406 }
407
408 /**
409 * Calls <code>dragExit</code> on the registered
410 * <code>DropTargetListener</code> and passes it
411 * the specified <code>DropTargetEvent</code>.
412 * Has no effect if this <code>DropTarget</code>
413 * is not active.
414 * <p>
415 * This method itself does not throw any exception
416 * for null parameter but for exceptions thrown by
417 * the respective method of the listener.
418 *
419 * @param dte the <code>DropTargetEvent</code>
420 *
421 * @see #isActive
422 */
423 public synchronized void dragExit(DropTargetEvent dte) {
424 if (!active) return;
425
426 if (dtListener != null && active) dtListener.dragExit(dte);
427
428 clearAutoscroll();
429 }
430
431 /**
432 * Calls <code>drop</code> on the registered
433 * <code>DropTargetListener</code> and passes it
434 * the specified <code>DropTargetDropEvent</code>
435 * if this <code>DropTarget</code> is active.
436 *
437 * @param dtde the <code>DropTargetDropEvent</code>
438 *
439 * @throws NullPointerException if <code>dtde</code> is null
440 * and at least one of the following is true: this
441 * <code>DropTarget</code> is not active, or there is
442 * no a <code>DropTargetListener</code> registered.
443 *
444 * @see #isActive
445 */
446 public synchronized void drop(DropTargetDropEvent dtde) {
447 clearAutoscroll();
448
449 if (dtListener != null && active)
450 dtListener.drop(dtde);
451 else { // we should'nt get here ...
452 dtde.rejectDrop();
453 }
454 }
455
456 /**
457 * Gets the <code>FlavorMap</code>
458 * associated with this <code>DropTarget</code>.
459 * If no <code>FlavorMap</code> has been set for this
460 * <code>DropTarget</code>, it is associated with the default
461 * <code>FlavorMap</code>.
462 * <P>
463 * @return the FlavorMap for this DropTarget
464 */
465
466 public FlavorMap getFlavorMap() { return flavorMap; }
467
468 /**
469 * Sets the <code>FlavorMap</code> associated
470 * with this <code>DropTarget</code>.
471 * <P>
472 * @param fm the new <code>FlavorMap</code>, or null to
473 * associate the default FlavorMap with this DropTarget.
474 */
475
476 public void setFlavorMap(FlavorMap fm) {
477 flavorMap = fm == null ? SystemFlavorMap.getDefaultFlavorMap() : fm;
478 }
479
480 /**
481 * Notify the DropTarget that it has been associated with a Component
482 *
483 **********************************************************************
484 * This method is usually called from java.awt.Component.addNotify() of
485 * the Component associated with this DropTarget to notify the DropTarget
486 * that a ComponentPeer has been associated with that Component.
487 *
488 * Calling this method, other than to notify this DropTarget of the
489 * association of the ComponentPeer with the Component may result in
490 * a malfunction of the DnD system.
491 **********************************************************************
492 * <P>
493 * @param peer The Peer of the Component we are associated with!
494 *
495 */
496
497 public void addNotify(ComponentPeer peer) {
498 if (peer == componentPeer) return;
499
500 componentPeer = peer;
501
502 for (Component c = component;
503 c != null && peer instanceof LightweightPeer; c = c.getParent()) {
504 peer = c.getPeer();
505 }
506
507 if (peer instanceof DropTargetPeer) {
508 nativePeer = peer;
509 ((DropTargetPeer)peer).addDropTarget(this);
510 } else {
511 nativePeer = null;
512 }
513 }
514
515 /**
516 * Notify the DropTarget that it has been disassociated from a Component
517 *
518 **********************************************************************
519 * This method is usually called from java.awt.Component.removeNotify() of
520 * the Component associated with this DropTarget to notify the DropTarget
521 * that a ComponentPeer has been disassociated with that Component.
522 *
523 * Calling this method, other than to notify this DropTarget of the
524 * disassociation of the ComponentPeer from the Component may result in
525 * a malfunction of the DnD system.
526 **********************************************************************
527 * <P>
528 * @param peer The Peer of the Component we are being disassociated from!
529 */
530
531 public void removeNotify(ComponentPeer peer) {
532 if (nativePeer != null)
533 ((DropTargetPeer)nativePeer).removeDropTarget(this);
534
535 componentPeer = nativePeer = null;
536 }
537
538 /**
539 * Gets the <code>DropTargetContext</code> associated
540 * with this <code>DropTarget</code>.
541 * <P>
542 * @return the <code>DropTargetContext</code> associated with this <code>DropTarget</code>.
543 */
544
545 public DropTargetContext getDropTargetContext() {
546 return dropTargetContext;
547 }
548
549 /**
550 * Creates the DropTargetContext associated with this DropTarget.
551 * Subclasses may override this method to instantiate their own
552 * DropTargetContext subclass.
553 *
554 * This call is typically *only* called by the platform's
555 * DropTargetContextPeer as a drag operation encounters this
556 * DropTarget. Accessing the Context while no Drag is current
557 * has undefined results.
558 */
559
560 protected DropTargetContext createDropTargetContext() {
561 return new DropTargetContext(this);
562 }
563
564 /**
565 * Serializes this <code>DropTarget</code>. Performs default serialization,
566 * and then writes out this object's <code>DropTargetListener</code> if and
567 * only if it can be serialized. If not, <code>null</code> is written
568 * instead.
569 *
570 * @serialData The default serializable fields, in alphabetical order,
571 * followed by either a <code>DropTargetListener</code>
572 * instance, or <code>null</code>.
573 * @since 1.4
574 */
575 private void writeObject(ObjectOutputStream s) throws IOException {
576 s.defaultWriteObject();
577
578 s.writeObject(SerializationTester.test(dtListener)
579 ? dtListener : null);
580 }
581
582 /**
583 * Deserializes this <code>DropTarget</code>. This method first performs
584 * default deserialization for all non-<code>transient</code> fields. An
585 * attempt is then made to deserialize this object's
586 * <code>DropTargetListener</code> as well. This is first attempted by
587 * deserializing the field <code>dtListener</code>, because, in releases
588 * prior to 1.4, a non-<code>transient</code> field of this name stored the
589 * <code>DropTargetListener</code>. If this fails, the next object in the
590 * stream is used instead.
591 *
592 * @since 1.4
593 */
594 private void readObject(ObjectInputStream s)
595 throws ClassNotFoundException, IOException
596 {
597 ObjectInputStream.GetField f = s.readFields();
598
599 try {
600 dropTargetContext =
601 (DropTargetContext)f.get("dropTargetContext", null);
602 } catch (IllegalArgumentException e) {
603 // Pre-1.4 support. 'dropTargetContext' was previoulsy transient
604 }
605 if (dropTargetContext == null) {
606 dropTargetContext = createDropTargetContext();
607 }
608
609 component = (Component)f.get("component", null);
610 actions = f.get("actions", DnDConstants.ACTION_COPY_OR_MOVE);
611 active = f.get("active", true);
612
613 // Pre-1.4 support. 'dtListener' was previously non-transient
614 try {
615 dtListener = (DropTargetListener)f.get("dtListener", null);
616 } catch (IllegalArgumentException e) {
617 // 1.4-compatible byte stream. 'dtListener' was written explicitly
618 dtListener = (DropTargetListener)s.readObject();
619 }
620 }
621
622 /*********************************************************************/
623
624 /**
625 * this protected nested class implements autoscrolling
626 */
627
628 protected static class DropTargetAutoScroller implements ActionListener {
629
630 /**
631 * construct a DropTargetAutoScroller
632 * <P>
633 * @param c the <code>Component</code>
634 * @param p the <code>Point</code>
635 */
636
637 protected DropTargetAutoScroller(Component c, Point p) {
638 super();
639
640 component = c;
641 autoScroll = (Autoscroll)component;
642
643 Toolkit t = Toolkit.getDefaultToolkit();
644
645 Integer initial = Integer.valueOf(100);
646 Integer interval = Integer.valueOf(100);
647
648 try {
649 initial = (Integer)t.getDesktopProperty("DnD.Autoscroll.initialDelay");
650 } catch (Exception e) {
651 // ignore
652 }
653
654 try {
655 interval = (Integer)t.getDesktopProperty("DnD.Autoscroll.interval");
656 } catch (Exception e) {
657 // ignore
658 }
659
660 timer = new Timer(interval.intValue(), this);
661
662 timer.setCoalesce(true);
663 timer.setInitialDelay(initial.intValue());
664
665 locn = p;
666 prev = p;
667
668 try {
669 hysteresis = ((Integer)t.getDesktopProperty("DnD.Autoscroll.cursorHysteresis")).intValue();
670 } catch (Exception e) {
671 // ignore
672 }
673
674 timer.start();
675 }
676
677 /**
678 * update the geometry of the autoscroll region
679 */
680
681 private void updateRegion() {
682 Insets i = autoScroll.getAutoscrollInsets();
683 Dimension size = component.getSize();
684
685 if (size.width != outer.width || size.height != outer.height)
686 outer.reshape(0, 0, size.width, size.height);
687
688 if (inner.x != i.left || inner.y != i.top)
689 inner.setLocation(i.left, i.top);
690
691 int newWidth = size.width - (i.left + i.right);
692 int newHeight = size.height - (i.top + i.bottom);
693
694 if (newWidth != inner.width || newHeight != inner.height)
695 inner.setSize(newWidth, newHeight);
696
697 }
698
699 /**
700 * cause autoscroll to occur
701 * <P>
702 * @param newLocn the <code>Point</code>
703 */
704
705 protected synchronized void updateLocation(Point newLocn) {
706 prev = locn;
707 locn = newLocn;
708
709 if (Math.abs(locn.x - prev.x) > hysteresis ||
710 Math.abs(locn.y - prev.y) > hysteresis) {
711 if (timer.isRunning()) timer.stop();
712 } else {
713 if (!timer.isRunning()) timer.start();
714 }
715 }
716
717 /**
718 * cause autoscrolling to stop
719 */
720
721 protected void stop() { timer.stop(); }
722
723 /**
724 * cause autoscroll to occur
725 * <P>
726 * @param e the <code>ActionEvent</code>
727 */
728
729 public synchronized void actionPerformed(ActionEvent e) {
730 updateRegion();
731
732 if (outer.contains(locn) && !inner.contains(locn))
733 autoScroll.autoscroll(locn);
734 }
735
736 /*
737 * fields
738 */
739
740 private Component component;
741 private Autoscroll autoScroll;
742
743 private Timer timer;
744
745 private Point locn;
746 private Point prev;
747
748 private Rectangle outer = new Rectangle();
749 private Rectangle inner = new Rectangle();
750
751 private int hysteresis = 10;
752 }
753
754 /*********************************************************************/
755
756 /**
757 * create an embedded autoscroller
758 * <P>
759 * @param c the <code>Component</code>
760 * @param p the <code>Point</code>
761 */
762
763 protected DropTargetAutoScroller createDropTargetAutoScroller(Component c, Point p) {
764 return new DropTargetAutoScroller(c, p);
765 }
766
767 /**
768 * initialize autoscrolling
769 * <P>
770 * @param p the <code>Point</code>
771 */
772
773 protected void initializeAutoscrolling(Point p) {
774 if (component == null || !(component instanceof Autoscroll)) return;
775
776 autoScroller = createDropTargetAutoScroller(component, p);
777 }
778
779 /**
780 * update autoscrolling with current cursor locn
781 * <P>
782 * @param dragCursorLocn the <code>Point</code>
783 */
784
785 protected void updateAutoscroll(Point dragCursorLocn) {
786 if (autoScroller != null) autoScroller.updateLocation(dragCursorLocn);
787 }
788
789 /**
790 * clear autoscrolling
791 */
792
793 protected void clearAutoscroll() {
794 if (autoScroller != null) {
795 autoScroller.stop();
796 autoScroller = null;
797 }
798 }
799
800 /**
801 * The DropTargetContext associated with this DropTarget.
802 *
803 * @serial
804 */
805 private DropTargetContext dropTargetContext = createDropTargetContext();
806
807 /**
808 * The Component associated with this DropTarget.
809 *
810 * @serial
811 */
812 private Component component;
813
814 /*
815 * That Component's Peer
816 */
817 private transient ComponentPeer componentPeer;
818
819 /*
820 * That Component's "native" Peer
821 */
822 private transient ComponentPeer nativePeer;
823
824
825 /**
826 * Default permissible actions supported by this DropTarget.
827 *
828 * @see #setDefaultActions
829 * @see #getDefaultActions
830 * @serial
831 */
832 int actions = DnDConstants.ACTION_COPY_OR_MOVE;
833
834 /**
835 * <code>true</code> if the DropTarget is accepting Drag & Drop operations.
836 *
837 * @serial
838 */
839 boolean active = true;
840
841 /*
842 * the auto scrolling object
843 */
844
845 private transient DropTargetAutoScroller autoScroller;
846
847 /*
848 * The delegate
849 */
850
851 private transient DropTargetListener dtListener;
852
853 /*
854 * The FlavorMap
855 */
856
857 private transient FlavorMap flavorMap;
858 }