OSDN Git Service

libjava/
[pf3gnuchains/gcc-fork.git] / libjava / classpath / java / awt / dnd / DropTarget.java
1 /* DropTarget.java -- 
2    Copyright (C) 2002, 2003, 2004  Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
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)
9 any later version.
10
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.
15
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
19 02110-1301 USA.
20
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
24 combination.
25
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. */
37
38
39 package java.awt.dnd;
40
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;
57
58 import javax.swing.Timer;
59
60 /**
61  * @author Michael Koch
62  * @since 1.2
63  */
64 public class DropTarget
65   implements DropTargetListener, EventListener, Serializable
66 {
67   /**
68    * Compatible with JDK 1.2+
69    */
70   private static final long serialVersionUID = -6283860791671019047L;
71
72   protected static class DropTargetAutoScroller
73     implements ActionListener
74   {
75     /**
76      * The threshold that keeps the autoscroller running.
77      */
78     private static final int HYSTERESIS = 10;
79
80     /**
81      * The initial timer delay.
82      */
83     private static final int DELAY = 100;
84
85     private Component component;
86     private Point point;
87
88     /**
89      * The timer that triggers autoscrolling.
90      */
91     private Timer timer;
92
93     /**
94      * The outer region of the scroller. This is the component's size.
95      */
96     private Rectangle outer;
97
98     /**
99      * The inner region of the scroller. This is the component size without
100      * the autoscroll insets.
101      */
102     private Rectangle inner;
103
104     protected DropTargetAutoScroller (Component c, Point p)
105     {
106       component = c;
107       point = p;
108       timer = new Timer(DELAY, this);
109       timer.setCoalesce(true);
110       timer.start();
111     }
112
113     protected void updateLocation (Point newLocn)
114     {
115       Point previous = point;
116       point = newLocn;
117       if (Math.abs(point.x - previous.x) > HYSTERESIS
118           || Math.abs(point.y - previous.y) > HYSTERESIS)
119         {
120           if (timer.isRunning())
121             timer.stop();
122         }
123       else
124         {
125           if (! timer.isRunning())
126             timer.start();
127         }
128     }
129
130     protected void stop ()
131     {
132       timer.start();
133     }
134
135     public void actionPerformed (ActionEvent e)
136     {
137       Autoscroll autoScroll = (Autoscroll) component;
138
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);
151
152       // Scroll if the outer rectangle contains the location, but the
153       // inner doesn't.
154       if (outer.contains(point) && ! inner.contains(point))
155         autoScroll.autoscroll(point);
156     }
157   }
158
159   private Component component;
160   private FlavorMap flavorMap;
161   private int actions;
162   private DropTargetPeer peer;
163   private DropTargetContext dropTargetContext;
164   private DropTargetListener dropTargetListener;
165   private DropTarget.DropTargetAutoScroller autoscroller;
166   private boolean active = true;
167     
168   /**
169    * Creates a <code>DropTarget</code> object.
170    *
171    * @exception HeadlessException If GraphicsEnvironment.isHeadless()
172    * returns true.
173    */
174   public DropTarget ()
175   {
176     this (null, DnDConstants.ACTION_COPY_OR_MOVE, null, true, null);
177   }
178   
179   /**
180    * Creates a <code>DropTarget</code> object.
181    *
182    * @exception HeadlessException If GraphicsEnvironment.isHeadless()
183    * returns true.
184    */
185   public DropTarget (Component c, DropTargetListener dtl)
186   {
187     this (c, DnDConstants.ACTION_COPY_OR_MOVE, dtl, true, null);
188   }
189   
190   /**
191    * Creates a <code>DropTarget</code> object.
192    *
193    * @exception HeadlessException If GraphicsEnvironment.isHeadless()
194    * returns true.
195    */
196   public DropTarget (Component c, int i, DropTargetListener dtl)
197   {
198     this (c, i, dtl, true, null);
199   }
200   
201   /**
202    * Creates a <code>DropTarget</code> object.
203    *
204    * @exception HeadlessException If GraphicsEnvironment.isHeadless()
205    * returns true.
206    */
207   public DropTarget (Component c, int i, DropTargetListener dtl, boolean b)
208   {
209     this (c, i, dtl, b, null);
210   }
211   
212   /**
213    * Creates a <code>DropTarget</code> object.
214    *
215    * @exception HeadlessException If GraphicsEnvironment.isHeadless()
216    * returns true.
217    */
218   public DropTarget (Component c, int i, DropTargetListener dtl, boolean b,
219                      FlavorMap fm)
220   {
221     if (GraphicsEnvironment.isHeadless ())
222       throw new HeadlessException ();
223
224     setComponent(c);
225     setDefaultActions(i);
226     dropTargetListener = dtl;
227     
228     if (fm == null)
229       flavorMap = SystemFlavorMap.getDefaultFlavorMap();
230     else
231       flavorMap = fm;
232     
233     setActive (b);
234     
235     if (c != null)
236       c.setDropTarget(this);
237   }
238
239   /**
240    * Sets the component associated with this drop target object.
241    */
242   public void setComponent (Component c)
243   {
244     if (component != null)
245       clearAutoscroll();
246     component = c;
247   }
248
249   /**
250    * Returns the component associated with this drop target object.
251    */
252   public Component getComponent ()
253   {
254     return component;
255   }
256
257   /**
258    * Sets the default actions.
259    */
260   public void setDefaultActions (int ops)
261   {
262     actions = ops;
263   }
264
265   /**
266    * Returns the default actions.
267    */
268   public int getDefaultActions ()
269   {
270     return actions;
271   }
272
273   public void setActive (boolean active)
274   {
275     this.active = active;
276     if (! active)
277       clearAutoscroll();
278   }
279
280   public boolean isActive()
281   {
282     return active;
283   }
284
285   /**
286    * Adds a new <code>DropTargetListener</code>.
287    * 
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
291    * thing.
292    */
293   public void addDropTargetListener (DropTargetListener dtl)
294     throws TooManyListenersException
295   {
296     if (dtl == null)
297       return;
298     
299     if (dtl.equals(this))
300       throw new IllegalArgumentException();
301     
302     if (dropTargetListener != null)
303       throw new TooManyListenersException();
304     
305     dropTargetListener = dtl;
306   }
307
308   public void removeDropTargetListener(DropTargetListener dtl)
309   {
310     if (dropTargetListener != null)
311       dropTargetListener = null;
312   }
313
314   public void dragEnter(DropTargetDragEvent dtde)
315   {
316     if (active)
317       {
318         if (dropTargetListener != null)
319           dropTargetListener.dragEnter(dtde);
320         initializeAutoscrolling(dtde.getLocation());
321       }
322   }
323
324   public void dragOver(DropTargetDragEvent dtde)
325   {
326     if (active)
327       {
328         if (dropTargetListener != null)
329           dropTargetListener.dragOver(dtde);
330         updateAutoscroll(dtde.getLocation());
331       }
332   }
333
334   public void dropActionChanged(DropTargetDragEvent dtde)
335   {
336     if (active)
337       {
338         if (dropTargetListener != null)
339           dropTargetListener.dropActionChanged(dtde);
340         updateAutoscroll(dtde.getLocation());
341       }
342   }
343
344   public void dragExit(DropTargetEvent dte)
345   {
346     if (active)
347       {
348         if (dropTargetListener != null)
349           dropTargetListener.dragExit(dte);
350         clearAutoscroll();
351       }
352   }
353
354   public void drop(DropTargetDropEvent dtde)
355   {
356     clearAutoscroll();
357     if (dropTargetListener != null)
358       dropTargetListener.drop(dtde);
359   }
360
361   public FlavorMap getFlavorMap()
362   {
363     return flavorMap;
364   }
365
366   public void setFlavorMap(FlavorMap fm)
367   {
368     flavorMap = fm;
369   }
370
371   public void addNotify(ComponentPeer p)
372   {
373     Component c = component;
374     while (c != null && p instanceof LightweightPeer)
375       {
376         p = c.getPeer();
377         c = c.getParent();
378       }
379
380     if (p instanceof DropTargetPeer)
381       {
382         peer = ((DropTargetPeer) p);
383         peer.addDropTarget(this);
384       }
385     else
386       peer = null;
387   }
388
389   public void removeNotify(ComponentPeer p)
390   {
391     ((DropTargetPeer) peer).removeDropTarget(this);
392     peer = null;
393     p = null;
394   }
395
396   public DropTargetContext getDropTargetContext()
397   {
398     if (dropTargetContext == null)
399       dropTargetContext = createDropTargetContext ();
400     
401     return dropTargetContext;
402   }
403
404   protected DropTargetContext createDropTargetContext()
405   {
406     if (dropTargetContext == null)
407       dropTargetContext = new DropTargetContext (this);
408     
409     return dropTargetContext;
410   }
411
412   protected DropTarget.DropTargetAutoScroller createDropTargetAutoScroller
413                                                        (Component c, Point p)
414   {
415     return new DropTarget.DropTargetAutoScroller (c, p);
416   }
417
418   protected void initializeAutoscrolling(Point p)
419   {
420     if (component instanceof Autoscroll) // Checks for null too.
421       autoscroller = createDropTargetAutoScroller (component, p);
422   }
423
424   protected void updateAutoscroll(Point dragCursorLocn)
425   {
426     if (autoscroller != null)
427       autoscroller.updateLocation(dragCursorLocn);
428   }
429
430   protected void clearAutoscroll()
431   {
432     if (autoscroller != null)
433       {
434         autoscroller.stop();
435         autoscroller = null;
436       }
437   }
438 } // class DropTarget