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