未验证 提交 4479a3fb 编写于 作者: S Skylot

fix(gui): restore resource tabs on project open

上级 f5216b77
......@@ -69,10 +69,13 @@ public class DecompileTask implements IBackgroundTask {
@Override
public void onFinish(TaskStatus status, long skippedJobs) {
long taskTime = System.currentTimeMillis() - startTime;
long avgPerCls = taskTime / expectedCompleteCount;
LOG.info("Decompile task complete in {} ms (avg {} ms per class), classes: {},"
+ " time limit:{ total: {}ms, per cls: {}ms }, status: {}",
taskTime, avgPerCls, expectedCompleteCount, timeLimit(), CLS_LIMIT, status);
long avgPerCls = taskTime / Math.max(expectedCompleteCount, 1);
if (LOG.isInfoEnabled()) {
LOG.info("Decompile task complete in " + taskTime + " ms (avg " + avgPerCls + " ms per class)"
+ ", classes: " + expectedCompleteCount
+ ", time limit:{ total: " + timeLimit() + "ms, per cls: " + CLS_LIMIT + "ms }"
+ ", status: " + status);
}
IndexService indexService = mainWindow.getCacheObject().getIndexService();
indexService.setComplete(true);
......
......@@ -7,6 +7,8 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -24,9 +26,9 @@ import jadx.api.data.impl.JadxCodeRef;
import jadx.api.data.impl.JadxCodeRename;
import jadx.api.data.impl.JadxNodeRef;
import jadx.core.utils.GsonUtils;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.gui.settings.data.ProjectData;
import jadx.gui.settings.data.TabViewState;
import jadx.gui.ui.MainWindow;
import jadx.gui.ui.codearea.EditorViewState;
import jadx.gui.utils.PathTypeAdapter;
......@@ -127,13 +129,20 @@ public class JadxProject {
}
public void saveOpenTabs(List<EditorViewState> tabs, int activeTab) {
data.setOpenTabs(Utils.collectionMap(tabs, TabStateViewAdapter::build));
List<TabViewState> tabStateList = tabs.stream()
.map(TabStateViewAdapter::build)
.filter(Objects::nonNull)
.collect(Collectors.toList());
data.setOpenTabs(tabStateList);
data.setActiveTab(activeTab);
changed();
}
public List<EditorViewState> getOpenTabs(MainWindow mw) {
return Utils.collectionMap(data.getOpenTabs(), s -> TabStateViewAdapter.load(mw, s));
return data.getOpenTabs().stream()
.map(s -> TabStateViewAdapter.load(mw, s))
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
public int getActiveTab() {
......
package jadx.gui.settings;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.JavaClass;
import jadx.gui.settings.data.TabViewState;
import jadx.gui.settings.data.ViewPoint;
import jadx.gui.treemodel.JClass;
import jadx.gui.treemodel.JNode;
import jadx.gui.treemodel.JResource;
import jadx.gui.ui.MainWindow;
import jadx.gui.ui.codearea.EditorViewState;
public class TabStateViewAdapter {
private static final Logger LOG = LoggerFactory.getLogger(TabStateViewAdapter.class);
@Nullable
public static TabViewState build(EditorViewState viewState) {
TabViewState tvs = new TabViewState();
if (!saveJNode(tvs, viewState.getNode())) {
LOG.debug("Can't save view state: " + viewState);
return null;
}
tvs.setSubPath(viewState.getSubPath());
......@@ -26,20 +31,30 @@ public class TabStateViewAdapter {
@Nullable
public static EditorViewState load(MainWindow mw, TabViewState tvs) {
JNode node = loadJNode(mw, tvs);
if (node == null) {
try {
JNode node = loadJNode(mw, tvs);
if (node == null) {
return null;
}
return new EditorViewState(node, tvs.getSubPath(), tvs.getCaret(), tvs.getView().toPoint());
} catch (Exception e) {
LOG.error("Failed to load tab state: " + tvs, e);
return null;
}
return new EditorViewState(node, tvs.getSubPath(), tvs.getCaret(), tvs.getView().toPoint());
}
@Nullable
private static JNode loadJNode(MainWindow mw, TabViewState tvs) {
if ("class".equals(tvs.getType())) {
JavaClass javaClass = mw.getWrapper().searchJavaClassByRawName(tvs.getTabPath());
if (javaClass != null) {
return mw.getCacheObject().getNodeCache().makeFrom(javaClass);
}
switch (tvs.getType()) {
case "class":
JavaClass javaClass = mw.getWrapper().searchJavaClassByRawName(tvs.getTabPath());
if (javaClass != null) {
return mw.getCacheObject().getNodeCache().makeFrom(javaClass);
}
break;
case "resource":
JResource tmpNode = new JResource(null, tvs.getTabPath(), JResource.JResType.FILE);
return mw.getTreeRoot().searchNode(tmpNode); // equals method in JResource check only name
}
return null;
}
......@@ -50,6 +65,11 @@ public class TabStateViewAdapter {
tvs.setTabPath(((JClass) node).getCls().getRawName());
return true;
}
if (node instanceof JResource) {
tvs.setType("resource");
tvs.setTabPath(node.getName());
return true;
}
return false;
}
}
......@@ -3,7 +3,6 @@ package jadx.gui.treemodel;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Pattern;
......@@ -38,20 +37,16 @@ public class JRoot extends JNode {
removeAllChildren();
add(new JSources(this, wrapper));
List<JResource> resList = getHierarchyResources(wrapper.getResources());
for (JResource jRes : resList) {
jRes.update();
add(jRes);
List<ResourceFile> resources = wrapper.getResources();
if (!resources.isEmpty()) {
add(getHierarchyResources(resources));
}
for (JNode customNode : customNodes) {
add(customNode);
}
}
private List<JResource> getHierarchyResources(List<ResourceFile> resources) {
if (resources.isEmpty()) {
return Collections.emptyList();
}
private JResource getHierarchyResources(List<ResourceFile> resources) {
JResource root = new JResource(null, NLS.str("tree.resources_title"), JResType.ROOT);
String splitPathStr = Pattern.quote(File.separator);
for (ResourceFile rf : resources) {
......@@ -71,14 +66,15 @@ public class JRoot extends JNode {
if (i != count - 1) {
subRF = new JResource(null, name, JResType.DIR);
} else {
subRF = new JResource(rf, name, JResType.FILE);
subRF = new JResource(rf, rf.getOriginalName(), name, JResType.FILE);
}
curRf.getFiles().add(subRF);
}
curRf = subRF;
}
}
return Collections.singletonList(root);
root.update();
return root;
}
private JResource getResourceByName(JResource rf, String name) {
......@@ -90,7 +86,7 @@ public class JRoot extends JNode {
return null;
}
public JNode searchClassInTree(JNode node) {
public JNode searchNode(JNode node) {
Enumeration<?> en = this.breadthFirstEnumeration();
while (en.hasMoreElements()) {
Object obj = en.nextElement();
......
......@@ -124,7 +124,6 @@ import jadx.gui.update.data.Release;
import jadx.gui.utils.CacheObject;
import jadx.gui.utils.CodeUsageInfo;
import jadx.gui.utils.FontUtils;
import jadx.gui.utils.JNodeCache;
import jadx.gui.utils.JumpPosition;
import jadx.gui.utils.LafManager;
import jadx.gui.utils.Link;
......@@ -446,7 +445,7 @@ public class MainWindow extends JFrame {
deobfToggleBtn.setSelected(settings.isDeobfuscationOn());
initTree();
update();
restoreOpenTabs(project.getOpenTabs(this), project.getActiveTab());
restoreOpenTabs();
runInitialBackgroundJobs();
BreakpointManager.init(paths.get(0).getParent());
}
......@@ -567,27 +566,11 @@ public class MainWindow extends JFrame {
public void reOpenFile() {
List<Path> openedFile = wrapper.getOpenPaths();
if (openedFile != null) {
int activeTab = tabbedPane.getSelectedIndex();
List<EditorViewState> viewStates = tabbedPane.getEditorViewStates();
open(openedFile, () -> restoreOpenTabs(viewStates, activeTab));
saveOpenTabs();
open(openedFile);
}
}
private void restoreOpenTabs(List<EditorViewState> openTabs, int activeTab) {
if (openTabs.isEmpty()) {
return;
}
JNodeCache nodeCache = getCacheObject().getNodeCache();
for (EditorViewState viewState : openTabs) {
JNode node = nodeCache.renew(wrapper, viewState.getNode());
if (node != null) {
viewState.setNode(node);
tabbedPane.restoreEditorViewState(viewState);
}
}
tabbedPane.setSelectedIndex(activeTab);
}
private void saveAll(boolean export) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
......@@ -755,7 +738,7 @@ public class MainWindow extends JFrame {
JNode node = selectedContentPanel.getNode();
if (node.getParent() == null && treeRoot != null) {
// node not register in tree
node = treeRoot.searchClassInTree(node);
node = treeRoot.searchNode(node);
if (node == null) {
LOG.error("Class not found in tree");
return;
......@@ -1328,6 +1311,17 @@ public class MainWindow extends JFrame {
project.saveOpenTabs(tabbedPane.getEditorViewStates(), tabbedPane.getSelectedIndex());
}
private void restoreOpenTabs() {
List<EditorViewState> openTabs = project.getOpenTabs(this);
if (openTabs.isEmpty()) {
return;
}
for (EditorViewState viewState : openTabs) {
tabbedPane.restoreEditorViewState(viewState);
}
tabbedPane.setSelectedIndex(project.getActiveTab());
}
private void saveSplittersInfo() {
settings.setMainWindowVerticalSplitterLoc(verticalSplitter.getDividerLocation());
settings.setDebuggerStackFrameSplitterLoc(debuggerPanel.getLeftSplitterLocation());
......
......@@ -31,6 +31,7 @@ import jadx.gui.ui.codearea.EditorViewState;
import jadx.gui.ui.codearea.SmaliArea;
import jadx.gui.ui.panel.ContentPanel;
import jadx.gui.ui.panel.HtmlPanel;
import jadx.gui.ui.panel.IViewStateSupport;
import jadx.gui.ui.panel.ImagePanel;
import jadx.gui.utils.JumpManager;
import jadx.gui.utils.JumpPosition;
......@@ -263,9 +264,10 @@ public class TabbedPane extends JTabbedPane {
public List<EditorViewState> getEditorViewStates() {
List<EditorViewState> states = new ArrayList<>();
for (ContentPanel panel : openTabs.values()) {
EditorViewState viewState = panel.getEditorViewState();
if (viewState != null) {
states.add(viewState);
if (panel instanceof IViewStateSupport) {
states.add(((IViewStateSupport) panel).getEditorViewState());
} else {
states.add(new EditorViewState(panel.getNode(), "", 0, EditorViewState.ZERO));
}
}
return states;
......@@ -273,8 +275,8 @@ public class TabbedPane extends JTabbedPane {
public void restoreEditorViewState(EditorViewState viewState) {
ContentPanel contentPanel = getContentPanel(viewState.getNode());
if (contentPanel != null) {
contentPanel.restoreEditorViewState(viewState);
if (contentPanel instanceof IViewStateSupport) {
((IViewStateSupport) contentPanel).restoreEditorViewState(viewState);
}
}
......
......@@ -8,6 +8,7 @@ import javax.swing.border.EmptyBorder;
import jadx.gui.treemodel.JNode;
import jadx.gui.ui.TabbedPane;
import jadx.gui.ui.panel.IViewStateSupport;
import jadx.gui.utils.NLS;
/**
......@@ -18,7 +19,7 @@ import jadx.gui.utils.NLS;
* <li>Smali source code of the selected class</li>
* </ul>
*/
public final class ClassCodeContentPanel extends AbstractCodeContentPanel {
public final class ClassCodeContentPanel extends AbstractCodeContentPanel implements IViewStateSupport {
private static final long serialVersionUID = -7229931102504634591L;
private final transient CodePanel javaCodePanel;
......
package jadx.gui.ui.codearea;
import java.awt.BorderLayout;
import java.awt.Point;
import jadx.gui.treemodel.JNode;
import jadx.gui.ui.TabbedPane;
import jadx.gui.ui.panel.IViewStateSupport;
public final class CodeContentPanel extends AbstractCodeContentPanel {
public final class CodeContentPanel extends AbstractCodeContentPanel implements IViewStateSupport {
private static final long serialVersionUID = 5310536092010045565L;
private final CodePanel codePanel;
......@@ -47,4 +49,17 @@ public final class CodeContentPanel extends AbstractCodeContentPanel {
}
return '/' + s;
}
@Override
public EditorViewState getEditorViewState() {
int caretPos = codePanel.getCodeArea().getCaretPosition();
Point viewPoint = codePanel.getCodeScrollPane().getViewport().getViewPosition();
return new EditorViewState(getNode(), "", caretPos, viewPoint);
}
@Override
public void restoreEditorViewState(EditorViewState viewState) {
codePanel.getCodeScrollPane().getViewport().setViewPosition(viewState.getViewPoint());
codePanel.getCodeArea().setCaretPosition(viewState.getCaretPos());
}
}
......@@ -5,10 +5,12 @@ import java.awt.Point;
import jadx.gui.treemodel.JNode;
public class EditorViewState {
private JNode node;
private int caretPos;
private Point viewPoint;
private String subPath;
public static final Point ZERO = new Point(0, 0);
private final JNode node;
private final int caretPos;
private final Point viewPoint;
private final String subPath;
public EditorViewState(JNode node, String subPath, int caretPos, Point viewPoint) {
this.node = node;
......@@ -21,34 +23,18 @@ public class EditorViewState {
return node;
}
public void setNode(JNode node) {
this.node = node;
}
public int getCaretPos() {
return caretPos;
}
public void setCaretPos(int caretPos) {
this.caretPos = caretPos;
}
public Point getViewPoint() {
return viewPoint;
}
public void setViewPoint(Point viewPoint) {
this.viewPoint = viewPoint;
}
public String getSubPath() {
return subPath;
}
public void setSubPath(String subPath) {
this.subPath = subPath;
}
@Override
public String toString() {
return "EditorViewState{node=" + node
......
......@@ -7,7 +7,6 @@ import org.jetbrains.annotations.Nullable;
import jadx.gui.treemodel.JClass;
import jadx.gui.treemodel.JNode;
import jadx.gui.ui.TabbedPane;
import jadx.gui.ui.codearea.EditorViewState;
public abstract class ContentPanel extends JPanel {
......@@ -23,14 +22,6 @@ public abstract class ContentPanel extends JPanel {
public abstract void loadSettings();
public EditorViewState getEditorViewState() {
return null;
}
public void restoreEditorViewState(EditorViewState viewState) {
}
public TabbedPane getTabbedPane() {
return tabbedPane;
}
......
package jadx.gui.ui.panel;
import jadx.gui.ui.codearea.EditorViewState;
public interface IViewStateSupport {
EditorViewState getEditorViewState();
void restoreEditorViewState(EditorViewState viewState);
}
......@@ -3,15 +3,12 @@ package jadx.gui.utils;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jetbrains.annotations.Nullable;
import jadx.api.JavaClass;
import jadx.api.JavaField;
import jadx.api.JavaMethod;
import jadx.api.JavaNode;
import jadx.api.JavaVariable;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.gui.JadxWrapper;
import jadx.gui.treemodel.JClass;
import jadx.gui.treemodel.JField;
import jadx.gui.treemodel.JMethod;
......@@ -42,15 +39,6 @@ public class JNodeCache {
jn -> new JClass(javaCls, makeFrom(javaCls.getDeclaringClass())));
}
@Nullable
public JNode renew(JadxWrapper wrapper, JNode node) {
if (node instanceof JClass) {
String rawName = ((JClass) node).getCls().getRawName();
return makeFrom(wrapper.searchJavaClassByRawName(rawName));
}
return null;
}
private JNode convert(JavaNode node) {
if (node == null) {
return null;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册