From 9a67b19973876df1da90f957e1d5ce23384f70d8 Mon Sep 17 00:00:00 2001 From: Skylot Date: Fri, 11 Mar 2022 13:59:00 +0000 Subject: [PATCH] feat(gui): add zoom in/out actions (#1403) --- .../gui/ui/codearea/AbstractCodeArea.java | 3 + .../java/jadx/gui/ui/panel/HtmlPanel.java | 3 + .../main/java/jadx/gui/utils/FontUtils.java | 3 + .../java/jadx/gui/utils/ui/ActionHandler.java | 20 +++++ .../java/jadx/gui/utils/ui/ZoomActions.java | 78 +++++++++++++++++++ 5 files changed, 107 insertions(+) create mode 100644 jadx-gui/src/main/java/jadx/gui/utils/ui/ActionHandler.java create mode 100644 jadx-gui/src/main/java/jadx/gui/utils/ui/ZoomActions.java diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/AbstractCodeArea.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/AbstractCodeArea.java index e6bd7998..681087ad 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/AbstractCodeArea.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/AbstractCodeArea.java @@ -40,6 +40,7 @@ import jadx.gui.utils.DefaultPopupMenuListener; import jadx.gui.utils.JumpPosition; import jadx.gui.utils.NLS; import jadx.gui.utils.UiUtils; +import jadx.gui.utils.ui.ZoomActions; public abstract class AbstractCodeArea extends RSyntaxTextArea { private static final long serialVersionUID = -3980354865216031972L; @@ -67,6 +68,8 @@ public abstract class AbstractCodeArea extends RSyntaxTextArea { addCaretActions(); addFastCopyAction(); + + ZoomActions.register(this, settings, this::loadSettings); } private void addWrapLineMenuAction(JadxSettings settings) { diff --git a/jadx-gui/src/main/java/jadx/gui/ui/panel/HtmlPanel.java b/jadx-gui/src/main/java/jadx/gui/ui/panel/HtmlPanel.java index d9e21e54..ad2275f8 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/panel/HtmlPanel.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/panel/HtmlPanel.java @@ -11,6 +11,7 @@ import javax.swing.JScrollPane; import jadx.gui.settings.JadxSettings; import jadx.gui.treemodel.JNode; import jadx.gui.ui.TabbedPane; +import jadx.gui.utils.ui.ZoomActions; public final class HtmlPanel extends ContentPanel { private static final long serialVersionUID = -6251262855835426245L; @@ -27,6 +28,8 @@ public final class HtmlPanel extends ContentPanel { textArea.setEditable(false); JScrollPane sp = new JScrollPane(textArea); add(sp); + + ZoomActions.register(textArea, panel.getMainWindow().getSettings(), this::loadSettings); } @Override diff --git a/jadx-gui/src/main/java/jadx/gui/utils/FontUtils.java b/jadx-gui/src/main/java/jadx/gui/utils/FontUtils.java index 2829fdc6..417ed01b 100644 --- a/jadx-gui/src/main/java/jadx/gui/utils/FontUtils.java +++ b/jadx-gui/src/main/java/jadx/gui/utils/FontUtils.java @@ -42,6 +42,9 @@ public class FontUtils { } public static String convertToStr(Font font) { + if (font.getSize() < 1) { + throw new JadxRuntimeException("Bad font size: " + font.getSize()); + } return font.getFontName() + '/' + convertFontStyleToString(font.getStyle()) + '/' + font.getSize(); diff --git a/jadx-gui/src/main/java/jadx/gui/utils/ui/ActionHandler.java b/jadx-gui/src/main/java/jadx/gui/utils/ui/ActionHandler.java new file mode 100644 index 00000000..46ceacf9 --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/utils/ui/ActionHandler.java @@ -0,0 +1,20 @@ +package jadx.gui.utils.ui; + +import java.awt.event.ActionEvent; +import java.util.function.Consumer; + +import javax.swing.AbstractAction; + +public class ActionHandler extends AbstractAction { + + private final Consumer consumer; + + public ActionHandler(Consumer consumer) { + this.consumer = consumer; + } + + @Override + public void actionPerformed(ActionEvent e) { + consumer.accept(e); + } +} diff --git a/jadx-gui/src/main/java/jadx/gui/utils/ui/ZoomActions.java b/jadx-gui/src/main/java/jadx/gui/utils/ui/ZoomActions.java new file mode 100644 index 00000000..f8d0380a --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/utils/ui/ZoomActions.java @@ -0,0 +1,78 @@ +package jadx.gui.utils.ui; + +import java.awt.Container; +import java.awt.Font; +import java.awt.event.KeyEvent; + +import javax.swing.ActionMap; +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.KeyStroke; + +import jadx.gui.settings.JadxSettings; +import jadx.gui.utils.UiUtils; + +public class ZoomActions { + private final JComponent component; + private final JadxSettings settings; + private final Runnable update; + + public static void register(JComponent component, JadxSettings settings, Runnable update) { + ZoomActions actions = new ZoomActions(component, settings, update); + actions.register(); + } + + private ZoomActions(JComponent component, JadxSettings settings, Runnable update) { + this.component = component; + this.settings = settings; + this.update = update; + } + + private void register() { + String zoomIn = "TextZoomIn"; + String zoomOut = "TextZoomOut"; + int ctrlButton = UiUtils.ctrlButton(); + InputMap inputMap = component.getInputMap(); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, ctrlButton), zoomIn); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, ctrlButton), zoomIn); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ADD, ctrlButton), zoomIn); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, ctrlButton), zoomOut); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_SUBTRACT, ctrlButton), zoomOut); + ActionMap actionMap = component.getActionMap(); + actionMap.put(zoomIn, new ActionHandler(e -> textZoom(1))); + actionMap.put(zoomOut, new ActionHandler(e -> textZoom(-1))); + + component.addMouseWheelListener(e -> { + if (e.getModifiersEx() == UiUtils.ctrlButton()) { + textZoom(e.getWheelRotation() < 0 ? 1 : -1); + e.consume(); + } else { + // pass event to parent component, needed for scroll in JScrollPane + Container parent = component.getParent(); + if (parent != null) { + parent.dispatchEvent(e); + } + } + }); + } + + private void textZoom(int change) { + Font font = settings.getFont(); + if (component.getFont().equals(font)) { + settings.setFont(changeFontSize(font, change)); + } else { + settings.setSmaliFont(changeFontSize(settings.getSmaliFont(), change)); + } + settings.sync(); + update.run(); + } + + private Font changeFontSize(Font font, int change) { + float newSize = font.getSize() + change; + if (newSize < 2) { + // ignore change + return font; + } + return font.deriveFont(newSize); + } +}