From 045bd0155501042245324b23c2c9d76acb56bdc2 Mon Sep 17 00:00:00 2001 From: Mino260806 Date: Wed, 7 Aug 2024 11:42:07 +0100 Subject: [PATCH 1/5] optimize tabs reorder --- .../java/jadx/gui/ui/tab/ITabStatesListener.java | 4 ++-- .../main/java/jadx/gui/ui/tab/QuickTabsTree.java | 4 ++-- .../src/main/java/jadx/gui/ui/tab/TabbedPane.java | 13 +++++-------- .../main/java/jadx/gui/ui/tab/TabsController.java | 2 +- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/ITabStatesListener.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/ITabStatesListener.java index 805fa2c922a..bbc3cdcc03e 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/tab/ITabStatesListener.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/ITabStatesListener.java @@ -1,6 +1,6 @@ package jadx.gui.ui.tab; -import java.util.ArrayList; +import java.util.List; import jadx.gui.ui.codearea.EditorViewState; @@ -23,7 +23,7 @@ public interface ITabStatesListener { void onTabsRestoreDone(); - void onTabsReorder(ArrayList blueprints); + void onTabsReorder(List blueprints); void onTabSave(TabBlueprint blueprint, EditorViewState viewState); } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/QuickTabsTree.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/QuickTabsTree.java index 8cd63de1f69..78b693c2e8a 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/tab/QuickTabsTree.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/QuickTabsTree.java @@ -6,7 +6,7 @@ import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.util.ArrayList; +import java.util.List; import javax.swing.JPopupMenu; import javax.swing.JTree; @@ -238,7 +238,7 @@ public void onTabsRestoreDone() { } @Override - public void onTabsReorder(ArrayList blueprints) { + public void onTabsReorder(List blueprints) { } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java index 00742a3d777..2b94762067e 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java @@ -11,7 +11,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import javax.swing.JTabbedPane; import javax.swing.SwingUtilities; @@ -569,14 +568,12 @@ public void onTabsRestoreDone() { } @Override - public void onTabsReorder(ArrayList blueprints) { - ArrayList newBlueprints = new ArrayList<>(); + public void onTabsReorder(List blueprints) { + List newBlueprints = new ArrayList<>(blueprints.size()); + for (ContentPanel contentPanel : getTabs()) { - Optional blueprintFindResult = blueprints.stream() - .filter(b -> b.getNode() == contentPanel.getNode()) - .findFirst(); - if (blueprintFindResult.isPresent()) { - TabBlueprint blueprint = blueprintFindResult.get(); + TabBlueprint blueprint = controller.getTabByNode(contentPanel.getNode()); + if (blueprint != null) { blueprints.remove(blueprint); newBlueprints.add(blueprint); } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabsController.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabsController.java index 192e7695e6d..96ae9d5c799 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabsController.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabsController.java @@ -223,7 +223,7 @@ public void notifyRestoreEditorViewStateDone() { } public List getEditorViewStates() { - ArrayList reorderedTabs = new ArrayList<>(tabsMap.values()); + List reorderedTabs = new ArrayList<>(tabsMap.values()); listeners.forEach(l -> l.onTabsReorder(reorderedTabs)); List states = new ArrayList<>(); for (TabBlueprint blueprint : reorderedTabs) { From e5cd05a0834ddc3e2e508fffaf698b0330aca3d8 Mon Sep 17 00:00:00 2001 From: Mino260806 Date: Wed, 7 Aug 2024 12:26:09 +0100 Subject: [PATCH 2/5] restructure based on quick tabs architecture --- .../src/main/java/jadx/gui/logs/LogPanel.java | 8 +- .../gui/plugins/context/GuiPluginContext.java | 2 +- .../jadx/gui/plugins/quark/QuarkManager.java | 2 +- .../gui/plugins/quark/QuarkReportPanel.java | 6 +- .../gui/plugins/script/ScriptCodeArea.java | 4 +- .../plugins/script/ScriptContentPanel.java | 2 +- .../src/main/java/jadx/gui/ui/MainWindow.java | 18 +++-- .../gui/ui/codearea/AbstractCodeArea.java | 6 +- .../java/jadx/gui/ui/codearea/CodeArea.java | 4 +- .../java/jadx/gui/ui/codearea/CodePanel.java | 2 +- .../ui/codearea/GoToDeclarationAction.java | 2 +- .../java/jadx/gui/ui/codearea/HexArea.java | 4 +- .../java/jadx/gui/ui/codearea/SmaliArea.java | 14 ++-- .../gui/ui/dialog/CommonSearchDialog.java | 10 +-- .../java/jadx/gui/ui/panel/ContentPanel.java | 10 +++ .../java/jadx/gui/ui/panel/HtmlPanel.java | 2 +- .../jadx/gui/ui/panel/JDebuggerPanel.java | 2 +- .../jadx/gui/ui/tab/ITabStatesListener.java | 5 ++ .../java/jadx/gui/ui/tab/QuickTabsTree.java | 11 +++ .../main/java/jadx/gui/ui/tab/TabbedPane.java | 78 ++++--------------- .../java/jadx/gui/ui/tab/TabsController.java | 68 ++++++++++++++++ 21 files changed, 156 insertions(+), 104 deletions(-) diff --git a/jadx-gui/src/main/java/jadx/gui/logs/LogPanel.java b/jadx-gui/src/main/java/jadx/gui/logs/LogPanel.java index d0770b2d2f9..35802ec73e2 100644 --- a/jadx-gui/src/main/java/jadx/gui/logs/LogPanel.java +++ b/jadx-gui/src/main/java/jadx/gui/logs/LogPanel.java @@ -23,7 +23,7 @@ import jadx.gui.treemodel.JNode; import jadx.gui.ui.MainWindow; import jadx.gui.ui.codearea.AbstractCodeArea; -import jadx.gui.ui.panel.ContentPanel; +import jadx.gui.ui.tab.TabBlueprint; import jadx.gui.utils.NLS; public class LogPanel extends JPanel { @@ -141,9 +141,9 @@ private void registerLogListener(LogOptions logOptions) { } private @Nullable String getCurrentScriptName() { - ContentPanel selectedCodePanel = mainWindow.getTabbedPane().getSelectedContentPanel(); - if (selectedCodePanel != null) { - JNode node = selectedCodePanel.getNode(); + TabBlueprint selectedTab = mainWindow.getTabsController().getSelectedTab(); + if (selectedTab != null) { + JNode node = selectedTab.getNode(); if (node instanceof JInputScript) { return node.getName(); } diff --git a/jadx-gui/src/main/java/jadx/gui/plugins/context/GuiPluginContext.java b/jadx-gui/src/main/java/jadx/gui/plugins/context/GuiPluginContext.java index 9b9f9a5ab0b..eaa4f1b7d5d 100644 --- a/jadx-gui/src/main/java/jadx/gui/plugins/context/GuiPluginContext.java +++ b/jadx-gui/src/main/java/jadx/gui/plugins/context/GuiPluginContext.java @@ -179,7 +179,7 @@ public boolean open(ICodeNodeRef ref) { return false; } - commonContext.getMainWindow().getTabbedPane().codeJump(node); + commonContext.getMainWindow().getTabsController().codeJump(node); return true; } diff --git a/jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkManager.java b/jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkManager.java index 6b864dd9311..5b9e8af62d9 100644 --- a/jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkManager.java +++ b/jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkManager.java @@ -114,7 +114,7 @@ private void loadReport() { root.replaceCustomNode(quarkNode); root.update(); mainWindow.reloadTree(); - mainWindow.getTabbedPane().showNode(quarkNode); + mainWindow.getTabsController().selectTab(quarkNode); } catch (Exception e) { UiUtils.errorMessage(mainWindow, "Failed to load Quark report."); LOG.error("Failed to load Quark report.", e); diff --git a/jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkReportPanel.java b/jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkReportPanel.java index 18213572de0..313fe8ecc9b 100644 --- a/jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkReportPanel.java +++ b/jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkReportPanel.java @@ -117,7 +117,7 @@ public void mouseClicked(MouseEvent event) { Object node = getNodeUnderMouse(tree, event); if (node instanceof MethodTreeNode) { JMethod method = ((MethodTreeNode) node).getJMethod(); - tabbedPane.codeJump(method); + tabbedPane.getTabsController().codeJump(method); } } } @@ -159,7 +159,7 @@ private String buildHeader() { @Override public void loadSettings() { - Font settingsFont = getTabbedPane().getMainWindow().getSettings().getFont(); + Font settingsFont = getMainWindow().getSettings().getFont(); this.font = settingsFont.deriveFont(settingsFont.getSize2D() + 1.f); this.boldFont = font.deriveFont(Font.BOLD); header.setFont(font); @@ -279,7 +279,7 @@ public MutableTreeNode resolveMethod(String descr) { String[] parts = removeQuotes(descr).split(" ", 3); String cls = Utils.cleanObjectName(parts[0].replace('$', '.')); String mth = parts[1] + parts[2].replace(" ", ""); - MainWindow mainWindow = getTabbedPane().getMainWindow(); + MainWindow mainWindow = getMainWindow(); JadxWrapper wrapper = mainWindow.getWrapper(); JavaClass javaClass = wrapper.searchJavaClassByRawName(cls); if (javaClass == null) { diff --git a/jadx-gui/src/main/java/jadx/gui/plugins/script/ScriptCodeArea.java b/jadx-gui/src/main/java/jadx/gui/plugins/script/ScriptCodeArea.java index d7af18ae349..d088577ae62 100644 --- a/jadx-gui/src/main/java/jadx/gui/plugins/script/ScriptCodeArea.java +++ b/jadx-gui/src/main/java/jadx/gui/plugins/script/ScriptCodeArea.java @@ -25,8 +25,8 @@ public ScriptCodeArea(ContentPanel contentPanel, JInputScript node) { setCodeFoldingEnabled(true); setCloseCurlyBraces(true); - shortcutsController = contentPanel.getTabbedPane().getMainWindow().getShortcutsController(); - JadxSettings settings = contentPanel.getTabbedPane().getMainWindow().getSettings(); + shortcutsController = contentPanel.getMainWindow().getShortcutsController(); + JadxSettings settings = contentPanel.getMainWindow().getSettings(); autoCompletion = addAutoComplete(settings); } diff --git a/jadx-gui/src/main/java/jadx/gui/plugins/script/ScriptContentPanel.java b/jadx-gui/src/main/java/jadx/gui/plugins/script/ScriptContentPanel.java index 5d60687fc6c..2da8a81403c 100644 --- a/jadx-gui/src/main/java/jadx/gui/plugins/script/ScriptContentPanel.java +++ b/jadx-gui/src/main/java/jadx/gui/plugins/script/ScriptContentPanel.java @@ -232,7 +232,7 @@ private void applySettings() { } private void showScriptLog() { - getTabbedPane().getMainWindow().showLogViewer(LogOptions.forScript(getNode().getName())); + getMainWindow().showLogViewer(LogOptions.forScript(getNode().getName())); } @Override 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 1d91d66061a..fc7fb7be2b6 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java @@ -288,7 +288,7 @@ public void windowClosing(WindowEvent e) { private void processCommandLineArgs() { if (settings.getFiles().isEmpty()) { - tabbedPane.showNode(new StartPageNode()); + tabsController.selectTab(new StartPageNode()); } else { open(FileUtils.fileNamesToPaths(settings.getFiles()), this::handleSelectClassOption); } @@ -306,7 +306,7 @@ private void handleSelectClassOption() { NLS.str("error_dialog.title"), JOptionPane.ERROR_MESSAGE); return; } - tabbedPane.codeJump(cacheObject.getNodeCache().makeFrom(javaNode)); + tabsController.codeJump(cacheObject.getNodeCache().makeFrom(javaNode)); } } @@ -517,7 +517,7 @@ private void openProject(Path path, Runnable onFinish) { private void loadFiles(Runnable onFinish) { if (project.getFilePaths().isEmpty()) { - tabbedPane.showNode(new StartPageNode()); + tabsController.selectTab(new StartPageNode()); return; } AtomicReference wrapperException = new AtomicReference<>(); @@ -864,15 +864,17 @@ private boolean nodeClickAction(@Nullable Object obj) { JResource res = (JResource) obj; ResourceFile resFile = res.getResFile(); if (resFile != null && JResource.isSupportedForView(resFile.getType())) { - return tabbedPane.showNode(res); + tabsController.selectTab(res); + return true; } } else if (obj instanceof JNode) { JNode node = (JNode) obj; if (node.getRootClass() != null) { - tabbedPane.codeJump(node); + tabsController.codeJump(node); return true; } - return tabbedPane.showNode(node); + tabsController.selectTab(node); + return true; } } catch (Exception e) { LOG.error("Content loading error", e); @@ -962,7 +964,7 @@ public void goToMainActivity() { if (mainActivityClass == null) { throw new JadxRuntimeException("Failed to find main activity class: " + results.getMainActivity()); } - tabbedPane.codeJump(getCacheObject().getNodeCache().makeFrom(mainActivityClass)); + tabsController.codeJump(getCacheObject().getNodeCache().makeFrom(mainActivityClass)); } catch (Exception e) { LOG.error("Main activity not found", e); JOptionPane.showMessageDialog(MainWindow.this, @@ -992,7 +994,7 @@ public void goToApplication() { if (applicationClass == null) { throw new JadxRuntimeException("Failed to find application class: " + results.getApplication()); } - tabbedPane.codeJump(getCacheObject().getNodeCache().makeFrom(applicationClass)); + tabsController.codeJump(getCacheObject().getNodeCache().makeFrom(applicationClass)); } catch (Exception e) { LOG.error("Application not found", e); JOptionPane.showMessageDialog(MainWindow.this, 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 222c4212020..6756d24784e 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 @@ -90,7 +90,7 @@ public AbstractCodeArea(ContentPanel contentPanel, JNode node) { applyEditableProperties(node); loadSettings(); - JadxSettings settings = contentPanel.getTabbedPane().getMainWindow().getSettings(); + JadxSettings settings = contentPanel.getMainWindow().getSettings(); setLineWrap(settings.isCodeAreaLineWrap()); ZoomActions.register(this, settings, this::loadSettings); @@ -147,7 +147,7 @@ protected void appendFoldingMenu(JPopupMenu popup) { } private void appendWrapLineMenu(JPopupMenu popupMenu) { - JadxSettings settings = contentPanel.getTabbedPane().getMainWindow().getSettings(); + JadxSettings settings = contentPanel.getMainWindow().getSettings(); popupMenu.addSeparator(); JCheckBoxMenuItem wrapItem = new JCheckBoxMenuItem(NLS.str("popup.line_wrap"), getLineWrap()); wrapItem.setAction(new AbstractAction(NLS.str("popup.line_wrap")) { @@ -378,7 +378,7 @@ public static void loadCommonSettings(MainWindow mainWindow, RSyntaxTextArea are } public void loadSettings() { - loadCommonSettings(contentPanel.getTabbedPane().getMainWindow(), this); + loadCommonSettings(contentPanel.getMainWindow(), this); } public void scrollToPos(int pos) { diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java index d117378571e..414fcfd5442 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java @@ -87,7 +87,7 @@ private void navToDecl(Point point) { int offs = viewToModel2D(point); JNode node = getJNodeAtOffset(adjustOffsetForWordToken(offs)); if (node != null) { - contentPanel.getTabbedPane().codeJump(node); + contentPanel.getTabsController().codeJump(node); } } @@ -332,7 +332,7 @@ public void refreshClass() { } public MainWindow getMainWindow() { - return contentPanel.getTabbedPane().getMainWindow(); + return contentPanel.getMainWindow(); } public JadxWrapper getJadxWrapper() { diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodePanel.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodePanel.java index 49601020375..ce4ff7eb5ec 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodePanel.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodePanel.java @@ -82,7 +82,7 @@ public void actionPerformed(ActionEvent e) { AbstractAction globalSearchAction = new AbstractAction(NLS.str("popup.search_global", "")) { @Override public void actionPerformed(ActionEvent e) { - MainWindow mainWindow = codeArea.getContentPanel().getTabbedPane().getMainWindow(); + MainWindow mainWindow = codeArea.getContentPanel().getMainWindow(); SearchDialog.searchText(mainWindow, codeArea.getSelectedText()); } }; diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/GoToDeclarationAction.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/GoToDeclarationAction.java index 3fc92b74373..4b1b4531c45 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/GoToDeclarationAction.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/GoToDeclarationAction.java @@ -12,6 +12,6 @@ public GoToDeclarationAction(CodeArea codeArea) { @Override public void runAction(JNode node) { - getCodeArea().getContentPanel().getTabbedPane().codeJump(node); + getCodeArea().getContentPanel().getTabsController().codeJump(node); } } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/HexArea.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/HexArea.java index 4478c275ae6..479afe20c0a 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/HexArea.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/HexArea.java @@ -85,10 +85,10 @@ public void loadSettings() { } private void applyTheme() { - Font font = getContentPanel().getTabbedPane().getMainWindow().getSettings().getSmaliFont(); + Font font = getContentPanel().getMainWindow().getSettings().getSmaliFont(); setFont(font); - Theme theme = contentPanel.getTabbedPane().getMainWindow().getEditorTheme(); + Theme theme = contentPanel.getMainWindow().getEditorTheme(); if (hexPreviewPanel != null) { hexPreviewPanel.applyTheme(theme, font); } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/SmaliArea.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/SmaliArea.java index 7b381047176..7d21b1f47ce 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/SmaliArea.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/SmaliArea.java @@ -74,7 +74,7 @@ public final class SmaliArea extends AbstractCodeArea { @Override public void actionPerformed(ActionEvent e) { - JadxSettings settings = getContentPanel().getTabbedPane().getMainWindow().getSettings(); + JadxSettings settings = getContentPanel().getMainWindow().getSettings(); settings.setSmaliAreaShowBytecode(!settings.getSmaliAreaShowBytecode()); contentPanel.getTabbedPane().getTabs().forEach(v -> { if (v instanceof ClassCodeContentPanel) { @@ -127,7 +127,7 @@ private void switchModel() { } public void scrollToDebugPos(int pos) { - getContentPanel().getTabbedPane().getMainWindow() + getContentPanel().getMainWindow() .getSettings().setSmaliAreaShowBytecode(true); // don't sync when it's set programmatically. cbUseSmaliV2.setState(shouldUseSmaliPrinterV2()); if (!(model instanceof DebugModel)) { @@ -151,7 +151,7 @@ public Font getFontForTokenType(int type) { } private boolean shouldUseSmaliPrinterV2() { - return getContentPanel().getTabbedPane().getMainWindow().getSettings().getSmaliAreaShowBytecode(); + return getContentPanel().getMainWindow().getSettings().getSmaliAreaShowBytecode(); } private abstract class SmaliModel { @@ -177,7 +177,7 @@ void togglePosHighlight(int pos) { private class NormalModel extends SmaliModel { public NormalModel() { - Theme theme = getContentPanel().getTabbedPane().getMainWindow().getEditorTheme(); + Theme theme = getContentPanel().getMainWindow().getEditorTheme(); setSyntaxScheme(theme.scheme); setSyntaxEditingStyle(SYNTAX_STYLE_SMALI); } @@ -323,16 +323,16 @@ private class SmaliV2Style extends SyntaxScheme { public SmaliV2Style(SmaliArea smaliArea) { super(true); - curTheme = smaliArea.getContentPanel().getTabbedPane().getMainWindow().getEditorTheme(); + curTheme = smaliArea.getContentPanel().getMainWindow().getEditorTheme(); updateTheme(); } public Font getFont() { - return getContentPanel().getTabbedPane().getMainWindow().getSettings().getSmaliFont(); + return getContentPanel().getMainWindow().getSettings().getSmaliFont(); } public boolean refreshTheme() { - Theme theme = getContentPanel().getTabbedPane().getMainWindow().getEditorTheme(); + Theme theme = getContentPanel().getMainWindow().getEditorTheme(); boolean refresh = theme != curTheme; if (refresh) { curTheme = theme; diff --git a/jadx-gui/src/main/java/jadx/gui/ui/dialog/CommonSearchDialog.java b/jadx-gui/src/main/java/jadx/gui/ui/dialog/CommonSearchDialog.java index 53dca461d44..8e0007d5d56 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/dialog/CommonSearchDialog.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/dialog/CommonSearchDialog.java @@ -52,7 +52,7 @@ import jadx.gui.ui.MainWindow; import jadx.gui.ui.codearea.AbstractCodeArea; import jadx.gui.ui.panel.ProgressPanel; -import jadx.gui.ui.tab.TabbedPane; +import jadx.gui.ui.tab.TabsController; import jadx.gui.utils.CacheObject; import jadx.gui.utils.JNodeCache; import jadx.gui.utils.JumpPosition; @@ -67,7 +67,7 @@ public abstract class CommonSearchDialog extends JFrame { private static final Logger LOG = LoggerFactory.getLogger(CommonSearchDialog.class); private static final long serialVersionUID = 8939332306115370276L; - protected final transient TabbedPane tabbedPane; + protected final transient TabsController tabsController; protected final transient CacheObject cache; protected final transient MainWindow mainWindow; protected final transient Font codeFont; @@ -84,7 +84,7 @@ public abstract class CommonSearchDialog extends JFrame { public CommonSearchDialog(MainWindow mainWindow, String title) { this.mainWindow = mainWindow; - this.tabbedPane = mainWindow.getTabbedPane(); + this.tabsController = mainWindow.getTabsController(); this.cache = mainWindow.getCacheObject(); this.codeFont = mainWindow.getSettings().getFont(); this.windowTitle = title; @@ -145,9 +145,9 @@ protected void openSelectedItem() { protected void openItem(JNode node) { if (node instanceof JResSearchNode) { JumpPosition jmpPos = new JumpPosition(((JResSearchNode) node).getResNode(), node.getPos()); - tabbedPane.codeJump(jmpPos); + tabsController.codeJump(jmpPos); } else { - tabbedPane.codeJump(node); + tabsController.codeJump(node); } if (!mainWindow.getSettings().getKeepCommonDialogOpen()) { dispose(); diff --git a/jadx-gui/src/main/java/jadx/gui/ui/panel/ContentPanel.java b/jadx-gui/src/main/java/jadx/gui/ui/panel/ContentPanel.java index 2825044b578..20f1e1ba4b9 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/panel/ContentPanel.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/panel/ContentPanel.java @@ -7,7 +7,9 @@ import jadx.gui.settings.JadxSettings; import jadx.gui.treemodel.JClass; import jadx.gui.treemodel.JNode; +import jadx.gui.ui.MainWindow; import jadx.gui.ui.tab.TabbedPane; +import jadx.gui.ui.tab.TabsController; public abstract class ContentPanel extends JPanel { @@ -27,6 +29,14 @@ public TabbedPane getTabbedPane() { return tabbedPane; } + public TabsController getTabsController() { + return tabbedPane.getTabsController(); + } + + public MainWindow getMainWindow() { + return tabbedPane.getMainWindow(); + } + public JNode getNode() { return node; } 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 735c253529d..d9117b7a10b 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 @@ -34,7 +34,7 @@ public HtmlPanel(TabbedPane panel, JNode jnode) { @Override public void loadSettings() { - JadxSettings settings = getTabbedPane().getMainWindow().getSettings(); + JadxSettings settings = getMainWindow().getSettings(); textArea.setFont(settings.getFont()); } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/panel/JDebuggerPanel.java b/jadx-gui/src/main/java/jadx/gui/ui/panel/JDebuggerPanel.java index d98006f15fb..540f66faece 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/panel/JDebuggerPanel.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/panel/JDebuggerPanel.java @@ -445,7 +445,7 @@ public void resetUI() { } public void scrollToSmaliLine(JClass cls, int pos, boolean debugMode) { - SwingUtilities.invokeLater(() -> getMainWindow().getTabbedPane().smaliJump(cls, pos, debugMode)); + SwingUtilities.invokeLater(() -> getMainWindow().getTabsController().smaliJump(cls, pos, debugMode)); } public void resetAllDebuggingInfo() { diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/ITabStatesListener.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/ITabStatesListener.java index bbc3cdcc03e..540383c4bcb 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/tab/ITabStatesListener.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/ITabStatesListener.java @@ -3,12 +3,17 @@ import java.util.List; import jadx.gui.ui.codearea.EditorViewState; +import jadx.gui.utils.JumpPosition; public interface ITabStatesListener { void onTabOpen(TabBlueprint blueprint); void onTabSelect(TabBlueprint blueprint); + void onTabCodeJump(TabBlueprint blueprint, JumpPosition position); + + void onTabSmaliJump(TabBlueprint blueprint, int pos, boolean debugMode); + void onTabClose(TabBlueprint blueprint); void onTabPositionFirst(TabBlueprint blueprint); diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/QuickTabsTree.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/QuickTabsTree.java index 78b693c2e8a..bbef6e8e53e 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/tab/QuickTabsTree.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/QuickTabsTree.java @@ -21,6 +21,7 @@ import jadx.gui.treemodel.JNode; import jadx.gui.ui.MainWindow; import jadx.gui.ui.codearea.EditorViewState; +import jadx.gui.utils.JumpPosition; import jadx.gui.utils.UiUtils; public class QuickTabsTree extends JTree implements ITabStatesListener, TreeSelectionListener { @@ -185,6 +186,16 @@ public void onTabSelect(TabBlueprint blueprint) { } + @Override + public void onTabCodeJump(TabBlueprint blueprint, JumpPosition position) { + + } + + @Override + public void onTabSmaliJump(TabBlueprint blueprint, int pos, boolean debugMode) { + + } + @Override public void onTabClose(TabBlueprint blueprint) { removeJNode(openParentNode, blueprint.getNode()); diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java index 2b94762067e..20b8458069e 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java @@ -10,7 +10,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import javax.swing.JTabbedPane; import javax.swing.SwingUtilities; @@ -19,10 +18,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import jadx.api.JavaClass; -import jadx.api.metadata.ICodeAnnotation; -import jadx.api.metadata.ICodeNodeRef; -import jadx.api.metadata.annotations.NodeDeclareRef; import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.gui.treemodel.JClass; import jadx.gui.treemodel.JNode; @@ -39,7 +34,6 @@ import jadx.gui.ui.tab.dnd.TabDndController; import jadx.gui.utils.JumpManager; import jadx.gui.utils.JumpPosition; -import jadx.gui.utils.NLS; import jadx.gui.utils.UiUtils; public class TabbedPane extends JTabbedPane implements ITabStatesListener { @@ -211,53 +205,11 @@ public MainWindow getMainWindow() { return mainWindow; } - /** - * Jump to node definition - */ - public void codeJump(JNode node) { - JClass parentCls = node.getJParent(); - if (parentCls != null) { - JavaClass cls = node.getJParent().getCls(); - JavaClass origTopCls = cls.getOriginalTopParentClass(); - JavaClass codeParent = cls.getTopParentClass(); - if (!Objects.equals(codeParent, origTopCls)) { - JClass jumpCls = mainWindow.getCacheObject().getNodeCache().makeFrom(codeParent); - mainWindow.getBackgroundExecutor().execute( - NLS.str("progress.load"), - jumpCls::loadNode, // load code in background - status -> { - // search original node in jump class - codeParent.getCodeInfo().getCodeMetadata().searchDown(0, (pos, ann) -> { - if (ann.getAnnType() == ICodeAnnotation.AnnType.DECLARATION) { - ICodeNodeRef declNode = ((NodeDeclareRef) ann).getNode(); - if (declNode.equals(node.getJavaNode().getCodeNodeRef())) { - codeJump(new JumpPosition(jumpCls, pos)); - return true; - } - } - return null; - }); - }); - return; - } - } - - // Not an inline node, jump normally - if (node.getPos() != 0 || node.getRootClass() == null) { - codeJump(new JumpPosition(node)); - return; - } - // node need loading - mainWindow.getBackgroundExecutor().execute( - NLS.str("progress.load"), - () -> node.getRootClass().getCodeInfo(), // run heavy loading in background - status -> codeJump(new JumpPosition(node))); + public TabsController getTabsController() { + return controller; } - /** - * Prefer {@link TabbedPane#codeJump(JNode)} method - */ - public void codeJump(JumpPosition pos) { + private void codeJump(JumpPosition pos) { saveJump(pos); showCode(pos); } @@ -279,15 +231,6 @@ private void saveJump(JumpPosition pos) { return contentPanel; } - public boolean showNode(JNode node) { - final ContentPanel contentPanel = getContentPanel(node); - if (contentPanel == null) { - return false; - } - selectTab(contentPanel); - return true; - } - private void scrollToPos(ContentPanel contentPanel, int pos) { if (pos == 0) { LOG.warn("Ignore zero jump!", new JadxRuntimeException()); @@ -304,7 +247,7 @@ public void selectTab(ContentPanel contentPanel) { controller.selectTab(contentPanel.getNode()); } - public void smaliJump(JClass cls, int pos, boolean debugMode) { + private void smaliJump(JClass cls, int pos, boolean debugMode) { ContentPanel panel = getTabByNode(cls); if (panel == null) { panel = showCode(new JumpPosition(cls, 1)); @@ -497,6 +440,19 @@ public void onTabSelect(TabBlueprint blueprint) { } } + @Override + public void onTabCodeJump(TabBlueprint blueprint, JumpPosition position) { + codeJump(position); + } + + @Override + public void onTabSmaliJump(TabBlueprint blueprint, int pos, boolean debugMode) { + JNode node = blueprint.getNode(); + if (node instanceof JClass) { + smaliJump((JClass) node, pos, debugMode); + } + } + @Override public void onTabClose(TabBlueprint blueprint) { ContentPanel contentPanel = getTabByNode(blueprint.getNode()); diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabsController.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabsController.java index 96ae9d5c799..14b5e2fe2a8 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabsController.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabsController.java @@ -4,13 +4,22 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.org.jline.utils.Log; +import jadx.api.JavaClass; +import jadx.api.metadata.ICodeAnnotation; +import jadx.api.metadata.ICodeNodeRef; +import jadx.api.metadata.annotations.NodeDeclareRef; +import jadx.gui.treemodel.JClass; import jadx.gui.treemodel.JNode; import jadx.gui.ui.MainWindow; import jadx.gui.ui.codearea.EditorViewState; +import jadx.gui.utils.JumpPosition; +import jadx.gui.utils.NLS; public class TabsController { private final transient MainWindow mainWindow; @@ -69,6 +78,65 @@ public void selectTab(JNode node) { listeners.forEach(l -> l.onTabSelect(blueprint)); } + /** + * Jump to node definition + */ + public void codeJump(JNode node) { + JClass parentCls = node.getJParent(); + if (parentCls != null) { + JavaClass cls = node.getJParent().getCls(); + JavaClass origTopCls = cls.getOriginalTopParentClass(); + JavaClass codeParent = cls.getTopParentClass(); + if (!Objects.equals(codeParent, origTopCls)) { + JClass jumpCls = mainWindow.getCacheObject().getNodeCache().makeFrom(codeParent); + mainWindow.getBackgroundExecutor().execute( + NLS.str("progress.load"), + jumpCls::loadNode, // load code in background + status -> { + // search original node in jump class + codeParent.getCodeInfo().getCodeMetadata().searchDown(0, (pos, ann) -> { + if (ann.getAnnType() == ICodeAnnotation.AnnType.DECLARATION) { + ICodeNodeRef declNode = ((NodeDeclareRef) ann).getNode(); + if (declNode.equals(node.getJavaNode().getCodeNodeRef())) { + codeJump(new JumpPosition(jumpCls, pos)); + return true; + } + } + return null; + }); + }); + return; + } + } + + // Not an inline node, jump normally + if (node.getPos() != 0 || node.getRootClass() == null) { + codeJump(new JumpPosition(node)); + return; + } + // node need loading + mainWindow.getBackgroundExecutor().execute( + NLS.str("progress.load"), + () -> node.getRootClass().getCodeInfo(), // run heavy loading in background + status -> codeJump(new JumpPosition(node))); + } + + /** + * Prefer {@link TabsController#codeJump(JNode)} method + */ + public void codeJump(JumpPosition pos) { + if (selectedTab == null) { + Log.warn("Cannot codeJump because selectedTab is null"); + return; + } + listeners.forEach(l -> l.onTabCodeJump(selectedTab, pos)); + } + + public void smaliJump(JClass cls, int pos, boolean debugMode) { + TabBlueprint blueprint = openTab(cls); + listeners.forEach(l -> l.onTabSmaliJump(blueprint, pos, debugMode)); + } + public void closeTab(JNode node) { closeTab(node, false); } From 4f8eb6bc2d7bb5138082caa4f0e063d5a134b698 Mon Sep 17 00:00:00 2001 From: Mino260806 Date: Tue, 13 Aug 2024 16:02:00 +0100 Subject: [PATCH 3/5] code formatting --- .../src/main/java/jadx/gui/ui/MainWindow.java | 16 ++- .../jadx/gui/ui/tab/NavigationController.java | 122 ++++++++++++++++++ .../main/java/jadx/gui/ui/tab/TabbedPane.java | 30 +---- 3 files changed, 135 insertions(+), 33 deletions(-) create mode 100644 jadx-gui/src/main/java/jadx/gui/ui/tab/NavigationController.java 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 fc7fb7be2b6..8d0d4d6934c 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java @@ -139,6 +139,7 @@ import jadx.gui.ui.panel.JDebuggerPanel; import jadx.gui.ui.panel.ProgressPanel; import jadx.gui.ui.popupmenu.RecentProjectsMenuListener; +import jadx.gui.ui.tab.NavigationController; import jadx.gui.ui.tab.QuickTabsTree; import jadx.gui.ui.tab.TabbedPane; import jadx.gui.ui.tab.TabsController; @@ -210,6 +211,7 @@ public class MainWindow extends JFrame { private DefaultTreeModel treeModel; private JRoot treeRoot; private TabsController tabsController; + private NavigationController navController; private TabbedPane tabbedPane; private HeapUsageBar heapUsageBar; private transient boolean treeReloading; @@ -783,6 +785,7 @@ public void initTree() { } private void clearTree() { + navController.reset(); tabbedPane.reset(); treeRoot = null; treeModel.setRoot(null); @@ -1087,10 +1090,10 @@ private void initMenuAndToolbar() { JadxGuiAction showLogAction = new JadxGuiAction(ActionModel.SHOW_LOG, () -> showLogViewer(LogOptions.current())); JadxGuiAction aboutAction = new JadxGuiAction(ActionModel.ABOUT, () -> new AboutDialog().setVisible(true)); - JadxGuiAction backAction = new JadxGuiAction(ActionModel.BACK, tabbedPane::navBack); - JadxGuiAction backVariantAction = new JadxGuiAction(ActionModel.BACK_V, tabbedPane::navBack); - JadxGuiAction forwardAction = new JadxGuiAction(ActionModel.FORWARD, tabbedPane::navForward); - JadxGuiAction forwardVariantAction = new JadxGuiAction(ActionModel.FORWARD_V, tabbedPane::navForward); + JadxGuiAction backAction = new JadxGuiAction(ActionModel.BACK, navController::navBack); + JadxGuiAction backVariantAction = new JadxGuiAction(ActionModel.BACK_V, navController::navBack); + JadxGuiAction forwardAction = new JadxGuiAction(ActionModel.FORWARD, navController::navForward); + JadxGuiAction forwardVariantAction = new JadxGuiAction(ActionModel.FORWARD_V, navController::navForward); JadxGuiAction quarkAction = new JadxGuiAction(ActionModel.QUARK, () -> new QuarkDialog(MainWindow.this).setVisible(true)); JadxGuiAction openDeviceAction = new JadxGuiAction(ActionModel.OPEN_DEVICE, @@ -1348,6 +1351,7 @@ public void treeWillCollapse(TreeExpansionEvent event) { treeSplitPane.setLeftComponent(leftPane); tabsController = new TabsController(this); + navController = new NavigationController(this); tabbedPane = new TabbedPane(this, tabsController); tabbedPane.setMinimumSize(new Dimension(150, 150)); new TabDndController(tabbedPane, settings); @@ -1583,6 +1587,10 @@ public TabsController getTabsController() { return tabsController; } + public NavigationController getNavController() { + return navController; + } + public JadxSettings getSettings() { return settings; } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/NavigationController.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/NavigationController.java new file mode 100644 index 00000000000..bc39ae9118e --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/NavigationController.java @@ -0,0 +1,122 @@ +package jadx.gui.ui.tab; + +import java.util.List; + +import jadx.gui.ui.MainWindow; +import jadx.gui.ui.codearea.EditorViewState; +import jadx.gui.utils.JumpManager; +import jadx.gui.utils.JumpPosition; + +public class NavigationController implements ITabStatesListener { + private final transient MainWindow mainWindow; + + private final transient JumpManager jumps = new JumpManager(); + + public NavigationController(MainWindow mainWindow) { + this.mainWindow = mainWindow; + + mainWindow.getTabsController().addListener(this); + } + + public void saveJump(JumpPosition pos) { + JumpPosition curPos = mainWindow.getTabbedPane().getCurrentPosition(); + if (curPos != null) { + jumps.addPosition(curPos); + jumps.addPosition(pos); + } + } + + public void navBack() { + if (jumps.size() > 1) { + jumps.updateCurPosition(mainWindow.getTabbedPane().getCurrentPosition()); + } + JumpPosition pos = jumps.getPrev(); + if (pos != null) { + mainWindow.getTabsController().codeJump(pos); + } + } + + public void navForward() { + if (jumps.size() > 1) { + jumps.updateCurPosition(mainWindow.getTabbedPane().getCurrentPosition()); + } + JumpPosition pos = jumps.getNext(); + if (pos != null) { + mainWindow.getTabsController().codeJump(pos); + } + } + + @Override + public void onTabOpen(TabBlueprint blueprint) { + + } + + @Override + public void onTabSelect(TabBlueprint blueprint) { + + } + + @Override + public void onTabCodeJump(TabBlueprint blueprint, JumpPosition position) { + + } + + @Override + public void onTabSmaliJump(TabBlueprint blueprint, int pos, boolean debugMode) { + + } + + @Override + public void onTabClose(TabBlueprint blueprint) { + + } + + @Override + public void onTabPositionFirst(TabBlueprint blueprint) { + + } + + @Override + public void onTabPinChange(TabBlueprint blueprint) { + + } + + @Override + public void onTabBookmarkChange(TabBlueprint blueprint) { + + } + + @Override + public void onTabVisibilityChange(TabBlueprint blueprint) { + + } + + @Override + public void onTabRestore(TabBlueprint blueprint, EditorViewState viewState) { + + } + + @Override + public void onTabsRestoreDone() { + + } + + @Override + public void onTabsReorder(List blueprints) { + + } + + @Override + public void onTabSave(TabBlueprint blueprint, EditorViewState viewState) { + + } + + public void reset() { + jumps.reset(); + } + + public void dispose() { + reset(); + mainWindow.getTabsController().removeListener(this); + } +} diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java index 20b8458069e..33215bd527a 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java @@ -32,7 +32,6 @@ import jadx.gui.ui.panel.IViewStateSupport; import jadx.gui.ui.panel.ImagePanel; import jadx.gui.ui.tab.dnd.TabDndController; -import jadx.gui.utils.JumpManager; import jadx.gui.utils.JumpPosition; import jadx.gui.utils.UiUtils; @@ -45,8 +44,6 @@ public class TabbedPane extends JTabbedPane implements ITabStatesListener { private final transient TabsController controller; private final transient Map tabsMap = new HashMap<>(); - private final transient JumpManager jumps = new JumpManager(); - private transient ContentPanel curTab; private transient ContentPanel lastTab; @@ -215,11 +212,7 @@ private void codeJump(JumpPosition pos) { } private void saveJump(JumpPosition pos) { - JumpPosition curPos = getCurrentPosition(); - if (curPos != null) { - jumps.addPosition(curPos); - jumps.addPosition(pos); - } + mainWindow.getNavController().saveJump(pos); } private @Nullable ContentPanel showCode(JumpPosition jumpPos) { @@ -276,26 +269,6 @@ public JumpPosition getCurrentPosition() { return null; } - public void navBack() { - if (jumps.size() > 1) { - jumps.updateCurPosition(getCurrentPosition()); - } - JumpPosition pos = jumps.getPrev(); - if (pos != null) { - showCode(pos); - } - } - - public void navForward() { - if (jumps.size() > 1) { - jumps.updateCurPosition(getCurrentPosition()); - } - JumpPosition pos = jumps.getNext(); - if (pos != null) { - showCode(pos); - } - } - private void addContentPanel(ContentPanel contentPanel) { tabsMap.put(contentPanel.getNode(), contentPanel); int tabCount = getTabCount(); @@ -402,7 +375,6 @@ public void loadSettings() { public void reset() { closeAllTabs(); tabsMap.clear(); - jumps.reset(); curTab = null; lastTab = null; FocusManager.reset(); From de26dc9a93975806550d41f669fa2877b67c4659 Mon Sep 17 00:00:00 2001 From: Skylot <118523+skylot@users.noreply.github.com> Date: Wed, 14 Aug 2024 20:50:27 +0100 Subject: [PATCH 4/5] log all exceptions from background executor --- .../main/java/jadx/gui/jobs/BackgroundExecutor.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java b/jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java index bf887198c45..0d6fbea8562 100644 --- a/jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java +++ b/jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java @@ -138,9 +138,17 @@ protected TaskStatus doInBackground() throws Exception { task.onDone(this); // treat UI task operations as part of the task to not mix with others UiUtils.uiRunAndWait(() -> { - progressPane.setVisible(false); - task.onFinish(this); + try { + progressPane.setVisible(false); + task.onFinish(this); + } catch (Throwable e) { + LOG.error("Task onFinish failed", e); + status = TaskStatus.ERROR; + } }); + } catch (Throwable e) { + LOG.error("Task onDone failed", e); + status = TaskStatus.ERROR; } finally { taskComplete(id); progressPane.changeVisibility(this, false); From 072d8fed837766a90a081427154a4d94eebb29ed Mon Sep 17 00:00:00 2001 From: Skylot <118523+skylot@users.noreply.github.com> Date: Wed, 14 Aug 2024 20:49:45 +0100 Subject: [PATCH 5/5] various improvements --- .../main/java/jadx/gui/treemodel/JNode.java | 3 +- .../src/main/java/jadx/gui/ui/MainWindow.java | 32 +++---- .../jadx/gui/ui/tab/EditorSyncManager.java | 33 +++++++ .../jadx/gui/ui/tab/ITabStatesListener.java | 41 +++++--- .../java/jadx/gui/ui/tab/LogTabStates.java | 81 ++++++++++++++++ .../jadx/gui/ui/tab/NavigationController.java | 93 +++++-------------- .../java/jadx/gui/ui/tab/QuickTabsTree.java | 43 --------- .../java/jadx/gui/ui/tab/TabBlueprint.java | 29 +++++- .../main/java/jadx/gui/ui/tab/TabbedPane.java | 46 +++++---- .../java/jadx/gui/ui/tab/TabsController.java | 18 ++-- .../main/java/jadx/gui/utils/JumpManager.java | 3 +- 11 files changed, 244 insertions(+), 178 deletions(-) create mode 100644 jadx-gui/src/main/java/jadx/gui/ui/tab/EditorSyncManager.java create mode 100644 jadx-gui/src/main/java/jadx/gui/ui/tab/LogTabStates.java diff --git a/jadx-gui/src/main/java/jadx/gui/treemodel/JNode.java b/jadx-gui/src/main/java/jadx/gui/treemodel/JNode.java index aab77ba4912..88f7b18c984 100644 --- a/jadx-gui/src/main/java/jadx/gui/treemodel/JNode.java +++ b/jadx-gui/src/main/java/jadx/gui/treemodel/JNode.java @@ -40,8 +40,7 @@ public ICodeNodeRef getCodeNodeRef() { return null; } - @Nullable - public ContentPanel getContentPanel(TabbedPane tabbedPane) { + public @Nullable ContentPanel getContentPanel(TabbedPane tabbedPane) { return null; } 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 8d0d4d6934c..bebab60ebc4 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java @@ -139,6 +139,7 @@ import jadx.gui.ui.panel.JDebuggerPanel; import jadx.gui.ui.panel.ProgressPanel; import jadx.gui.ui.popupmenu.RecentProjectsMenuListener; +import jadx.gui.ui.tab.EditorSyncManager; import jadx.gui.ui.tab.NavigationController; import jadx.gui.ui.tab.QuickTabsTree; import jadx.gui.ui.tab.TabbedPane; @@ -196,6 +197,10 @@ public class MainWindow extends JFrame { private final transient CacheManager cacheManager; private final transient BackgroundExecutor backgroundExecutor; + private final TabsController tabsController; + private final NavigationController navController; + private final EditorSyncManager editorSyncManager; + private transient @NotNull JadxProject project; private transient JadxGuiAction newProjectAction; @@ -210,8 +215,6 @@ public class MainWindow extends JFrame { private JTree tree; private DefaultTreeModel treeModel; private JRoot treeRoot; - private TabsController tabsController; - private NavigationController navController; private TabbedPane tabbedPane; private HeapUsageBar heapUsageBar; private transient boolean treeReloading; @@ -240,7 +243,7 @@ public class MainWindow extends JFrame { private boolean loaded; private boolean settingsOpen = false; - private ShortcutsController shortcutsController; + private final ShortcutsController shortcutsController; private JadxMenuBar menuBar; private JMenu pluginsMenu; @@ -255,16 +258,19 @@ public MainWindow(JadxSettings settings) { this.renameMappings = new RenameMappingsGui(this); this.cacheManager = new CacheManager(settings); this.shortcutsController = new ShortcutsController(settings); + this.tabsController = new TabsController(this); + this.navController = new NavigationController(this); JadxEventQueue.register(); resetCache(); FontUtils.registerBundledFonts(); setEditorTheme(settings.getEditorThemePath()); initUI(); + this.editorSyncManager = new EditorSyncManager(this, tabbedPane); this.backgroundExecutor = new BackgroundExecutor(settings, progressPane); initMenuAndToolbar(); UiUtils.setWindowIcons(this); - shortcutsController.registerMouseEventListener(this); + this.shortcutsController.registerMouseEventListener(this); loadSettings(); update(); @@ -564,6 +570,8 @@ private void saveAll() { private void closeAll() { notifyLoadListeners(false); cancelBackgroundJobs(); + navController.reset(); + tabbedPane.reset(); clearTree(); resetCache(); LogCollector.getInstance().reset(); @@ -785,8 +793,6 @@ public void initTree() { } private void clearTree() { - navController.reset(); - tabbedPane.reset(); treeRoot = null; treeModel.setRoot(null); treeModel.reload(); @@ -906,12 +912,8 @@ private JNode getJNodeUnderMouse(MouseEvent mouseEvent) { return null; } - public void syncWithEditor() { - ContentPanel selectedContentPanel = tabbedPane.getSelectedContentPanel(); - if (selectedContentPanel == null) { - return; - } - JNode node = selectedContentPanel.getNode(); + // TODO: extract tree component into new class + public void selectNodeInTree(JNode node) { if (node.getParent() == null && treeRoot != null) { // node not register in tree node = treeRoot.searchNode(node); @@ -1047,7 +1049,7 @@ private void initMenuAndToolbar() { alwaysSelectOpened.addActionListener(event -> { settings.setAlwaysSelectOpened(!settings.isAlwaysSelectOpened()); if (settings.isAlwaysSelectOpened()) { - this.syncWithEditor(); + this.editorSyncManager.sync(); } }); @@ -1066,7 +1068,7 @@ private void initMenuAndToolbar() { setQuickTabsVisibility(true); } - JadxGuiAction syncAction = new JadxGuiAction(ActionModel.SYNC, this::syncWithEditor); + JadxGuiAction syncAction = new JadxGuiAction(ActionModel.SYNC, this.editorSyncManager::sync); JadxGuiAction textSearchAction = new JadxGuiAction(ActionModel.TEXT_SEARCH, this::textSearch); JadxGuiAction clsSearchAction = new JadxGuiAction(ActionModel.CLASS_SEARCH, () -> SearchDialog.search(MainWindow.this, SearchDialog.SearchPreset.CLASS)); @@ -1350,8 +1352,6 @@ public void treeWillCollapse(TreeExpansionEvent event) { leftPane.add(bottomPane, BorderLayout.PAGE_END); treeSplitPane.setLeftComponent(leftPane); - tabsController = new TabsController(this); - navController = new NavigationController(this); tabbedPane = new TabbedPane(this, tabsController); tabbedPane.setMinimumSize(new Dimension(150, 150)); new TabDndController(tabbedPane, settings); diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/EditorSyncManager.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/EditorSyncManager.java new file mode 100644 index 00000000000..1485a8e8d16 --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/EditorSyncManager.java @@ -0,0 +1,33 @@ +package jadx.gui.ui.tab; + +import jadx.gui.ui.MainWindow; +import jadx.gui.ui.panel.ContentPanel; + +public class EditorSyncManager implements ITabStatesListener { + private final MainWindow mainWindow; + private final TabbedPane tabbedPane; + + public EditorSyncManager(MainWindow mainWindow, TabbedPane tabbedPane) { + this.mainWindow = mainWindow; + this.tabbedPane = tabbedPane; + mainWindow.getTabsController().addListener(this); + } + + public void sync() { + ContentPanel selectedContentPanel = tabbedPane.getSelectedContentPanel(); + if (selectedContentPanel != null) { + mainWindow.selectNodeInTree(selectedContentPanel.getNode()); + } + } + + @Override + public void onTabSelect(TabBlueprint blueprint) { + if (mainWindow.getSettings().isAlwaysSelectOpened()) { + // verify that tab opened for this blueprint (some nodes don't open tab with content) + ContentPanel selectedContentPanel = tabbedPane.getSelectedContentPanel(); + if (selectedContentPanel != null && selectedContentPanel.getNode().equals(blueprint.getNode())) { + sync(); + } + } + } +} diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/ITabStatesListener.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/ITabStatesListener.java index 540383c4bcb..b99736b6faa 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/tab/ITabStatesListener.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/ITabStatesListener.java @@ -6,29 +6,44 @@ import jadx.gui.utils.JumpPosition; public interface ITabStatesListener { - void onTabOpen(TabBlueprint blueprint); - void onTabSelect(TabBlueprint blueprint); + default void onTabOpen(TabBlueprint blueprint) { + } - void onTabCodeJump(TabBlueprint blueprint, JumpPosition position); + default void onTabSelect(TabBlueprint blueprint) { + } - void onTabSmaliJump(TabBlueprint blueprint, int pos, boolean debugMode); + default void onTabCodeJump(TabBlueprint blueprint, JumpPosition position) { + } - void onTabClose(TabBlueprint blueprint); + default void onTabSmaliJump(TabBlueprint blueprint, int pos, boolean debugMode) { + } - void onTabPositionFirst(TabBlueprint blueprint); + default void onTabClose(TabBlueprint blueprint) { + } - void onTabPinChange(TabBlueprint blueprint); + default void onTabPositionFirst(TabBlueprint blueprint) { + } - void onTabBookmarkChange(TabBlueprint blueprint); + default void onTabPinChange(TabBlueprint blueprint) { + } - void onTabVisibilityChange(TabBlueprint blueprint); + default void onTabBookmarkChange(TabBlueprint blueprint) { + } - void onTabRestore(TabBlueprint blueprint, EditorViewState viewState); + default void onTabVisibilityChange(TabBlueprint blueprint) { + } - void onTabsRestoreDone(); + default void onTabRestore(TabBlueprint blueprint, EditorViewState viewState) { + } - void onTabsReorder(List blueprints); + default void onTabsRestoreDone() { + } + + default void onTabsReorder(List blueprints) { + } + + default void onTabSave(TabBlueprint blueprint, EditorViewState viewState) { + } - void onTabSave(TabBlueprint blueprint, EditorViewState viewState); } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/LogTabStates.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/LogTabStates.java new file mode 100644 index 00000000000..e47ebbc7495 --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/LogTabStates.java @@ -0,0 +1,81 @@ +package jadx.gui.ui.tab; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import jadx.gui.ui.codearea.EditorViewState; +import jadx.gui.utils.JumpPosition; + +/** + * Utility class to log events from TabsController by implementing ITabStatesListener. + */ +public class LogTabStates implements ITabStatesListener { + private static final Logger LOG = LoggerFactory.getLogger(LogTabStates.class); + + @Override + public void onTabBookmarkChange(TabBlueprint blueprint) { + LOG.debug("onTabBookmarkChange: blueprint={}", blueprint); + } + + @Override + public void onTabClose(TabBlueprint blueprint) { + LOG.debug("onTabClose: blueprint={}", blueprint); + } + + @Override + public void onTabCodeJump(TabBlueprint blueprint, JumpPosition position) { + LOG.debug("onTabCodeJump: blueprint={}, position={}", blueprint, position); + } + + @Override + public void onTabOpen(TabBlueprint blueprint) { + LOG.debug("onTabOpen: blueprint={}", blueprint); + } + + @Override + public void onTabPinChange(TabBlueprint blueprint) { + LOG.debug("onTabPinChange: blueprint={}", blueprint); + } + + @Override + public void onTabPositionFirst(TabBlueprint blueprint) { + LOG.debug("onTabPositionFirst: blueprint={}", blueprint); + } + + @Override + public void onTabRestore(TabBlueprint blueprint, EditorViewState viewState) { + LOG.debug("onTabRestore: blueprint={}, viewState={}", blueprint, viewState); + } + + @Override + public void onTabSave(TabBlueprint blueprint, EditorViewState viewState) { + LOG.debug("onTabSave: blueprint={}, viewState={}", blueprint, viewState); + } + + @Override + public void onTabSelect(TabBlueprint blueprint) { + LOG.debug("onTabSelect: blueprint={}", blueprint); + } + + @Override + public void onTabSmaliJump(TabBlueprint blueprint, int pos, boolean debugMode) { + LOG.debug("onTabSmaliJump: blueprint={}, pos={}, debugMode={}", blueprint, pos, debugMode); + } + + @Override + public void onTabsReorder(List blueprints) { + LOG.debug("onTabsReorder: blueprints={}", blueprints); + } + + @Override + public void onTabsRestoreDone() { + LOG.debug("onTabsRestoreDone"); + } + + @Override + public void onTabVisibilityChange(TabBlueprint blueprint) { + LOG.debug("onTabVisibilityChange: blueprint={}", blueprint); + } +} diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/NavigationController.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/NavigationController.java index bc39ae9118e..e3bc3c52ec4 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/tab/NavigationController.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/NavigationController.java @@ -1,12 +1,14 @@ package jadx.gui.ui.tab; -import java.util.List; +import org.jetbrains.annotations.Nullable; import jadx.gui.ui.MainWindow; -import jadx.gui.ui.codearea.EditorViewState; import jadx.gui.utils.JumpManager; import jadx.gui.utils.JumpPosition; +/** + * TODO: Save jumps history into project file to restore after reload or reopen + */ public class NavigationController implements ITabStatesListener { private final transient MainWindow mainWindow; @@ -14,101 +16,50 @@ public class NavigationController implements ITabStatesListener { public NavigationController(MainWindow mainWindow) { this.mainWindow = mainWindow; - mainWindow.getTabsController().addListener(this); } - public void saveJump(JumpPosition pos) { - JumpPosition curPos = mainWindow.getTabbedPane().getCurrentPosition(); - if (curPos != null) { - jumps.addPosition(curPos); - jumps.addPosition(pos); - } - } - public void navBack() { if (jumps.size() > 1) { jumps.updateCurPosition(mainWindow.getTabbedPane().getCurrentPosition()); } - JumpPosition pos = jumps.getPrev(); - if (pos != null) { - mainWindow.getTabsController().codeJump(pos); - } + jump(jumps.getPrev()); } public void navForward() { if (jumps.size() > 1) { jumps.updateCurPosition(mainWindow.getTabbedPane().getCurrentPosition()); } - JumpPosition pos = jumps.getNext(); + jump(jumps.getNext()); + } + + private void jump(@Nullable JumpPosition pos) { if (pos != null) { mainWindow.getTabsController().codeJump(pos); } } - @Override - public void onTabOpen(TabBlueprint blueprint) { - - } - - @Override - public void onTabSelect(TabBlueprint blueprint) { - - } - @Override public void onTabCodeJump(TabBlueprint blueprint, JumpPosition position) { - + if (position.equals(jumps.getCurrent())) { + // ignore self-initiated jumps + return; + } + saveCurrentPosition(); + jumps.addPosition(position); } @Override public void onTabSmaliJump(TabBlueprint blueprint, int pos, boolean debugMode) { - - } - - @Override - public void onTabClose(TabBlueprint blueprint) { - - } - - @Override - public void onTabPositionFirst(TabBlueprint blueprint) { - + saveCurrentPosition(); + // TODO: save smali jump } - @Override - public void onTabPinChange(TabBlueprint blueprint) { - - } - - @Override - public void onTabBookmarkChange(TabBlueprint blueprint) { - - } - - @Override - public void onTabVisibilityChange(TabBlueprint blueprint) { - - } - - @Override - public void onTabRestore(TabBlueprint blueprint, EditorViewState viewState) { - - } - - @Override - public void onTabsRestoreDone() { - - } - - @Override - public void onTabsReorder(List blueprints) { - - } - - @Override - public void onTabSave(TabBlueprint blueprint, EditorViewState viewState) { - + private void saveCurrentPosition() { + JumpPosition curPos = mainWindow.getTabbedPane().getCurrentPosition(); + if (curPos != null) { + jumps.addPosition(curPos); + } } public void reset() { diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/QuickTabsTree.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/QuickTabsTree.java index bbef6e8e53e..c5da98539e6 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/tab/QuickTabsTree.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/QuickTabsTree.java @@ -6,7 +6,6 @@ import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.util.List; import javax.swing.JPopupMenu; import javax.swing.JTree; @@ -20,8 +19,6 @@ import jadx.gui.treemodel.JNode; import jadx.gui.ui.MainWindow; -import jadx.gui.ui.codearea.EditorViewState; -import jadx.gui.utils.JumpPosition; import jadx.gui.utils.UiUtils; public class QuickTabsTree extends JTree implements ITabStatesListener, TreeSelectionListener { @@ -181,21 +178,6 @@ public void onTabOpen(TabBlueprint blueprint) { } } - @Override - public void onTabSelect(TabBlueprint blueprint) { - - } - - @Override - public void onTabCodeJump(TabBlueprint blueprint, JumpPosition position) { - - } - - @Override - public void onTabSmaliJump(TabBlueprint blueprint, int pos, boolean debugMode) { - - } - @Override public void onTabClose(TabBlueprint blueprint) { removeJNode(openParentNode, blueprint.getNode()); @@ -203,11 +185,6 @@ public void onTabClose(TabBlueprint blueprint) { removeJNode(bookmarkParentNode, blueprint.getNode()); } - @Override - public void onTabPositionFirst(TabBlueprint blueprint) { - - } - @Override public void onTabPinChange(TabBlueprint blueprint) { JNode node = blueprint.getNode(); @@ -238,26 +215,6 @@ public void onTabVisibilityChange(TabBlueprint blueprint) { } } - @Override - public void onTabRestore(TabBlueprint blueprint, EditorViewState viewState) { - - } - - @Override - public void onTabsRestoreDone() { - - } - - @Override - public void onTabsReorder(List blueprints) { - - } - - @Override - public void onTabSave(TabBlueprint blueprint, EditorViewState viewState) { - - } - private class Root extends DefaultMutableTreeNode { } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabBlueprint.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabBlueprint.java index 6059c48bd08..1ccf6d50d50 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabBlueprint.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabBlueprint.java @@ -1,5 +1,7 @@ package jadx.gui.ui.tab; +import java.util.Objects; + import jadx.gui.treemodel.JNode; public class TabBlueprint { @@ -9,7 +11,7 @@ public class TabBlueprint { private boolean hidden; public TabBlueprint(JNode node) { - this.node = node; + this.node = Objects.requireNonNull(node); } public JNode getNode() { @@ -47,4 +49,29 @@ public boolean isHidden() { public void setHidden(boolean hidden) { this.hidden = hidden; } + + @Override + public final boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof TabBlueprint)) { + return false; + } + return node.equals(((TabBlueprint) o).node); + } + + @Override + public int hashCode() { + return node.hashCode(); + } + + @Override + public String toString() { + return "TabBlueprint{node=" + node + + ", bookmarked=" + bookmarked + + ", pinned=" + pinned + + ", hidden=" + hidden + + '}'; + } } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java index d51a1daed4b..5b731828485 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java @@ -8,8 +8,10 @@ import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import javax.swing.JTabbedPane; import javax.swing.SwingUtilities; @@ -206,15 +208,6 @@ public TabsController getTabsController() { return controller; } - private void codeJump(JumpPosition pos) { - saveJump(pos); - showCode(pos); - } - - private void saveJump(JumpPosition pos) { - mainWindow.getNavController().saveJump(pos); - } - private @Nullable ContentPanel showCode(JumpPosition jumpPos) { ContentPanel contentPanel = getContentPanel(jumpPos.getNode()); if (contentPanel != null) { @@ -260,8 +253,7 @@ private void smaliJump(JClass cls, int pos, boolean debugMode) { smaliArea.requestFocus(); } - @Nullable - public JumpPosition getCurrentPosition() { + public @Nullable JumpPosition getCurrentPosition() { ContentPanel selectedCodePanel = getSelectedContentPanel(); if (selectedCodePanel instanceof AbstractCodeContentPanel) { return ((AbstractCodeContentPanel) selectedCodePanel).getCodeArea().getCurrentPosition(); @@ -297,7 +289,15 @@ public List getTabs() { } public @Nullable TabComponent getTabComponentByNode(JNode node) { - Component component = getTabComponentAt(indexOfComponent(getTabByNode(node))); + ContentPanel contentPanel = getTabByNode(node); + if (contentPanel == null) { + return null; + } + int index = indexOfComponent(contentPanel); + if (index == -1) { + return null; + } + Component component = getTabComponentAt(index); if (!(component instanceof TabComponent)) { return null; } @@ -399,22 +399,23 @@ public void onTabOpen(TabBlueprint blueprint) { return; } ContentPanel newPanel = blueprint.getNode().getContentPanel(this); - FocusManager.listen(newPanel); - addContentPanel(newPanel); + if (newPanel != null) { + FocusManager.listen(newPanel); + addContentPanel(newPanel); + } } @Override public void onTabSelect(TabBlueprint blueprint) { ContentPanel contentPanel = getContentPanel(blueprint.getNode()); - setSelectedComponent(contentPanel); - if (mainWindow.getSettings().isAlwaysSelectOpened()) { - mainWindow.syncWithEditor(); + if (contentPanel != null) { + setSelectedComponent(contentPanel); } } @Override public void onTabCodeJump(TabBlueprint blueprint, JumpPosition position) { - codeJump(position); + showCode(position); } @Override @@ -491,22 +492,19 @@ public void onTabRestore(TabBlueprint blueprint, EditorViewState viewState) { } } - @Override - public void onTabsRestoreDone() { - } - @Override public void onTabsReorder(List blueprints) { List newBlueprints = new ArrayList<>(blueprints.size()); for (ContentPanel contentPanel : getTabs()) { TabBlueprint blueprint = controller.getTabByNode(contentPanel.getNode()); if (blueprint != null) { - blueprints.remove(blueprint); newBlueprints.add(blueprint); } } // Add back hidden tabs - newBlueprints.addAll(blueprints); + Set set = new LinkedHashSet<>(blueprints); + newBlueprints.forEach(set::remove); + newBlueprints.addAll(set); blueprints.clear(); blueprints.addAll(newBlueprints); diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabsController.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabsController.java index 76740bc4a27..75313991059 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabsController.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabsController.java @@ -8,7 +8,8 @@ import java.util.stream.Collectors; import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.org.jline.utils.Log; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import jadx.api.JavaClass; import jadx.api.metadata.ICodeAnnotation; @@ -22,13 +23,15 @@ import jadx.gui.utils.NLS; public class TabsController { - private final transient MainWindow mainWindow; + private static final Logger LOG = LoggerFactory.getLogger(TabsController.class); + + private final MainWindow mainWindow; private final Map tabsMap = new HashMap<>(); private final List listeners = new ArrayList<>(); private boolean forceClose; - private TabBlueprint selectedTab = null; + private @Nullable TabBlueprint selectedTab; public TabsController(MainWindow mainWindow) { this.mainWindow = mainWindow; @@ -66,7 +69,6 @@ public TabBlueprint openTab(JNode node, boolean hidden) { } blueprint = newBlueprint; } - setTabHiddenInternal(blueprint, hidden); return blueprint; } @@ -74,7 +76,6 @@ public TabBlueprint openTab(JNode node, boolean hidden) { public void selectTab(JNode node) { TabBlueprint blueprint = openTab(node); selectedTab = blueprint; - listeners.forEach(l -> l.onTabSelect(blueprint)); } @@ -126,7 +127,7 @@ public void codeJump(JNode node) { */ public void codeJump(JumpPosition pos) { if (selectedTab == null) { - Log.warn("Cannot codeJump because selectedTab is null"); + LOG.warn("Cannot codeJump because selectedTab is null"); return; } listeners.forEach(l -> l.onTabCodeJump(selectedTab, pos)); @@ -287,6 +288,11 @@ public void restoreEditorViewState(EditorViewState viewState) { } public void notifyRestoreEditorViewStateDone() { + if (selectedTab == null && !tabsMap.isEmpty()) { + JNode node = tabsMap.values().iterator().next().getNode(); + LOG.warn("No active tab found, select {}", node); // TODO: find the reason of this issue + selectTab(node); + } listeners.forEach(ITabStatesListener::onTabsRestoreDone); } diff --git a/jadx-gui/src/main/java/jadx/gui/utils/JumpManager.java b/jadx-gui/src/main/java/jadx/gui/utils/JumpManager.java index 077b924c03b..fba2c8f29d0 100644 --- a/jadx-gui/src/main/java/jadx/gui/utils/JumpManager.java +++ b/jadx-gui/src/main/java/jadx/gui/utils/JumpManager.java @@ -43,8 +43,7 @@ private boolean ignoreJump(JumpPosition pos) { return pos.equals(current); } - @Nullable - private JumpPosition getCurrent() { + public @Nullable JumpPosition getCurrent() { if (currentPos >= 0 && currentPos < list.size()) { return list.get(currentPos); }