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 
  26 package java.awt.dnd;
  27 
  28 import 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 
  72 public 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     private void setNewModifiers() {
 285         if ((gestureModifiers & InputEvent.BUTTON1_MASK) != 0) {
 286             gestureModifiers |= InputEvent.BUTTON1_DOWN_MASK;
 287         }
 288         if ((gestureModifiers & InputEvent.BUTTON2_MASK) != 0) {
 289             gestureModifiers |= InputEvent.BUTTON2_DOWN_MASK;
 290         }
 291         if ((gestureModifiers & InputEvent.BUTTON3_MASK) != 0) {
 292             gestureModifiers |= InputEvent.BUTTON3_DOWN_MASK;
 293         }
 294         if ((gestureModifiers & InputEvent.SHIFT_MASK) != 0) {
 295             gestureModifiers |= InputEvent.SHIFT_DOWN_MASK;
 296         }
 297         if ((gestureModifiers & InputEvent.CTRL_MASK) != 0) {
 298             gestureModifiers |= InputEvent.CTRL_DOWN_MASK;
 299         }
 300         if ((gestureModifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
 301             gestureModifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
 302         }
 303     }
 304 
 305     /**
 306      * Sets old modifiers by the new ones.
 307      */
 308     private void setOldModifiers() {
 309         if ((gestureModifiers & InputEvent.BUTTON1_DOWN_MASK) != 0) {
 310             gestureModifiers |= InputEvent.BUTTON1_MASK;
 311         }
 312         if ((gestureModifiers & InputEvent.BUTTON2_DOWN_MASK) != 0) {
 313             gestureModifiers |= InputEvent.BUTTON2_MASK;
 314         }
 315         if ((gestureModifiers & InputEvent.BUTTON3_DOWN_MASK) != 0) {
 316             gestureModifiers |= InputEvent.BUTTON3_MASK;
 317         }
 318         if ((gestureModifiers & InputEvent.SHIFT_DOWN_MASK) != 0) {
 319             gestureModifiers |= InputEvent.SHIFT_MASK;
 320         }
 321         if ((gestureModifiers & InputEvent.CTRL_DOWN_MASK) != 0) {
 322             gestureModifiers |= InputEvent.CTRL_MASK;
 323         }
 324         if ((gestureModifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) {
 325             gestureModifiers |= InputEvent.ALT_GRAPH_MASK;
 326         }
 327     }
 328 }