1 /*
   2  * Copyright (c) 2010, 2017, 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 a new {@code KeyEvent} event from the specified parameters.
 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 a new {@code KeyEvent} event from the specified parameters,
 146      * with a {@code null} source and target.
 147      * @param eventType The type of the event.
 148      * @param character The character or sequence of characters associated with the event
 149      * @param text A String describing the key code
 150      * @param code The integer key code
 151      * @param shiftDown true if shift modifier was pressed.
 152      * @param controlDown true if control modifier was pressed.
 153      * @param altDown true if alt modifier was pressed.
 154      * @param metaDown true if meta modifier was pressed.
 155      * @since JavaFX 8.0
 156      */
 157     public KeyEvent(@NamedArg("eventType") EventType<KeyEvent> eventType, @NamedArg("character") String character,
 158             @NamedArg("text") String text, @NamedArg("code") KeyCode code, @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown,
 159             @NamedArg("altDown") boolean altDown, @NamedArg("metaDown") boolean metaDown) {
 160         super(eventType);
 161         boolean isKeyTyped = eventType == KEY_TYPED;
 162 
 163         this.character = isKeyTyped ? character : KeyEvent.CHAR_UNDEFINED;
 164         this.text = isKeyTyped ? "" : text;
 165         this.code = isKeyTyped ? KeyCode.UNDEFINED : code;
 166         this.shiftDown = shiftDown;
 167         this.controlDown = controlDown;
 168         this.altDown = altDown;
 169         this.metaDown = metaDown;
 170     }
 171 
 172     /**
 173      * KEY_PRESSED and KEY_RELEASED events which do not map to a valid Unicode
 174      * character use this for the keyChar value.
 175      */
 176     public static final String CHAR_UNDEFINED = KeyCode.UNDEFINED.ch;
 177 
 178     /**
 179      * The Unicode character or sequence of characters associated with the key
 180      * typed event. Contains multiple elements if the key produced a single
 181      * Unicode character from outside of the Basic Multilingual Plane which
 182      * needs to be encoded by the corresponding surrogate pair in Java or if
 183      * the key produced multiple Unicode characters itself.
 184      * <p>
 185      * For example, {@code character} will have the value "A" for a key typed
 186      * event generated by pressing SHIFT + 'a'.
 187      * For key pressed and key released events, {@code character} is always
 188      * {@code CHAR_UNDEFINED}.
 189      */
 190     private final String character;
 191 
 192     /**
 193      * The Unicode character or sequence of characters associated with the key
 194      * typed event. Contains multiple elements if the key produced a single
 195      * Unicode character from outside of the Basic Multilingual Plane which
 196      * needs to be encoded by the corresponding surrogate pair in Java or if
 197      * the key produced multiple Unicode characters itself.
 198      * <p>
 199      * For example, {@code character} will have the value "A" for a key typed
 200      * event generated by pressing SHIFT + 'a'.
 201      * For key pressed and key released events, {@code character} is always
 202      * {@code CHAR_UNDEFINED}.
 203      *
 204      * @return The Unicode character(s) associated with the key typed event
 205      */
 206     public final String getCharacter() {
 207         return character;
 208     }
 209 
 210     /**
 211      * A String describing the key code, such as "HOME", "F1" or "A",
 212      * for key pressed and key released events.
 213      * For key typed events, {@code text} is always the empty string.
 214      */
 215     private final String text;
 216 
 217     /**
 218      * A String describing the key code, such as "HOME", "F1" or "A",
 219      * for key pressed and key released events.
 220      * For key typed events, {@code text} is always the empty string.
 221      *
 222      * @return A String describing the key code
 223      */
 224     public final String getText() {
 225         return text;
 226     }
 227 
 228     /**
 229      * The integer key code associated with the key in this key
 230      * pressed or key released event.
 231      * For key typed events, {@code code} is always {@code KeyCode.UNDEFINED}.
 232      */
 233     private final KeyCode code;
 234 
 235     /**
 236      * The key code associated with the key in this key pressed or key released
 237      * event. For key typed events, {@code code} is always {@code KeyCode.UNDEFINED}.
 238      *
 239      * @return The key code associated with the key in this event,
 240      * {@code KeyCode.UNDEFINED} for key typed event
 241      */
 242     public final KeyCode getCode() {
 243         return code;
 244     }
 245 
 246     /**
 247      * Returns whether or not the Shift modifier is down on this event.
 248      */
 249     private final boolean shiftDown;
 250 
 251     /**
 252      * Returns whether or not the Shift modifier is down on this event.
 253      * @return whether or not the Shift modifier is down on this event.
 254      */
 255     public final boolean isShiftDown() {
 256         return shiftDown;
 257     }
 258 
 259     /**
 260      * Returns whether or not the Control modifier is down on this event.
 261      */
 262     private final boolean controlDown;
 263 
 264     /**
 265      * Returns whether or not the Control modifier is down on this event.
 266      * @return whether or not the Control modifier is down on this event.
 267      */
 268     public final boolean isControlDown() {
 269         return controlDown;
 270     }
 271 
 272     /**
 273      * Returns whether or not the Alt modifier is down on this event.
 274      */
 275     private final boolean altDown;
 276 
 277     /**
 278      * Returns whether or not the Alt modifier is down on this event.
 279      * @return whether or not the Alt modifier is down on this event.
 280      */
 281     public final boolean isAltDown() {
 282         return altDown;
 283     }
 284 
 285     /**
 286      * Returns whether or not the Meta modifier is down on this event.
 287      */
 288     private final boolean metaDown;
 289 
 290     /**
 291      * Returns whether or not the Meta modifier is down on this event.
 292      * @return whether or not the Meta modifier is down on this event.
 293      */
 294     public final boolean isMetaDown() {
 295         return metaDown;
 296     }
 297 
 298 
 299     /**
 300      * Returns whether or not the host platform common shortcut modifier is
 301      * down on this event. This common shortcut modifier is a modifier key which
 302      * is used commonly in shortcuts on the host platform. It is for example
 303      * {@code control} on Windows and {@code meta} (command key) on Mac.
 304      *
 305      * @return {@code true} if the shortcut modifier is down, {@code false}
 306      *      otherwise
 307      */
 308     public final boolean isShortcutDown() {
 309         switch (Toolkit.getToolkit().getPlatformShortcutKey()) {
 310             case SHIFT:
 311                 return shiftDown;
 312 
 313             case CONTROL:
 314                 return controlDown;
 315 
 316             case ALT:
 317                 return altDown;
 318 
 319             case META:
 320                 return metaDown;
 321 
 322             default:
 323                 return false;
 324         }
 325     }
 326 
 327     /**
 328      * Returns a string representation of this {@code KeyEvent} object.
 329      * @return a string representation of this {@code KeyEvent} object.
 330      */
 331     @Override public String toString() {
 332         final StringBuilder sb = new StringBuilder("KeyEvent [");
 333 
 334         sb.append("source = ").append(getSource());
 335         sb.append(", target = ").append(getTarget());
 336         sb.append(", eventType = ").append(getEventType());
 337         sb.append(", consumed = ").append(isConsumed());
 338 
 339         sb.append(", character = ").append(getCharacter());
 340         sb.append(", text = ").append(getText());
 341         sb.append(", code = ").append(getCode());
 342 
 343         if (isShiftDown()) {
 344             sb.append(", shiftDown");
 345         }
 346         if (isControlDown()) {
 347             sb.append(", controlDown");
 348         }
 349         if (isAltDown()) {
 350             sb.append(", altDown");
 351         }
 352         if (isMetaDown()) {
 353             sb.append(", metaDown");
 354         }
 355         if (isShortcutDown()) {
 356             sb.append(", shortcutDown");
 357         }
 358 
 359         return sb.append("]").toString();
 360     }
 361 
 362     @Override
 363     public KeyEvent copyFor(Object newSource, EventTarget newTarget) {
 364         return (KeyEvent) super.copyFor(newSource, newTarget);
 365     }
 366 
 367     /**
 368      * Creates a copy of the given event with the given fields substituted.
 369      * @param source the new source of the copied event
 370      * @param target the new target of the copied event
 371      * @param type the new event type.
 372      * @return the event copy with the fields substituted
 373      * @since JavaFX 8.0
 374      */
 375     public KeyEvent copyFor(Object source, EventTarget target, EventType<KeyEvent> type) {
 376         KeyEvent e = copyFor(source, target);
 377         e.eventType = type;
 378         return e;
 379     }
 380 
 381     @Override
 382     public EventType<KeyEvent> getEventType() {
 383         return (EventType<KeyEvent>) super.getEventType();
 384     }
 385 
 386 
 387 
 388 }