1/*
2 * Copyright (c) 1997, 2013, 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
26package java.awt.dnd;
27
28import java.awt.event.InputEvent;
29
30/**
31 * The {@code DragSourceDragEvent} is
32 * delivered from the {@code DragSourceContextPeer},
33 * via the {@code DragSourceContext}, to the {@code DragSourceListener}
34 * registered with that {@code DragSourceContext} and with its associated
35 * {@code DragSource}.
36 * <p>
37 * The {@code DragSourceDragEvent} reports the <i>target drop action</i>
38 * and the <i>user drop action</i> that reflect the current state of
39 * the drag operation.
40 * <p>
41 * <i>Target drop action</i> is one of {@code DnDConstants} that represents
42 * the drop action selected by the current drop target if this drop action is
43 * supported by the drag source or {@code DnDConstants.ACTION_NONE} if this
44 * drop action is not supported by the drag source.
45 * <p>
46 * <i>User drop action</i> depends on the drop actions supported by the drag
47 * source and the drop action selected by the user. The user can select a drop
48 * action by pressing modifier keys during the drag operation:
49 * <pre>
50 *   Ctrl + Shift -&gt; ACTION_LINK
51 *   Ctrl         -&gt; ACTION_COPY
52 *   Shift        -&gt; ACTION_MOVE
53 * </pre>
54 * If the user selects a drop action, the <i>user drop action</i> is one of
55 * {@code DnDConstants} that represents the selected drop action if this
56 * drop action is supported by the drag source or
57 * {@code DnDConstants.ACTION_NONE} if this drop action is not supported
58 * by the drag source.
59 * <p>
60 * If the user doesn't select a drop action, the set of
61 * {@code DnDConstants} that represents the set of drop actions supported
62 * by the drag source is searched for {@code DnDConstants.ACTION_MOVE},
63 * then for {@code DnDConstants.ACTION_COPY}, then for
64 * {@code DnDConstants.ACTION_LINK} and the <i>user drop action</i> is the
65 * first constant found. If no constant is found the <i>user drop action</i>
66 * is {@code DnDConstants.ACTION_NONE}.
67 *
68 * @since 1.2
69 *
70 */
71
72public class DragSourceDragEvent extends DragSourceEvent {
73
74    private static final long serialVersionUID = 481346297933902471L;
75
76    /**
77     * Constructs a {@code DragSourceDragEvent}.
78     * This class is typically
79     * instantiated by the {@code DragSourceContextPeer}
80     * rather than directly
81     * by client code.
82     * The coordinates for this {@code DragSourceDragEvent}
83     * are not specified, so {@code getLocation} will return
84     * {@code null} for this event.
85     * <p>
86     * The arguments {@code dropAction} and {@code action} should
87     * be one of {@code DnDConstants} that represents a single action.
88     * The argument {@code modifiers} should be either a bitwise mask
89     * of old {@code java.awt.event.InputEvent.*_MASK} constants or a
90     * bitwise mask of extended {@code java.awt.event.InputEvent.*_DOWN_MASK}
91     * constants.
92     * This constructor does not throw any exception for invalid {@code dropAction},
93     * {@code action} and {@code modifiers}.
94     *
95     * @param dsc the {@code DragSourceContext} that is to manage
96     *            notifications for this event.
97     * @param dropAction the user drop action.
98     * @param action the target drop action.
99     * @param modifiers the modifier keys down during event (shift, ctrl,
100     *        alt, meta)
101     *        Either extended _DOWN_MASK or old _MASK modifiers
102     *        should be used, but both models should not be mixed
103     *        in one event. Use of the extended modifiers is
104     *        preferred.
105     *
106     * @throws IllegalArgumentException if {@code dsc} is {@code null}.
107     *
108     * @see java.awt.event.InputEvent
109     * @see DragSourceEvent#getLocation
110     */
111
112    public DragSourceDragEvent(DragSourceContext dsc, int dropAction,
113                               int action, int modifiers) {
114        super(dsc);
115
116        targetActions    = action;
117        gestureModifiers = modifiers;
118        this.dropAction  = dropAction;
119        if ((modifiers & ~(JDK_1_3_MODIFIERS | JDK_1_4_MODIFIERS)) != 0) {
120            invalidModifiers = true;
121        } else if ((getGestureModifiers() != 0) && (getGestureModifiersEx() == 0)) {
122            setNewModifiers();
123        } else if ((getGestureModifiers() == 0) && (getGestureModifiersEx() != 0)) {
124            setOldModifiers();
125        } else {
126            invalidModifiers = true;
127        }
128    }
129
130    /**
131     * Constructs a {@code DragSourceDragEvent} given the specified
132     * {@code DragSourceContext}, user drop action, target drop action,
133     * modifiers and coordinates.
134     * <p>
135     * The arguments {@code dropAction} and {@code action} should
136     * be one of {@code DnDConstants} that represents a single action.
137     * The argument {@code modifiers} should be either a bitwise mask
138     * of old {@code java.awt.event.InputEvent.*_MASK} constants or a
139     * bitwise mask of extended {@code java.awt.event.InputEvent.*_DOWN_MASK}
140     * constants.
141     * This constructor does not throw any exception for invalid {@code dropAction},
142     * {@code action} and {@code modifiers}.
143     *
144     * @param dsc the {@code DragSourceContext} associated with this
145     *        event.
146     * @param dropAction the user drop action.
147     * @param action the target drop action.
148     * @param modifiers the modifier keys down during event (shift, ctrl,
149     *        alt, meta)
150     *        Either extended _DOWN_MASK or old _MASK modifiers
151     *        should be used, but both models should not be mixed
152     *        in one event. Use of the extended modifiers is
153     *        preferred.
154     * @param x   the horizontal coordinate for the cursor location
155     * @param y   the vertical coordinate for the cursor location
156     *
157     * @throws IllegalArgumentException if {@code dsc} is {@code null}.
158     *
159     * @see java.awt.event.InputEvent
160     * @since 1.4
161     */
162    public DragSourceDragEvent(DragSourceContext dsc, int dropAction,
163                               int action, int modifiers, int x, int y) {
164        super(dsc, x, y);
165
166        targetActions    = action;
167        gestureModifiers = modifiers;
168        this.dropAction  = dropAction;
169        if ((modifiers & ~(JDK_1_3_MODIFIERS | JDK_1_4_MODIFIERS)) != 0) {
170            invalidModifiers = true;
171        } else if ((getGestureModifiers() != 0) && (getGestureModifiersEx() == 0)) {
172            setNewModifiers();
173        } else if ((getGestureModifiers() == 0) && (getGestureModifiersEx() != 0)) {
174            setOldModifiers();
175        } else {
176            invalidModifiers = true;
177        }
178    }
179
180    /**
181     * This method returns the target drop action.
182     *
183     * @return the target drop action.
184     */
185    public int getTargetActions() {
186        return targetActions;
187    }
188
189
190    private static final int JDK_1_3_MODIFIERS = InputEvent.SHIFT_DOWN_MASK - 1;
191    private static final int JDK_1_4_MODIFIERS =
192            ((InputEvent.ALT_GRAPH_DOWN_MASK << 1) - 1) & ~JDK_1_3_MODIFIERS;
193
194    /**
195     * This method returns an {@code int} representing
196     * the current state of the input device modifiers
197     * associated with the user's gesture. Typically these
198     * would be mouse buttons or keyboard modifiers.
199     * <P>
200     * If the {@code modifiers} passed to the constructor
201     * are invalid, this method returns them unchanged.
202     *
203     * @return the current state of the input device modifiers
204     */
205
206    public int getGestureModifiers() {
207        return invalidModifiers ? gestureModifiers : gestureModifiers & JDK_1_3_MODIFIERS;
208    }
209
210    /**
211     * This method returns an {@code int} representing
212     * the current state of the input device extended modifiers
213     * associated with the user's gesture.
214     * See {@link InputEvent#getModifiersEx}
215     * <P>
216     * If the {@code modifiers} passed to the constructor
217     * are invalid, this method returns them unchanged.
218     *
219     * @return the current state of the input device extended modifiers
220     * @since 1.4
221     */
222
223    public int getGestureModifiersEx() {
224        return invalidModifiers ? gestureModifiers : gestureModifiers & JDK_1_4_MODIFIERS;
225    }
226
227    /**
228     * This method returns the user drop action.
229     *
230     * @return the user drop action.
231     */
232    public int getUserAction() { return dropAction; }
233
234    /**
235     * This method returns the logical intersection of
236     * the target drop action and the set of drop actions supported by
237     * the drag source.
238     *
239     * @return the logical intersection of the target drop action and
240     *         the set of drop actions supported by the drag source.
241     */
242    public int getDropAction() {
243        return targetActions & getDragSourceContext().getSourceActions();
244    }
245
246    /*
247     * fields
248     */
249
250    /**
251     * The target drop action.
252     *
253     * @serial
254     */
255    private int     targetActions    = DnDConstants.ACTION_NONE;
256
257    /**
258     * The user drop action.
259     *
260     * @serial
261     */
262    private int     dropAction       = DnDConstants.ACTION_NONE;
263
264    /**
265     * The state of the input device modifiers associated with the user
266     * gesture.
267     *
268     * @serial
269     */
270    private int     gestureModifiers = 0;
271
272    /**
273     * Indicates whether the {@code gestureModifiers} are invalid.
274     *
275     * @serial
276     */
277    private boolean invalidModifiers;
278
279    /**
280     * Sets new modifiers by the old ones.
281     * The mouse modifiers have higher priority than overlaying key
282     * modifiers.
283     */
284    @SuppressWarnings("deprecation")
285    private void setNewModifiers() {
286        if ((gestureModifiers & InputEvent.BUTTON1_MASK) != 0) {
287            gestureModifiers |= InputEvent.BUTTON1_DOWN_MASK;
288        }
289        if ((gestureModifiers & InputEvent.BUTTON2_MASK) != 0) {
290            gestureModifiers |= InputEvent.BUTTON2_DOWN_MASK;
291        }
292        if ((gestureModifiers & InputEvent.BUTTON3_MASK) != 0) {
293            gestureModifiers |= InputEvent.BUTTON3_DOWN_MASK;
294        }
295        if ((gestureModifiers & InputEvent.SHIFT_MASK) != 0) {
296            gestureModifiers |= InputEvent.SHIFT_DOWN_MASK;
297        }
298        if ((gestureModifiers & InputEvent.CTRL_MASK) != 0) {
299            gestureModifiers |= InputEvent.CTRL_DOWN_MASK;
300        }
301        if ((gestureModifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
302            gestureModifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
303        }
304    }
305
306    /**
307     * Sets old modifiers by the new ones.
308     */
309    @SuppressWarnings("deprecation")
310    private void setOldModifiers() {
311        if ((gestureModifiers & InputEvent.BUTTON1_DOWN_MASK) != 0) {
312            gestureModifiers |= InputEvent.BUTTON1_MASK;
313        }
314        if ((gestureModifiers & InputEvent.BUTTON2_DOWN_MASK) != 0) {
315            gestureModifiers |= InputEvent.BUTTON2_MASK;
316        }
317        if ((gestureModifiers & InputEvent.BUTTON3_DOWN_MASK) != 0) {
318            gestureModifiers |= InputEvent.BUTTON3_MASK;
319        }
320        if ((gestureModifiers & InputEvent.SHIFT_DOWN_MASK) != 0) {
321            gestureModifiers |= InputEvent.SHIFT_MASK;
322        }
323        if ((gestureModifiers & InputEvent.CTRL_DOWN_MASK) != 0) {
324            gestureModifiers |= InputEvent.CTRL_MASK;
325        }
326        if ((gestureModifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) {
327            gestureModifiers |= InputEvent.ALT_GRAPH_MASK;
328        }
329    }
330}
331