2 Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
41 import java.awt.Component;
42 import java.awt.GraphicsEnvironment;
43 import java.awt.HeadlessException;
44 import java.awt.Insets;
45 import java.awt.Point;
46 import java.awt.Rectangle;
47 import java.awt.datatransfer.FlavorMap;
48 import java.awt.datatransfer.SystemFlavorMap;
49 import java.awt.dnd.peer.DropTargetPeer;
50 import java.awt.event.ActionEvent;
51 import java.awt.event.ActionListener;
52 import java.awt.peer.ComponentPeer;
53 import java.awt.peer.LightweightPeer;
54 import java.io.Serializable;
55 import java.util.EventListener;
56 import java.util.TooManyListenersException;
58 import javax.swing.Timer;
61 * @author Michael Koch
64 public class DropTarget
65 implements DropTargetListener, EventListener, Serializable
68 * Compatible with JDK 1.2+
70 private static final long serialVersionUID = -6283860791671019047L;
72 protected static class DropTargetAutoScroller
73 implements ActionListener
76 * The threshold that keeps the autoscroller running.
78 private static final int HYSTERESIS = 10;
81 * The initial timer delay.
83 private static final int DELAY = 100;
85 private Component component;
89 * The timer that triggers autoscrolling.
94 * The outer region of the scroller. This is the component's size.
96 private Rectangle outer;
99 * The inner region of the scroller. This is the component size without
100 * the autoscroll insets.
102 private Rectangle inner;
104 protected DropTargetAutoScroller (Component c, Point p)
108 timer = new Timer(DELAY, this);
109 timer.setCoalesce(true);
113 protected void updateLocation (Point newLocn)
115 Point previous = point;
117 if (Math.abs(point.x - previous.x) > HYSTERESIS
118 || Math.abs(point.y - previous.y) > HYSTERESIS)
120 if (timer.isRunning())
125 if (! timer.isRunning())
130 protected void stop ()
135 public void actionPerformed (ActionEvent e)
137 Autoscroll autoScroll = (Autoscroll) component;
139 // First synchronize the inner and outer rectangles.
140 Insets i = autoScroll.getAutoscrollInsets();
141 int width = component.getWidth();
142 int height = component.getHeight();
143 if (width != outer.width || height != outer.height)
144 outer.setBounds(0, 0, width, height);
145 if (inner.x != i.left || inner.y != i.top)
146 inner.setLocation(i.left, i.top);
147 int inWidth = width - i.left - i.right;
148 int inHeight = height - i.top - i.bottom;
149 if (inWidth != inner.width || inHeight != inner.height)
150 inner.setSize(inWidth, inHeight);
152 // Scroll if the outer rectangle contains the location, but the
154 if (outer.contains(point) && ! inner.contains(point))
155 autoScroll.autoscroll(point);
159 private Component component;
160 private FlavorMap flavorMap;
162 private DropTargetPeer peer;
163 private DropTargetContext dropTargetContext;
164 private DropTargetListener dropTargetListener;
165 private DropTarget.DropTargetAutoScroller autoscroller;
166 private boolean active = true;
169 * Creates a <code>DropTarget</code> object.
171 * @exception HeadlessException If GraphicsEnvironment.isHeadless()
176 this (null, DnDConstants.ACTION_COPY_OR_MOVE, null, true, null);
180 * Creates a <code>DropTarget</code> object.
182 * @exception HeadlessException If GraphicsEnvironment.isHeadless()
185 public DropTarget (Component c, DropTargetListener dtl)
187 this (c, DnDConstants.ACTION_COPY_OR_MOVE, dtl, true, null);
191 * Creates a <code>DropTarget</code> object.
193 * @exception HeadlessException If GraphicsEnvironment.isHeadless()
196 public DropTarget (Component c, int i, DropTargetListener dtl)
198 this (c, i, dtl, true, null);
202 * Creates a <code>DropTarget</code> object.
204 * @exception HeadlessException If GraphicsEnvironment.isHeadless()
207 public DropTarget (Component c, int i, DropTargetListener dtl, boolean b)
209 this (c, i, dtl, b, null);
213 * Creates a <code>DropTarget</code> object.
215 * @exception HeadlessException If GraphicsEnvironment.isHeadless()
218 public DropTarget (Component c, int i, DropTargetListener dtl, boolean b,
221 if (GraphicsEnvironment.isHeadless ())
222 throw new HeadlessException ();
225 setDefaultActions(i);
226 dropTargetListener = dtl;
229 flavorMap = SystemFlavorMap.getDefaultFlavorMap();
236 c.setDropTarget(this);
240 * Sets the component associated with this drop target object.
242 public void setComponent (Component c)
244 if (component != null)
250 * Returns the component associated with this drop target object.
252 public Component getComponent ()
258 * Sets the default actions.
260 public void setDefaultActions (int ops)
266 * Returns the default actions.
268 public int getDefaultActions ()
273 public void setActive (boolean active)
275 this.active = active;
280 public boolean isActive()
286 * Adds a new <code>DropTargetListener</code>.
288 * @exception TooManyListenersException Sun's JDK does not, despite
289 * documentation, throw this exception here when you install an additional
290 * <code>DropTargetListener</code>. So to be compatible, we do the same
293 public void addDropTargetListener (DropTargetListener dtl)
294 throws TooManyListenersException
299 if (dtl.equals(this))
300 throw new IllegalArgumentException();
302 if (dropTargetListener != null)
303 throw new TooManyListenersException();
305 dropTargetListener = dtl;
308 public void removeDropTargetListener(DropTargetListener dtl)
310 if (dropTargetListener != null)
311 dropTargetListener = null;
314 public void dragEnter(DropTargetDragEvent dtde)
318 if (dropTargetListener != null)
319 dropTargetListener.dragEnter(dtde);
320 initializeAutoscrolling(dtde.getLocation());
324 public void dragOver(DropTargetDragEvent dtde)
328 if (dropTargetListener != null)
329 dropTargetListener.dragOver(dtde);
330 updateAutoscroll(dtde.getLocation());
334 public void dropActionChanged(DropTargetDragEvent dtde)
338 if (dropTargetListener != null)
339 dropTargetListener.dropActionChanged(dtde);
340 updateAutoscroll(dtde.getLocation());
344 public void dragExit(DropTargetEvent dte)
348 if (dropTargetListener != null)
349 dropTargetListener.dragExit(dte);
354 public void drop(DropTargetDropEvent dtde)
357 if (dropTargetListener != null)
358 dropTargetListener.drop(dtde);
361 public FlavorMap getFlavorMap()
366 public void setFlavorMap(FlavorMap fm)
371 public void addNotify(ComponentPeer p)
373 Component c = component;
374 while (c != null && p instanceof LightweightPeer)
380 if (p instanceof DropTargetPeer)
382 peer = ((DropTargetPeer) p);
383 peer.addDropTarget(this);
389 public void removeNotify(ComponentPeer p)
391 ((DropTargetPeer) peer).removeDropTarget(this);
396 public DropTargetContext getDropTargetContext()
398 if (dropTargetContext == null)
399 dropTargetContext = createDropTargetContext ();
401 return dropTargetContext;
404 protected DropTargetContext createDropTargetContext()
406 if (dropTargetContext == null)
407 dropTargetContext = new DropTargetContext (this);
409 return dropTargetContext;
412 protected DropTarget.DropTargetAutoScroller createDropTargetAutoScroller
413 (Component c, Point p)
415 return new DropTarget.DropTargetAutoScroller (c, p);
418 protected void initializeAutoscrolling(Point p)
420 if (component instanceof Autoscroll) // Checks for null too.
421 autoscroller = createDropTargetAutoScroller (component, p);
424 protected void updateAutoscroll(Point dragCursorLocn)
426 if (autoscroller != null)
427 autoscroller.updateLocation(dragCursorLocn);
430 protected void clearAutoscroll()
432 if (autoscroller != null)
438 } // class DropTarget