From f8039733cc313af71e6a9a6c90b8ad1e2e1dcbaa Mon Sep 17 00:00:00 2001 From: Ahmed Ashour Date: Sat, 20 Apr 2019 20:02:00 +0300 Subject: [PATCH] feat(gui): save tree expansions in project (PR #605) --- .../src/main/java/jadx/api/JavaClass.java | 2 +- .../java/jadx/gui/settings/JadxProject.java | 22 ++++++ .../src/main/java/jadx/gui/ui/MainWindow.java | 70 ++++++++++++++++++- .../java/jadx/gui/utils/PathTypeAdapter.java | 2 +- 4 files changed, 92 insertions(+), 4 deletions(-) diff --git a/jadx-core/src/main/java/jadx/api/JavaClass.java b/jadx-core/src/main/java/jadx/api/JavaClass.java index e25b5a52..25034545 100644 --- a/jadx-core/src/main/java/jadx/api/JavaClass.java +++ b/jadx-core/src/main/java/jadx/api/JavaClass.java @@ -68,7 +68,7 @@ public final class JavaClass implements JavaNode { cls.unload(); } - ClassNode getClassNode() { + public ClassNode getClassNode() { return cls; } diff --git a/jadx-gui/src/main/java/jadx/gui/settings/JadxProject.java b/jadx-gui/src/main/java/jadx/gui/settings/JadxProject.java index f1508b49..004d5d45 100644 --- a/jadx-gui/src/main/java/jadx/gui/settings/JadxProject.java +++ b/jadx-gui/src/main/java/jadx/gui/settings/JadxProject.java @@ -3,7 +3,9 @@ package jadx.gui.settings; import java.io.BufferedWriter; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Iterator; import java.util.List; import org.slf4j.Logger; @@ -29,6 +31,8 @@ public class JadxProject { private transient String name = "New Project"; private transient Path projectPath; private List filesPath; + private List treeExpansions = new ArrayList<>(); + private transient boolean saved; private transient boolean initial = true; @@ -63,6 +67,24 @@ public class JadxProject { } } + public List getTreeExpansions() { + return treeExpansions; + } + + public void addTreeExpansion(String[] expansion) { + treeExpansions.add(expansion); + changed(); + } + + public void removeTreeExpansion(String[] expansion) { + for (Iterator it = treeExpansions.iterator(); it.hasNext(); ) { + if (Arrays.equals(it.next(), expansion)) { + it.remove(); + } + } + changed(); + } + private void changed() { if (settings.isAutoSaveProject()) { save(); 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 c34f542b..6d7c922e 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java @@ -23,7 +23,9 @@ import java.io.FileInputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.Locale; import java.util.Timer; import java.util.TimerTask; @@ -130,6 +132,7 @@ public class MainWindow extends JFrame { private JRoot treeRoot; private TabbedPane tabbedPane; private HeapUsageBar heapUsageBar; + private transient boolean treeReloading; private boolean isFlattenPackage; private JToggleButton flatPkgButton; @@ -431,8 +434,34 @@ public class MainWindow extends JFrame { } private void reloadTree() { + treeReloading = true; + treeModel.reload(); - tree.expandRow(1); + List treeExpansions = project.getTreeExpansions(); + if (!treeExpansions.isEmpty()) { + expand(treeRoot, treeExpansions); + } else { + tree.expandRow(1); + } + + treeReloading = false; + } + + private void expand(TreeNode node, List treeExpansions) { + TreeNode[] pathNodes = treeModel.getPathToRoot(node); + if (pathNodes == null) { + return; + } + TreePath path = new TreePath(pathNodes); + for (String[] expansion : treeExpansions) { + if (Arrays.equals(expansion, getPathExpansion(path))) { + tree.expandPath(path); + break; + } + } + for (int i = node.getChildCount() - 1; i >= 0; i--) { + expand(node.getChildAt(i), treeExpansions); + } } private void toggleFlattenPackage() { @@ -824,11 +853,18 @@ public class MainWindow extends JFrame { if (node instanceof JLoadableNode) { ((JLoadableNode) node).loadNode(); } + if (!treeReloading) { + project.addTreeExpansion(getPathExpansion(event.getPath())); + update(); + } } @Override public void treeWillCollapse(TreeExpansionEvent event) { - // ignore + if (!treeReloading) { + project.removeTreeExpansion(getPathExpansion(event.getPath())); + update(); + } } }); @@ -851,6 +887,36 @@ public class MainWindow extends JFrame { setTitle(DEFAULT_TITLE); } + private static String[] getPathExpansion(TreePath path) { + List pathList = new ArrayList<>(); + while (path != null) { + Object node = path.getLastPathComponent(); + String name; + if (node instanceof JClass) { + name = ((JClass) node).getCls().getClassNode().getClassInfo().getFullName(); + } + else { + name = node.toString(); + } + pathList.add(name); + path = path.getParentPath(); + } + return pathList.toArray(new String[pathList.size()]); + } + + public static void getExpandedPaths(JTree tree, TreePath path, List list) { + if (tree.isExpanded(path)) { + list.add(path); + + TreeNode node = (TreeNode) path.getLastPathComponent(); + for (int i = node.getChildCount() - 1; i >= 0; i--) { + TreeNode n = node.getChildAt(i); + TreePath child = path.pathByAddingChild(n); + getExpandedPaths(tree, child, list); + } + } + } + public void setLocationAndPosition() { if (this.settings.loadWindowPos(this)) { return; diff --git a/jadx-gui/src/main/java/jadx/gui/utils/PathTypeAdapter.java b/jadx-gui/src/main/java/jadx/gui/utils/PathTypeAdapter.java index d36b67e3..12778357 100644 --- a/jadx-gui/src/main/java/jadx/gui/utils/PathTypeAdapter.java +++ b/jadx-gui/src/main/java/jadx/gui/utils/PathTypeAdapter.java @@ -9,7 +9,7 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; -public class PathTypeAdapter { +public class PathTypeAdapter { private static TypeAdapter SINGLETON; -- GitLab