--- old/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/KeyBinding.java 2015-09-03 15:17:22.205605300 -0700 +++ /dev/null 2015-09-03 15:17:23.000000000 -0700 @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.javafx.scene.control.behavior; - -import com.sun.javafx.util.Utils; -import static com.sun.javafx.scene.control.behavior.OptionalBoolean.ANY; -import static com.sun.javafx.scene.control.behavior.OptionalBoolean.FALSE; -import static com.sun.javafx.scene.control.behavior.OptionalBoolean.TRUE; -import com.sun.javafx.tk.Toolkit; -import javafx.event.EventType; -import javafx.scene.control.Control; -import javafx.scene.input.KeyCode; -import javafx.scene.input.KeyEvent; - -/** - * KeyBindings are used to describe which action should occur based on some - * KeyEvent state and Control state. These bindings are used to populate the - * keyBindings variable on BehaviorBase. The KeyBinding can be subclassed to - * add additional matching criteria. A match in a subclass should always have - * a specificity that is 1 greater than its superclass in the case of a match, - * or 0 in the case where there is no match. - * - * Note that this API is, at present, quite odd in that you use a constructor - * and then use shift(), ctrl(), alt(), or meta() separately. It gave me an - * object-literal like approach but isn't ideal. We will want some builder - * approach here (similar as in other places). - */ -public class KeyBinding { - private KeyCode code; - private EventType eventType = KeyEvent.KEY_PRESSED; - private String action; - private OptionalBoolean shift = FALSE; - private OptionalBoolean ctrl = FALSE; - private OptionalBoolean alt = FALSE; - private OptionalBoolean meta = FALSE; - - public KeyBinding(KeyCode code, String action) { - this.code = code; - this.action = action; - } - - public KeyBinding(KeyCode code, EventType type, String action) { - this.code = code; - this.eventType = type; - this.action = action; - } - - public KeyBinding shift() { - return shift(TRUE); - } - - public KeyBinding shift(OptionalBoolean value) { - shift = value; - return this; - } - - public KeyBinding ctrl() { - return ctrl(TRUE); - } - - public KeyBinding ctrl(OptionalBoolean value) { - ctrl = value; - return this; - } - - public KeyBinding alt() { - return alt(TRUE); - } - - public KeyBinding alt(OptionalBoolean value) { - alt = value; - return this; - } - - public KeyBinding meta() { - return meta(TRUE); - } - - public KeyBinding meta(OptionalBoolean value) { - meta = value; - return this; - } - - public KeyBinding shortcut() { - if (Toolkit.getToolkit().getClass().getName().endsWith("StubToolkit")) { - // FIXME: We've hit the terrible StubToolkit (which only appears - // during testing). We will dumb down what we do here - if (Utils.isMac()) { - return meta(); - } else { - return ctrl(); - } - } else { - switch (Toolkit.getToolkit().getPlatformShortcutKey()) { - case SHIFT: - return shift(); - - case CONTROL: - return ctrl(); - - case ALT: - return alt(); - - case META: - return meta(); - - default: - return this; - } - } - } - - public final KeyCode getCode() { return code; } - public final EventType getType() { return eventType; } - public final String getAction() { return action; } - public final OptionalBoolean getShift() { return shift; } - public final OptionalBoolean getCtrl() { return ctrl; } - public final OptionalBoolean getAlt() { return alt; } - public final OptionalBoolean getMeta() { return meta; } - - public int getSpecificity(Control control, KeyEvent event) { - int s = 0; - if (code != null && code != event.getCode()) return 0; else s = 1; - if (!shift.equals(event.isShiftDown())) return 0; else if (shift != ANY) s++; - if (!ctrl.equals(event.isControlDown())) return 0; else if (ctrl != ANY) s++; - if (!alt.equals(event.isAltDown())) return 0; else if (alt != ANY) s++; - if (!meta.equals(event.isMetaDown())) return 0; else if (meta != ANY) s++; - if (eventType != null && eventType != event.getEventType()) return 0; else s++; - // We can now trivially accept it - return s; - } - - @Override public String toString() { - return "KeyBinding [code=" + code + ", shift=" + shift + - ", ctrl=" + ctrl + ", alt=" + alt + - ", meta=" + meta + ", type=" + eventType + - ", action=" + action + "]"; - } -} --- /dev/null 2015-09-03 15:17:23.000000000 -0700 +++ new/modules/controls/src/main/java/com/sun/javafx/scene/control/inputmap/KeyBinding.java 2015-09-03 15:17:21.458562600 -0700 @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.javafx.scene.control.inputmap; + +import com.sun.javafx.util.Utils; +import com.sun.javafx.tk.Toolkit; +import javafx.event.EventType; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; + +import java.util.Objects; + +import static com.sun.javafx.scene.control.inputmap.KeyBinding.OptionalBoolean.*; + +/** + * KeyBindings are used to describe which action should occur based on some + * KeyEvent state and Control state. These bindings are used to populate the + * keyBindings variable on BehaviorBase. The KeyBinding can be subclassed to + * add additional matching criteria. A match in a subclass should always have + * a specificity that is 1 greater than its superclass in the case of a match, + * or 0 in the case where there is no match. + * + * Note that this API is, at present, quite odd in that you use a constructor + * and then use shift(), ctrl(), alt(), or meta() separately. It gave me an + * object-literal like approach but isn't ideal. We will want some builder + * approach here (similar as in other places). + * + * @since 9 + */ +public class KeyBinding { + private final KeyCode code; + private final EventType eventType; + private OptionalBoolean shift = FALSE; + private OptionalBoolean ctrl = FALSE; + private OptionalBoolean alt = FALSE; + private OptionalBoolean meta = FALSE; + + public KeyBinding(KeyCode code) { + this(code, null); + } + + /** + * Designed for 'catch-all' situations, e.g. all KeyTyped events. + * @param type + */ + public KeyBinding(EventType type) { + this(null, type); + } + + public KeyBinding(KeyCode code, EventType type) { + this.code = code; + this.eventType = type != null ? type : KeyEvent.KEY_PRESSED; + } + + public final KeyBinding shift() { + return shift(TRUE); + } + + public final KeyBinding shift(OptionalBoolean value) { + shift = value; + return this; + } + + public final KeyBinding ctrl() { + return ctrl(TRUE); + } + + public final KeyBinding ctrl(OptionalBoolean value) { + ctrl = value; + return this; + } + + public final KeyBinding alt() { + return alt(TRUE); + } + + public final KeyBinding alt(OptionalBoolean value) { + alt = value; + return this; + } + + public final KeyBinding meta() { + return meta(TRUE); + } + + public final KeyBinding meta(OptionalBoolean value) { + meta = value; + return this; + } + + public final KeyBinding shortcut() { + if (Toolkit.getToolkit().getClass().getName().endsWith("StubToolkit")) { + // FIXME: We've hit the terrible StubToolkit (which only appears + // during testing). We will dumb down what we do here + if (Utils.isMac()) { + return meta(); + } else { + return ctrl(); + } + } else { + switch (Toolkit.getToolkit().getPlatformShortcutKey()) { + case SHIFT: + return shift(); + + case CONTROL: + return ctrl(); + + case ALT: + return alt(); + + case META: + return meta(); + + default: + return this; + } + } + } + + + + public final KeyCode getCode() { return code; } + public final EventType getType() { return eventType; } + public final OptionalBoolean getShift() { return shift; } + public final OptionalBoolean getCtrl() { return ctrl; } + public final OptionalBoolean getAlt() { return alt; } + public final OptionalBoolean getMeta() { return meta; } + + public int getSpecificity(KeyEvent event) { + int s = 0; + if (code != null && code != event.getCode()) return 0; else s = 1; + if (!shift.equals(event.isShiftDown())) return 0; else if (shift != ANY) s++; + if (!ctrl.equals(event.isControlDown())) return 0; else if (ctrl != ANY) s++; + if (!alt.equals(event.isAltDown())) return 0; else if (alt != ANY) s++; + if (!meta.equals(event.isMetaDown())) return 0; else if (meta != ANY) s++; + if (eventType != null && eventType != event.getEventType()) return 0; else s++; + // We can now trivially accept it + return s; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return "KeyBinding [code=" + code + ", shift=" + shift + + ", ctrl=" + ctrl + ", alt=" + alt + + ", meta=" + meta + ", type=" + eventType + "]"; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof KeyBinding)) return false; + KeyBinding that = (KeyBinding) o; + return Objects.equals(getCode(), that.getCode()) && + Objects.equals(eventType, that.eventType) && + Objects.equals(getShift(), that.getShift()) && + Objects.equals(getCtrl(), that.getCtrl()) && + Objects.equals(getAlt(), that.getAlt()) && + Objects.equals(getMeta(), that.getMeta()); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + return Objects.hash(getCode(), eventType, getShift(), getCtrl(), getAlt(), getMeta()); + } + + public static KeyBinding toKeyBinding(KeyEvent keyEvent) { + KeyBinding newKeyBinding = new KeyBinding(keyEvent.getCode(), keyEvent.getEventType()); + if (keyEvent.isShiftDown()) newKeyBinding.shift(); + if (keyEvent.isControlDown()) newKeyBinding.ctrl(); + if (keyEvent.isAltDown()) newKeyBinding.alt(); + if (keyEvent.isShortcutDown()) newKeyBinding.shortcut(); + return newKeyBinding; + } + + /** + * A tri-state boolean used with KeyBinding. + */ + public enum OptionalBoolean { + TRUE, + FALSE, + ANY; + + public boolean equals(boolean b) { + if (this == ANY) return true; + if (b && this == TRUE) return true; + if (!b && this == FALSE) return true; + return false; + } + } + +}