changeset 5256:8b1a40fed5c8

RT-20391: Mnemonic-parsing with special characters Reviewed-by: mickf
author leifs
date Thu, 03 Oct 2013 10:52:57 -0700
parents f7b87969cd45
children 4f55a53bfabd
files modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TextBinding.java modules/controls/src/main/java/com/sun/javafx/scene/control/skin/LabeledSkinBase.java modules/controls/src/main/java/com/sun/javafx/scene/control/skin/Utils.java modules/controls/src/test/java/com/sun/javafx/scene/control/skin/ButtonSkinTest.java
diffstat 4 files changed, 146 insertions(+), 84 deletions(-) [+]
line wrap: on
line diff
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TextBinding.java	Thu Oct 03 13:02:17 2013 -0400
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TextBinding.java	Thu Oct 03 10:52:57 2013 -0700
@@ -29,6 +29,8 @@
 import java.util.StringTokenizer;
 
 import javafx.scene.input.KeyCode;
+import javafx.scene.input.KeyEvent;
+import javafx.scene.input.KeyCombination;
 
 /**
  * <p>
@@ -104,21 +106,37 @@
     }
 
     /**
-     * The mnemonic or {@link KeyCode#UNDEFINED} if there is no mnemonic.
+     * The mnemonic or {@code null} if there is no mnemonic.
      */
-    private KeyCode mnemonic = KeyCode.UNDEFINED;
+    private String mnemonic = null;
+    private KeyCombination mnemonicKeyCombination = null;
 
     /**
-     * Returns the mnemonic or {@link KeyCode#UNDEFINED} if there is no
+     * Returns the mnemonic or {@code null} if there is no
      * mnemonic.
      * 
-     * @return the mnemonic or {@link KeyCode#UNDEFINED} if there is no
+     * @return the mnemonic or {@code null} if there is no
      *         mnemonic
      */
