001    /* DragSource.java --
002       Copyright (C) 2002 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package java.awt.dnd;
040    
041    import gnu.classpath.NotImplementedException;
042    
043    import java.awt.Component;
044    import java.awt.Cursor;
045    import java.awt.GraphicsEnvironment;
046    import java.awt.HeadlessException;
047    import java.awt.Image;
048    import java.awt.Point;
049    import java.awt.Toolkit;
050    import java.awt.datatransfer.FlavorMap;
051    import java.awt.datatransfer.SystemFlavorMap;
052    import java.awt.datatransfer.Transferable;
053    import java.awt.dnd.peer.DragSourceContextPeer;
054    import java.io.Serializable;
055    import java.util.EventListener;
056    
057    /**
058     * @since 1.2
059     */
060    public 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