diff --git a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java index 272936202..56aede8e9 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java @@ -576,6 +576,7 @@ public class MainWindow extends JFrame { LogCollector.getInstance().reset(); wrapper.close(); tabsController.forceCloseAllTabs(); + shortcutsController.reset(); UiUtils.resetClipboardOwner(); System.gc(); update(); diff --git a/jadx-gui/src/main/java/jadx/gui/ui/action/JadxGuiAction.java b/jadx-gui/src/main/java/jadx/gui/ui/action/JadxGuiAction.java index ab1d1bb7d..f66b3c28f 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/action/JadxGuiAction.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/action/JadxGuiAction.java @@ -13,8 +13,7 @@ import jadx.gui.utils.UiUtils; import jadx.gui.utils.shortcut.Shortcut; import jadx.gui.utils.ui.ActionHandler; -public class JadxGuiAction extends ActionHandler - implements IShortcutAction { +public class JadxGuiAction extends ActionHandler implements IShortcutAction { private static final String COMMAND = "JadxGuiAction.Command.%s"; private final ActionModel actionModel; @@ -24,7 +23,6 @@ public class JadxGuiAction extends ActionHandler private Shortcut shortcut; public JadxGuiAction(ActionModel actionModel) { - super(); this.actionModel = actionModel; this.id = actionModel.name(); @@ -48,7 +46,6 @@ public class JadxGuiAction extends ActionHandler } public JadxGuiAction(String id) { - super(); this.actionModel = null; this.id = id; @@ -138,4 +135,9 @@ public class JadxGuiAction extends ActionHandler addedKeyStroke = keyStroke; } } + + @Override + public String toString() { + return "JadxGuiAction{" + id + ", component: " + shortcutComponent + '}'; + } } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/menu/JadxMenu.java b/jadx-gui/src/main/java/jadx/gui/ui/menu/JadxMenu.java index 17c495070..d5ec1a36c 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/menu/JadxMenu.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/menu/JadxMenu.java @@ -1,6 +1,7 @@ package jadx.gui.ui.menu; import javax.swing.Action; +import javax.swing.JComponent; import javax.swing.JMenu; import javax.swing.JMenuItem; @@ -10,11 +11,18 @@ import jadx.gui.utils.shortcut.Shortcut; import jadx.gui.utils.shortcut.ShortcutsController; public class JadxMenu extends JMenu { + // fake component to fill action shortcut component property + private static final JComponent JADX_MENU_COMPONENT = new JComponent() { + @Override + public String toString() { + return "JADX_MENU_COMPONENT"; + } + }; + private final ShortcutsController shortcutsController; public JadxMenu(String name, ShortcutsController shortcutsController) { super(name); - this.shortcutsController = shortcutsController; } @@ -33,7 +41,12 @@ public class JadxMenu extends JMenu { public void bindAction(Action action) { if (action instanceof JadxGuiAction) { - shortcutsController.bind((JadxGuiAction) action); + JadxGuiAction guiAction = (JadxGuiAction) action; + JComponent shortcutComponent = guiAction.getShortcutComponent(); + if (shortcutComponent == null) { + guiAction.setShortcutComponent(JADX_MENU_COMPONENT); + } + shortcutsController.bind(guiAction); } } diff --git a/jadx-gui/src/main/java/jadx/gui/utils/shortcut/ShortcutsController.java b/jadx-gui/src/main/java/jadx/gui/utils/shortcut/ShortcutsController.java index b9f0e9bc1..e98a2a633 100644 --- a/jadx-gui/src/main/java/jadx/gui/utils/shortcut/ShortcutsController.java +++ b/jadx-gui/src/main/java/jadx/gui/utils/shortcut/ShortcutsController.java @@ -3,6 +3,8 @@ package jadx.gui.utils.shortcut; import java.awt.AWTEvent; import java.awt.Toolkit; import java.awt.event.MouseEvent; +import java.util.EnumMap; +import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -12,41 +14,42 @@ import javax.swing.JComponent; import javax.swing.KeyStroke; import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.gui.settings.JadxSettings; import jadx.gui.settings.data.ShortcutsWrapper; import jadx.gui.ui.MainWindow; +import jadx.gui.ui.action.ActionCategory; import jadx.gui.ui.action.ActionModel; import jadx.gui.ui.action.IShortcutAction; import jadx.gui.utils.UiUtils; public class ShortcutsController { - private ShortcutsWrapper shortcuts; + private static final Logger LOG = LoggerFactory.getLogger(ShortcutsController.class); + private final JadxSettings settings; + private final Map> boundActions = new EnumMap<>(ActionModel.class); + private final Set mouseActions = EnumSet.noneOf(ActionModel.class); - private final Map> boundActions = new HashMap<>(); - - private Set mouseActions = null; + private ShortcutsWrapper shortcuts; public ShortcutsController(JadxSettings settings) { this.settings = settings; } public void loadSettings() { - this.shortcuts = settings.getShortcuts(); - + shortcuts = settings.getShortcuts(); indexMouseActions(); - - for (Map.Entry> actionsEntry : boundActions.entrySet()) { - ActionModel actionModel = actionsEntry.getKey(); - Set actions = actionsEntry.getValue(); - Shortcut shortcut = get(actionModel); + boundActions.forEach((actionModel, actions) -> { if (actions != null) { + Shortcut shortcut = get(actionModel); for (IShortcutAction action : actions) { action.setShortcut(shortcut); } } - } + }); } @Nullable @@ -56,17 +59,20 @@ public class ShortcutsController { public KeyStroke getKeyStroke(ActionModel actionModel) { Shortcut shortcut = get(actionModel); - KeyStroke keyStroke = null; if (shortcut != null && shortcut.isKeyboard()) { - keyStroke = shortcut.toKeyStroke(); + return shortcut.toKeyStroke(); } - return keyStroke; + return null; } - /* + /** * Binds to an action and updates its shortcut every time loadSettings is called */ public void bind(IShortcutAction action) { + if (action.getShortcutComponent() == null) { + LOG.warn("No shortcut component in action: {}", action, new JadxRuntimeException()); + return; + } boundActions.computeIfAbsent(action.getActionModel(), k -> new HashSet<>()); boundActions.get(action.getActionModel()).add(action); } @@ -93,7 +99,6 @@ public class ShortcutsController { if (mw.isSettingsOpen()) { return; } - if (!(event instanceof MouseEvent)) { return; } @@ -101,7 +106,6 @@ public class ShortcutsController { if (mouseEvent.getID() != MouseEvent.MOUSE_PRESSED) { return; } - int mouseButton = mouseEvent.getButton(); for (ActionModel actionModel : mouseActions) { Shortcut shortcut = shortcuts.get(actionModel); @@ -121,22 +125,33 @@ public class ShortcutsController { } private void indexMouseActions() { - mouseActions = new HashSet<>(); + mouseActions.clear(); for (ActionModel actionModel : ActionModel.values()) { Shortcut shortcut = shortcuts.get(actionModel); if (shortcut != null && shortcut.isMouse()) { mouseActions.add(actionModel); - } else { - mouseActions.remove(actionModel); } } } public void unbindActionsForComponent(JComponent component) { - for (ActionModel actionModel : ActionModel.values()) { - Set actions = boundActions.get(actionModel); + for (Set actions : boundActions.values()) { if (actions != null) { - actions.removeIf(action -> action != null && action.getShortcutComponent() == component); + actions.removeIf(action -> action == null + || action.getShortcutComponent() == null + || action.getShortcutComponent() == component); + } + } + } + + /** + * Keep only actions bound to the main window. + * Other actions will be added on demand. + */ + public void reset() { + for (ActionModel actionModel : ActionModel.values()) { + if (actionModel.getCategory() != ActionCategory.MENU_TOOLBAR) { + boundActions.remove(actionModel); } } }