-    public KeyCode getMnemonic() {
+    public String getMnemonic() {
         return mnemonic;
     }
 
+
+    /**
+     * Returns the mnemonic KeyCombination or {@code null} if there is no
+     * mnemonic.
+     * 
+     * @return the mnemonic KeyCombination or {@code null} if there is no
+     *         mnemonic
+     */
+    public KeyCombination getMnemonicKeyCombination() {
+        if (mnemonic != null && mnemonicKeyCombination == null) {
+            mnemonicKeyCombination = new MnemonicKeyCombination(mnemonic);
+        }
+        return mnemonicKeyCombination;
+    }
+
     /**
      * The index of the mnemonic character in the text property or -1 if there
      * is no mnemonic character in the text. This is only non-negative if the
@@ -281,8 +299,7 @@
                 temp.delete(index, index + 1); // delete the extra MNEMONIC_SYMBOL
             } else if (temp.charAt(index + 1) != '('
                        || index == temp.length() - 2) {
-                String mnemonicChar = temp.substring(index + 1, index + 2);
-                mnemonic = KeyCode.getKeyCode(mnemonicChar.toUpperCase());
+                mnemonic = temp.substring(index + 1, index + 2);
                 if (mnemonic != null) {
                     mnemonicIndex = index;
                 }
@@ -291,16 +308,14 @@
             } else {
                 int endIndex = temp.indexOf(")", index + 3);
                 if (endIndex == -1) { // "(" is actually the mnemonic
-                    String mnemonicChar = temp.substring(index + 1, index + 2);
-                    mnemonic = KeyCode.getKeyCode(mnemonicChar.toUpperCase());
+                    mnemonic = temp.substring(index + 1, index + 2);
                     if (mnemonic != null) {
                         mnemonicIndex = index;
                     }
                     temp.delete(index, index + 1);
                     break;
                 } else if (endIndex == index + 3) {
-                    String mnemonicChar = temp.substring(index + 2, index + 3);
-                    mnemonic = KeyCode.getKeyCode(mnemonicChar.toUpperCase());
+                    mnemonic = temp.substring(index + 2, index + 3);
                     extendedMnemonicText = temp.substring(index + 1, index + 4);
                     temp.delete(index, endIndex + 3);
                     break;
@@ -392,4 +407,107 @@
             + ", accelerator=" + getAccelerator() + ", acceleratorText="
             + getAcceleratorText() + "]";
     }
+
+    /**
+     * A modified version of KeyCharacterCombination, which matches
+     * on the text property of a KeyEvent instead of on the KeyCode.
+     */
+    public static class MnemonicKeyCombination extends KeyCombination {
+        private String character = "";
+
+        /**
+         * Constructs a {@code MnemonicKeyCombination} for the specified main key
+         * character.
+         *
+         * @param character the main key character
+         */
+        public MnemonicKeyCombination(String character) {
+            super(com.sun.javafx.PlatformUtil.isMac()
+                                  ? KeyCombination.META_DOWN
+                                  : KeyCombination.ALT_DOWN);
+            this.character = character;
+        }
+
+        /** 
+         * Gets the key character associated with this key combination. 
+         * @return The key character associated with this key combination
+         */
+        public final String getCharacter() {
+            return character;
+        }
+
+        /**
+         * Tests whether this key combination matches the key combination in the
+         * given {@code KeyEvent}.
+         *
+         * @param event the key event
+         * @return {@code true} if the key combinations match, {@code false}
+         *      otherwise
+         */
+        @Override public boolean match(final KeyEvent event) {
+            String text = event.getText();
+            return (text != null
+                    && !text.isEmpty()
+                    && text.equalsIgnoreCase(getCharacter())
+                    && super.match(event));
+        }
+
+        /**
+         * Returns a string representation of this {@code MnemonicKeyCombination}.
+         * <p>
+         * The string representation consists of sections separated by plus
+         * characters. Each section specifies either a modifier key or the main key.
+         * <p>
+         * A modifier key section contains the {@code KeyCode} name of a modifier
+         * key. It can be prefixed with the {@code Ignored} keyword. A non-prefixed
+         * modifier key implies its {@code PRESSED} value while the prefixed version
+         * implies the {@code IGNORED} value. If some modifier key is not specified
+         * in the string at all, it means it has the default {@code RELEASED} value.
+         * <p>
+         * The main key section contains the main key character enclosed in single
+         * quotes and is the last section in the returned string.
+         *
+         * @return the string representation of this {@code MnemonicKeyCombination}
+         */
+        @Override public String getName() {
+            StringBuilder sb = new StringBuilder();
+
+            sb.append(super.getName());
+            if (sb.length() > 0) {
+                sb.append("+");
+            }
+
+            return sb.append('\'').append(character.replace("'", "\\'"))
+                    .append('\'').toString();
+        }
+
+        /**
+         * Tests whether this {@code MnemonicKeyCombination} equals to the
+         * specified object.
+         *
+         * @param obj the object to compare to
+         * @return {@code true} if the objects are equal, {@code false} otherwise
+         */
+        @Override public boolean equals(final Object obj) {
+            if (this == obj) {
+                return true;
+            }
+
+            if (!(obj instanceof MnemonicKeyCombination)) {
+                return false;
+            }
+
+            return (this.character.equals(((MnemonicKeyCombination)obj).getCharacter())
+                    && super.equals(obj));
+        }
+
+        /**
+         * Returns a hash code value for this {@code MnemonicKeyCombination}.
+         *
+         * @return the hash code value
+         */
+        @Override public int hashCode() {
+            return 23 * super.hashCode() + character.hashCode();
+        }
+    }
 }
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/LabeledSkinBase.java	Thu Oct 03 13:02:17 2013 -0400
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/LabeledSkinBase.java	Thu Oct 03 10:52:57 2013 -0700
@@ -40,8 +40,6 @@
 import javafx.scene.control.Label;
 import javafx.scene.control.Labeled;
 import javafx.scene.control.OverrunStyle;
-import javafx.scene.input.KeyCode;
-import javafx.scene.input.KeyCodeCombination;
 import javafx.scene.input.KeyCombination;
 import javafx.scene.input.Mnemonic;
 import javafx.scene.shape.Line;
