This is an automated email from the ASF dual-hosted git repository. ebakke pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/netbeans.git
commit f5c239ad21708fa614d045c36b2a429a8538e0ea Author: Eirik Bakke <[email protected]> AuthorDate: Thu Sep 22 22:55:13 2022 -0400 Centralize presentation string generation for keyboard shortcuts in a new method Actions.keyStrokeToString, and make some improvements. Details: * Move the logic in o.n.editor.Utilities.keyStrokeToString to a new public method org.openide.awt.Actions.keyStrokeToString, and delegate to the latter. This avoids duplication of logic, and makes the logic available from modules that do not depend on the editor infrastructure. * Use InputEvent.getModifiersExText instead of the deprecated KeyEvent.getKeyModifiersText. * On MacOS, use proper modifier key symbols in the canonical order, without a plus sign between them. * Use NetBeans' preferred 'NumPad-' prefix instead of 'KP_' for e.g. 'KP_LEFT'. --- .../src/org/netbeans/editor/Utilities.java | 42 ++-------- platform/openide.awt/apichanges.xml | 17 ++++ .../openide.awt/src/org/openide/awt/Actions.java | 98 +++++++++++++++++++--- .../src/org/openide/awt/Bundle.properties | 3 + 4 files changed, 112 insertions(+), 48 deletions(-) diff --git a/ide/editor.lib/src/org/netbeans/editor/Utilities.java b/ide/editor.lib/src/org/netbeans/editor/Utilities.java index ddb3af35ba..e5fa316eb6 100644 --- a/ide/editor.lib/src/org/netbeans/editor/Utilities.java +++ b/ide/editor.lib/src/org/netbeans/editor/Utilities.java @@ -83,6 +83,7 @@ import org.netbeans.modules.editor.lib.BeforeSaveTasks; import org.netbeans.modules.editor.lib2.EditorPreferencesDefaults; import org.netbeans.modules.editor.lib2.view.DocumentView; import org.netbeans.modules.editor.lib2.view.EditorView; +import org.openide.awt.Actions; import org.openide.util.Exceptions; import org.openide.util.Mutex; import org.openide.util.NbBundle; @@ -1292,47 +1293,14 @@ public class Utilities { /** * Creates nice textual representation of KeyStroke. - * Modifiers and an actual key label are concated by plus signs + * Modifiers and an actual key label are concated per the platform-specific convention * @param stroke the KeyStroke to get description of * @return String describing the KeyStroke */ public static String keyStrokeToString( KeyStroke stroke ) { - String modifText = KeyEvent.getKeyModifiersText( stroke.getModifiers() ); - String keyText = (stroke.getKeyCode() == KeyEvent.VK_UNDEFINED) ? - String.valueOf(stroke.getKeyChar()) : getKeyText(stroke.getKeyCode()); - if( modifText.length() > 0 ) return modifText + '+' + keyText; - else return keyText; - } - - /** @return slight modification of what KeyEvent.getKeyText() returns. - * The numpad Left, Right, Down, Up get extra result. - */ - private static String getKeyText(int keyCode) { - String ret = KeyEvent.getKeyText(keyCode); - if (ret != null) { - switch (keyCode) { - case KeyEvent.VK_KP_DOWN: - ret = prefixNumpad(ret, KeyEvent.VK_DOWN); - break; - case KeyEvent.VK_KP_LEFT: - ret = prefixNumpad(ret, KeyEvent.VK_LEFT); - break; - case KeyEvent.VK_KP_RIGHT: - ret = prefixNumpad(ret, KeyEvent.VK_RIGHT); - break; - case KeyEvent.VK_KP_UP: - ret = prefixNumpad(ret, KeyEvent.VK_UP); - break; - } - } - return ret; - } - - private static String prefixNumpad(String key, int testKeyCode) { - if (key.equals(KeyEvent.getKeyText(testKeyCode))) { - key = NbBundle.getBundle(BaseKit.class).getString("key-prefix-numpad") + key; - } - return key; + /* The related logic has now been moved into org.openide.awt.Actions, so that it can be used + by modules that do not depend on the editor infrastructure. */ + return Actions.keyStrokeToString(stroke); } private static void checkOffsetValid(Document doc, int offset) throws BadLocationException { diff --git a/platform/openide.awt/apichanges.xml b/platform/openide.awt/apichanges.xml index 3413a01ae5..656ddf2f87 100644 --- a/platform/openide.awt/apichanges.xml +++ b/platform/openide.awt/apichanges.xml @@ -26,6 +26,23 @@ <apidef name="awt">AWT API</apidef> </apidefs> <changes> + <change id="add-actions-keyStrokeToString"> + <api name="awt"/> + <summary>Add Actions.keyStrokeToString utility method.</summary> + <version major="7" minor="88"/> + <date day="25" month="3" year="2023"/> + <author login="ebakke"/> + <compatibility binary="compatible" semantic="compatible" source="compatible" addition="yes" deprecation="no" deletion="no"/> + <description> + <p>The Actions.keyStrokeToString method has been added as a public API, to avoid + duplication of the same logic in the editor.lib module. This method has identical + semantics to the existing org.netbeans.editor.Utilities.Actions.keyStrokeToString + method (which now delegates to the new Actions.keyStrokeToString), but is available + without depending on the editor infrastructure. + </p> + </description> + <class name="Actions" package="org.openide.awt"/> + </change> <change id="configureDefaultRenderingHints"> <api name="awt"/> <summary>Added GraphicsUtils.configureDefaultRenderingHints(Graphics).</summary> diff --git a/platform/openide.awt/src/org/openide/awt/Actions.java b/platform/openide.awt/src/org/openide/awt/Actions.java index 310d2caae8..5b7c70e8da 100644 --- a/platform/openide.awt/src/org/openide/awt/Actions.java +++ b/platform/openide.awt/src/org/openide/awt/Actions.java @@ -24,6 +24,7 @@ import java.awt.Dimension; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -128,25 +129,100 @@ public class Actions { return null; } - KeyStroke accelerator = (KeyStroke) action.getValue(Action.ACCELERATOR_KEY); + KeyStroke stroke = (KeyStroke) action.getValue(Action.ACCELERATOR_KEY); - if (accelerator == null) { + if (stroke == null) { return null; } - int modifiers = accelerator.getModifiers(); - String acceleratorText = ""; // NOI18N + return keyStrokeToString(stroke); + } - if (modifiers > 0) { - acceleratorText = KeyEvent.getKeyModifiersText(modifiers); - acceleratorText += "+"; // NOI18N - } else if (accelerator.getKeyCode() == KeyEvent.VK_UNDEFINED) { - return ""; // NOI18N + // Based on com.formdev.flatlaf.FlatMenuItemRenderer.getMacOSModifiersExText + private static String getMacOSModifiersExText(int modifiersEx) { + /* Use the proper MacOS convention, which uses single-character modifier symbols, in the + order below, without "+" or space separators. */ + StringBuilder buf = new StringBuilder(); + if ((modifiersEx & InputEvent.CTRL_DOWN_MASK) != 0) { + buf.append('\u2303'); // MacOS "control key" symbol. + } + if ((modifiersEx & (InputEvent.ALT_DOWN_MASK | InputEvent.ALT_GRAPH_DOWN_MASK)) != 0) { + buf.append('\u2325'); // MacOS "option key" symbol. + } + if ((modifiersEx & InputEvent.SHIFT_DOWN_MASK) != 0) { + buf.append('\u21E7'); // MacOS "shift key" symbol. } + if ((modifiersEx & InputEvent.META_DOWN_MASK) != 0) { + buf.append('\u2318'); // MacOS "command key" symbol. + } + return buf.toString(); + } - acceleratorText += KeyEvent.getKeyText(accelerator.getKeyCode()); + /** + * Creates nice textual representation of KeyStroke. + * Modifiers and an actual key label are concated per the platform-specific convention + * @param stroke the KeyStroke to get description of + * @return String describing the KeyStroke + */ + public static String keyStrokeToString( KeyStroke stroke ) { + boolean macOS = Utilities.isMac(); + String modifText = macOS + ? getMacOSModifiersExText(stroke.getModifiers()) + : InputEvent.getModifiersExText(stroke.getModifiers()); + String keyText = (stroke.getKeyCode() == KeyEvent.VK_UNDEFINED) ? + String.valueOf(stroke.getKeyChar()) : getKeyText(stroke.getKeyCode()); + if (!modifText.isEmpty()) { + if (macOS) { + return modifText + keyText; + } else { + return modifText + '+' + keyText; + } + } else { + return keyText; + } + } - return acceleratorText; + /** @return slight modification of what KeyEvent.getKeyText() returns. + * The numpad Left, Right, Down, Up get extra result. + */ + private static String getKeyText(int keyCode) { + String ret = KeyEvent.getKeyText(keyCode); + if (ret != null) { + switch (keyCode) { + case KeyEvent.VK_KP_DOWN: + ret = prefixNumpad(ret, KeyEvent.VK_DOWN); + break; + case KeyEvent.VK_KP_LEFT: + ret = prefixNumpad(ret, KeyEvent.VK_LEFT); + break; + case KeyEvent.VK_KP_RIGHT: + ret = prefixNumpad(ret, KeyEvent.VK_RIGHT); + break; + case KeyEvent.VK_KP_UP: + ret = prefixNumpad(ret, KeyEvent.VK_UP); + break; + } + } + return ret; + } + + private static String prefixNumpad(String key, int nonNumpadCode) { + final String REPLACABLE_PREFIX = "KP_"; + final String usePrefix = NbBundle.getMessage(Actions.class, "key-prefix-numpad"); + final String nonNumpadName = KeyEvent.getKeyText(nonNumpadCode); + if (key.equals(nonNumpadName)) { + /* AWT's name for the key does not distinguish the numpad vs. non-numpad version of the + key; add our "Numpad-" prefix. */ + return usePrefix + key; + } else if (key.startsWith(REPLACABLE_PREFIX)) { + /* AWT's name for the numpad key uses the somewhat confusing "KP_" prefix (e.g. + "KP_LEFT"); use our own preferred prefix instead (e.g. "Numpad-LEFT"). */ + return usePrefix + key.substring(REPLACABLE_PREFIX.length()); + } else { + /* AWT is using some other convention to disambiguate the numpad vs. non-numpad version + of the key. Use AWT's name in this case. */ + return key; + } } /** Attaches menu item to an action. diff --git a/platform/openide.awt/src/org/openide/awt/Bundle.properties b/platform/openide.awt/src/org/openide/awt/Bundle.properties index 301d991a31..4b85d99e5a 100644 --- a/platform/openide.awt/src/org/openide/awt/Bundle.properties +++ b/platform/openide.awt/src/org/openide/awt/Bundle.properties @@ -62,6 +62,9 @@ ACSD_SplittedPanel_EmptySplitter=N/A # {1} = shortcut FMT_ButtonHint={0} ({1}) +# Used by Actions.keyStrokeToString +key-prefix-numpad=NumPad- + # SwingBrowserImpl ACS_SwingBrowserImpl_SwingBrowser=N/A #Title while loading --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected] For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
