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
27package java.awt.dnd;
28
29import java.awt.Component;
30import java.awt.Cursor;
31
32import java.awt.Image;
33import java.awt.Point;
34
35import java.awt.event.InputEvent;
36
37import java.awt.datatransfer.Transferable;
38
39import java.io.InvalidObjectException;
40import java.util.EventObject;
41
42import java.util.Collections;
43import java.util.List;
44import java.util.Iterator;
45
46import java.io.IOException;
47import java.io.ObjectInputStream;
48import java.io.ObjectOutputStream;
49
50
51/**
52 * A {@code DragGestureEvent} is passed
53 * to {@code DragGestureListener}'s
54 * dragGestureRecognized() method
55 * when a particular {@code DragGestureRecognizer} detects that a
56 * platform dependent drag initiating gesture has occurred
57 * on the {@code Component} 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
74public class DragGestureEvent extends EventObject {
75
76    private static final long serialVersionUID = 9080172649166731306L;
77
78    /**
79     * Constructs a {@code DragGestureEvent} object given by the
80     * {@code DragGestureRecognizer} 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} 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} 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}.
127     *
128     * @return the source as a {@code DragGestureRecognizer}
129     */
130
131    public DragGestureRecognizer getSourceAsDragGestureRecognizer() {
132        return (DragGestureRecognizer)getSource();
133    }
134
135    /**
136     * Returns the {@code Component} associated
137     * with this {@code DragGestureEvent}.
138     *
139     * @return the Component
140     */
141
142    public Component getComponent() { return component; }
143
144    /**
145     * Returns the {@code DragSource}.
146     *
147     * @return the {@code DragSource}
148     */
149
150    public DragSource getDragSource() { return dragSource; }
151
152    /**
153     * Returns a {@code Point} in the coordinates
154     * of the {@code Component} 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} 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} 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} 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} 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} for this drag
212     * operation and the {@code Transferable} representing the source data
213     * for this drag operation.
214     * <br>
215     * If a {@code null Cursor} is specified no exception will
216     * be thrown and default drag cursors will be used instead.
217     * <br>
218     * If a {@code null Transferable} is specified
219     * {@code NullPointerException} 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} 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} to display,
243     * the {@code Transferable} object,
244     * and the {@code DragSourceListener} 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} to display,
268     * a drag {@code Image}, the offset of
269     * the {@code Image},
270     * the {@code Transferable} object, and
271     * the {@code DragSourceListener} 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}. Performs default
297     * serialization and then writes out this object's {@code List} of
298     * gesture events if and only if the {@code List} can be serialized.
299     * If not, {@code null} is written instead. In this case, a
300     * {@code DragGestureEvent} created from the resulting deserialized
301     * stream will contain an empty {@code List} of gesture events.
302     *
303     * @serialData The default serializable fields, in alphabetical order,
304     *             followed by either a {@code List} instance, or
305     *             {@code null}.
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}. This method first
316     * performs default deserialization for all non-{@code transient}
317     * fields. An attempt is then made to deserialize this object's
318     * {@code List} of gesture events as well. This is first attempted
319     * by deserializing the field {@code events}, because, in releases
320     * prior to 1.4, a non-{@code transient} field of this name stored the
321     * {@code List} of gesture events. If this fails, the next object in
322     * the stream is used instead. If the resulting {@code List} is
323     * {@code null}, this object's {@code List} of gesture events
324     * is set to an empty {@code List}.
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}
414