@@ -262,12 +260,7 @@
     */
     protected void mnemonicTargetChanged() {
         if (containsMnemonic == true) {
-            KeyCodeCombination mnemonicKeyCombo =
-                new KeyCodeCombination(
-                                       mnemonicCode,
-                                       com.sun.javafx.PlatformUtil.isMac()
-                                       ? KeyCombination.META_DOWN
-                                       : KeyCombination.ALT_DOWN);
+            KeyCombination mnemonicKeyCombo = mnemonicCode;
 
             /*
             ** was there previously a labelFor
@@ -326,13 +319,7 @@
             ** left on the scene
             */
             if (mnemonicScene != null) {
-                KeyCodeCombination mnemonicKeyCombo =
-                    new KeyCodeCombination(
-                                           mnemonicCode,
-                                           com.sun.javafx.PlatformUtil.isMac()
-                                           ? KeyCombination.META_DOWN
-                                           : KeyCombination.ALT_DOWN);
-
+                KeyCombination mnemonicKeyCombo = mnemonicCode;
                 Mnemonic myMnemonic = new Mnemonic(labeledNode, mnemonicKeyCombo);
                 mnemonicScene.removeMnemonic(myMnemonic);
                 mnemonicScene = null;
@@ -344,13 +331,7 @@
             ** add any mnemonics etc to the scene.
             */
             if (containsMnemonic == true) {
-                KeyCodeCombination mnemonicKeyCombo =
-                    new KeyCodeCombination(
-                                           mnemonicCode,
-                                           com.sun.javafx.PlatformUtil.isMac()
-                                           ? KeyCombination.META_DOWN
-                                           : KeyCombination.ALT_DOWN);
-
+                KeyCombination mnemonicKeyCombo = mnemonicCode;
                 if (labeledNode != null) {
                     Mnemonic myMnemonic = new Mnemonic(labeledNode, mnemonicKeyCombo);
                     mnemonicScene = labeledNode.getScene();
@@ -421,14 +402,10 @@
                 ** are we no longer a mnemonic, or have we changed code?
                 */
                 if (mnemonicScene != null) {
-                    if (mnemonicIndex == -1 || (bindings != null && bindings.getMnemonic() != mnemonicCode)) {
-                        KeyCodeCombination mnemonicKeyCombo =
-                            new KeyCodeCombination(
-                                                   mnemonicCode,
-                                                   com.sun.javafx.PlatformUtil.isMac()
-                                                   ? KeyCombination.META_DOWN
-                                                   : KeyCombination.ALT_DOWN);
-                        
+                    if (mnemonicIndex == -1 ||
+                        (bindings != null && !bindings.getMnemonicKeyCombination().equals(mnemonicCode))) {
+
+                        KeyCombination mnemonicKeyCombo = mnemonicCode;
                         Mnemonic myMnemonic = new Mnemonic(labeledNode, mnemonicKeyCombo);
                         mnemonicScene.removeMnemonic(myMnemonic);
                         mnemonicScene = null;
@@ -442,13 +419,7 @@
                 ** disabled on a previously valid mnemonic
                 */
                 if (mnemonicScene != null && labeledNode != null) {
-                    KeyCodeCombination mnemonicKeyCombo =
-                        new KeyCodeCombination(
-                                               mnemonicCode,
-                                               com.sun.javafx.PlatformUtil.isMac()
-                                               ? KeyCombination.META_DOWN
-                                               : KeyCombination.ALT_DOWN);
-
+                    KeyCombination mnemonicKeyCombo = mnemonicCode;
                     Mnemonic myMnemonic = new Mnemonic(labeledNode, mnemonicKeyCombo);
                     mnemonicScene.removeMnemonic(myMnemonic);
                     mnemonicScene = null;
@@ -461,15 +432,9 @@
             if (s != null && s.length() > 0) {
                 if (mnemonicIndex >= 0 && containsMnemonic == false) {
                     containsMnemonic = true;
-                    mnemonicCode = bindings.getMnemonic();
+                    mnemonicCode = bindings.getMnemonicKeyCombination();
 
-                    KeyCodeCombination mnemonicKeyCombo =
-                            new KeyCodeCombination(
-                                    mnemonicCode,
-                                    com.sun.javafx.PlatformUtil.isMac()
-                                            ? KeyCombination.META_DOWN
-                                            : KeyCombination.ALT_DOWN);
-
+                    KeyCombination mnemonicKeyCombo = mnemonicCode;
                     if (labeledNode != null) {
                         Mnemonic myMnemonic = new Mnemonic(labeledNode, mnemonicKeyCombo);
                         mnemonicScene = labeledNode.getScene();
@@ -911,7 +876,7 @@
 
     private boolean containsMnemonic = false;
     private Scene mnemonicScene = null;
-    private KeyCode mnemonicCode;
+    private KeyCombination mnemonicCode;
     // needs to be an object, as MenuItem isn't a node
     private Node labeledNode = null;
 
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/Utils.java	Thu Oct 03 13:02:17 2013 -0400
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/Utils.java	Thu Oct 03 10:52:57 2013 -0700
@@ -46,8 +46,6 @@
 import javafx.scene.control.ContextMenu;
 import javafx.scene.control.MenuItem;
 import javafx.scene.control.OverrunStyle;
-import javafx.scene.input.KeyCode;
-import javafx.scene.input.KeyCodeCombination;
 import javafx.scene.input.KeyCombination;
 import javafx.scene.input.Mnemonic;
 import javafx.scene.text.Font;
@@ -644,16 +642,7 @@
                     TextBinding bindings = new TextBinding(menuitem.getText());
                     int mnemonicIndex = bindings.getMnemonicIndex() ;
                     if (mnemonicIndex >= 0) {
-
-                        KeyCode mnemonicCode = bindings.getMnemonic();
-                    
-                        KeyCodeCombination mnemonicKeyCombo =
-                                new KeyCodeCombination(
-                                        mnemonicCode,
-                                        com.sun.javafx.PlatformUtil.isMac()
-                                                ? KeyCombination.META_DOWN
-                                                : KeyCombination.ALT_DOWN);
-
+                        KeyCombination mnemonicKeyCombo = bindings.getMnemonicKeyCombination();
                         Mnemonic myMnemonic = new Mnemonic(cmContent.getLabelAt(i), mnemonicKeyCombo);
                         scene.addMnemonic(myMnemonic);
                         cmContent.getLabelAt(i).impl_setShowMnemonics(initialState);
@@ -682,15 +671,7 @@
                     TextBinding bindings = new TextBinding(menuitem.getText());
                     int mnemonicIndex = bindings.getMnemonicIndex() ;
                     if (mnemonicIndex >= 0) {
-
-                        KeyCode mnemonicCode = bindings.getMnemonic();
-                    
-                        KeyCodeCombination mnemonicKeyCombo =
-                                new KeyCodeCombination(
-                                        mnemonicCode,
-                                        com.sun.javafx.PlatformUtil.isMac()
-                                                ? KeyCombination.META_DOWN
-                                                : KeyCombination.ALT_DOWN);
+                        KeyCombination mnemonicKeyCombo = bindings.getMnemonicKeyCombination();
 
                         ObservableList<Mnemonic> mnemonicsList = scene.getMnemonics().get(mnemonicKeyCombo);
                         if (mnemonicsList != null) {
--- a/modules/controls/src/test/java/com/sun/javafx/scene/control/skin/ButtonSkinTest.java	Thu Oct 03 13:02:17 2013 -0400
+++ b/modules/controls/src/test/java/com/sun/javafx/scene/control/skin/ButtonSkinTest.java	Thu Oct 03 10:52:57 2013 -0700
@@ -35,10 +35,10 @@
 import javafx.stage.Stage;
 import javafx.scene.input.Mnemonic;
 import javafx.collections.ObservableList;
-import javafx.scene.input.KeyCode;
-import javafx.scene.input.KeyCodeCombination;
 import javafx.scene.input.KeyCombination;
 
+import com.sun.javafx.scene.control.behavior.TextBinding.MnemonicKeyCombination;
+
 import org.junit.Before;
 import org.junit.Test;
 
@@ -83,8 +83,7 @@
         
             stage.show();
         
-            KeyCodeCombination mnemonicKeyCombo =
-                new KeyCodeCombination(KeyCode.M,KeyCombination.ALT_DOWN);
+            KeyCombination mnemonicKeyCombo = new MnemonicKeyCombination("M");
 
             ObservableList<Mnemonic> mnemonicsList = scene.getMnemonics().get(mnemonicKeyCombo);
             if (mnemonicsList != null) {
@@ -114,8 +113,7 @@
         
             stage.show();
         
-            KeyCodeCombination mnemonicKeyCombo =
-                new KeyCodeCombination(KeyCode.A,KeyCombination.ALT_DOWN);
+            KeyCombination mnemonicKeyCombo = new MnemonicKeyCombination("A");
 
             ObservableList<Mnemonic> mnemonicsList = scene.getMnemonics().get(mnemonicKeyCombo);
             if (mnemonicsList != null) {