Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.scene.input;
027
028import com.sun.javafx.tk.Toolkit;
029import javafx.event.EventTarget;
030import javafx.event.EventType;
031
032import com.sun.javafx.robot.impl.FXRobotHelper;
033import com.sun.javafx.robot.impl.FXRobotHelper.FXRobotInputAccessor;
034import com.sun.javafx.scene.input.KeyCodeMap;
035import javafx.event.Event;
036import javafx.scene.input.ScrollEvent.HorizontalTextScrollUnits;
037import javafx.scene.input.ScrollEvent.VerticalTextScrollUnits;
038
039/**
040 * An event which indicates that a keystroke occurred in a {@link javafx.scene.Node}.
041 * <p>
042 * This event is generated when a key is pressed, released, or typed.
043 * Depending on the type of the event it is passed
044 * to {@link javafx.scene.Node#onKeyPressedProperty onKeyPressed}, {@link javafx.scene.Node#onKeyTypedProperty onKeyTyped}
045 * or {@link javafx.scene.Node#onKeyReleasedProperty onKeyReleased} function.
046 *
047 * <p>
048 * <em>"Key typed" events</em> are higher-level and generally do not depend on
049 * the platform or keyboard layout.  They are generated when a Unicode character
050 * is entered, and are the preferred way to find out about character input.
051 * In the simplest case, a key typed event is produced by a single key press
052 * (e.g., 'a').  Often, however, characters are produced by series of key
053 * presses (e.g., SHIFT + 'a'), and the mapping from key pressed events to
054 * key typed events may be many-to-one or many-to-many.  Key releases are not
055 * usually necessary to generate a key typed event, but there are some cases
056 * where the key typed event is not generated until a key is released (e.g.,
057 * entering ASCII sequences via the Alt-Numpad method in Windows).
058 * No key typed events are generated for keys that don't generate Unicode
059 * characters (e.g., action keys, modifier keys, etc.).
060 *
061 * <p>
062 * The {@code character} variable always contains a valid Unicode character(s)
063 * or CHAR_UNDEFINED. Character input is reported by key typed events;
064 * key pressed and key released events are not necessarily associated
065 * with character input. Therefore, the {@code character} variable
066 * is guaranteed to be meaningful only for key typed events.
067 *
068 * <p>
069 * For key pressed and key released events, the {@code code} variable contains
070 * the event's key code.  For key typed events, the {@code code} variable
071 * always contains {@code KeyCode.UNDEFINED}.
072 *
073 * <p>
074 * <em>"Key pressed" and "key released" events</em> are lower-level and depend
075 * on the platform and keyboard layout. They are generated whenever a key is
076 * pressed or released, and are the only way to find out about keys that don't
077 * generate character input (e.g., action keys, modifier keys, etc.). The key
078 * being pressed or released is indicated by the code variable, which contains
079 * a virtual key code.
080 *
081 * <p>
082 * For triggering context menus see the {@link ContextMenuEvent}.
083 */
084public final class KeyEvent extends InputEvent {
085
086    private static final long serialVersionUID = 20121107L;
087    
088    /**
089     * Common supertype for all key event types.
090     */
091    public static final EventType<KeyEvent> ANY =
092            new EventType<KeyEvent>(InputEvent.ANY, "KEY");
093
094    /**
095     * This event occurs when a key has been pressed.
096     */
097    public static final EventType<KeyEvent> KEY_PRESSED =
098            new EventType<KeyEvent>(KeyEvent.ANY, "KEY_PRESSED");
099
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 key has been typed (pressed and released).
108     * This event contains the {@code character} field containing the typed
109     * string, the {@code code} and {@code text} fields are not used.
110     */
111    public static final EventType<KeyEvent> KEY_TYPED =
112            new EventType<KeyEvent>(KeyEvent.ANY, "KEY_TYPED");
113
114    static {
115        FXRobotInputAccessor a = new FXRobotInputAccessor() {
116            @Override public int getCodeForKeyCode(KeyCode keyCode) {
117                return keyCode.code;
118            }
119            @Override public KeyCode getKeyCodeForCode(int code) {
120                return KeyCodeMap.valueOf(code);
121            }
122            @Override public KeyEvent createKeyEvent(
123                EventType<? extends KeyEvent> eventType,
124                KeyCode code, String character, String text,
125                boolean shiftDown, boolean controlDown,
126                boolean altDown, boolean metaDown)
127            {
128                return new KeyEvent((EventType<KeyEvent>)eventType, character, text, code,
129                        shiftDown, controlDown, altDown, metaDown);
130            }
131            @Override public MouseEvent createMouseEvent(
132                EventType<? extends MouseEvent> eventType,
133                int x, int y, int screenX, int screenY,
134                MouseButton button, int clickCount, boolean shiftDown,
135                boolean controlDown, boolean altDown, boolean metaDown,
136                boolean popupTrigger, boolean primaryButtonDown,
137                boolean middleButtonDown, boolean secondaryButtonDown)
138            {
139                return new MouseEvent(eventType, x, y,
140                                           screenX, screenY,
141                                           button, clickCount,
142                                           shiftDown,
143                                           controlDown,
144                                           altDown,
145                                           metaDown,
146                                           primaryButtonDown,
147                                           middleButtonDown,
148                                           secondaryButtonDown,
149                                           false,
150                                           popupTrigger,
151                                           false,
152                                           null
153                                           );
154            }
155
156            @Override
157            public ScrollEvent createScrollEvent(
158                    EventType<? extends ScrollEvent> eventType, 
159                    int scrollX, int scrollY, 
160                    HorizontalTextScrollUnits xTextUnits, int xText, 
161                    VerticalTextScrollUnits yTextUnits, int yText, 
162                    int x, int y, int screenX, int screenY, 
163                    boolean shiftDown, boolean controlDown, 
164                    boolean altDown, boolean metaDown) {
165                return new ScrollEvent(ScrollEvent.SCROLL,
166                        x, y, screenX, screenY, 
167                        shiftDown, controlDown, altDown, metaDown, false, false,
168                        scrollX, scrollY, 0, 0,
169                        xTextUnits, xText, yTextUnits, yText,
170                        0, null);
171            }
172        };
173        FXRobotHelper.setInputAccessor(a);
174    }
175
176    /**
177     * Constructs new KeyEvent event with null source and target and KeyCode object directly specified.
178     * @param source the source of the event. Can be null.
179     * @param target the target of the event. Can be null.
180     * @param eventType The type of the event.
181     * @param character The character or sequence of characters associated with the event
182     * @param text A String describing the key code
183     * @param code The integer key code
184     * @param shiftDown true if shift modifier was pressed.
185     * @param controlDown true if control modifier was pressed.
186     * @param altDown true if alt modifier was pressed.
187     * @param metaDown true if meta modifier was pressed.
188     */
189    public KeyEvent(Object source, EventTarget target, EventType<KeyEvent> eventType, String character,
190            String text, KeyCode code, boolean shiftDown, boolean controlDown,
191            boolean altDown, boolean metaDown) {
192        super(source, target, eventType);
193        boolean isKeyTyped = eventType == KEY_TYPED;
194
195        this.character = isKeyTyped ? character : KeyEvent.CHAR_UNDEFINED;
196        this.text = isKeyTyped ? "" : text;
197        this.code = isKeyTyped ? KeyCode.UNDEFINED : code;
198        this.shiftDown = shiftDown;
199        this.controlDown = controlDown;
200        this.altDown = altDown;
201        this.metaDown = metaDown;
202    }
203
204    /**
205     * Constructs new KeyEvent event with null source and target and KeyCode object directly specified.
206     * @param eventType The type of the event.
207     * @param character The character or sequence of characters associated with the event
208     * @param text A String describing the key code
209     * @param code The integer key code
210     * @param shiftDown true if shift modifier was pressed.
211     * @param controlDown true if control modifier was pressed.
212     * @param altDown true if alt modifier was pressed.
213     * @param metaDown true if meta modifier was pressed.
214     */
215    public KeyEvent(EventType<KeyEvent> eventType, String character,
216            String text, KeyCode code, boolean shiftDown, boolean controlDown,
217            boolean altDown, boolean metaDown) {
218        super(eventType);
219        boolean isKeyTyped = eventType == KEY_TYPED;
220
221        this.character = isKeyTyped ? character : KeyEvent.CHAR_UNDEFINED;
222        this.text = isKeyTyped ? "" : text;
223        this.code = isKeyTyped ? KeyCode.UNDEFINED : code;
224        this.shiftDown = shiftDown;
225        this.controlDown = controlDown;
226        this.altDown = altDown;
227        this.metaDown = metaDown;
228    }
229
230    /**
231     * KEY_PRESSED and KEY_RELEASED events which do not map to a valid Unicode
232     * character use this for the keyChar value.
233     */
234    public static final String CHAR_UNDEFINED = KeyCode.UNDEFINED.ch;
235    
236    /**
237     * The Unicode character or sequence of characters associated with the key
238     * typed event. Contains multiple elements if the key produced a single
239     * Unicode character from outside of the Basic Multilingual Plane which
240     * needs to be encoded by the corresponding surrogate pair in Java or if
241     * the key produced multiple Unicode characters itself.
242     * <p/>
243     * For example, {@code character} will have the value "A" for a key typed
244     * event generated by pressing SHIFT + 'a'.
245     * For key pressed and key released events, {@code character} is always
246     * {@code CHAR_UNDEFINED}.
247     */
248    private final String character;
249
250    /**
251     * The Unicode character or sequence of characters associated with the key
252     * typed event. Contains multiple elements if the key produced a single
253     * Unicode character from outside of the Basic Multilingual Plane which
254     * needs to be encoded by the corresponding surrogate pair in Java or if
255     * the key produced multiple Unicode characters itself.
256     * <p/>
257     * For example, {@code character} will have the value "A" for a key typed
258     * event generated by pressing SHIFT + 'a'.
259     * For key pressed and key released events, {@code character} is always
260     * {@code CHAR_UNDEFINED}.
261     *
262     * @return The Unicode character(s) associated with the key typed event
263     */
264    public final String getCharacter() {
265        return character;
266    }
267
268    /**
269     * A String describing the key code, such as "HOME", "F1" or "A",
270     * for key pressed and key released events.
271     * For key typed events, {@code text} is always the empty string.
272     */
273    private final String text;
274
275    /**
276     * A String describing the key code, such as "HOME", "F1" or "A",
277     * for key pressed and key released events.
278     * For key typed events, {@code text} is always the empty string.
279     *
280     * @return A String describing the key code
281     */
282    public final String getText() {
283        return text;
284    }
285
286    /**
287     * The integer key code associated with the key in this key
288     * pressed or key released event.
289     * For key typed events, {@code code} is always {@code KeyCode.UNDEFINED}.
290     */
291    private final KeyCode code;
292
293    /**
294     * The key code associated with the key in this key pressed or key released 
295     * event. For key typed events, {@code code} is always {@code KeyCode.UNDEFINED}.
296     *
297     * @return The key code associated with the key in this event, 
298     * {@code KeyCode.UNDEFINED} for key typed event
299     */
300    public final KeyCode getCode() {
301        return code;
302    }
303
304    /**
305     * Returns whether or not the Shift modifier is down on this event.
306     */
307    private final boolean shiftDown;
308
309    /**
310     * Returns whether or not the Shift modifier is down on this event.
311     * @return whether or not the Shift modifier is down on this event.
312     */
313    public final boolean isShiftDown() {
314        return shiftDown;
315    }
316
317    /**
318     * Returns whether or not the Control modifier is down on this event.
319     */
320    private final boolean controlDown;
321
322    /**
323     * Returns whether or not the Control modifier is down on this event.
324     * @return whether or not the Control modifier is down on this event.
325     */
326    public final boolean isControlDown() {
327        return controlDown;
328    }
329
330    /**
331     * Returns whether or not the Alt modifier is down on this event.
332     */
333    private final boolean altDown;
334
335    /**
336     * Returns whether or not the Alt modifier is down on this event.
337     * @return whether or not the Alt modifier is down on this event.
338     */
339    public final boolean isAltDown() {
340        return altDown;
341    }
342
343    /**
344     * Returns whether or not the Meta modifier is down on this event.
345     */
346    private final boolean metaDown;
347
348    /**
349     * Returns whether or not the Meta modifier is down on this event.
350     * @return whether or not the Meta modifier is down on this event.
351     */
352    public final boolean isMetaDown() {
353        return metaDown;
354    }
355
356
357    /**
358     * Returns whether or not the host platform common shortcut modifier is
359     * down on this event. This common shortcut modifier is a modifier key which
360     * is used commonly in shortcuts on the host platform. It is for example
361     * {@code control} on Windows and {@code meta} (command key) on Mac.
362     *
363     * @return {@code true} if the shortcut modifier is down, {@code false}
364     *      otherwise
365     */
366    public final boolean isShortcutDown() {
367        switch (Toolkit.getToolkit().getPlatformShortcutKey()) {
368            case SHIFT:
369                return shiftDown;
370
371            case CONTROL:
372                return controlDown;
373
374            case ALT:
375                return altDown;
376
377            case META:
378                return metaDown;
379
380            default:
381                return false;
382        }
383    }
384    
385    /**
386     * Returns a string representation of this {@code KeyEvent} object.
387     * @return a string representation of this {@code KeyEvent} object.
388     */ 
389    @Override public String toString() {
390        final StringBuilder sb = new StringBuilder("KeyEvent [");
391
392        sb.append("source = ").append(getSource());
393        sb.append(", target = ").append(getTarget());
394        sb.append(", eventType = ").append(getEventType());
395        sb.append(", consumed = ").append(isConsumed());
396        
397        sb.append(", character = ").append(getCharacter());
398        sb.append(", text = ").append(getText());
399        sb.append(", code = ").append(getCode());
400        
401        if (isShiftDown()) {
402            sb.append(", shiftDown");
403        }
404        if (isControlDown()) {
405            sb.append(", controlDown");
406        }
407        if (isAltDown()) {
408            sb.append(", altDown");
409        }
410        if (isMetaDown()) {
411            sb.append(", metaDown");
412        }
413        if (isShortcutDown()) {
414            sb.append(", shortcutDown");
415        }
416
417        return sb.append("]").toString();
418    }
419
420    @Override
421    public KeyEvent copyFor(Object newSource, EventTarget newTarget) {
422        return (KeyEvent) super.copyFor(newSource, newTarget);
423    }
424
425    /**
426     * Creates a copy of the given event with the given fields substituted.
427     * @param source the new source of the copied event
428     * @param target the new target of the copied event
429     * @param type the new event type.
430     * @return the event copy with the fields substituted
431     */
432    public KeyEvent copyFor(Object source, EventTarget target, EventType<KeyEvent> type) {
433        KeyEvent e = copyFor(source, target);
434        e.eventType = type;
435        return e;
436    }
437
438    @Override
439    public EventType<KeyEvent> getEventType() {
440        return (EventType<KeyEvent>) super.getEventType();
441    }
442    
443    
444
445}