001    /* DragSourceContext.java --
002       Copyright (C) 2002 Free Software Foundation
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 java.awt.Component;
042    import java.awt.Cursor;
043    import java.awt.Image;
044    import java.awt.Point;
045    import java.awt.datatransfer.Transferable;
046    import java.awt.dnd.peer.DragSourceContextPeer;
047    import java.io.Serializable;
048    import java.util.TooManyListenersException;
049    
050    /**
051     * @since 1.2
052     */
053    public class DragSourceContext
054      implements DragSourceListener, DragSourceMotionListener, Serializable
055    {
056      /**
057       * Compatible with JDK 1.2+
058       */
059      static final long serialVersionUID = -115407898692194719L;
060    
061      protected static final int DEFAULT = 0;
062      protected static final int ENTER = 1;
063      protected static final int OVER = 2;
064      protected static final int CHANGED = 3;
065    
066      private DragSourceContextPeer peer;
067      private Cursor cursor;
068      private Transferable transferable;
069      private DragGestureEvent trigger;
070      private DragSourceListener dragSourceListener;
071      private boolean useCustomCursor;
072      private int sourceActions;
073      private Image image;
074      private Point offset;
075    
076      /**
077       * Initializes a drag source context.
078       *
079       * @exception IllegalArgumentException If Component or DragSource of trigger
080       * are null, the drag action for the trigger event is DnDConstants.ACTION_NONE
081       * or if the source actions for the DragGestureRecognizer associated with the
082       * trigger event are equal to DnDConstants.ACTION_NONE.
083       * @exception NullPointerException If peer, trans or trigger is null or if the
084       * image is not null but the offset is.
085       */
086      public DragSourceContext (DragSourceContextPeer peer,
087                                DragGestureEvent trigger, Cursor cursor,
088                                Image image, Point offset, Transferable trans,
089                                DragSourceListener dsl)
090      {
091        if (peer == null
092            || trigger == null || trans == null
093            || (image != null && offset == null))
094          throw new NullPointerException ();
095    
096        if (trigger.getComponent () == null
097            || trigger.getDragSource () == null
098            || trigger.getDragAction () == DnDConstants.ACTION_NONE
099            || trigger.getSourceAsDragGestureRecognizer ()
100                  .getSourceActions () == DnDConstants.ACTION_NONE)
101          throw new IllegalArgumentException ();
102    
103        this.peer = peer;
104        this.trigger = trigger;
105        this.cursor = cursor;
106        this.image = image;
107        this.offset = offset;
108        this.transferable = trans;
109        this.dragSourceListener = dsl;
110        this.sourceActions = trigger.getSourceAsDragGestureRecognizer().getSourceActions();
111    
112        setCursor(cursor);
113        updateCurrentCursor(trigger.getDragAction(), sourceActions, DEFAULT);
114      }
115    
116      /**
117       * Returns the DragSource object associated with the
118       * DragGestureEvent.
119       *
120       * @return the DragSource associated with the trigger.
121       */
122      public DragSource getDragSource()
123      {
124        return trigger.getDragSource ();
125      }
126    
127      /**
128       * Returns the component associated with this.
129       *
130       * @return the component associated with the trigger.
131       */
132      public Component getComponent()
133      {
134        return trigger.getComponent ();
135      }
136    
137      /**
138       * Gets the trigger associated with this.
139       *
140       * @return the trigger.
141       */
142      public DragGestureEvent getTrigger()
143      {
144        return trigger;
145      }
146    
147      /**
148       * Returns the source actions for the DragGestureRecognizer.
149       *
150       * @return the source actions for DragGestureRecognizer.
151       */
152      public int getSourceActions()
153      {
154        if (sourceActions == 0)
155          sourceActions = trigger.getSourceAsDragGestureRecognizer().getSourceActions();
156        return sourceActions;
157      }
158    
159      /**
160       * Sets the cursor for this drag operation to the specified cursor.
161       *
162       * @param cursor c - the Cursor to use, or null to use the default drag
163       *          cursor.
164       */
165      public void setCursor(Cursor cursor)
166      {
167        if (cursor == null)
168          useCustomCursor = false;
169        else
170          useCustomCursor = true;
171        this.cursor = cursor;
172        peer.setCursor(cursor);
173      }
174    
175      /**
176       * Returns the current cursor or null if the default
177       * drag cursor is used.
178       *
179       * @return the current cursor or null.
180       */
181      public Cursor getCursor()
182      {
183        return cursor;
184      }
185    
186      /**
187       * Adds a <code>DragSourceListener</code>.
188       *
189       * @exception TooManyListenersException If a <code>DragSourceListener</code>
190       * has already been added.
191       */
192      public void addDragSourceListener (DragSourceListener dsl)
193        throws TooManyListenersException
194      {
195        if (dragSourceListener != null)
196          throw new TooManyListenersException ();
197    
198        dragSourceListener = dsl;
199      }
200    
201      public void removeDragSourceListener (DragSourceListener dsl)
202      {
203        if (dragSourceListener == dsl)
204          dragSourceListener = null;
205      }
206    
207      /**
208       * This function tells the peer that the DataFlavors have been modified.
209       */
210      public void transferablesFlavorsChanged()
211      {
212        peer.transferablesFlavorsChanged();
213      }
214    
215      /**
216       * Calls dragEnter on the listeners registered with this
217       * and with the DragSource.
218       *
219       * @param e - the DragSourceDragEvent
220       */
221      public void dragEnter(DragSourceDragEvent e)
222      {
223        if (dragSourceListener != null)
224          dragSourceListener.dragEnter(e);
225    
226        DragSource ds = getDragSource();
227        DragSourceListener[] dsl = ds.getDragSourceListeners();
228        for (int i = 0; i < dsl.length; i++)
229          dsl[i].dragEnter(e);
230    
231        updateCurrentCursor(e.getDropAction(), e.getTargetActions(), ENTER);
232      }
233    
234      /**
235       * Calls dragOver on the listeners registered with this
236       * and with the DragSource.
237       *
238       * @param e - the DragSourceDragEvent
239       */
240      public void dragOver(DragSourceDragEvent e)
241      {
242        if (dragSourceListener != null)
243          dragSourceListener.dragOver(e);
244    
245        DragSource ds = getDragSource();
246        DragSourceListener[] dsl = ds.getDragSourceListeners();
247        for (int i = 0; i < dsl.length; i++)
248          dsl[i].dragOver(e);
249    
250        updateCurrentCursor(e.getDropAction(), e.getTargetActions(), OVER);
251      }
252    
253      /**
254       * Calls dragExit on the listeners registered with this
255       * and with the DragSource.
256       *
257       * @param e - the DragSourceEvent
258       */
259      public void dragExit(DragSourceEvent e)
260      {
261        if (dragSourceListener != null)
262          dragSourceListener.dragExit(e);
263    
264        DragSource ds = getDragSource();
265        DragSourceListener[] dsl = ds.getDragSourceListeners();
266        for (int i = 0; i < dsl.length; i++)
267          dsl[i].dragExit(e);
268    
269        updateCurrentCursor(DnDConstants.ACTION_NONE, DnDConstants.ACTION_NONE,
270                            DEFAULT);
271      }
272    
273      /**
274       * Calls dropActionChanged on the listeners registered with this
275       * and with the DragSource.
276       *
277       * @param e - the DragSourceDragEvent
278       */
279      public void dropActionChanged(DragSourceDragEvent e)
280      {
281        if (dragSourceListener != null)
282          dragSourceListener.dropActionChanged(e);
283    
284        DragSource ds = getDragSource();
285        DragSourceListener[] dsl = ds.getDragSourceListeners();
286        for (int i = 0; i < dsl.length; i++)
287          dsl[i].dropActionChanged(e);
288    
289        updateCurrentCursor(e.getDropAction(), e.getTargetActions(), CHANGED);
290      }
291    
292      /**
293       * Calls dragDropEnd on the listeners registered with this
294       * and with the DragSource.
295       *
296       * @param e - the DragSourceDropEvent
297       */
298      public void dragDropEnd(DragSourceDropEvent e)
299      {
300        if (dragSourceListener != null)
301          dragSourceListener.dragDropEnd(e);
302    
303        DragSource ds = getDragSource();
304        DragSourceListener[] dsl = ds.getDragSourceListeners();
305        for (int i = 0; i < dsl.length; i++)
306          dsl[i].dragDropEnd(e);
307      }
308    
309      /**
310       * Calls dragMouseMoved on the listeners registered with the DragSource.
311       *
312       * @param e - the DragSourceDragEvent
313       */
314      public void dragMouseMoved(DragSourceDragEvent e)
315      {
316        DragSource ds = getDragSource();
317        DragSourceMotionListener[] dsml = ds.getDragSourceMotionListeners();
318        for (int i = 0; i < dsml.length; i++)
319          dsml[i].dragMouseMoved(e);
320      }
321    
322      /**
323       * Returns the Transferable set with this object.
324       *
325       * @return the transferable.
326       */
327      public Transferable getTransferable()
328      {
329        return transferable;
330      }
331    
332      /**
333       * This function sets the drag cursor for the specified operation, actions and
334       * status if the default drag cursor is active. Otherwise, the cursor is not
335       * updated in any way.
336       *
337       * @param dropOp - the current operation.
338       * @param targetAct - the supported actions.
339       * @param status - the status of the cursor (constant).
340       */
341      protected void updateCurrentCursor(int dropOp, int targetAct, int status)
342      {
343        if (! useCustomCursor)
344          {
345            Cursor newCursor = null;
346            switch (status)
347              {
348              default:
349                targetAct = DnDConstants.ACTION_NONE;
350              case ENTER:
351              case CHANGED:
352              case OVER:
353                int action = dropOp & targetAct;
354                if (action == DnDConstants.ACTION_NONE)
355                  {
356                    if ((dropOp & DnDConstants.ACTION_LINK) != 0)
357                      newCursor = DragSource.DefaultLinkNoDrop;
358                    else if ((dropOp & DnDConstants.ACTION_MOVE) != 0)
359                      newCursor = DragSource.DefaultMoveNoDrop;
360                    else
361                      newCursor = DragSource.DefaultCopyNoDrop;
362                  }
363                else
364                  {
365                    if ((dropOp & DnDConstants.ACTION_LINK) != 0)
366                      newCursor = DragSource.DefaultLinkDrop;
367                    else if ((dropOp & DnDConstants.ACTION_MOVE) != 0)
368                      newCursor = DragSource.DefaultMoveDrop;
369                    else
370                      newCursor = DragSource.DefaultCopyDrop;
371                  }
372              }
373    
374            if (cursor == null || ! cursor.equals(newCursor))
375              {
376                cursor = newCursor;
377                DragSourceContextPeer p = peer;
378                if (p != null)
379                  p.setCursor(cursor);
380              }
381          }
382      }
383    } // class DragSourceContext