From d403bcb6de92262a77efd5f75d49a9bb3832e6ab Mon Sep 17 00:00:00 2001 From: Hiroshi Miura Date: Wed, 13 Mar 2024 08:58:32 +0900 Subject: [PATCH 1/4] feat: AbstractMnemonicsAction class - Introduce MnemonicsAction interface - Give Action with mnemonics processing Signed-off-by: Hiroshi Miura --- .../openide/awt/AbstractMnemonicsAction.java | 22 ++++++++ src/org/openide/awt/Mnemonics.java | 51 +++++++++++-------- src/org/openide/awt/MnemonicsAction.java | 16 ++++++ test/src/org/openide/awt/MnemonicsTest.java | 33 ++++++++++-- 4 files changed, 98 insertions(+), 24 deletions(-) create mode 100644 src/org/openide/awt/AbstractMnemonicsAction.java create mode 100644 src/org/openide/awt/MnemonicsAction.java diff --git a/src/org/openide/awt/AbstractMnemonicsAction.java b/src/org/openide/awt/AbstractMnemonicsAction.java new file mode 100644 index 0000000..98bc4f2 --- /dev/null +++ b/src/org/openide/awt/AbstractMnemonicsAction.java @@ -0,0 +1,22 @@ +package org.openide.awt; + +import javax.swing.*; +import java.util.Locale; + +public abstract class AbstractMnemonicsAction extends AbstractAction implements MnemonicsAction { + public AbstractMnemonicsAction(String text, Locale locale) { + super(); + setText(text, locale); + } + + 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..22fd9be 100644 --- a/src/org/openide/awt/Mnemonics.java +++ b/src/org/openide/awt/Mnemonics.java @@ -45,8 +45,7 @@ import java.util.ResourceBundle; import java.util.regex.Pattern; -import javax.swing.AbstractButton; -import javax.swing.JLabel; +import javax.swing.*; /** * Support class for setting button, menu, and label text strings with mnemonics. @@ -54,7 +53,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 +193,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) { + public 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 +214,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 +260,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,14 +274,14 @@ 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 { + } else if (item instanceof JLabel) { ((JLabel)item).setText(text); } } @@ -286,12 +292,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/src/org/openide/awt/MnemonicsAction.java b/src/org/openide/awt/MnemonicsAction.java new file mode 100644 index 0000000..808b840 --- /dev/null +++ b/src/org/openide/awt/MnemonicsAction.java @@ -0,0 +1,16 @@ +package org.openide.awt; + +import javax.swing.Action; +import java.util.Locale; + +public interface MnemonicsAction extends Action { + /** + * Set NAME attribute with mnemonics processing. + * When given "&Text" then it set NAME attribute as + * "Text" and put mnemonics for "T". + * @param text Label text. + * @param locale locale of the text. + */ + void setText(String text, Locale locale); + +} diff --git a/test/src/org/openide/awt/MnemonicsTest.java b/test/src/org/openide/awt/MnemonicsTest.java index 3140345..4ec5ab3 100644 --- a/test/src/org/openide/awt/MnemonicsTest.java +++ b/test/src/org/openide/awt/MnemonicsTest.java @@ -10,9 +10,9 @@ import org.junit.Test; import org.junit.Assert; -import javax.swing.JLabel; -import javax.swing.JMenuItem; +import javax.swing.*; +import java.awt.event.ActionEvent; import java.util.Locale; import static org.openide.awt.Mnemonics.isMacOS; @@ -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 @@ -52,6 +52,23 @@ public void testSetLocalizedTextLabel() { Assert.assertEquals(isMacOS()? 0: 'G', item.getDisplayedMnemonic()); } + @Test + public void testSetLocalizedTextAction() { + AbstractMnemonicsAction item = new MyAbstractMnemonicsAction(); + + Assert.assertEquals("Simple Text", item.getValue(Action.NAME)); + Assert.assertEquals(isMacOS()? -1: 0, item.getValue(Action.DISPLAYED_MNEMONIC_INDEX_KEY)); + // + item.setText("Rock & Roll", new Locale("en")); + 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)); + } + @Test public void testSetLocalizedTextMenuItem() { JMenuItem item = new JMenuItem(); @@ -69,4 +86,14 @@ public void testSetLocalizedTextMenuItem() { Assert.assertEquals(isMacOS()? -1: 0, item.getDisplayedMnemonicIndex()); Assert.assertEquals(isMacOS()? 0: 'G', item.getMnemonic()); } + + private static class MyAbstractMnemonicsAction extends AbstractMnemonicsAction { + public MyAbstractMnemonicsAction() { + super("&Simple Text", new Locale("en")); + } + + @Override + public void actionPerformed(ActionEvent e) { + } + } } From 62af5ba4c70859ae388333af719aedb40909de86 Mon Sep 17 00:00:00 2001 From: Hiroshi Miura Date: Sat, 16 Mar 2024 12:23:58 +0900 Subject: [PATCH 2/4] feat: add constructor and method that take a bundle or omitting locale --- .../openide/awt/AbstractMnemonicsAction.java | 28 ++++++++++++++- src/org/openide/awt/Mnemonics.java | 8 +++-- src/org/openide/awt/MnemonicsAction.java | 16 --------- .../org/openide/awt/MnemonicsActionTest.java | 34 +++++++++++++++++++ test/src/org/openide/awt/MnemonicsTest.java | 31 ++--------------- 5 files changed, 68 insertions(+), 49 deletions(-) delete mode 100644 src/org/openide/awt/MnemonicsAction.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 index 98bc4f2..e296d8a 100644 --- a/src/org/openide/awt/AbstractMnemonicsAction.java +++ b/src/org/openide/awt/AbstractMnemonicsAction.java @@ -2,13 +2,39 @@ 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 abstract class AbstractMnemonicsAction extends AbstractAction implements MnemonicsAction { 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) { diff --git a/src/org/openide/awt/Mnemonics.java b/src/org/openide/awt/Mnemonics.java index 22fd9be..6d1cb46 100644 --- a/src/org/openide/awt/Mnemonics.java +++ b/src/org/openide/awt/Mnemonics.java @@ -279,10 +279,12 @@ private static void setMnemonicIndex (Object item, int index) { * @param text the text to set */ private static void setText(Object item, String text) { - if (item instanceof AbstractButton) { - ((AbstractButton)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); + ((JLabel) item).setText(text); } } diff --git a/src/org/openide/awt/MnemonicsAction.java b/src/org/openide/awt/MnemonicsAction.java deleted file mode 100644 index 808b840..0000000 --- a/src/org/openide/awt/MnemonicsAction.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.openide.awt; - -import javax.swing.Action; -import java.util.Locale; - -public interface MnemonicsAction extends Action { - /** - * Set NAME attribute with mnemonics processing. - * When given "&Text" then it set NAME attribute as - * "Text" and put mnemonics for "T". - * @param text Label text. - * @param locale locale of the text. - */ - void setText(String text, Locale locale); - -} 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 4ec5ab3..8efae75 100644 --- a/test/src/org/openide/awt/MnemonicsTest.java +++ b/test/src/org/openide/awt/MnemonicsTest.java @@ -10,9 +10,9 @@ import org.junit.Test; import org.junit.Assert; -import javax.swing.*; +import javax.swing.JLabel; +import javax.swing.JMenuItem; -import java.awt.event.ActionEvent; import java.util.Locale; import static org.openide.awt.Mnemonics.isMacOS; @@ -52,23 +52,6 @@ public void testSetLocalizedTextLabel() { Assert.assertEquals(isMacOS()? 0: 'G', item.getDisplayedMnemonic()); } - @Test - public void testSetLocalizedTextAction() { - AbstractMnemonicsAction item = new MyAbstractMnemonicsAction(); - - Assert.assertEquals("Simple Text", item.getValue(Action.NAME)); - Assert.assertEquals(isMacOS()? -1: 0, item.getValue(Action.DISPLAYED_MNEMONIC_INDEX_KEY)); - // - item.setText("Rock & Roll", new Locale("en")); - 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)); - } - @Test public void testSetLocalizedTextMenuItem() { JMenuItem item = new JMenuItem(); @@ -86,14 +69,4 @@ public void testSetLocalizedTextMenuItem() { Assert.assertEquals(isMacOS()? -1: 0, item.getDisplayedMnemonicIndex()); Assert.assertEquals(isMacOS()? 0: 'G', item.getMnemonic()); } - - private static class MyAbstractMnemonicsAction extends AbstractMnemonicsAction { - public MyAbstractMnemonicsAction() { - super("&Simple Text", new Locale("en")); - } - - @Override - public void actionPerformed(ActionEvent e) { - } - } } From bca35e77e73825c8f4d59a39a386f6cb127ccd41 Mon Sep 17 00:00:00 2001 From: Hiroshi Miura Date: Sat, 16 Mar 2024 12:25:31 +0900 Subject: [PATCH 3/4] style: imports --- src/org/openide/awt/Mnemonics.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/org/openide/awt/Mnemonics.java b/src/org/openide/awt/Mnemonics.java index 6d1cb46..c5912b7 100644 --- a/src/org/openide/awt/Mnemonics.java +++ b/src/org/openide/awt/Mnemonics.java @@ -45,7 +45,9 @@ import java.util.ResourceBundle; import java.util.regex.Pattern; -import javax.swing.*; +import javax.swing.AbstractButton; +import javax.swing.Action; +import javax.swing.JLabel; /** * Support class for setting button, menu, and label text strings with mnemonics. From 0c232a3c88b40158c65c23929a487459c0a69c34 Mon Sep 17 00:00:00 2001 From: Hiroshi Miura Date: Sat, 16 Mar 2024 12:26:20 +0900 Subject: [PATCH 4/4] refactor: weaken visibility --- src/org/openide/awt/Mnemonics.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/openide/awt/Mnemonics.java b/src/org/openide/awt/Mnemonics.java index c5912b7..02ba0f2 100644 --- a/src/org/openide/awt/Mnemonics.java +++ b/src/org/openide/awt/Mnemonics.java @@ -198,7 +198,7 @@ public static int findMnemonicAmpersand(String text) { * @param locale locale of the text. * @param index Index of the Character to underline under JDK1.4 */ - public 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