mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-25 18:36:07 +08:00
GP-4471 cleaning up menu mnemonic processing
This commit is contained in:
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -127,7 +127,7 @@ public class MenuData {
|
||||
StringBuilder buildy = new StringBuilder();
|
||||
for (int i = 0; i < menuPath.length; i++) {
|
||||
if (i != (menuPath.length - 1)) {
|
||||
buildy.append(processMenuItemName(menuPath[i]));
|
||||
buildy.append(stripMnemonicAmp(menuPath[i]));
|
||||
buildy.append("->");
|
||||
}
|
||||
else {
|
||||
@@ -272,7 +272,7 @@ public class MenuData {
|
||||
* of the characters of the name as the new mnemonic of this item
|
||||
*/
|
||||
public void setMenuItemName(String newMenuItemName) {
|
||||
String processedMenuItemName = processMenuItemName(newMenuItemName);
|
||||
String processedMenuItemName = stripMnemonicAmp(newMenuItemName);
|
||||
if (processedMenuItemName.equals(menuPath[menuPath.length - 1])) {
|
||||
return;
|
||||
}
|
||||
@@ -298,22 +298,23 @@ public class MenuData {
|
||||
firePropertyChanged(oldData);
|
||||
}
|
||||
|
||||
private static int getMnemonic(String[] menuPath) {
|
||||
public static int getMnemonic(String[] menuPath) {
|
||||
if (menuPath == null || menuPath.length == 0) {
|
||||
return NO_MNEMONIC;
|
||||
}
|
||||
return getMnemonic(menuPath[menuPath.length - 1]);
|
||||
}
|
||||
|
||||
private static int getMnemonic(String string) {
|
||||
int indexOf;
|
||||
int fromIndex = 0;
|
||||
do {
|
||||
indexOf = string.indexOf('&', fromIndex);
|
||||
fromIndex = indexOf + 2;
|
||||
} while (indexOf >= 0 && indexOf < string.length() - 1 && string.charAt(indexOf + 1) == '&');
|
||||
if (indexOf >= 0 && indexOf < string.length() - 1) {
|
||||
return string.charAt(indexOf + 1);
|
||||
/**
|
||||
* Parses the mnemonic key from the menu items text.
|
||||
* @param menuName the menu item text
|
||||
* @return the mnemonic key for encoded in the actions menu text. Returns 0 if there is none.
|
||||
*/
|
||||
public static int getMnemonic(String menuName) {
|
||||
String cleaned = menuName.replaceAll("&&", "");
|
||||
int firstIndex = cleaned.indexOf('&');
|
||||
if (firstIndex >= 0 && firstIndex < cleaned.length() - 1) {
|
||||
return cleaned.charAt(firstIndex + 1);
|
||||
}
|
||||
return NO_MNEMONIC;
|
||||
}
|
||||
@@ -321,27 +322,36 @@ public class MenuData {
|
||||
private static String[] processMenuPath(String[] menuPath) {
|
||||
String[] copy = Arrays.copyOf(menuPath, menuPath.length);
|
||||
if (copy != null && copy.length > 0) {
|
||||
copy[copy.length - 1] = processMenuItemName(copy[copy.length - 1]);
|
||||
copy[copy.length - 1] = stripMnemonicAmp(copy[copy.length - 1]);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
private static String processMenuItemName(String string) {
|
||||
int firstAmp = string.indexOf('&');
|
||||
if (firstAmp < 0) {
|
||||
return string;
|
||||
/**
|
||||
* Removes any single '&' characters used to set the mnemonic from the menu item name. The
|
||||
* '&' character can be included in the name by escaping with another '&' character.
|
||||
* @param menuItemName the name that may include mnemonic information
|
||||
* @return the menu item name with single '&' characters removed.
|
||||
*/
|
||||
public static String stripMnemonicAmp(String menuItemName) {
|
||||
if (menuItemName.indexOf('&') < 0) {
|
||||
return menuItemName;
|
||||
}
|
||||
StringBuilder builder = new StringBuilder(string.substring(0, firstAmp));
|
||||
for (int i = firstAmp; i < string.length(); i++) {
|
||||
char ch = string.charAt(i);
|
||||
if (ch == '&') {
|
||||
if (i < string.length() - 1 && string.charAt(i+1) == '&') {
|
||||
builder.append('&');
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
builder.append(ch);
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
boolean previousWasAmpersand = false;
|
||||
for (int i = 0; i < menuItemName.length(); i++) {
|
||||
char c = menuItemName.charAt(i);
|
||||
if (c != '&') {
|
||||
builder.append(c);
|
||||
previousWasAmpersand = false;
|
||||
continue;
|
||||
}
|
||||
if (previousWasAmpersand) {
|
||||
// add in escaped ampersand (double ampersands are replace with one ampersand)
|
||||
builder.append('&');
|
||||
}
|
||||
previousWasAmpersand = !previousWasAmpersand;
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -103,8 +103,8 @@ public class MenuBarManager implements MenuGroupListener {
|
||||
*/
|
||||
private MenuManager getMenuManager(String menuName) {
|
||||
|
||||
char mk = MenuManager.getMnemonicKey(menuName);
|
||||
menuName = MenuManager.stripMnemonicAmp(menuName);
|
||||
int mk = MenuData.getMnemonic(menuName);
|
||||
menuName = MenuData.stripMnemonicAmp(menuName);
|
||||
|
||||
MenuManager mgr = menuManagers.get(menuName);
|
||||
if (mgr == null) {
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -34,7 +34,7 @@ public class MenuManager implements ManagedMenuItem {
|
||||
|
||||
private String name;
|
||||
private final String[] menuPath;
|
||||
private char mnemonicKey = '\0';
|
||||
private int mnemonicKey = MenuData.NO_MNEMONIC;
|
||||
private int level;
|
||||
private boolean usePopupPath;
|
||||
private MenuHandler menuHandler;
|
||||
@@ -53,7 +53,7 @@ public class MenuManager implements ManagedMenuItem {
|
||||
* @param menuHandler Listener to be notified of menu behavior.
|
||||
* @param menuGroupMap maps menu groups to menu paths
|
||||
*/
|
||||
public MenuManager(String name, char mnemonicKey, String group, boolean usePopupPath,
|
||||
public MenuManager(String name, int mnemonicKey, String group, boolean usePopupPath,
|
||||
MenuHandler menuHandler, MenuGroupMap menuGroupMap) {
|
||||
this(name, new String[] { name }, mnemonicKey, 0, group, usePopupPath, menuHandler,
|
||||
menuGroupMap);
|
||||
@@ -71,7 +71,7 @@ public class MenuManager implements ManagedMenuItem {
|
||||
* @param menuHandler Listener to be notified of menu behavior.
|
||||
* @param menuGroupMap maps menu groups to menu paths
|
||||
*/
|
||||
MenuManager(String name, String[] menuPath, char mnemonicKey, int level, String group,
|
||||
MenuManager(String name, String[] menuPath, int mnemonicKey, int level, String group,
|
||||
boolean usePopupPath, MenuHandler menuHandler, MenuGroupMap menuGroupMap) {
|
||||
this.name = name;
|
||||
this.menuPath = menuPath;
|
||||
@@ -120,8 +120,8 @@ public class MenuManager implements ManagedMenuItem {
|
||||
|
||||
String[] fullPath = menuData.getMenuPath();
|
||||
String displayName = fullPath[level];
|
||||
char mnemonic = getMnemonicKey(displayName);
|
||||
String realName = stripMnemonicAmp(displayName);
|
||||
int mnemonic = MenuData.getMnemonic(displayName);
|
||||
String realName = MenuData.stripMnemonicAmp(displayName);
|
||||
MenuManager subMenu = subMenus.get(realName);
|
||||
if (subMenu != null) {
|
||||
return subMenu;
|
||||
@@ -187,37 +187,6 @@ public class MenuManager implements ManagedMenuItem {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the mnemonic key from the menu items text.
|
||||
* @param str the menu item text
|
||||
* @return the mnemonic key for encoded in the actions menu text. Returns 0 if there is none.
|
||||
*/
|
||||
public static char getMnemonicKey(String str) {
|
||||
int ampLoc = str.indexOf('&');
|
||||
char mk = '\0';
|
||||
if (ampLoc >= 0 && ampLoc < str.length() - 1) {
|
||||
mk = str.charAt(ampLoc + 1);
|
||||
}
|
||||
return mk;
|
||||
}
|
||||
|
||||
/***
|
||||
* Removes the Mnemonic indicator character (&) from the text
|
||||
* @param text the text to strip
|
||||
* @return the stripped mnemonic
|
||||
*/
|
||||
public static String stripMnemonicAmp(String text) {
|
||||
int ampLoc = text.indexOf('&');
|
||||
if (ampLoc < 0) {
|
||||
return text;
|
||||
}
|
||||
String s = text.substring(0, ampLoc);
|
||||
if (ampLoc < (text.length() - 1)) {
|
||||
s += text.substring(++ampLoc);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if this menu is empty.
|
||||
*/
|
||||
@@ -233,7 +202,7 @@ public class MenuManager implements ManagedMenuItem {
|
||||
public JMenu getMenu() {
|
||||
if (menu == null) {
|
||||
menu = new JMenu(name);
|
||||
if (mnemonicKey != '\0') {
|
||||
if (mnemonicKey != MenuData.NO_MNEMONIC) {
|
||||
menu.setMnemonic(mnemonicKey);
|
||||
}
|
||||
if (menuHandler != null) {
|
||||
@@ -261,7 +230,7 @@ public class MenuManager implements ManagedMenuItem {
|
||||
@Override
|
||||
public JMenuItem getMenuItem() {
|
||||
JMenu localMenu = getMenu();
|
||||
localMenu.setUI((DockingMenuUI) DockingMenuUI.createUI(localMenu));
|
||||
localMenu.setUI(DockingMenuUI.createUI(localMenu));
|
||||
return localMenu;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -32,16 +32,16 @@ public class MenuDataTest {
|
||||
@Test
|
||||
public void testMenuDataParsesMnemonicFromAmpersand() {
|
||||
MenuData menuData = new MenuData(new String[] { "One", "Two", "&Three" });
|
||||
assertEquals(menuData.getMnemonic(), 'T');
|
||||
assertEquals('T', menuData.getMnemonic());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* There should be no mnemonic, the ampersand is escaped.
|
||||
*/
|
||||
@Test
|
||||
public void testMenuDataMnemonicSkipsEscapedAmpersand() {
|
||||
MenuData menuData = new MenuData(new String[] { "One", "Two", "&&Three" });
|
||||
assertEquals(menuData.getMnemonic(), MenuData.NO_MNEMONIC);
|
||||
assertEquals(MenuData.NO_MNEMONIC, menuData.getMnemonic());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,7 +51,7 @@ public class MenuDataTest {
|
||||
@Test
|
||||
public void testMenuDataMnemonicEscapesAmpersandLeftToRight() {
|
||||
MenuData menuData = new MenuData(new String[] { "One", "Two", "T&&&hree" });
|
||||
assertEquals(menuData.getMnemonic(), 'h');
|
||||
assertEquals('h', menuData.getMnemonic());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,7 +61,7 @@ public class MenuDataTest {
|
||||
@Test
|
||||
public void testMenuDataMnemonicIgnoresTrailingAmpersand() {
|
||||
MenuData menuData = new MenuData(new String[] { "One", "Two", "Three&" });
|
||||
assertEquals(menuData.getMnemonic(), MenuData.NO_MNEMONIC);
|
||||
assertEquals(MenuData.NO_MNEMONIC, menuData.getMnemonic());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,7 +71,7 @@ public class MenuDataTest {
|
||||
@Test
|
||||
public void testMenuDataMnemonicParsesLeftToRight() {
|
||||
MenuData menuData = new MenuData(new String[] { "One", "Two", "&T&hree" });
|
||||
assertEquals(menuData.getMnemonic(), 'T');
|
||||
assertEquals('T', menuData.getMnemonic());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,7 +81,7 @@ public class MenuDataTest {
|
||||
public void testMenuDataPassedMnemonicWins() {
|
||||
MenuData menuData = new MenuData(
|
||||
new String[] { "One", "Two", "&Three" }, null, null, 'h', null);
|
||||
assertEquals(menuData.getMnemonic(), 'h');
|
||||
assertEquals('h', menuData.getMnemonic());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,7 +110,7 @@ public class MenuDataTest {
|
||||
|
||||
String newName = "Completely New Name";
|
||||
menuData.setMenuItemName(newName);
|
||||
assertEquals(menuData.getMnemonic(), MenuData.NO_MNEMONIC);
|
||||
assertEquals(MenuData.NO_MNEMONIC, menuData.getMnemonic());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -123,15 +123,15 @@ public class MenuDataTest {
|
||||
String newName = "Completely New Name";
|
||||
String[] newPath = { "Four", newName };
|
||||
menuData.setMenuPath(newPath);
|
||||
assertEquals(menuData.getMnemonic(), MenuData.NO_MNEMONIC);
|
||||
assertEquals(MenuData.NO_MNEMONIC, menuData.getMnemonic());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetMenuItemNameEscapesAmpersand() {
|
||||
MenuData menuData = new MenuData(new String[] { "One", "Two", "&&Three" });
|
||||
assertEquals(menuData.getMenuItemName(), "&Three");
|
||||
assertEquals("&Three", menuData.getMenuItemName());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ampersands that are not escaped should be ignored regardless of use as
|
||||
* mnemonics.
|
||||
@@ -140,8 +140,8 @@ public class MenuDataTest {
|
||||
public void testGetMenuItemNameIgnoresUnescapedAmpersand() {
|
||||
MenuData menuData = new MenuData(new String[] { "One", "Two", "Three&" });
|
||||
assertEquals(menuData.getMenuItemName(), "Three");
|
||||
|
||||
|
||||
menuData.setMenuItemName("&T&hree");
|
||||
assertEquals(menuData.getMenuItemName(), "Three");
|
||||
assertEquals("Three", menuData.getMenuItemName());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user