1 /*
   2  * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 
  27 package java.awt.dnd;
  28 
  29 import java.awt.Component;
  30 import java.awt.Cursor;
  31 
  32 import java.awt.Image;
  33 import java.awt.Point;
  34 
  35 import java.awt.event.InputEvent;
  36 
  37 import java.awt.datatransfer.Transferable;
  38 
  39 import java.util.EventObject;
  40 
  41 import java.util.Collections;
  42 import java.util.List;
  43 import java.util.Iterator;
  44 
  45 import java.io.IOException;
  46 import java.io.ObjectInputStream;
  47 import java.io.ObjectOutputStream;
  48 
  49 
  50 /**
  51  * A <code>DragGestureEvent</code> is passed
  52  * to <code>DragGestureListener</code>'s
  53  * dragGestureRecognized() method
  54  * when a particular <code>DragGestureRecognizer</code> detects that a
  55  * platform dependent drag initiating gesture has occurred
  56  * on the <code>Component</code> that it is tracking.
  57  *
  58  * The {@code action} field of any {@code DragGestureEvent} instance should take one of the following
  59  * values:
  60  * <ul>
  61  * <li> {@code DnDConstants.ACTION_COPY}
  62  * <li> {@code DnDConstants.ACTION_MOVE}
  63  * <li> {@code DnDConstants.ACTION_LINK}
  64  * </ul>
  65  * Assigning the value different from listed above will cause an unspecified behavior.
  66  *
  67  * @see java.awt.dnd.DragGestureRecognizer
  68  * @see java.awt.dnd.DragGestureListener
  69  * @see java.awt.dnd.DragSource
  70  * @see java.awt.dnd.DnDConstants
  71  */
  72 
  73 public class DragGestureEvent extends EventObject {
  74 
  75     private static final long serialVersionUID = 9080172649166731306L;
  76 
  77     /**
  78      * Constructs a <code>DragGestureEvent</code> object given by the
  79      * <code>DragGestureRecognizer</code> instance firing this event,
  80      * an {@code act} parameter representing
  81      * the user's preferred action, an {@code ori} parameter
  82      * indicating the origin of the drag, and a {@code List} of
  83      * events that comprise the gesture({@code evs} parameter).
  84      * <P>
  85      * @param dgr The <code>DragGestureRecognizer</code> firing this event
  86      * @param act The user's preferred action.
  87      *            For information on allowable values, see
  88      *            the class description for {@link DragGestureEvent}
  89      * @param ori The origin of the drag
  90      * @param evs The <code>List</code> of events that comprise the gesture
  91      * <P>
  92      * @throws IllegalArgumentException if any parameter equals {@code null}
  93      * @throws IllegalArgumentException if the act parameter does not comply with
  94      *                                  the values given in the class
  95      *                                  description for {@link DragGestureEvent}
  96      * @see java.awt.dnd.DnDConstants
  97      */
  98 
  99     public DragGestureEvent(DragGestureRecognizer dgr, int act, Point ori,
 100                             List<? extends InputEvent> evs)
 101     {
 102         super(dgr);
 103 
 104         if ((component = dgr.getComponent()) == null)
 105             throw new IllegalArgumentException("null component");
 106         if ((dragSource = dgr.getDragSource()) == null)
 107             throw new IllegalArgumentException("null DragSource");
 108 
 109         if (evs == null || evs.isEmpty())
 110             throw new IllegalArgumentException("null or empty list of events");
 111 
 112         if (act != DnDConstants.ACTION_COPY &&
 113             act != DnDConstants.ACTION_MOVE &&
 114             act != DnDConstants.ACTION_LINK)
 115             throw new IllegalArgumentException("bad action");
 116 
 117         if (ori == null) throw new IllegalArgumentException("null origin");
 118 
 119         events     = evs;
 120         action     = act;
 121         origin     = ori;
 122     }
 123 
 124     /**
 125      * Returns the source as a <code>DragGestureRecognizer</code>.
 126      * <P>
 127      * @return the source as a <code>DragGestureRecognizer</code>
 128      */
 129 
 130     public DragGestureRecognizer getSourceAsDragGestureRecognizer() {
 131         return (DragGestureRecognizer)getSource();
 132     }
 133 
 134     /**
 135      * Returns the <code>Component</code> associated
 136      * with this <code>DragGestureEvent</code>.
 137      * <P>
 138      * @return the Component
 139      */
 140 
 141     public Component getComponent() { return component; }
 142 
 143     /**
 144      * Returns the <code>DragSource</code>.
 145      * <P>
 146      * @return the <code>DragSource</code>
 147      */
 148 
 149     public DragSource getDragSource() { return dragSource; }
 150 
 151     /**
 152      * Returns a <code>Point</code> in the coordinates
 153      * of the <code>Component</code> over which the drag originated.
 154      * <P>
 155      * @return the Point where the drag originated in Component coords.
 156      */
 157 
 158     public Point getDragOrigin() {
 159         return origin;
 160     }
 161 
 162     /**
 163      * Returns an <code>Iterator</code> for the events
 164      * comprising the gesture.
 165      * <P>
 166      * @return an Iterator for the events comprising the gesture
 167      */
 168     @SuppressWarnings("unchecked")
 169     public Iterator<InputEvent> iterator() { return events.iterator(); }
 170 
 171     /**
 172      * Returns an <code>Object</code> array of the
 173      * events comprising the drag gesture.
 174      * <P>
 175      * @return an array of the events comprising the gesture
 176      */
 177 
 178     public Object[] toArray() { return events.toArray(); }
 179 
 180     /**
 181      * Returns an array of the events comprising the drag gesture.
 182      * <P>
 183      * @param array the array of <code>EventObject</code> sub(types)
 184      * <P>
 185      * @return an array of the events comprising the gesture
 186      */
 187     @SuppressWarnings("unchecked")
 188     public Object[] toArray(Object[] array) { return events.toArray(array); }
 189 
 190     /**
 191      * Returns an <code>int</code> representing the
 192      * action selected by the user.
 193      * <P>
 194      * @return the action selected by the user
 195      */
 196 
 197     public int getDragAction() { return action; }
 198 
 199     /**
 200      * Returns the initial event that triggered the gesture.
 201      * <P>
 202      * @return the first "triggering" event in the sequence of the gesture
 203      */
 204 
 205     public InputEvent getTriggerEvent() {
 206         return getSourceAsDragGestureRecognizer().getTriggerEvent();
 207     }
 208 
 209     /**
 210      * Starts the drag operation given the <code>Cursor</code> for this drag
 211      * operation and the <code>Transferable</code> representing the source data
 212      * for this drag operation.
 213      * <br>
 214      * If a <code>null</code> <code>Cursor</code> is specified no exception will
 215      * be thrown and default drag cursors will be used instead.
 216      * <br>
 217      * If a <code>null</code> <code>Transferable</code> is specified
 218      * <code>NullPointerException</code> will be thrown.
 219      * @param dragCursor     The initial {@code Cursor} for this drag operation
 220      *                       or {@code null} for the default cursor handling;
 221      *                       see
 222      *                       <a href="DragSourceContext.html#defaultCursor">DragSourceContext</a>
 223      *                       for more details on the cursor handling mechanism
 224      *                       during drag and drop
 225      * @param transferable The <code>Transferable</code> representing the source
 226      *                     data for this drag operation.
 227      *
 228      * @throws InvalidDnDOperationException if the Drag and Drop
 229      *         system is unable to initiate a drag operation, or if the user
 230      *         attempts to start a drag while an existing drag operation is
 231      *         still executing.
 232      * @throws NullPointerException if the {@code Transferable} is {@code null}
 233      * @since 1.4
 234      */
 235     public void startDrag(Cursor dragCursor, Transferable transferable)
 236       throws InvalidDnDOperationException {
 237         dragSource.startDrag(this, dragCursor, transferable, null);
 238     }
 239 
 240     /**
 241      * Starts the drag given the initial <code>Cursor</code> to display,
 242      * the <code>Transferable</code> object,
 243      * and the <code>DragSourceListener</code> to use.
 244      * <P>
 245      * @param dragCursor     The initial {@code Cursor} for this drag operation
 246      *                       or {@code null} for the default cursor handling;
 247      *                       see
 248      *                       <a href="DragSourceContext.html#defaultCursor">DragSourceContext</a>
 249      *                       for more details on the cursor handling mechanism
 250      *                       during drag and drop
 251      * @param transferable The source's Transferable
 252      * @param dsl          The source's DragSourceListener
 253      * <P>
 254      * @throws InvalidDnDOperationException if
 255      * the Drag and Drop system is unable to
 256      * initiate a drag operation, or if the user
 257      * attempts to start a drag while an existing
 258      * drag operation is still executing.
 259      */
 260 
 261     public void startDrag(Cursor dragCursor, Transferable transferable, DragSourceListener dsl) throws InvalidDnDOperationException {
 262         dragSource.startDrag(this, dragCursor, transferable, dsl);
 263     }
 264 
 265     /**
 266      * Start the drag given the initial <code>Cursor</code> to display,
 267      * a drag <code>Image</code>, the offset of
 268      * the <code>Image</code>,
 269      * the <code>Transferable</code> object, and
 270      * the <code>DragSourceListener</code> to use.
 271      * <P>
 272      * @param dragCursor     The initial {@code Cursor} for this drag operation
 273      *                       or {@code null} for the default cursor handling;
 274      *                       see
 275      *                       <a href="DragSourceContext.html#defaultCursor">DragSourceContext</a>
 276      *                       for more details on the cursor handling mechanism
 277      *                       during drag and drop
 278      * @param dragImage    The source's dragImage
 279      * @param imageOffset  The dragImage's offset
 280      * @param transferable The source's Transferable
 281      * @param dsl          The source's DragSourceListener
 282      * <P>
 283      * @throws InvalidDnDOperationException if
 284      * the Drag and Drop system is unable to
 285      * initiate a drag operation, or if the user
 286      * attempts to start a drag while an existing
 287      * drag operation is still executing.
 288      */
 289 
 290     public void startDrag(Cursor dragCursor, Image dragImage, Point imageOffset, Transferable transferable, DragSourceListener dsl) throws InvalidDnDOperationException {
 291         dragSource.startDrag(this,  dragCursor, dragImage, imageOffset, transferable, dsl);
 292     }
 293 
 294     /**
 295      * Serializes this <code>DragGestureEvent</code>. Performs default
 296      * serialization and then writes out this object's <code>List</code> of
 297      * gesture events if and only if the <code>List</code> can be serialized.
 298      * If not, <code>null</code> is written instead. In this case, a
 299      * <code>DragGestureEvent</code> created from the resulting deserialized
 300      * stream will contain an empty <code>List</code> of gesture events.
 301      *
 302      * @serialData The default serializable fields, in alphabetical order,
 303      *             followed by either a <code>List</code> instance, or
 304      *             <code>null</code>.
 305      * @since 1.4
 306      */
 307     private void writeObject(ObjectOutputStream s) throws IOException {
 308         s.defaultWriteObject();
 309 
 310         s.writeObject(SerializationTester.test(events) ? events : null);
 311     }
 312 
 313     /**
 314      * Deserializes this <code>DragGestureEvent</code>. This method first
 315      * performs default deserialization for all non-<code>transient</code>
 316      * fields. An attempt is then made to deserialize this object's
 317      * <code>List</code> of gesture events as well. This is first attempted
 318      * by deserializing the field <code>events</code>, because, in releases
 319      * prior to 1.4, a non-<code>transient</code> field of this name stored the
 320      * <code>List</code> of gesture events. If this fails, the next object in
 321      * the stream is used instead. If the resulting <code>List</code> is
 322      * <code>null</code>, this object's <code>List</code> of gesture events
 323      * is set to an empty <code>List</code>.
 324      *
 325      * @since 1.4
 326      */
 327     private void readObject(ObjectInputStream s)
 328         throws ClassNotFoundException, IOException
 329     {
 330         ObjectInputStream.GetField f = s.readFields();
 331 
 332         dragSource = (DragSource)f.get("dragSource", null);
 333         component = (Component)f.get("component", null);
 334         origin = (Point)f.get("origin", null);
 335         action = f.get("action", 0);
 336         // Pre-1.4 support. 'events' was previously non-transient
 337         try {
 338             events = (List)f.get("events", null);
 339         } catch (IllegalArgumentException e) {
 340             // 1.4-compatible byte stream. 'events' was written explicitly
 341             events = (List)s.readObject();
 342         }
 343 
 344         // Implementation assumes 'events' is never null.
 345         if (events == null) {
 346             events = Collections.EMPTY_LIST;
 347         }
 348     }
 349 
 350     /*
 351      * fields
 352      */
 353     @SuppressWarnings("rawtypes")
 354     private transient List events;
 355 
 356     /**
 357      * The DragSource associated with this DragGestureEvent.
 358      *
 359      * @serial
 360      */
 361     private DragSource dragSource;
 362 
 363     /**
 364      * The Component associated with this DragGestureEvent.
 365      *
 366      * @serial
 367      */
 368     private Component  component;
 369 
 370     /**
 371      * The origin of the drag.
 372      *
 373      * @serial
 374      */
 375     private Point      origin;
 376 
 377     /**
 378      * The user's preferred action.
 379      *
 380      * @serial
 381      */
 382     private int        action;
 383 }