fix(gui): improved preview tab behaviors (PR #2477)

* fix(gui): improved preview tab behaviors

* Update jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java

---------

Co-authored-by: skylot <118523+skylot@users.noreply.github.com>
This commit is contained in:
Yaroslav
2025-05-08 23:53:15 +03:00
committed by GitHub
parent 47647bbb9a
commit fd6cb2451b
7 changed files with 53 additions and 8 deletions
@@ -32,6 +32,7 @@ public class TabStateViewAdapter {
tvs.setPinned(viewState.isPinned());
tvs.setBookmarked(viewState.isBookmarked());
tvs.setHidden(viewState.isHidden());
tvs.setPreviewTab(viewState.isPreviewTab());
return tvs;
}
@@ -47,6 +48,7 @@ public class TabStateViewAdapter {
viewState.setPinned(tvs.isPinned());
viewState.setBookmarked(tvs.isBookmarked());
viewState.setHidden(tvs.isHidden());
viewState.setPreviewTab(tvs.isPreviewTab());
return viewState;
} catch (Exception e) {
LOG.error("Failed to load tab state: " + tvs, e);
@@ -10,6 +10,7 @@ public class TabViewState {
boolean pinned;
boolean bookmarked;
boolean hidden;
boolean previewTab;
public String getType() {
return type;
@@ -82,4 +83,12 @@ public class TabViewState {
public void setHidden(boolean hidden) {
this.hidden = hidden;
}
public boolean isPreviewTab() {
return previewTab;
}
public void setPreviewTab(boolean previewTab) {
this.previewTab = previewTab;
}
}
@@ -115,11 +115,15 @@ import jadx.gui.settings.ui.JadxSettingsWindow;
import jadx.gui.settings.ui.plugins.PluginSettings;
import jadx.gui.tree.TreeExpansionService;
import jadx.gui.treemodel.ApkSignature;
import jadx.gui.treemodel.JInputFiles;
import jadx.gui.treemodel.JInputScripts;
import jadx.gui.treemodel.JInputs;
import jadx.gui.treemodel.JLoadableNode;
import jadx.gui.treemodel.JNode;
import jadx.gui.treemodel.JPackage;
import jadx.gui.treemodel.JResource;
import jadx.gui.treemodel.JRoot;
import jadx.gui.treemodel.JSources;
import jadx.gui.ui.action.ActionModel;
import jadx.gui.ui.action.JadxGuiAction;
import jadx.gui.ui.codearea.AbstractCodeArea;
@@ -882,8 +886,15 @@ public class MainWindow extends JFrame {
return true;
}
} else if (obj instanceof JNode) {
tabsController.codeJump((JNode) obj, true);
return true;
JNode treeNode = (JNode) obj;
if (!(treeNode instanceof JPackage)
&& !(treeNode instanceof JSources)
&& !(treeNode instanceof JInputs)
&& !(treeNode instanceof JInputFiles)
&& !(treeNode instanceof JInputScripts)) {
tabsController.codeJump(treeNode, true);
return true;
}
}
} catch (Exception e) {
LOG.error("Content loading error", e);
@@ -1062,11 +1073,10 @@ public class MainWindow extends JFrame {
flatPkgMenuItem = new JCheckBoxMenuItem(NLS.str("menu.flatten"), Icons.FLAT_PKG);
flatPkgMenuItem.setState(isFlattenPackage);
JCheckBoxMenuItem enablePreviewTabMenuItem = new JCheckBoxMenuItem(NLS.str("menu.enable_preview_tab"));
enablePreviewTabMenuItem.setState(settings.isEnablePreviewTab());
enablePreviewTabMenuItem.addActionListener(event -> {
JadxGuiAction enablePreviewTabAction = new JadxGuiAction(ActionModel.PREVIEW_TAB, () -> {
settings.setEnablePreviewTab(!settings.isEnablePreviewTab());
});
enablePreviewTabAction.setSelected(settings.isEnablePreviewTab());
JCheckBoxMenuItem heapUsageBarMenuItem = new JCheckBoxMenuItem(NLS.str("menu.heapUsageBar"));
heapUsageBarMenuItem.setState(settings.isShowHeapUsageBar());
@@ -1159,7 +1169,7 @@ public class MainWindow extends JFrame {
view.add(quickTabsAction.makeCheckBoxMenuItem());
view.add(flatPkgMenuItem);
view.addSeparator();
view.add(enablePreviewTabMenuItem);
view.add(enablePreviewTabAction.makeCheckBoxMenuItem());
view.add(syncAction);
view.add(alwaysSelectOpened);
view.addSeparator();
@@ -1241,6 +1251,7 @@ public class MainWindow extends JFrame {
toolbar.addSeparator();
toolbar.add(syncAction);
toolbar.add(flatPkgButton);
toolbar.add(enablePreviewTabAction.makeToggleButton());
toolbar.add(quickTabsAction.makeToggleButton());
toolbar.addSeparator();
toolbar.add(textSearchAction);
@@ -57,6 +57,8 @@ public enum ActionModel {
Shortcut.keyboard(KeyEvent.VK_A, UiUtils.ctrlButton() | KeyEvent.SHIFT_DOWN_MASK)),
GO_TO_ANDROID_MANIFEST(MENU_TOOLBAR, "menu.go_to_android_manifest", "menu.go_to_android_manifest", "ui/androidManifest",
Shortcut.none()),
PREVIEW_TAB(MENU_TOOLBAR, "menu.enable_preview_tab", "menu.enable_preview_tab", "ui/editorPreview",
Shortcut.none()),
DECOMPILE_ALL(MENU_TOOLBAR, "menu.decompile_all", "menu.decompile_all", "ui/runAll",
Shortcut.none()),
RESET_CACHE(MENU_TOOLBAR, "menu.reset_cache", "menu.reset_cache", "ui/reset",
@@ -17,6 +17,7 @@ public class EditorViewState {
private boolean pinned;
private boolean bookmarked;
private boolean hidden;
private boolean previewTab;
public EditorViewState(JNode node) {
this(node, "", 0, EditorViewState.ZERO);
@@ -85,6 +86,14 @@ public class EditorViewState {
return hidden;
}
public boolean isPreviewTab() {
return previewTab;
}
public void setPreviewTab(boolean previewTab) {
this.previewTab = previewTab;
}
public void setHidden(boolean hidden) {
this.hidden = hidden;
}
@@ -83,7 +83,7 @@ public class TabsController {
public TabBlueprint previewTab(JNode node) {
TabBlueprint blueprint = getPreviewTab();
if (blueprint != null) {
closeTabForce(blueprint);
closeTab(blueprint.getNode());
}
blueprint = openTab(node, false, true);
@@ -244,6 +244,7 @@ public class TabsController {
public void setTabPinnedInternal(TabBlueprint blueprint, boolean pinned) {
if (blueprint.isPinned() != pinned) {
blueprint.setPreviewTab(false);
blueprint.setPinned(pinned);
listeners.forEach(l -> l.onTabPinChange(blueprint));
}
@@ -256,6 +257,7 @@ public class TabsController {
private void setTabBookmarkedInternal(TabBlueprint blueprint, boolean bookmarked) {
if (blueprint.isBookmarked() != bookmarked) {
blueprint.setPreviewTab(false);
blueprint.setBookmarked(bookmarked);
listeners.forEach(l -> l.onTabBookmarkChange(blueprint));
removeTabIfNotReferenced(blueprint);
@@ -269,6 +271,7 @@ public class TabsController {
private void setTabHiddenInternal(TabBlueprint blueprint, boolean hidden) {
if (blueprint != null && blueprint.isHidden() != hidden) {
blueprint.setPreviewTab(false);
blueprint.setHidden(hidden);
listeners.forEach(l -> l.onTabVisibilityChange(blueprint));
}
@@ -338,7 +341,7 @@ public class TabsController {
public void restoreEditorViewState(EditorViewState viewState) {
JNode node = viewState.getNode();
TabBlueprint blueprint = openTab(node, viewState.isHidden());
TabBlueprint blueprint = openTab(node, viewState.isHidden(), viewState.isPreviewTab());
setTabPinnedInternal(blueprint, viewState.isPinned());
setTabBookmarkedInternal(blueprint, viewState.isBookmarked());
listeners.forEach(l -> l.onTabRestore(blueprint, viewState));
@@ -373,6 +376,7 @@ public class TabsController {
viewState.setPinned(blueprint.isPinned());
viewState.setBookmarked(blueprint.isBookmarked());
viewState.setHidden(blueprint.isHidden());
viewState.setPreviewTab(blueprint.isPreviewTab());
return viewState;
}
}
@@ -0,0 +1,8 @@
<!-- Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="3" width="5" height="1" rx="0.5" fill="#6E6E6E"/>
<rect x="1" y="6" width="5" height="1" rx="0.5" fill="#6E6E6E"/>
<rect x="1" y="9" width="5" height="1" rx="0.5" fill="#6E6E6E"/>
<rect x="1" y="12" width="5" height="1" rx="0.5" fill="#6E6E6E"/>
<path d="M8.5 4C8.5 3.17157 9.17157 2.5 10 2.5H13C13.8284 2.5 14.5 3.17157 14.5 4V12C14.5 12.8284 13.8284 13.5 13 13.5H10C9.17157 13.5 8.5 12.8284 8.5 12V4Z" stroke="#6E6E6E"/>
</svg>

After

Width:  |  Height:  |  Size: 668 B