1 /*
   2  * Copyright (c) 2010, 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 package javafx.scene.input;
  27 
  28 import com.sun.javafx.tk.Toolkit;
  29 import javafx.beans.NamedArg;
  30 import javafx.event.EventTarget;
  31 import javafx.event.EventType;
  32 
  33 import com.sun.javafx.scene.input.KeyCodeMap;
  34 import javafx.event.Event;
  35 import javafx.scene.input.ScrollEvent.HorizontalTextScrollUnits;
  36 import javafx.scene.input.ScrollEvent.VerticalTextScrollUnits;
  37 
  38 /**
  39  * An event which indicates that a keystroke occurred in a {@link javafx.scene.Node}.
  40  * <p>
  41  * This event is generated when a key is pressed, released, or typed.
  42  * Depending on the type of the event it is passed
  43  * to {@link javafx.scene.Node#onKeyPressedProperty onKeyPressed}, {@link javafx.scene.Node#onKeyTypedProperty onKeyTyped}
  44  * or {@link javafx.scene.Node#onKeyReleasedProperty onKeyReleased} function.
  45  *
  46  * <p>
  47  * <em>"Key typed" events</em> are higher-level and generally do not depend on
  48  * the platform or keyboard layout.  They are generated when a Unicode character
  49  * is entered, and are the preferred way to find out about character input.
  50  * In the simplest case, a key typed event is produced by a single key press
  51  * (e.g., 'a').  Often, however, characters are produced by series of key
  52  * presses (e.g., SHIFT + 'a'), and the mapping from key pressed events to
  53  * key typed events may be many-to-one or many-to-many.  Key releases are not
  54  * usually necessary to generate a key typed event, but there are some cases
  55  * where the key typed event is not generated until a key is released (e.g.,
  56  * entering ASCII sequences via the Alt-Numpad method in Windows).
  57  * No key typed events are generated for keys that don't generate Unicode
  58  * characters (e.g., action keys, modifier keys, etc.).
  59  *
  60  * <p>
  61  * The {@code character} variable always contains a valid Unicode character(s)
  62  * or CHAR_UNDEFINED. Character input is reported by key typed events;
  63  * key pressed and key released events are not necessarily associated
  64  * with character input. Therefore, the {@code character} variable
  65  * is guaranteed to be meaningful only for key typed events.
  66  *
  67  * <p>
  68  * For key pressed and key released events, the {@code code} variable contains
  69  * the event's key code.  For key typed events, the {@code code} variable
  70  * always contains {@code KeyCode.UNDEFINED}.
  71  *
  72  * <p>
  73  * <em>"Key pressed" and "key released" events</em> are lower-level and depend
  74  * on the platform and keyboard layout. They are generated whenever a key is
  75  * pressed or released, and are the only way to find out about keys that don't
  76  * generate character input (e.g., action keys, modifier keys, etc.). The key
  77  * being pressed or released is indicated by the code variable, which contains
  78  * a virtual key code.
  79  *
  80  * <p>
  81  * For triggering context menus see the {@link ContextMenuEvent}.
  82  * @since JavaFX 2.0
  83  */
  84 public final class KeyEvent extends InputEvent {
  85 
  86     private static final long serialVersionUID = 20121107L;
  87 
  88     /**
  89      * Common supertype for all key event types.
  90      */
  91     public static final EventType<KeyEvent> ANY =
  92             new EventType<KeyEvent>(InputEvent.ANY, "KEY");
  93 
  94     /**
  95      * This event occurs when a key has been pressed.
  96      */
  97     public static final EventType<KeyEvent> KEY_PRESSED =
  98             new EventType<KeyEvent>(KeyEvent.ANY, "KEY_PRESSED");
  99 
 100     /**
 101      * This event occurs when a key has been released.
 102      */
 103     public static final EventType<KeyEvent> KEY_RELEASED =
 104             new EventType<KeyEvent>(KeyEvent.ANY, "KEY_RELEASED");
 105 
 106     /**
 107      * This event occurs when a character-generating key was typed
 108      * (pressed and released).  The event contains the {@code character}
 109      * field containing the typed string, the {@code code} and {@code text}
 110      * fields are not used.
 111      */
 112     public static final EventType<KeyEvent> KEY_TYPED =
 113             new EventType<KeyEvent>(KeyEvent.ANY, "KEY_TYPED");
 114 
 115     /**
 116      * Constructs new KeyEvent event with null source and target and KeyCode object directly specified.
 117      * @param source the source of the event. Can be null.
 118      * @param target the target of the event. Can be null.
 119      * @param eventType The type of the event.
 120      * @param character The character or sequence of characters associated with the event
 121      * @param text A String describing the key code
 122      * @param code The integer key code
 123      * @param shiftDown true if shift modifier was pressed.
 124      * @param controlDown true if control modifier was pressed.
 125      * @param altDown true if alt modifier was pressed.
 126      * @param metaDown true if meta modifier was pressed.
 127      * @since JavaFX 8.0
 128      */
 129     public KeyEvent(@NamedArg("source") Object source, @NamedArg("target") EventTarget target, @NamedArg("eventType") EventType<KeyEvent> eventType, @NamedArg("character") String character,
 130             @NamedArg("text") String text, @NamedArg("code") KeyCode code, @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown,
 131             @NamedArg("altDown") boolean altDown, @NamedArg("metaDown") boolean metaDown) {
 132         super(source, target, eventType);
 133         boolean isKeyTyped = eventType == KEY_TYPED;
 134 
 135         this.character = isKeyTyped ? character : KeyEvent.CHAR_UNDEFINED;
 136         this.text = isKeyTyped ? "" : text;
 137         this.code = isKeyTyped ? KeyCode.UNDEFINED : code;
 138         this.shiftDown = shiftDown;
 139         this.controlDown = controlDown;
 140         this.altDown = altDown;
 141         this.metaDown = metaDown;
 142     }
 143 
 144     /**
 145      * Constructs new KeyEvent event with null source and target and KeyCode object directly specified.
 146      * @param eventType The type of the event.
 147      * @param character The character or sequence of characters associated with the event
 148      * @param text A String describing the key code
 149      * @param code The integer key code
 150      * @param shiftDown true if shift modifier was pressed.
 151      * @param controlDown true if control modifier was pressed.
 152      * @param altDown true if alt modifier was pressed.
 153      * @param metaDown true if meta modifier was pressed.
 154      * @since JavaFX 8.0
 155      */
 156     public KeyEvent(@NamedArg("eventType") EventType<KeyEvent> eventType, @NamedArg("character") String character,
 157             @NamedArg("text") String text, @NamedArg("code") KeyCode code, @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown,
 158             @NamedArg("altDown") boolean altDown, @NamedArg("metaDown") boolean metaDown) {
 159         super(eventType);
 160         boolean isKeyTyped = eventType == KEY_TYPED;
 161 
 162         this.character = isKeyTyped ? character : KeyEvent.CHAR_UNDEFINED;
 163         this.text = isKeyTyped ? "" : text;
 164         this.code = isKeyTyped ? KeyCode.UNDEFINED : code;
 165         this.shiftDown = shiftDown;
 166         this.controlDown = controlDown;
 167         this.altDown = altDown;
 168         this.metaDown = metaDown;
 169     }
 170 
 171     /**
 172      * KEY_PRESSED and KEY_RELEASED events which do not map to a valid Unicode
 173      * character use this for the keyChar value.
 174      */
 175     public static final String CHAR_UNDEFINED = KeyCode.UNDEFINED.ch;
 176 
 177     /**
 178      * The Unicode character or sequence of characters associated with the key
 179      * typed event. Contains multiple elements if the key produced a single
 180      * Unicode character from outside of the Basic Multilingual Plane which
 181      * needs to be encoded by the corresponding surrogate pair in Java or if
 182      * the key produced multiple Unicode characters itself.
 183      * <p/>
 184      * For example, {@code character} will have the value "A" for a key typed
 185      * event generated by pressing SHIFT + 'a'.
 186      * For key pressed and key released events, {@code character} is always
 187      * {@code CHAR_UNDEFINED}.
 188      */
 189     private final String character;
 190 
 191     /**
 192      * The Unicode character or sequence of characters associated with the key
 193      * typed event. Contains multiple elements if the key produced a single
 194      * Unicode character from outside of the Basic Multilingual Plane which
 195      * needs to be encoded by the corresponding surrogate pair in Java or if
 196      * the key produced multiple Unicode characters itself.
 197      * <p/>
 198      * For example, {@code character} will have the value "A" for a key typed
 199      * event generated by pressing SHIFT + 'a'.
 200      * For key pressed and key released events, {@code character} is always
 201      * {@code CHAR_UNDEFINED}.
 202      *
 203      * @return The Unicode character(s) associated with the key typed event
 204      */
 205     public final String getCharacter() {
 206         return character;
 207     }
 208 
 209     /**
 210      * A String describing the key code, such as "HOME", "F1" or "A",
 211      * for key pressed and key released events.
 212      * For key typed events, {@code text} is always the empty string.
 213      */
 214     private final String text;
 215 
 216     /**
 217      * A String describing the key code, such as "HOME", "F1" or "A",
 218      * for key pressed and key released events.
 219      * For key typed events, {@code text} is always the empty string.
 220      *
 221      * @return A String describing the key code
 222      */
 223     public final String getText() {
 224         return text;
 225     }
 226 
 227     /**
 228      * The integer key code associated with the key in this key
 229      * pressed or key released event.
 230      * For key typed events, {@code code} is always {@code KeyCode.UNDEFINED}.
 231      */
 232     private final KeyCode code;
 233 
 234     /**
 235      * The key code associated with the key in this key pressed or key released
 236      * event. For key typed events, {@code code} is always {@code KeyCode.UNDEFINED}.
 237      *
 238      * @return The key code associated with the key in this event,
 239      * {@code KeyCode.UNDEFINED} for key typed event
 240      */
 241     public final KeyCode getCode() {
 242         return code;
 243     }
 244 
 245     /**
 246      * Returns whether or not the Shift modifier is down on this event.
 247      */
 248     private final boolean shiftDown;
 249 
 250     /**
 251      * Returns whether or not the Shift modifier is down on this event.
 252      * @return whether or not the Shift modifier is down on this event.
 253      */
 254     public final boolean isShiftDown() {
 255         return shiftDown;
 256     }
 257 
 258     /**
 259      * Returns whether or not the Control modifier is down on this event.
 260      */
 261     private final boolean controlDown;
 262 
 263     /**
 264      * Returns whether or not the Control modifier is down on this event.
 265      * @return whether or not the Control modifier is down on this event.
 266      */
 267     public final boolean isControlDown() {
 268         return controlDown;
 269     }
 270 
 271     /**
 272      * Returns whether or not the Alt modifier is down on this event.
 273      */
 274     private final boolean altDown;
 275 
 276     /**
 277      * Returns whether or not the Alt modifier is down on this event.
 278      * @return whether or not the Alt modifier is down on this event.
 279      */
 280     public final boolean isAltDown() {
 281         return altDown;
 282     }
 283 
 284     /**
 285      * Returns whether or not the Meta modifier is down on this event.
 286      */
 287     private final boolean metaDown;
 288 
 289     /**
 290      * Returns whether or not the Meta modifier is down on this event.
 291      * @return whether or not the Meta modifier is down on this event.
 292      */
 293     public final boolean isMetaDown() {
 294         return metaDown;
 295     }
 296 
 297 
 298     /**
 299      * Returns whether or not the host platform common shortcut modifier is
 300      * down on this event. This common shortcut modifier is a modifier key which
 301      * is used commonly in shortcuts on the host platform. It is for example
 302      * {@code control} on Windows and {@code meta} (command key) on Mac.
 303      *
 304      * @return {@code true} if the shortcut modifier is down, {@code false}
 305      *      otherwise
 306      */
 307     public final boolean isShortcutDown() {
 308         switch (Toolkit.getToolkit().getPlatformShortcutKey()) {
 309             case SHIFT:
 310                 return shiftDown;
 311 
 312             case CONTROL:
 313                 return controlDown;
 314 
 315             case ALT:
 316                 return altDown;
 317 
 318             case META:
 319                 return metaDown;
 320 
 321             default:
 322                 return false;
 323         }
 324     }
 325 
 326     /**
 327      * Returns a string representation of this {@code KeyEvent} object.
 328      * @return a string representation of this {@code KeyEvent} object.
 329      */
 330     @Override public String toString() {
 331         final StringBuilder sb = new StringBuilder("KeyEvent [");
 332 
 333         sb.append("source = ").append(getSource());
 334         sb.append(", target = ").append(getTarget());
 335         sb.append(", eventType = ").append(getEventType());
 336         sb.append(", consumed = ").append(isConsumed());
 337 
 338         sb.append(", character = ").append(getCharacter());
 339         sb.append(", text = ").append(getText());
 340         sb.append(", code = ").append(getCode());
 341 
 342         if (isShiftDown()) {
 343             sb.append(", shiftDown");
 344         }
 345         if (isControlDown()) {
 346             sb.append(", controlDown");
 347         }
 348         if (isAltDown()) {
 349             sb.append(", altDown");
 350         }
 351         if (isMetaDown()) {
 352             sb.append(", metaDown");
 353         }
 354         if (isShortcutDown()) {
 355             sb.append(", shortcutDown");
 356         }
 357 
 358         return sb.append("]").toString();
 359     }
 360 
 361     @Override
 362     public KeyEvent copyFor(Object newSource, EventTarget newTarget) {
 363         return (KeyEvent) super.copyFor(newSource, newTarget);
 364     }
 365 
 366     /**
 367      * Creates a copy of the given event with the given fields substituted.
 368      * @param source the new source of the copied event
 369      * @param target the new target of the copied event
 370      * @param type the new event type.
 371      * @return the event copy with the fields substituted
 372      * @since JavaFX 8.0
 373      */
 374     public KeyEvent copyFor(Object source, EventTarget target, EventType<KeyEvent> type) {
 375         KeyEvent e = copyFor(source, target);
 376         e.eventType = type;
 377         return e;
 378     }
 379 
 380     @Override
 381     public EventType<KeyEvent> getEventType() {
 382         return (EventType<KeyEvent>) super.getEventType();
 383     }
 384 
 385 
 386 
 387 }