Author: rwhitcomb Date: Wed Apr 14 19:55:19 2021 New Revision: 1888774 URL: http://svn.apache.org/viewvc?rev=1888774&view=rev Log: Enhancements to Keyboard to recognize the OSX modifier key symbols.
Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/Keyboard.java Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/Keyboard.java URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/Keyboard.java?rev=1888774&r1=1888773&r2=1888774&view=diff ============================================================================== --- pivot/trunk/wtk/src/org/apache/pivot/wtk/Keyboard.java (original) +++ pivot/trunk/wtk/src/org/apache/pivot/wtk/Keyboard.java Wed Apr 14 19:55:19 2021 @@ -39,7 +39,30 @@ public final class Keyboard { * Enumeration representing keyboard modifiers. */ public enum Modifier { - SHIFT, CTRL, ALT, META; + SHIFT(InputEvent.SHIFT_DOWN_MASK), + CTRL(InputEvent.CTRL_DOWN_MASK), + ALT(InputEvent.ALT_DOWN_MASK), + META(InputEvent.META_DOWN_MASK); + + /** + * The AWT modifier value. + */ + private final int awtModifier; + + /** + * The standard modifier text appropriate for the platform. + */ + private final String keySymbol; + + /** + * Define the enum value, along with the AWT modifier value. + * + * @param modifier The AWT modifier for this enum. + */ + private Modifier(final int modifier) { + awtModifier = modifier; + keySymbol = InputEvent.getModifiersExText(modifier); + } /** * @return The one-bit mask for this modifier, which is @@ -76,12 +99,54 @@ public final class Keyboard { } /** + * Determine the complete set of AWT modifiers for a set of mask values. + * + * @param mask The complete mask set of our modifiers. + * @return The complete mask for AWT use. + */ + public static int getAWTMask(final int mask) { + int awtMask = 0; + for (Modifier m : values()) { + if ((mask & m.getMask()) > 0) { + awtMask |= m.awtModifier; + } + } + return awtMask; + } + + /** * The set of all possible keyboard modifiers (for use with {@link #isPressed}, * or {@link Modifier#getMask(Set)}, {@link #areAllPressed(Set)}, or * {@link #areAnyPressed(Set)}). */ public static final Set<Modifier> ALL_MODIFIERS = EnumSet.of(Modifier.SHIFT, Modifier.CTRL, Modifier.ALT, Modifier.META); + + /** + * Convert the input string into one of our enum values. + * + * @param input Should be one of the enum constants, but we will also + * recognize the constant regardless of case, and also + * allow the Unicode character equivalent to be valid. + * @return The enum value corresponding to the input. + * @throws IllegalArgumentException if the input cannot be recognized + * @throws NullPointerException if the input value is {@code null} + */ + public static final Modifier decode(final String input) { + if (input == null) { + throw new NullPointerException("Null input to Modifier.decode"); + } + + for (Modifier m : values()) { + if (m.toString().equalsIgnoreCase(input)) { + return m; + } else if (m.keySymbol.equals(input)) { + return m; + } + } + + throw new IllegalArgumentException("Illegal input to Modifier.decode: '" + input + "'"); + } } /** @@ -108,8 +173,8 @@ public final class Keyboard { * @see Keyboard.Modifier */ public KeyStroke(final int code, final int modifiers) { - this.keyCode = code; - this.keyModifiers = modifiers; + keyCode = code; + keyModifiers = modifiers; } /** @@ -143,7 +208,7 @@ public final class Keyboard { public int hashCode() { // NOTE Key codes are currently defined as 16-bit values, so // shifting by 4 bits to append the modifiers should be OK. - // However, if Sun changes the key code values in the future, + // However, i:w f Sun changes the key code values in the future, // this may no longer be safe. int hashCode = keyCode << 4 | keyModifiers; return hashCode; @@ -151,27 +216,12 @@ public final class Keyboard { @Override public String toString() { - int awtModifiers = 0x00; - - if (((keyModifiers & Modifier.META.getMask()) > 0)) { - awtModifiers |= InputEvent.META_DOWN_MASK; - } - - if (((keyModifiers & Modifier.CTRL.getMask()) > 0)) { - awtModifiers |= InputEvent.CTRL_DOWN_MASK; - } - - if (((keyModifiers & Modifier.ALT.getMask()) > 0)) { - awtModifiers |= InputEvent.ALT_DOWN_MASK; - } - - if (((keyModifiers & Modifier.SHIFT.getMask()) > 0)) { - awtModifiers |= InputEvent.SHIFT_DOWN_MASK; - } + int awtModifiers = Modifier.getAWTMask(keyModifiers); if (awtModifiers != 0x00) { - return InputEvent.getModifiersExText(awtModifiers) - + Platform.getKeyStrokeModifierSeparator() + KeyEvent.getKeyText(keyCode); + String sep = Platform.getKeyStrokeModifierSeparator(); + return InputEvent.getModifiersExText(awtModifiers).replace("+", sep) + + sep + KeyEvent.getKeyText(keyCode); } return KeyEvent.getKeyText(keyCode); @@ -180,8 +230,8 @@ public final class Keyboard { /** * Decode a keystroke value from its string representation. * - * @param value Input value, such as {@code "Cmd-F1"} or - * {@code "Ctrl-Shift-Left"}. + * @param value Input value, such as {@code "Cmd-F1"}, + * {@code "Ctrl-Shift-Left"}, or even <code>"⌃⌘F1"</code>. * @return The corresponding {@code KeyStroke} value. * @throws IllegalArgumentException if the input string cannot be * decoded. @@ -191,10 +241,12 @@ public final class Keyboard { int keyCode = KeyCode.UNDEFINED; int keyModifiers = 0x00; + String sep = Platform.getKeyStrokeModifierSeparator(); + boolean emptySep = sep.equals(""); - String[] keys = value.split("-"); + String[] keys = value.split(sep); for (int i = 0, n = keys.length; i < n; i++) { - if (i < n - 1) { + if ((emptySep && keys[i].charAt(0) < 0x1000) || (i < n - 1)) { // The first n-1 parts are Modifier values String modifierAbbreviation = keys[i].toUpperCase(Locale.ENGLISH); @@ -202,14 +254,15 @@ public final class Keyboard { if (modifierAbbreviation.equals(COMMAND_ABBREVIATION)) { modifier = Platform.getCommandModifier(); } else { - modifier = Modifier.valueOf(modifierAbbreviation); + modifier = Modifier.decode(modifierAbbreviation); } keyModifiers |= modifier.getMask(); } else { // The final part is the KeyCode itself + String code = emptySep ? value.substring(i) : keys[i]; try { - Field keyCodeField = KeyCode.class.getField(keys[i].toUpperCase(Locale.ENGLISH)); + Field keyCodeField = KeyCode.class.getField(code.toUpperCase(Locale.ENGLISH)); keyCode = ((Integer) keyCodeField.get(null)).intValue(); } catch (Exception exception) { throw new IllegalArgumentException(exception);