From 6f1fb17e89d090c71b913111bcc631e98e0d6eb9 Mon Sep 17 00:00:00 2001 From: Hiroshi Miura Date: Sat, 16 Mar 2024 12:51:55 +0900 Subject: [PATCH] feat: AbstractMnemonicsAction class (#8) * feat: AbstractMnemonicsAction class - Introduce MnemonicsAction interface - Give Action with mnemonics processing Signed-off-by: Hiroshi Miura * feat: add constructor and method that take a bundle or omitting locale * style: imports * refactor: weaken visibility --------- Signed-off-by: Hiroshi Miura --- .../openide/awt/AbstractMnemonicsAction.java | 48 ++++++++++++++++ src/org/openide/awt/Mnemonics.java | 57 ++++++++++++------- .../org/openide/awt/MnemonicsActionTest.java | 34 +++++++++++ test/src/org/openide/awt/MnemonicsTest.java | 2 +- 4 files changed, 118 insertions(+), 23 deletions(-) create mode 100644 src/org/openide/awt/AbstractMnemonicsAction.java create mode 100644 test/src/org/openide/awt/MnemonicsActionTest.java diff --git a/src/org/openide/awt/AbstractMnemonicsAction.java b/src/org/openide/awt/AbstractMnemonicsAction.java new file mode 100644 index 0000000..e296d8a --- /dev/null +++ b/src/org/openide/awt/AbstractMnemonicsAction.java @@ -0,0 +1,48 @@ +package org.openide.awt; + +import javax.swing.*; +import java.util.Locale; +import java.util.ResourceBundle; + +/** + * @author Hiroshi Miura + */ +public abstract class AbstractMnemonicsAction extends AbstractAction { + public AbstractMnemonicsAction() { + super(); + } + + public AbstractMnemonicsAction(String key, ResourceBundle bundle) { + super(); + setText(key, bundle); + } + + public AbstractMnemonicsAction(String text, Locale locale) { + super(); + setText(text, locale); + } + + public AbstractMnemonicsAction(String text) { + super(); + setText(text); + } + + public void setText(String key, ResourceBundle bundle) { + setText(bundle.getString(key), bundle.getLocale()); + } + + public void setText(String text) { + setText(text, new Locale("en")); + } + + public void setText(String text, Locale locale) { + int i = Mnemonics.findMnemonicAmpersand(text); + if (i < 0) { + putValue(Action.NAME, text); + putValue(Action.DISPLAYED_MNEMONIC_INDEX_KEY, -1); + } else { + putValue(Action.NAME, text.substring(0, i) + text.substring(i + 1)); + Mnemonics.setMnemonicAndIndex(this, text.charAt(i + 1), i, locale); + } + } +} diff --git a/src/org/openide/awt/Mnemonics.java b/src/org/openide/awt/Mnemonics.java index f31f842..02ba0f2 100644 --- a/src/org/openide/awt/Mnemonics.java +++ b/src/org/openide/awt/Mnemonics.java @@ -46,6 +46,7 @@ import java.util.regex.Pattern; import javax.swing.AbstractButton; +import javax.swing.Action; import javax.swing.JLabel; /** @@ -54,7 +55,7 @@ * @since 3.37 * @see Issue #26640 */ -public final class Mnemonics extends Object { +public final class Mnemonics { private static final Pattern RE_MNEMONIC_END = Pattern.compile("\\s*\\(&[A-Za-z0-9]\\)(?=[.\\uFF1A]*$)"); private static final Pattern RE_MNEMONIC_INSIDE = Pattern.compile("&(\\p{L})"); @@ -194,18 +195,20 @@ public static int findMnemonicAmpersand(String text) { * @param item AbstractButton/JLabel or subclasses * @param ch Mnemonic char to set, may be a char in some locale + * @param locale locale of the text. * @param index Index of the Character to underline under JDK1.4 */ - private static void setMnemonicAndIndex (Object item, char ch, int index, Locale locale) { + static void setMnemonicAndIndex(Object item, char ch, int index, Locale locale) { // OmegaT tweak // if we're running on non-MacOSX, we don't set any mnemonics - if (isMacOS()) { - setMnemonic(item, 0); + if (isMacOS() || ch == 0) { + setMnemonic(item, 0); + setMnemonicIndex(item, -1); } else { if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) { - // it's latin character or arabic digit, + // it's a latin character or arabic digit, // setting it as mnemonics setMnemonic(item, ch); // If it's something like "Save &As", we need to set another @@ -213,20 +216,23 @@ private static void setMnemonicAndIndex (Object item, char ch, int index, Locale // see #29676 setMnemonicIndex(item, index); } else { - // it's non-latin, getting the latin correspondance + // it's non-latin, getting the latin correspondence int latinCode = getLatinKeycode(ch, locale); setMnemonic(item, latinCode); - if( latinCode!=0 ) + if (latinCode == 0) { + setMnemonicIndex(item, -1); + } else { setMnemonicIndex(item, index); + } } } } /** - * Gets the Latin symbol which corresponds + * Gets the Latin symbol, which corresponds * to some non-Latin symbol on the localized keyboard. - * The search is done via lookup of Resource bundle - * for pairs having the form (e.g.) MNEMONIC_\u0424=A. + * The search is done via lookup of a Resource bundle + * for pairs having the form (e.g.) MNEMONIC_ะค=A. * * @param localeChar non-Latin character or a punctuator to be used as mnemonic * @return character on latin keyboard, corresponding to the locale character, @@ -256,11 +262,13 @@ private static int getLatinKeycode(char localeChar, Locale locale) { *
  • Under JDK1.4 calls the method on item *
  • Under JDK1.3 adds " (<latin character>)" (if needed) * to label and sets the latin character as mnemonics. - * @param item AbstractButton/JLabel or subclasses + * @param item AbstractButton/JLabel/Action or subclasses * @param index Index of the Character to underline under JDK1.4 */ private static void setMnemonicIndex (Object item, int index) { - if (item instanceof AbstractButton) { + if (item instanceof Action) { + ((Action) item).putValue(Action.DISPLAYED_MNEMONIC_INDEX_KEY, index); + } else if (item instanceof AbstractButton) { ((AbstractButton)item).setDisplayedMnemonicIndex(index); } else if (item instanceof JLabel) { ((JLabel)item).setDisplayedMnemonicIndex(index); @@ -268,15 +276,17 @@ private static void setMnemonicIndex (Object item, int index) { } /** - * Wrapper for AbstractButton/JLabel.setText - * @param item AbstractButton/JLabel + * Wrapper for AbstractButton/JLabel.setText and Action.putValue. + * @param item AbstractButton/JLabel/Action * @param text the text to set */ private static void setText(Object item, String text) { - if (item instanceof AbstractButton) { - ((AbstractButton)item).setText(text); - } else { - ((JLabel)item).setText(text); + if (item instanceof Action) { + ((Action) item).putValue(Action.NAME, text); + } else if (item instanceof AbstractButton) { + ((AbstractButton) item).setText(text); + } else if (item instanceof JLabel) { + ((JLabel) item).setText(text); } } @@ -286,12 +296,15 @@ private static void setText(Object item, String text) { * @param mnem Mnemonic char to set, latin [a-z,A-Z], digit [0-9], or any VK_ code */ private static void setMnemonic(Object item, int mnem) { - if(mnem>='a' && mnem<='z') + if (mnem>='a' && mnem<='z') { mnem=mnem+('A'-'a'); - if (item instanceof AbstractButton) { - ((AbstractButton)item).setMnemonic(mnem); + } + if (item instanceof Action) { + ((Action) item).putValue(Action.MNEMONIC_KEY, mnem); + } else if (item instanceof AbstractButton) { + ((AbstractButton) item).setMnemonic(mnem); } else { - ((JLabel)item).setDisplayedMnemonic(mnem); + ((JLabel) item).setDisplayedMnemonic(mnem); } } diff --git a/test/src/org/openide/awt/MnemonicsActionTest.java b/test/src/org/openide/awt/MnemonicsActionTest.java new file mode 100644 index 0000000..5a304d8 --- /dev/null +++ b/test/src/org/openide/awt/MnemonicsActionTest.java @@ -0,0 +1,34 @@ +package org.openide.awt; + +import org.junit.Assert; +import org.junit.Test; + +import javax.swing.Action; +import java.awt.event.ActionEvent; +import java.util.Locale; + +import static org.openide.awt.Mnemonics.isMacOS; + +public class MnemonicsActionTest { + + @Test + public void testSetLocalizedTextAction() { + AbstractMnemonicsAction item = new AbstractMnemonicsAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + } + }; + item.setText("&Simple Text"); + Assert.assertEquals("Simple Text", item.getValue(Action.NAME)); + Assert.assertEquals(isMacOS()? -1: 0, item.getValue(Action.DISPLAYED_MNEMONIC_INDEX_KEY)); + // + item.setText("Rock & Roll"); + Assert.assertEquals("Rock & Roll", item.getValue(Action.NAME)); + Assert.assertEquals(-1, item.getValue(Action.DISPLAYED_MNEMONIC_INDEX_KEY)); + // + item.setText("&\u041F\u043E\u0438\u0441\u043A", new Locale("ru")); + Assert.assertEquals("\u041F\u043E\u0438\u0441\u043A", item.getValue(Action.NAME)); + Assert.assertEquals(isMacOS()? -1: 0, item.getValue(Action.DISPLAYED_MNEMONIC_INDEX_KEY)); + Assert.assertEquals(isMacOS()? 0: 71, item.getValue(Action.MNEMONIC_KEY)); + } +} diff --git a/test/src/org/openide/awt/MnemonicsTest.java b/test/src/org/openide/awt/MnemonicsTest.java index 3140345..8efae75 100644 --- a/test/src/org/openide/awt/MnemonicsTest.java +++ b/test/src/org/openide/awt/MnemonicsTest.java @@ -20,7 +20,7 @@ public final class MnemonicsTest { @Test - public void testRemoveMnemonics() throws Exception { + public void testRemoveMnemonics() { Assert.assertEquals("Simple test", Mnemonics.removeMnemonics("&Simple test")); Assert.assertEquals("Rock & Roll", Mnemonics.removeMnemonics("Rock & Roll")); // Parenthesis at the end, but with latin characters