1 /*
   2  * Copyright (c) 1998, 2014, 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.io.InvalidObjectException;
  40 import java.util.EventObject;
  41 
  42 import java.util.Collections;
  43 import java.util.List;
  44 import java.util.Iterator;
  45 
  46 import java.io.IOException;
  47 import java.io.ObjectInputStream;
  48 import java.io.ObjectOutputStream;
  49 
  50 
  51 /**
  52  * A <code>DragGestureEvent</code> is passed
  53  * to <code>DragGestureListener</code>'s
  54  * dragGestureRecognized() method
  55  * when a particular <code>DragGestureRecognizer</code> detects that a
  56  * platform dependent drag initiating gesture has occurred
  57  * on the <code>Component</code> that it is tracking.
  58  *
  59  * The {@code action} field of any {@code DragGestureEvent} instance should take one of the following
  60  * values:
  61  * <ul>
  62  * <li> {@code DnDConstants.ACTION_COPY}
  63  * <li> {@code DnDConstants.ACTION_MOVE}
  64  * <li> {@code DnDConstants.ACTION_LINK}
  65  * </ul>
  66  * Assigning the value different from listed above will cause an unspecified behavior.
  67  *
  68  * @see java.awt.dnd.DragGestureRecognizer
  69  * @see java.awt.dnd.DragGestureListener
  70  * @see java.awt.dnd.DragSource
  71  * @see java.awt.dnd.DnDConstants
  72  */
  73 
  74 public class DragGestureEvent extends EventObject {
  75 
  76     private static final long serialVersionUID = 9080172649166731306L;
  77 
  78     /**
  79      * Constructs a <code>DragGestureEvent</code> object given by the
  80      * <code>DragGestureRecognizer</code> instance firing this event,
  81      * an {@code act} parameter representing
  82      * the user's preferred action, an {@code ori} parameter
  83      * indicating the origin of the drag, and a {@code List} of
  84      * events that comprise the gesture({@code evs} parameter).
  85      *
  86      * @param dgr The <code>DragGestureRecognizer</code> firing this event
  87      * @param act The user's preferred action.
  88      *            For information on allowable values, see
  89      *            the class description for {@link DragGestureEvent}
  90      * @param ori The origin of the drag
  91      * @param evs The <code>List</code> of events that comprise the gesture
  92      *
  93      * @throws IllegalArgumentException if any parameter equals {@code null}
  94      * @throws IllegalArgumentException if the act parameter does not comply with
  95      *                                  the values given in the class
  96      *                                  description for {@link DragGestureEvent}
  97      * @see java.awt.dnd.DnDConstants
  98      */
  99 
 100     public DragGestureEvent(DragGestureRecognizer dgr, int act, Point ori,
 101                             List<? extends InputEvent> evs)
 102     {
 103         super(dgr);
 104 
 105         if ((component = dgr.getComponent()) == null)
 106             throw new IllegalArgumentException("null component");
 107         if ((dragSource = dgr.getDragSource()) == null)
 108             throw new IllegalArgumentException("null DragSource");
 109 
 110         if (evs == null || evs.isEmpty())
 111             throw new IllegalArgumentException("null or empty list of events");
 112 
 113         if (act != DnDConstants.ACTION_COPY &&
 114             act != DnDConstants.ACTION_MOVE &&
 115             act != DnDConstants.ACTION_LINK)
 116             throw new IllegalArgumentException("bad action");
 117 
 118         if (ori == null) throw new IllegalArgumentException("null origin");
 119 
 120         events     = evs;
 121         action     = act;
 122         origin     = ori;
 123     }
 124 
 125     /**
 126      * Returns the source as a <code>DragGestureRecognizer</code>.
 127      *
 128      * @return the source as a <code>DragGestureRecognizer</code>
 129      */
 130 
 131     public DragGestureRecognizer getSourceAsDragGestureRecognizer() {
 132         return (DragGestureRecognizer)getSource();
 133     }
 134 
 135     /**
 136      * Returns the <code>Component</code> associated
 137      * with this <code>DragGestureEvent</code>.
 138      *
 139      * @return the Component
 140      */
 141 
 142     public Component getComponent() { return component; }
 143 
 144     /**
 145      * Returns the <code>DragSource</code>.
 146      *
 147      * @return the <code>DragSource</code>
 148      */
 149 
 150     public DragSource getDragSource() { return dragSource; }
 151 
 152     /**
 153      * Returns a <code>Point</code> in the coordinates
 154      * of the <code>Component</code> over which the drag originated.
 155      *
 156      * @return the Point where the drag originated in Component coords.
 157      */
 158 
 159     public Point getDragOrigin() {
 160         return origin;
 161     }
 162 
 163     /**
 164      * Returns an <code>Iterator</code> for the events
 165      * comprising the gesture.
 166      *
 167      * @return an Iterator for the events comprising the gesture
 168      */
 169     @SuppressWarnings("unchecked")
 170     public Iterator<InputEvent> iterator() { return events.iterator(); }
 171 
 172     /**
 173      * Returns an <code>Object</code> array of the
 174      * events comprising the drag gesture.
 175      *
 176      * @return an array of the events comprising the gesture
 177      */
 178 
 179     public Object[] toArray() { return events.toArray(); }
 180 
 181     /**
 182      * Returns an array of the events comprising the drag gesture.
 183      *
 184      * @param array the array of <code>EventObject</code> sub(types)
 185      *
 186      * @return an array of the events comprising the gesture
 187      */
 188     @SuppressWarnings("unchecked")
 189     public Object[] toArray(Object[] array) { return events.toArray(array); }
 190 
 191     /**
 192      * Returns an <code>int</code> representing the
 193      * action selected by the user.
 194      *
 195      * @return the action selected by the user
 196      */
 197 
 198     public int getDragAction() { return action; }
 199 
 200     /**
 201      * Returns the initial event that triggered the gesture.
 202      *
 203      * @return the first "triggering" event in the sequence of the gesture
 204      */
 205 
 206     public InputEvent getTriggerEvent() {
 207         return getSourceAsDragGestureRecognizer().getTriggerEvent();
 208     }
 209 
 210     /**
 211      * Starts the drag operation given the <code>Cursor</code> for this drag
 212      * operation and the <code>Transferable</code> representing the source data
 213      * for this drag operation.
 214      * <br>
 215      * If a <code>null</code> <code>Cursor</code> is specified no exception will
 216      * be thrown and default drag cursors will be used instead.
 217      * <br>
 218      * If a <code>null</code> <code>Transferable</code> is specified
 219      * <code>NullPointerException</code> will be thrown.
 220      * @param dragCursor     The initial {@code Cursor} for this drag operation
 221      *                       or {@code null} for the default cursor handling;
 222      *                       see
 223      *                       <a href="DragSourceContext.html#defaultCursor">DragSourceContext</a>
 224      *                       for more details on the cursor handling mechanism
 225      *                       during drag and drop
 226      * @param transferable The <code>Transferable</code> representing the source
 227      *                     data for this drag operation.
 228      *
 229      * @throws InvalidDnDOperationException if the Drag and Drop
 230      *         system is unable to initiate a drag operation, or if the user
 231      *         attempts to start a drag while an existing drag operation is
 232      *         still executing.
 233      * @throws NullPointerException if the {@code Transferable} is {@code null}
 234      * @since 1.4
 235      */
 236     public void startDrag(Cursor dragCursor, Transferable transferable)
 237       throws InvalidDnDOperationException {
 238         dragSource.startDrag(this, dragCursor, transferable, null);
 239     }
 240 
 241     /**
 242      * Starts the drag given the initial <code>Cursor</code> to display,
 243      * the <code>Transferable</code> object,
 244      * and the <code>DragSourceListener</code> to use.
 245      *
 246      * @param dragCursor     The initial {@code Cursor} for this drag operation
 247      *                       or {@code null} for the default cursor handling;
 248      *                       see
 249      *                       <a href="DragSourceContext.html#defaultCursor">DragSourceContext</a>
 250      *                       for more details on the cursor handling mechanism
 251      *                       during drag and drop
 252      * @param transferable The source's Transferable
 253      * @param dsl          The source's DragSourceListener
 254      *
 255      * @throws InvalidDnDOperationException if
 256      * the Drag and Drop system is unable to
 257      * initiate a drag operation, or if the user
 258      * attempts to start a drag while an existing
 259      * drag operation is still executing.
 260      */
 261 
 262     public void startDrag(Cursor dragCursor, Transferable transferable, DragSourceListener dsl) throws InvalidDnDOperationException {
 263         dragSource.startDrag(this, dragCursor, transferable, dsl);
 264     }
 265 
 266     /**
 267      * Start the drag given the initial <code>Cursor</code> to display,
 268      * a drag <code>Image</code>, the offset of
 269      * the <code>Image</code>,
 270      * the <code>Transferable</code> object, and
 271      * the <code>DragSourceListener</code> to use.
 272      *
 273      * @param dragCursor     The initial {@code Cursor} for this drag operation
 274      *                       or {@code null} for the default cursor handling;
 275      *                       see
 276      *                       <a href="DragSourceContext.html#defaultCursor">DragSourceContext</a>
 277      *                       for more details on the cursor handling mechanism
 278      *                       during drag and drop
 279      * @param dragImage    The source's dragImage
 280      * @param imageOffset  The dragImage's offset
 281      * @param transferable The source's Transferable
 282      * @param dsl          The source's DragSourceListener
 283      *
 284      * @throws InvalidDnDOperationException if
 285      * the Drag and Drop system is unable to
 286      * initiate a drag operation, or if the user
 287      * attempts to start a drag while an existing
 288      * drag operation is still executing.
 289      */
 290 
 291     public void startDrag(Cursor dragCursor, Image dragImage, Point imageOffset, Transferable transferable, DragSourceListener dsl) throws InvalidDnDOperationException {
 292         dragSource.startDrag(this,  dragCursor, dragImage, imageOffset, transferable, dsl);
 293     }
 294 
 295     /**
 296      * Serializes this <code>DragGestureEvent</code>. Performs default
 297      * serialization and then writes out this object's <code>List</code> of
 298      * gesture events if and only if the <code>List</code> can be serialized.
 299      * If not, <code>null</code> is written instead. In this case, a
 300      * <code>DragGestureEvent</code> created from the resulting deserialized
 301      * stream will contain an empty <code>List</code> of gesture events.
 302      *
 303      * @serialData The default serializable fields, in alphabetical order,
 304      *             followed by either a <code>List</code> instance, or
 305      *             <code>null</code>.
 306      * @since 1.4
 307      */
 308     private void writeObject(ObjectOutputStream s) throws IOException {
 309         s.defaultWriteObject();
 310 
 311         s.writeObject(SerializationTester.test(events) ? events : null);
 312     }
 313 
 314     /**
 315      * Deserializes this <code>DragGestureEvent</code>. This method first
 316      * performs default deserialization for all non-<code>transient</code>
 317      * fields. An attempt is then made to deserialize this object's
 318      * <code>List</code> of gesture events as well. This is first attempted
 319      * by deserializing the field <code>events</code>, because, in releases
 320      * prior to 1.4, a non-<code>transient</code> field of this name stored the
 321      * <code>List</code> of gesture events. If this fails, the next object in
 322      * the stream is used instead. If the resulting <code>List</code> is
 323      * <code>null</code>, this object's <code>List</code> of gesture events
 324      * is set to an empty <code>List</code>.
 325      *
 326      * @since 1.4
 327      */
 328     private void readObject(ObjectInputStream s)
 329         throws ClassNotFoundException, IOException
 330     {
 331         ObjectInputStream.GetField f = s.readFields();
 332 
 333         DragSource newDragSource = (DragSource)f.get("dragSource", null);
 334         if (newDragSource == null) {
 335             throw new InvalidObjectException("null DragSource");
 336         }
 337         dragSource = newDragSource;
 338 
 339         Component newComponent = (Component)f.get("component", null);
 340         if (newComponent == null) {
 341             throw new InvalidObjectException("null component");
 342         }
 343         component = newComponent;
 344 
 345         Point newOrigin = (Point)f.get("origin", null);
 346         if (newOrigin == null) {
 347             throw new InvalidObjectException("null origin");
 348         }
 349         origin = newOrigin;
 350 
 351         int newAction = f.get("action", 0);
 352         if (newAction != DnDConstants.ACTION_COPY &&
 353                 newAction != DnDConstants.ACTION_MOVE &&
 354                 newAction != DnDConstants.ACTION_LINK) {
 355             throw new InvalidObjectException("bad action");
 356         }
 357         action = newAction;
 358 
 359         // Pre-1.4 support. 'events' was previously non-transient
 360         @SuppressWarnings("rawtypes")
 361         List newEvents;
 362         try {
 363             newEvents = (List)f.get("events", null);
 364         } catch (IllegalArgumentException e) {
 365             // 1.4-compatible byte stream. 'events' was written explicitly
 366             newEvents = (List)s.readObject();
 367         }
 368 
 369         // Implementation assumes 'events' is never null.
 370         if (newEvents != null && newEvents.isEmpty()) {
 371             // Constructor treats empty events list as invalid value
 372             // Throw exception if serialized list is empty
 373             throw new InvalidObjectException("empty list of events");
 374         } else if (newEvents == null) {
 375             newEvents = Collections.emptyList();
 376         }
 377         events = newEvents;
 378     }
 379 
 380     /*
 381      * fields
 382      */
 383     @SuppressWarnings("rawtypes")
 384     private transient List events;
 385 
 386     /**
 387      * The DragSource associated with this DragGestureEvent.
 388      *
 389      * @serial
 390      */
 391     private DragSource dragSource;
 392 
 393     /**
 394      * The Component associated with this DragGestureEvent.
 395      *
 396      * @serial
 397      */
 398     private Component  component;
 399 
 400     /**
 401      * The origin of the drag.
 402      *
 403      * @serial
 404      */
 405     private Point      origin;
 406 
 407     /**
 408      * The user's preferred action.
 409      *
 410      * @serial
 411      */
 412     private int        action;
 413 }