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