001/* DragSource.java --
002   Copyright (C) 2002 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.awt.dnd;
040
041import gnu.classpath.NotImplementedException;
042
043import java.awt.Component;
044import java.awt.Cursor;
045import java.awt.GraphicsEnvironment;
046import java.awt.HeadlessException;
047import java.awt.Image;
048import java.awt.Point;
049import java.awt.Toolkit;
050import java.awt.datatransfer.FlavorMap;
051import java.awt.datatransfer.SystemFlavorMap;
052import java.awt.datatransfer.Transferable;
053import java.awt.dnd.peer.DragSourceContextPeer;
054import java.io.Serializable;
055import java.util.EventListener;
056
057/**
058 * @since 1.2
059 */
060public class DragSource implements Serializable
061{
062  /**
063   * Compatible with JDK 1.2+.
064   */
065  private static final long serialVersionUID = 6236096958971414066L;
066
067  public static final Cursor DefaultCopyDrop = null;
068  public static final Cursor DefaultMoveDrop = null;
069  public static final Cursor DefaultLinkDrop = null;
070  public static final Cursor DefaultCopyNoDrop = null;
071  public static final Cursor DefaultMoveNoDrop = null;
072  public static final Cursor DefaultLinkNoDrop = null;
073
074  private transient FlavorMap flavorMap = SystemFlavorMap.getDefaultFlavorMap ();
075  private transient DragSourceListener dragSourceListener;
076  private transient DragSourceMotionListener dragSourceMotionListener;
077
078  private static DragSource ds;
079  private DragSourceContextPeer peer;
080  private DragSourceContext context;
081
082  /**
083   * Initializes the drag source.
084   *
085   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
086   */
087  public DragSource()
088  {
089    if (GraphicsEnvironment.isHeadless())
090      {
091        ds = null;
092        throw new HeadlessException();
093      }
094  }
095
096  /**
097   * Gets the default drag source.
098   *
099   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
100   */
101  public static DragSource getDefaultDragSource()
102  {
103    if (GraphicsEnvironment.isHeadless())
104      {
105        ds = null;
106        throw new HeadlessException();
107      }
108
109    if (ds == null)
110      ds = new DragSource();
111    return ds;
112  }
113
114  public static boolean isDragImageSupported()
115  {
116    // In all cases, Sun returns false here.
117    return false;
118  }
119
120  /**
121   * Start a drag, given the DragGestureEvent that initiated the drag.
122   *
123   * @exception InvalidDnDOperationException If the Drag and Drop system is
124   * unable to initiate a drag operation, or if the user attempts to start
125   * a drag while an existing drag operation is still executing.
126   */
127  public void startDrag(DragGestureEvent trigger, Cursor dragCursor,
128                        Image dragImage, Point imageOffset,
129                        Transferable trans, DragSourceListener dsl,
130                        FlavorMap map)
131  {
132    // http://www.javaworld.com/javaworld/jw-03-1999/jw-03-dragndrop.html
133
134    // This function creates a DragSourceContext object. This object tracks the
135    // state of the operation by listening to a native peer. In this situation,
136    // the DragSource may be obtained from the event or by an instance variable.
137    // This function also creates a new DragSourceContextPeer.
138
139    // This function sends the same message to the context, which then forwards
140    // it to the peer, passing itself as a parameter. Now, the native system has
141    // access to the Transferable through the context.
142
143    try
144      {
145        flavorMap = map;
146
147        if (peer == null)
148          peer = Toolkit.getDefaultToolkit().createDragSourceContextPeer(trigger);
149
150        if (context == null)
151          context = createDragSourceContext(peer, trigger,
152                                                            dragCursor,
153                                                            dragImage,
154                                                            imageOffset, trans,
155                                                            dsl);
156
157        if (peer == null)
158          throw new InvalidDnDOperationException();
159
160        peer.startDrag(context, dragCursor, dragImage, imageOffset);
161      }
162    catch (Exception e)
163      {
164        throw new InvalidDnDOperationException("Drag and Drop system is "
165                                + "unable to initiate a drag operation.");
166      }
167  }
168
169  /**
170   * Start a drag, given the DragGestureEvent that initiated the drag.
171   *
172   * @exception InvalidDnDOperationException If the Drag and Drop system is
173   * unable to initiate a drag operation, or if the user attempts to start
174   * a drag while an existing drag operation is still executing.
175   */
176  public void startDrag(DragGestureEvent trigger, Cursor dragCursor,
177                        Transferable trans, DragSourceListener dsl,
178                        FlavorMap map)
179  {
180    startDrag(trigger, dragCursor, null, null, trans, dsl, map);
181  }
182
183  /**
184   * Start a drag, given the DragGestureEvent that initiated the drag.
185   *
186   * @exception InvalidDnDOperationException If the Drag and Drop system is
187   * unable to initiate a drag operation, or if the user attempts to start
188   * a drag while an existing drag operation is still executing.
189   */
190  public void startDrag(DragGestureEvent trigger, Cursor dragCursor,
191                        Image dragImage, Point imageOffset,
192                        Transferable trans, DragSourceListener dsl)
193  {
194    startDrag(trigger, dragCursor, dragImage, imageOffset, trans, dsl, null);
195  }
196
197  /**
198   * Start a drag, given the DragGestureEvent that initiated the drag.
199   *
200   * @exception InvalidDnDOperationException If the Drag and Drop system is
201   * unable to initiate a drag operation, or if the user attempts to start
202   * a drag while an existing drag operation is still executing.
203   */
204  public void startDrag(DragGestureEvent trigger, Cursor dragCursor,
205                        Transferable trans, DragSourceListener dsl)
206  {
207    startDrag(trigger, dragCursor, null, null, trans, dsl, null);
208  }
209
210  /**
211   * Creates the DragSourceContext to handle this drag.
212   *
213   * @exception IllegalArgumentException
214   * @exception NullPointerException If dscp, dgl, dragImage or t is null.
215   */
216  protected DragSourceContext
217    createDragSourceContext(DragSourceContextPeer peer, DragGestureEvent dge,
218                            Cursor cursor, Image image, Point offset,
219                            Transferable t, DragSourceListener dsl)
220  {
221    return new DragSourceContext(peer, dge, cursor, image, offset, t, dsl);
222  }
223
224  public FlavorMap getFlavorMap()
225  {
226    return flavorMap;
227  }
228
229  public <T extends DragGestureRecognizer> T
230                    createDragGestureRecognizer(Class<T> recognizer,
231                                                Component c,
232                                                int actions,
233                                                DragGestureListener dgl)
234  {
235    return (T) Toolkit.getDefaultToolkit().createDragGestureRecognizer(recognizer,
236                                                                       this, c,
237                                                                       actions, dgl);
238  }
239
240  public DragGestureRecognizer createDefaultDragGestureRecognizer(Component c,
241                                                                  int actions,
242                                                                  DragGestureListener dgl)
243  {
244    return createDragGestureRecognizer(MouseDragGestureRecognizer.class, c,
245                                       actions, dgl);
246  }
247
248  /**
249   * @since 1.4
250   */
251  public void addDragSourceListener(DragSourceListener l)
252  {
253    DnDEventMulticaster.add (dragSourceListener, l);
254  }
255
256  /**
257   * @since 1.4
258   */
259  public void removeDragSourceListener(DragSourceListener l)
260  {
261    DnDEventMulticaster.remove (dragSourceListener, l);
262  }
263
264  /**
265   * @since 1.4
266   */
267  public DragSourceListener[] getDragSourceListeners()
268  {
269    return (DragSourceListener[]) getListeners (DragSourceListener.class);
270  }
271
272  /**
273   * @since 1.4
274   */
275  public void addDragSourceMotionListener(DragSourceMotionListener l)
276  {
277    DnDEventMulticaster.add (dragSourceMotionListener, l);
278  }
279
280  /**
281   * @since 1.4
282   */
283  public void removeDragSourceMotionListener(DragSourceMotionListener l)
284  {
285    DnDEventMulticaster.remove (dragSourceMotionListener, l);
286  }
287
288  /**
289   * @since 1.4
290   */
291  public DragSourceMotionListener[] getDragSourceMotionListeners ()
292  {
293    return (DragSourceMotionListener[]) getListeners
294                                         (DragSourceMotionListener.class);
295  }
296
297  /**
298   * @since 1.4
299   */
300  public <T extends EventListener> T[] getListeners (Class<T> listenerType)
301  {
302    if (listenerType == DragSourceListener.class)
303      return DnDEventMulticaster.getListeners (dragSourceListener,
304                                               listenerType);
305
306    if (listenerType == DragSourceMotionListener.class)
307      return DnDEventMulticaster.getListeners (dragSourceMotionListener,
308                                               listenerType);
309
310    // Return an empty EventListener array.
311    return (T[]) new EventListener [0];
312  }
313
314  /**
315   * TODO
316   * @return TODO
317   *
318   * @since 1.5
319   */
320  public static int getDragThreshold()
321    throws NotImplementedException
322  {
323    // FIXME: Not implemented.
324    return 8;
325  }
326} // class DragSource