提交 5f8f454b 编写于 作者: S Skylot

gui: show resources

上级 3700ecb7
...@@ -4,6 +4,7 @@ import jadx.api.IJadxArgs; ...@@ -4,6 +4,7 @@ import jadx.api.IJadxArgs;
import jadx.api.JadxDecompiler; import jadx.api.JadxDecompiler;
import jadx.api.JavaClass; import jadx.api.JavaClass;
import jadx.api.JavaPackage; import jadx.api.JavaPackage;
import jadx.api.ResourceFile;
import jadx.core.utils.exceptions.DecodeException; import jadx.core.utils.exceptions.DecodeException;
import jadx.core.utils.exceptions.JadxException; import jadx.core.utils.exceptions.JadxException;
...@@ -42,7 +43,6 @@ public class JadxWrapper { ...@@ -42,7 +43,6 @@ public class JadxWrapper {
public void run() { public void run() {
try { try {
decompiler.setOutputDir(dir); decompiler.setOutputDir(dir);
decompiler.parseAndSaveXML();
ThreadPoolExecutor ex = (ThreadPoolExecutor) decompiler.getSaveExecutor(); ThreadPoolExecutor ex = (ThreadPoolExecutor) decompiler.getSaveExecutor();
ex.shutdown(); ex.shutdown();
while (ex.isTerminating()) { while (ex.isTerminating()) {
...@@ -69,6 +69,10 @@ public class JadxWrapper { ...@@ -69,6 +69,10 @@ public class JadxWrapper {
return decompiler.getPackages(); return decompiler.getPackages();
} }
public List<ResourceFile> getResources() {
return decompiler.getResources();
}
public File getOpenFile() { public File getOpenFile() {
return openFile; return openFile;
} }
......
...@@ -10,6 +10,8 @@ import jadx.gui.utils.Utils; ...@@ -10,6 +10,8 @@ import jadx.gui.utils.Utils;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
public class JClass extends JNode { public class JClass extends JNode {
private static final long serialVersionUID = -1239986875244097177L; private static final long serialVersionUID = -1239986875244097177L;
...@@ -68,10 +70,15 @@ public class JClass extends JNode { ...@@ -68,10 +70,15 @@ public class JClass extends JNode {
} }
} }
public String getCode() { public String getContent() {
return cls.getCode(); return cls.getCode();
} }
@Override
public String getSyntaxName() {
return SyntaxConstants.SYNTAX_STYLE_JAVA;
}
@Override @Override
public Icon getIcon() { public Icon getIcon() {
AccessInfo accessInfo = cls.getAccessInfo(); AccessInfo accessInfo = cls.getAccessInfo();
...@@ -118,6 +125,11 @@ public class JClass extends JNode { ...@@ -118,6 +125,11 @@ public class JClass extends JNode {
return cls.getDecompiledLine(); return cls.getDecompiledLine();
} }
@Override
public Integer getSourceLine(int line) {
return cls.getSourceLine(line);
}
@Override @Override
public int hashCode() { public int hashCode() {
return cls.hashCode(); return cls.hashCode();
......
...@@ -9,6 +9,8 @@ import jadx.core.utils.exceptions.JadxRuntimeException; ...@@ -9,6 +9,8 @@ import jadx.core.utils.exceptions.JadxRuntimeException;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultMutableTreeNode;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
public abstract class JNode extends DefaultMutableTreeNode { public abstract class JNode extends DefaultMutableTreeNode {
public static JNode makeFrom(JavaNode node) { public static JNode makeFrom(JavaNode node) {
if (node instanceof JavaClass) { if (node instanceof JavaClass) {
...@@ -38,7 +40,21 @@ public abstract class JNode extends DefaultMutableTreeNode { ...@@ -38,7 +40,21 @@ public abstract class JNode extends DefaultMutableTreeNode {
return null; return null;
} }
public abstract int getLine(); public String getContent() {
return null;
}
public String getSyntaxName() {
return SyntaxConstants.SYNTAX_STYLE_NONE;
}
public int getLine() {
return 0;
}
public Integer getSourceLine(int line) {
return null;
}
public abstract Icon getIcon(); public abstract Icon getIcon();
......
package jadx.gui.treemodel;
import jadx.api.ResourceFile;
import jadx.api.ResourceType;
import jadx.core.codegen.CodeWriter;
import jadx.gui.utils.OverlayIcon;
import jadx.gui.utils.Utils;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
public class JResource extends JNode implements Comparable<JResource> {
private static final long serialVersionUID = -201018424302612434L;
private static final ImageIcon ROOT_ICON = Utils.openIcon("cf_obj");
private static final ImageIcon FOLDER_ICON = Utils.openIcon("folder");
private static final ImageIcon FILE_ICON = Utils.openIcon("file_obj");
private static final ImageIcon MANIFEST_ICON = Utils.openIcon("template_obj");
private static final ImageIcon JAVA_ICON = Utils.openIcon("java_ovr");
private static final ImageIcon ERROR_ICON = Utils.openIcon("error_co");
public static enum JResType {
ROOT,
DIR,
FILE
}
private final String name;
private final List<JResource> files = new ArrayList<JResource>(1);
private final JResType type;
private final ResourceFile resFile;
private boolean loaded;
private String content;
private Map<Integer, Integer> lineMapping;
public JResource(ResourceFile resFile, String name, JResType type) {
this.resFile = resFile;
this.name = name;
this.type = type;
}
public final void update() {
removeAllChildren();
for (JResource res : files) {
res.update();
add(res);
}
}
public String getName() {
return name;
}
public List<JResource> getFiles() {
return files;
}
public String getContent() {
if (!loaded && resFile != null && type == JResType.FILE) {
loaded = true;
if (isSupportedForView(resFile.getType())) {
CodeWriter cw = resFile.getContent();
if (cw != null) {
lineMapping = cw.getLineMapping();
content = cw.toString();
}
}
}
return content;
}
@Override
public Integer getSourceLine(int line) {
if (lineMapping == null) {
return null;
}
return lineMapping.get(line);
}
@Override
public String getSyntaxName() {
switch (resFile.getType()) {
case CODE:
return super.getSyntaxName();
case MANIFEST:
case XML:
return SyntaxConstants.SYNTAX_STYLE_XML;
}
String syntax = getSyntaxByExtension(resFile.getName());
if (syntax != null) {
return syntax;
}
return super.getSyntaxName();
}
private String getSyntaxByExtension(String name) {
int dot = name.lastIndexOf('.');
if (dot == -1) {
return null;
}
String ext = name.substring(dot + 1);
if (ext.equals("js")) {
return SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT;
}
if (ext.equals("css")) {
return SyntaxConstants.SYNTAX_STYLE_CSS;
}
if (ext.equals("html")) {
return SyntaxConstants.SYNTAX_STYLE_HTML;
}
return null;
}
@Override
public Icon getIcon() {
switch (type) {
case ROOT:
return ROOT_ICON;
case DIR:
return FOLDER_ICON;
case FILE:
ResourceType resType = resFile.getType();
if (resType == ResourceType.MANIFEST) {
return MANIFEST_ICON;
}
if (resType == ResourceType.CODE) {
return new OverlayIcon(FILE_ICON, ERROR_ICON, JAVA_ICON);
}
if (!isSupportedForView(resType)) {
return new OverlayIcon(FILE_ICON, ERROR_ICON);
}
return FILE_ICON;
}
return FILE_ICON;
}
private boolean isSupportedForView(ResourceType type) {
switch (type) {
case CODE:
case XML:
case ARSC:
case FONT:
case IMG:
case LIB:
return false;
case MANIFEST:
case UNKNOWN:
return true;
}
return true;
}
@Override
public JClass getJParent() {
return null;
}
@Override
public int compareTo(JResource o) {
return name.compareTo(o.name);
}
@Override
public String makeString() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
return name.equals(((JResource) o).name);
}
@Override
public int hashCode() {
return name.hashCode();
}
}
package jadx.gui.treemodel; package jadx.gui.treemodel;
import jadx.api.JavaPackage; import jadx.api.ResourceFile;
import jadx.gui.JadxWrapper; import jadx.gui.JadxWrapper;
import jadx.gui.treemodel.JResource.JResType;
import jadx.gui.utils.Utils; import jadx.gui.utils.Utils;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.regex.Pattern;
import java.util.Set;
public class JRoot extends JNode { public class JRoot extends JNode {
private static final long serialVersionUID = 8888495789773527342L; private static final long serialVersionUID = 8888495789773527342L;
...@@ -33,102 +29,53 @@ public class JRoot extends JNode { ...@@ -33,102 +29,53 @@ public class JRoot extends JNode {
public final void update() { public final void update() {
removeAllChildren(); removeAllChildren();
if (flatPackages) { add(new JSources(this, wrapper));
for (JavaPackage pkg : wrapper.getPackages()) {
add(new JPackage(pkg)); List<JResource> resList = getHierarchyResources(wrapper.getResources());
} for (JResource jRes : resList) {
} else { jRes.update();
// build packages hierarchy add(jRes);
List<JPackage> rootPkgs = getHierarchyPackages(wrapper.getPackages());
for (JPackage jPackage : rootPkgs) {
jPackage.update();
add(jPackage);
}
} }
} }
/** private List<JResource> getHierarchyResources(List<ResourceFile> resources) {
* Convert packages list to hierarchical packages representation if (resources.isEmpty()) {
* return Collections.emptyList();
* @param packages input packages list
* @return root packages
*/
List<JPackage> getHierarchyPackages(List<JavaPackage> packages) {
Map<String, JPackage> pkgMap = new HashMap<String, JPackage>();
for (JavaPackage pkg : packages) {
addPackage(pkgMap, new JPackage(pkg));
} }
// merge packages without classes JResource root = new JResource(null, "Resources", JResType.ROOT);
boolean repeat; String splitPathStr = Pattern.quote(File.separator);
do { for (ResourceFile rf : resources) {
repeat = false; String[] parts = new File(rf.getName()).getPath().split(splitPathStr);
for (JPackage pkg : pkgMap.values()) { JResource curRf = root;
if (pkg.getInnerPackages().size() == 1 && pkg.getClasses().isEmpty()) { int count = parts.length;
JPackage innerPkg = pkg.getInnerPackages().get(0); for (int i = 0; i < count; i++) {
pkg.getInnerPackages().clear(); String name = parts[i];
pkg.getInnerPackages().addAll(innerPkg.getInnerPackages()); JResource subRF = getResourceByName(curRf, name);
pkg.getClasses().addAll(innerPkg.getClasses()); if (subRF == null) {
pkg.setName(pkg.getName() + "." + innerPkg.getName()); subRF = new JResource(rf, name, i != count - 1 ? JResType.DIR : JResType.FILE);
curRf.getFiles().add(subRF);
innerPkg.getInnerPackages().clear();
innerPkg.getClasses().clear();
repeat = true;
break;
} }
} curRf = subRF;
} while (repeat);
// remove empty packages
for (Iterator<Map.Entry<String, JPackage>> it = pkgMap.entrySet().iterator(); it.hasNext(); ) {
JPackage pkg = it.next().getValue();
if (pkg.getInnerPackages().isEmpty() && pkg.getClasses().isEmpty()) {
it.remove();
} }
} }
// use identity set for collect inner packages return Collections.singletonList(root);
Set<JPackage> innerPackages = Collections.newSetFromMap(new IdentityHashMap<JPackage, Boolean>());
for (JPackage pkg : pkgMap.values()) {
innerPackages.addAll(pkg.getInnerPackages());
}
// find root packages
List<JPackage> rootPkgs = new ArrayList<JPackage>();
for (JPackage pkg : pkgMap.values()) {
if (!innerPackages.contains(pkg)) {
rootPkgs.add(pkg);
}
}
Collections.sort(rootPkgs);
return rootPkgs;
} }
private void addPackage(Map<String, JPackage> pkgs, JPackage pkg) { private JResource getResourceByName(JResource rf, String name) {
String pkgName = pkg.getName(); for (JResource sub : rf.getFiles()) {
JPackage replaced = pkgs.put(pkgName, pkg); if (sub.getName().equals(name)) {
if (replaced != null) { return sub;
pkg.getInnerPackages().addAll(replaced.getInnerPackages());
pkg.getClasses().addAll(replaced.getClasses());
}
int dot = pkgName.lastIndexOf('.');
if (dot > 0) {
String prevPart = pkgName.substring(0, dot);
String shortName = pkgName.substring(dot + 1);
pkg.setName(shortName);
JPackage prevPkg = pkgs.get(prevPart);
if (prevPkg == null) {
prevPkg = new JPackage(prevPart);
addPackage(pkgs, prevPkg);
} }
prevPkg.getInnerPackages().add(pkg);
} }
return null;
} }
public JClass searchClassInTree(JClass node) { public JNode searchClassInTree(JNode node) {
Enumeration en = this.breadthFirstEnumeration(); Enumeration en = this.breadthFirstEnumeration();
while (en.hasMoreElements()) { while (en.hasMoreElements()) {
Object obj = en.nextElement(); Object obj = en.nextElement();
if (node.equals(obj)) { if (node.equals(obj)) {
return (JClass) obj; return (JNode) obj;
} }
} }
return null; return null;
......
package jadx.gui.treemodel;
import jadx.api.JavaPackage;
import jadx.gui.JadxWrapper;
import jadx.gui.utils.Utils;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class JSources extends JNode {
private static final long serialVersionUID = 8962924556824862801L;
private static final ImageIcon ROOT_ICON = Utils.openIcon("packagefolder_obj");
private final JadxWrapper wrapper;
private final boolean flatPackages;
public JSources(JRoot jRoot, JadxWrapper wrapper) {
this.flatPackages = jRoot.isFlatPackages();
this.wrapper = wrapper;
update();
}
public final void update() {
removeAllChildren();
if (flatPackages) {
for (JavaPackage pkg : wrapper.getPackages()) {
add(new JPackage(pkg));
}
} else {
// build packages hierarchy
List<JPackage> rootPkgs = getHierarchyPackages(wrapper.getPackages());
for (JPackage jPackage : rootPkgs) {
jPackage.update();
add(jPackage);
}
}
}
/**
* Convert packages list to hierarchical packages representation
*
* @param packages input packages list
* @return root packages
*/
List<JPackage> getHierarchyPackages(List<JavaPackage> packages) {
Map<String, JPackage> pkgMap = new HashMap<String, JPackage>();
for (JavaPackage pkg : packages) {
addPackage(pkgMap, new JPackage(pkg));
}
// merge packages without classes
boolean repeat;
do {
repeat = false;
for (JPackage pkg : pkgMap.values()) {
if (pkg.getInnerPackages().size() == 1 && pkg.getClasses().isEmpty()) {
JPackage innerPkg = pkg.getInnerPackages().get(0);
pkg.getInnerPackages().clear();
pkg.getInnerPackages().addAll(innerPkg.getInnerPackages());
pkg.getClasses().addAll(innerPkg.getClasses());
pkg.setName(pkg.getName() + "." + innerPkg.getName());
innerPkg.getInnerPackages().clear();
innerPkg.getClasses().clear();
repeat = true;
break;
}
}
} while (repeat);
// remove empty packages
for (Iterator<Map.Entry<String, JPackage>> it = pkgMap.entrySet().iterator(); it.hasNext(); ) {
JPackage pkg = it.next().getValue();
if (pkg.getInnerPackages().isEmpty() && pkg.getClasses().isEmpty()) {
it.remove();
}
}
// use identity set for collect inner packages
Set<JPackage> innerPackages = Collections.newSetFromMap(new IdentityHashMap<JPackage, Boolean>());
for (JPackage pkg : pkgMap.values()) {
innerPackages.addAll(pkg.getInnerPackages());
}
// find root packages
List<JPackage> rootPkgs = new ArrayList<JPackage>();
for (JPackage pkg : pkgMap.values()) {
if (!innerPackages.contains(pkg)) {
rootPkgs.add(pkg);
}
}
Collections.sort(rootPkgs);
return rootPkgs;
}
private void addPackage(Map<String, JPackage> pkgs, JPackage pkg) {
String pkgName = pkg.getName();
JPackage replaced = pkgs.put(pkgName, pkg);
if (replaced != null) {
pkg.getInnerPackages().addAll(replaced.getInnerPackages());
pkg.getClasses().addAll(replaced.getClasses());
}
int dot = pkgName.lastIndexOf('.');
if (dot > 0) {
String prevPart = pkgName.substring(0, dot);
String shortName = pkgName.substring(dot + 1);
pkg.setName(shortName);
JPackage prevPkg = pkgs.get(prevPart);
if (prevPkg == null) {
prevPkg = new JPackage(prevPart);
addPackage(pkgs, prevPkg);
}
prevPkg.getInnerPackages().add(pkg);
}
}
@Override
public Icon getIcon() {
return ROOT_ICON;
}
@Override
public JClass getJParent() {
return null;
}
@Override
public String makeString() {
return "Source code";
}
}
...@@ -2,6 +2,7 @@ package jadx.gui.ui; ...@@ -2,6 +2,7 @@ package jadx.gui.ui;
import jadx.api.CodePosition; import jadx.api.CodePosition;
import jadx.gui.treemodel.JClass; import jadx.gui.treemodel.JClass;
import jadx.gui.treemodel.JNode;
import jadx.gui.utils.Position; import jadx.gui.utils.Position;
import javax.swing.JViewport; import javax.swing.JViewport;
...@@ -18,31 +19,26 @@ import java.awt.Rectangle; ...@@ -18,31 +19,26 @@ import java.awt.Rectangle;
import org.fife.ui.rsyntaxtextarea.LinkGenerator; import org.fife.ui.rsyntaxtextarea.LinkGenerator;
import org.fife.ui.rsyntaxtextarea.LinkGeneratorResult; import org.fife.ui.rsyntaxtextarea.LinkGeneratorResult;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rsyntaxtextarea.SyntaxScheme; import org.fife.ui.rsyntaxtextarea.SyntaxScheme;
import org.fife.ui.rsyntaxtextarea.Token; import org.fife.ui.rsyntaxtextarea.Token;
import org.fife.ui.rsyntaxtextarea.TokenTypes; import org.fife.ui.rsyntaxtextarea.TokenTypes;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
class CodeArea extends RSyntaxTextArea { class ContentArea extends RSyntaxTextArea {
private static final Logger LOG = LoggerFactory.getLogger(CodeArea.class); private static final Logger LOG = LoggerFactory.getLogger(ContentArea.class);
private static final long serialVersionUID = 6312736869579635796L; private static final long serialVersionUID = 6312736869579635796L;
public static final Color BACKGROUND = new Color(0xFAFAFA); public static final Color BACKGROUND = new Color(0xFAFAFA);
public static final Color JUMP_TOKEN_FGD = new Color(0x491BA1); public static final Color JUMP_TOKEN_FGD = new Color(0x491BA1);
private final CodePanel codePanel; private final ContentPanel contentPanel;
private final JClass cls; private final JNode node;
CodeArea(CodePanel panel) { ContentArea(ContentPanel panel) {
this.codePanel = panel; this.contentPanel = panel;
this.cls = panel.getCls(); this.node = panel.getNode();
setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
SyntaxScheme scheme = getSyntaxScheme();
scheme.getStyle(Token.FUNCTION).foreground = Color.BLACK;
setMarkOccurrences(true); setMarkOccurrences(true);
setBackground(BACKGROUND); setBackground(BACKGROUND);
...@@ -54,12 +50,19 @@ class CodeArea extends RSyntaxTextArea { ...@@ -54,12 +50,19 @@ class CodeArea extends RSyntaxTextArea {
} }
caret.setVisible(true); caret.setVisible(true);
setHyperlinksEnabled(true); setSyntaxEditingStyle(node.getSyntaxName());
CodeLinkGenerator codeLinkProcessor = new CodeLinkGenerator(cls);
setLinkGenerator(codeLinkProcessor); if (node instanceof JClass) {
addHyperlinkListener(codeLinkProcessor); SyntaxScheme scheme = getSyntaxScheme();
scheme.getStyle(Token.FUNCTION).foreground = Color.BLACK;
setText(cls.getCode()); setHyperlinksEnabled(true);
CodeLinkGenerator codeLinkProcessor = new CodeLinkGenerator((JClass) node);
setLinkGenerator(codeLinkProcessor);
addHyperlinkListener(codeLinkProcessor);
}
setText(node.getContent());
} }
private boolean isJumpToken(Token token) { private boolean isJumpToken(Token token) {
...@@ -71,9 +74,11 @@ class CodeArea extends RSyntaxTextArea { ...@@ -71,9 +74,11 @@ class CodeArea extends RSyntaxTextArea {
return false; return false;
} }
} }
Position pos = getPosition(cls, this, token.getOffset()); if (node instanceof JClass) {
if (pos != null) { Position pos = getPosition((JClass) node, this, token.getOffset());
return true; if (pos != null) {
return true;
}
} }
} }
return false; return false;
...@@ -102,11 +107,11 @@ class CodeArea extends RSyntaxTextArea { ...@@ -102,11 +107,11 @@ class CodeArea extends RSyntaxTextArea {
} }
Position getCurrentPosition() { Position getCurrentPosition() {
return new Position(cls, getCaretLineNumber() + 1); return new Position(node, getCaretLineNumber() + 1);
} }
Integer getSourceLine(int line) { Integer getSourceLine(int line) {
return cls.getCls().getSourceLine(line); return node.getSourceLine(line);
} }
void scrollToLine(int line) { void scrollToLine(int line) {
...@@ -172,7 +177,7 @@ class CodeArea extends RSyntaxTextArea { ...@@ -172,7 +177,7 @@ class CodeArea extends RSyntaxTextArea {
@Override @Override
public HyperlinkEvent execute() { public HyperlinkEvent execute() {
return new HyperlinkEvent(defPos, HyperlinkEvent.EventType.ACTIVATED, null, return new HyperlinkEvent(defPos, HyperlinkEvent.EventType.ACTIVATED, null,
defPos.getCls().getFullName()); defPos.getNode().makeLongString());
} }
@Override @Override
...@@ -192,7 +197,7 @@ class CodeArea extends RSyntaxTextArea { ...@@ -192,7 +197,7 @@ class CodeArea extends RSyntaxTextArea {
if (obj instanceof Position) { if (obj instanceof Position) {
Position pos = (Position) obj; Position pos = (Position) obj;
LOG.debug("Code jump to: {}", pos); LOG.debug("Code jump to: {}", pos);
TabbedPane tabbedPane = codePanel.getTabbedPane(); TabbedPane tabbedPane = contentPanel.getTabbedPane();
tabbedPane.getJumpManager().addPosition(getCurrentPosition()); tabbedPane.getJumpManager().addPosition(getCurrentPosition());
tabbedPane.getJumpManager().addPosition(pos); tabbedPane.getJumpManager().addPosition(pos);
tabbedPane.showCode(pos); tabbedPane.showCode(pos);
......
package jadx.gui.ui; package jadx.gui.ui;
import jadx.gui.treemodel.JClass; import jadx.gui.treemodel.JNode;
import jadx.gui.utils.Utils; import jadx.gui.utils.Utils;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
...@@ -12,31 +12,31 @@ import java.awt.event.ActionEvent; ...@@ -12,31 +12,31 @@ import java.awt.event.ActionEvent;
import java.awt.event.InputEvent; import java.awt.event.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
class CodePanel extends JPanel { class ContentPanel extends JPanel {
private static final long serialVersionUID = 5310536092010045565L; private static final long serialVersionUID = 5310536092010045565L;
private final TabbedPane tabbedPane; private final TabbedPane tabbedPane;
private final JClass jClass; private final JNode node;
private final SearchBar searchBar; private final SearchBar searchBar;
private final CodeArea codeArea; private final ContentArea contentArea;
private final JScrollPane scrollPane; private final JScrollPane scrollPane;
CodePanel(TabbedPane panel, JClass cls) { ContentPanel(TabbedPane panel, JNode node) {
tabbedPane = panel; tabbedPane = panel;
jClass = cls; this.node = node;
codeArea = new CodeArea(this); contentArea = new ContentArea(this);
searchBar = new SearchBar(codeArea); searchBar = new SearchBar(contentArea);
scrollPane = new JScrollPane(codeArea); scrollPane = new JScrollPane(contentArea);
scrollPane.setRowHeaderView(new LineNumbers(codeArea)); scrollPane.setRowHeaderView(new LineNumbers(contentArea));
setLayout(new BorderLayout()); setLayout(new BorderLayout());
add(searchBar, BorderLayout.NORTH); add(searchBar, BorderLayout.NORTH);
add(scrollPane); add(scrollPane);
KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_MASK); KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_MASK);
Utils.addKeyBinding(codeArea, key, "SearchAction", new SearchAction()); Utils.addKeyBinding(contentArea, key, "SearchAction", new SearchAction());
} }
private class SearchAction extends AbstractAction { private class SearchAction extends AbstractAction {
...@@ -52,16 +52,16 @@ class CodePanel extends JPanel { ...@@ -52,16 +52,16 @@ class CodePanel extends JPanel {
return tabbedPane; return tabbedPane;
} }
JClass getCls() { JNode getNode() {
return jClass; return node;
} }
SearchBar getSearchBar() { SearchBar getSearchBar() {
return searchBar; return searchBar;
} }
CodeArea getCodeArea() { ContentArea getContentArea() {
return codeArea; return contentArea;
} }
JScrollPane getScrollPane() { JScrollPane getScrollPane() {
......
...@@ -32,18 +32,18 @@ public class LineNumbers extends JPanel implements CaretListener { ...@@ -32,18 +32,18 @@ public class LineNumbers extends JPanel implements CaretListener {
private static final int HEIGHT = Integer.MAX_VALUE - 1000000; private static final int HEIGHT = Integer.MAX_VALUE - 1000000;
private static final Color FOREGROUND = Color.GRAY; private static final Color FOREGROUND = Color.GRAY;
private static final Color BACKGROUND = CodeArea.BACKGROUND; private static final Color BACKGROUND = ContentArea.BACKGROUND;
private static final Color CURRENT_LINE_FOREGROUND = new Color(227, 0, 0); private static final Color CURRENT_LINE_FOREGROUND = new Color(227, 0, 0);
private CodeArea codeArea; private ContentArea contentArea;
private boolean useSourceLines = true; private boolean useSourceLines = true;
private int lastDigits; private int lastDigits;
private int lastLine; private int lastLine;
private Map<String, FontMetrics> fonts; private Map<String, FontMetrics> fonts;
public LineNumbers(CodeArea component) { public LineNumbers(ContentArea component) {
this.codeArea = component; this.contentArea = component;
setFont(component.getFont()); setFont(component.getFont());
setBackground(BACKGROUND); setBackground(BACKGROUND);
setForeground(FOREGROUND); setForeground(FOREGROUND);
...@@ -70,7 +70,7 @@ public class LineNumbers extends JPanel implements CaretListener { ...@@ -70,7 +70,7 @@ public class LineNumbers extends JPanel implements CaretListener {
} }
private void setPreferredWidth() { private void setPreferredWidth() {
Element root = codeArea.getDocument().getDefaultRootElement(); Element root = contentArea.getDocument().getDefaultRootElement();
int lines = root.getElementCount(); int lines = root.getElementCount();
int digits = Math.max(String.valueOf(lines).length(), 3); int digits = Math.max(String.valueOf(lines).length(), 3);
if (lastDigits != digits) { if (lastDigits != digits) {
...@@ -92,12 +92,12 @@ public class LineNumbers extends JPanel implements CaretListener { ...@@ -92,12 +92,12 @@ public class LineNumbers extends JPanel implements CaretListener {
@Override @Override
public void paintComponent(Graphics g) { public void paintComponent(Graphics g) {
super.paintComponent(g); super.paintComponent(g);
FontMetrics fontMetrics = codeArea.getFontMetrics(codeArea.getFont()); FontMetrics fontMetrics = contentArea.getFontMetrics(contentArea.getFont());
Insets insets = getInsets(); Insets insets = getInsets();
int availableWidth = getSize().width - insets.left - insets.right; int availableWidth = getSize().width - insets.left - insets.right;
Rectangle clip = g.getClipBounds(); Rectangle clip = g.getClipBounds();
int rowStartOffset = codeArea.viewToModel(new Point(0, clip.y)); int rowStartOffset = contentArea.viewToModel(new Point(0, clip.y));
int endOffset = codeArea.viewToModel(new Point(0, clip.y + clip.height)); int endOffset = contentArea.viewToModel(new Point(0, clip.y + clip.height));
while (rowStartOffset <= endOffset) { while (rowStartOffset <= endOffset) {
try { try {
...@@ -111,7 +111,7 @@ public class LineNumbers extends JPanel implements CaretListener { ...@@ -111,7 +111,7 @@ public class LineNumbers extends JPanel implements CaretListener {
int x = availableWidth - stringWidth + insets.left; int x = availableWidth - stringWidth + insets.left;
int y = getOffsetY(rowStartOffset, fontMetrics); int y = getOffsetY(rowStartOffset, fontMetrics);
g.drawString(lineNumber, x, y); g.drawString(lineNumber, x, y);
rowStartOffset = Utilities.getRowEnd(codeArea, rowStartOffset) + 1; rowStartOffset = Utilities.getRowEnd(contentArea, rowStartOffset) + 1;
} catch (Exception e) { } catch (Exception e) {
break; break;
} }
...@@ -119,19 +119,19 @@ public class LineNumbers extends JPanel implements CaretListener { ...@@ -119,19 +119,19 @@ public class LineNumbers extends JPanel implements CaretListener {
} }
private boolean isCurrentLine(int rowStartOffset) { private boolean isCurrentLine(int rowStartOffset) {
int caretPosition = codeArea.getCaretPosition(); int caretPosition = contentArea.getCaretPosition();
Element root = codeArea.getDocument().getDefaultRootElement(); Element root = contentArea.getDocument().getDefaultRootElement();
return root.getElementIndex(rowStartOffset) == root.getElementIndex(caretPosition); return root.getElementIndex(rowStartOffset) == root.getElementIndex(caretPosition);
} }
protected String getTextLineNumber(int rowStartOffset) { protected String getTextLineNumber(int rowStartOffset) {
Element root = codeArea.getDocument().getDefaultRootElement(); Element root = contentArea.getDocument().getDefaultRootElement();
int index = root.getElementIndex(rowStartOffset); int index = root.getElementIndex(rowStartOffset);
Element line = root.getElement(index); Element line = root.getElement(index);
if (line.getStartOffset() == rowStartOffset) { if (line.getStartOffset() == rowStartOffset) {
int lineNumber = index + 1; int lineNumber = index + 1;
if (useSourceLines) { if (useSourceLines) {
Integer sourceLine = codeArea.getSourceLine(lineNumber); Integer sourceLine = contentArea.getSourceLine(lineNumber);
if (sourceLine != null) { if (sourceLine != null) {
return String.valueOf(sourceLine); return String.valueOf(sourceLine);
} }
...@@ -143,7 +143,7 @@ public class LineNumbers extends JPanel implements CaretListener { ...@@ -143,7 +143,7 @@ public class LineNumbers extends JPanel implements CaretListener {
} }
private int getOffsetY(int rowStartOffset, FontMetrics fontMetrics) throws BadLocationException { private int getOffsetY(int rowStartOffset, FontMetrics fontMetrics) throws BadLocationException {
Rectangle r = codeArea.modelToView(rowStartOffset); Rectangle r = contentArea.modelToView(rowStartOffset);
if (r == null) { if (r == null) {
throw new BadLocationException("Can't get Y offset", rowStartOffset); throw new BadLocationException("Can't get Y offset", rowStartOffset);
} }
...@@ -156,7 +156,7 @@ public class LineNumbers extends JPanel implements CaretListener { ...@@ -156,7 +156,7 @@ public class LineNumbers extends JPanel implements CaretListener {
if (fonts == null) { if (fonts == null) {
fonts = new HashMap<String, FontMetrics>(); fonts = new HashMap<String, FontMetrics>();
} }
Element root = codeArea.getDocument().getDefaultRootElement(); Element root = contentArea.getDocument().getDefaultRootElement();
int index = root.getElementIndex(rowStartOffset); int index = root.getElementIndex(rowStartOffset);
Element line = root.getElement(index); Element line = root.getElement(index);
for (int i = 0; i < line.getElementCount(); i++) { for (int i = 0; i < line.getElementCount(); i++) {
...@@ -168,7 +168,7 @@ public class LineNumbers extends JPanel implements CaretListener { ...@@ -168,7 +168,7 @@ public class LineNumbers extends JPanel implements CaretListener {
FontMetrics fm = fonts.get(key); FontMetrics fm = fonts.get(key);
if (fm == null) { if (fm == null) {
Font font = new Font(fontFamily, Font.PLAIN, fontSize); Font font = new Font(fontFamily, Font.PLAIN, fontSize);
fm = codeArea.getFontMetrics(font); fm = contentArea.getFontMetrics(font);
fonts.put(key, fm); fonts.put(key, fm);
} }
descent = Math.max(descent, fm.getDescent()); descent = Math.max(descent, fm.getDescent());
...@@ -179,8 +179,8 @@ public class LineNumbers extends JPanel implements CaretListener { ...@@ -179,8 +179,8 @@ public class LineNumbers extends JPanel implements CaretListener {
@Override @Override
public void caretUpdate(CaretEvent e) { public void caretUpdate(CaretEvent e) {
int caretPosition = codeArea.getCaretPosition(); int caretPosition = contentArea.getCaretPosition();
Element root = codeArea.getDocument().getDefaultRootElement(); Element root = contentArea.getDocument().getDefaultRootElement();
int currentLine = root.getElementIndex(caretPosition); int currentLine = root.getElementIndex(caretPosition);
if (lastLine != currentLine) { if (lastLine != currentLine) {
repaint(); repaint();
......
...@@ -3,6 +3,7 @@ package jadx.gui.ui; ...@@ -3,6 +3,7 @@ package jadx.gui.ui;
import jadx.gui.JadxWrapper; import jadx.gui.JadxWrapper;
import jadx.gui.treemodel.JClass; import jadx.gui.treemodel.JClass;
import jadx.gui.treemodel.JNode; import jadx.gui.treemodel.JNode;
import jadx.gui.treemodel.JResource;
import jadx.gui.treemodel.JRoot; import jadx.gui.treemodel.JRoot;
import jadx.gui.update.JadxUpdate; import jadx.gui.update.JadxUpdate;
import jadx.gui.update.JadxUpdate.IUpdateCallback; import jadx.gui.update.JadxUpdate.IUpdateCallback;
...@@ -159,8 +160,12 @@ public class MainWindow extends JFrame { ...@@ -159,8 +160,12 @@ public class MainWindow extends JFrame {
treeRoot = new JRoot(wrapper); treeRoot = new JRoot(wrapper);
treeRoot.setFlatPackages(isFlattenPackage); treeRoot.setFlatPackages(isFlattenPackage);
treeModel.setRoot(treeRoot); treeModel.setRoot(treeRoot);
reloadTree();
}
private void reloadTree() {
treeModel.reload(); treeModel.reload();
tree.expandRow(0); tree.expandRow(1);
} }
private void toggleFlattenPackage() { private void toggleFlattenPackage() {
...@@ -178,37 +183,46 @@ public class MainWindow extends JFrame { ...@@ -178,37 +183,46 @@ public class MainWindow extends JFrame {
if (root instanceof JRoot) { if (root instanceof JRoot) {
JRoot treeRoot = (JRoot) root; JRoot treeRoot = (JRoot) root;
treeRoot.setFlatPackages(isFlattenPackage); treeRoot.setFlatPackages(isFlattenPackage);
treeModel.reload(); reloadTree();
tree.expandRow(0);
} }
} }
private void treeClickAction() { private void treeClickAction() {
Object obj = tree.getLastSelectedPathComponent(); try {
if (obj instanceof JNode) { Object obj = tree.getLastSelectedPathComponent();
JNode node = (JNode) obj; if (obj instanceof JResource) {
JClass cls = node.getRootClass(); JResource res = (JResource) obj;
if (cls != null) { if (res.getContent() != null) {
tabbedPane.showCode(new Position(cls, node.getLine())); tabbedPane.showCode(new Position(res, res.getLine()));
}
}
if (obj instanceof JNode) {
JNode node = (JNode) obj;
JClass cls = node.getRootClass();
if (cls != null) {
tabbedPane.showCode(new Position(cls, node.getLine()));
}
} }
} catch (Exception e) {
LOG.error("Content loading error", e);
} }
} }
private void syncWithEditor() { private void syncWithEditor() {
CodePanel selectedCodePanel = tabbedPane.getSelectedCodePanel(); ContentPanel selectedContentPanel = tabbedPane.getSelectedCodePanel();
if (selectedCodePanel == null) { if (selectedContentPanel == null) {
return; return;
} }
JClass jCls = selectedCodePanel.getCls(); JNode node = selectedContentPanel.getNode();
if (jCls.getParent() == null && treeRoot != null) { if (node.getParent() == null && treeRoot != null) {
// node not register in tree // node not register in tree
jCls = treeRoot.searchClassInTree(jCls); node = treeRoot.searchClassInTree(node);
if (jCls == null) { if (node == null) {
LOG.error("Class not found in tree"); LOG.error("Class not found in tree");
return; return;
} }
} }
TreeNode[] pathNodes = treeModel.getPathToRoot(jCls); TreeNode[] pathNodes = treeModel.getPathToRoot(node);
if (pathNodes == null) { if (pathNodes == null) {
return; return;
} }
...@@ -218,9 +232,9 @@ public class MainWindow extends JFrame { ...@@ -218,9 +232,9 @@ public class MainWindow extends JFrame {
} }
private void toggleFind() { private void toggleFind() {
CodePanel codePanel = tabbedPane.getSelectedCodePanel(); ContentPanel contentPanel = tabbedPane.getSelectedCodePanel();
if (codePanel != null) { if (contentPanel != null) {
codePanel.getSearchBar().toggle(); contentPanel.getSearchBar().toggle();
} }
} }
...@@ -432,8 +446,8 @@ public class MainWindow extends JFrame { ...@@ -432,8 +446,8 @@ public class MainWindow extends JFrame {
tree.setCellRenderer(new DefaultTreeCellRenderer() { tree.setCellRenderer(new DefaultTreeCellRenderer() {
@Override @Override
public Component getTreeCellRendererComponent(JTree tree, public Component getTreeCellRendererComponent(JTree tree,
Object value, boolean selected, boolean expanded, Object value, boolean selected, boolean expanded,
boolean isLeaf, int row, boolean focused) { boolean isLeaf, int row, boolean focused) {
Component c = super.getTreeCellRendererComponent(tree, value, selected, expanded, isLeaf, row, focused); Component c = super.getTreeCellRendererComponent(tree, value, selected, expanded, isLeaf, row, focused);
if (value instanceof JNode) { if (value instanceof JNode) {
setIcon(((JNode) value).getIcon()); setIcon(((JNode) value).getIcon());
......
package jadx.gui.ui; package jadx.gui.ui;
import jadx.gui.treemodel.JClass; import jadx.gui.treemodel.JNode;
import jadx.gui.utils.JumpManager; import jadx.gui.utils.JumpManager;
import jadx.gui.utils.NLS; import jadx.gui.utils.NLS;
import jadx.gui.utils.Position; import jadx.gui.utils.Position;
...@@ -37,7 +37,7 @@ class TabbedPane extends JTabbedPane { ...@@ -37,7 +37,7 @@ class TabbedPane extends JTabbedPane {
private static final ImageIcon ICON_CLOSE_INACTIVE = Utils.openIcon("cross_grayed"); private static final ImageIcon ICON_CLOSE_INACTIVE = Utils.openIcon("cross_grayed");
private final MainWindow mainWindow; private final MainWindow mainWindow;
private final Map<JClass, CodePanel> openTabs = new LinkedHashMap<JClass, CodePanel>(); private final Map<JNode, ContentPanel> openTabs = new LinkedHashMap<JNode, ContentPanel>();
private JumpManager jumps = new JumpManager(); private JumpManager jumps = new JumpManager();
TabbedPane(MainWindow window) { TabbedPane(MainWindow window) {
...@@ -66,14 +66,14 @@ class TabbedPane extends JTabbedPane { ...@@ -66,14 +66,14 @@ class TabbedPane extends JTabbedPane {
} }
void showCode(final Position pos) { void showCode(final Position pos) {
final CodePanel codePanel = getCodePanel(pos.getCls()); final ContentPanel contentPanel = getCodePanel(pos.getNode());
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override @Override
public void run() { public void run() {
setSelectedComponent(codePanel); setSelectedComponent(contentPanel);
CodeArea codeArea = codePanel.getCodeArea(); ContentArea contentArea = contentPanel.getContentArea();
codeArea.scrollToLine(pos.getLine()); contentArea.scrollToLine(pos.getLine());
codeArea.requestFocus(); contentArea.requestFocus();
} }
}); });
} }
...@@ -96,40 +96,40 @@ class TabbedPane extends JTabbedPane { ...@@ -96,40 +96,40 @@ class TabbedPane extends JTabbedPane {
return jumps; return jumps;
} }
private void addCodePanel(CodePanel codePanel) { private void addCodePanel(ContentPanel contentPanel) {
openTabs.put(codePanel.getCls(), codePanel); openTabs.put(contentPanel.getNode(), contentPanel);
add(codePanel); add(contentPanel);
} }
private void closeCodePanel(CodePanel codePanel) { private void closeCodePanel(ContentPanel contentPanel) {
openTabs.remove(codePanel.getCls()); openTabs.remove(contentPanel.getNode());
remove(codePanel); remove(contentPanel);
} }
private CodePanel getCodePanel(JClass cls) { private ContentPanel getCodePanel(JNode cls) {
CodePanel panel = openTabs.get(cls); ContentPanel panel = openTabs.get(cls);
if (panel == null) { if (panel == null) {
panel = new CodePanel(this, cls); panel = new ContentPanel(this, cls);
addCodePanel(panel); addCodePanel(panel);
setTabComponentAt(indexOfComponent(panel), makeTabComponent(panel)); setTabComponentAt(indexOfComponent(panel), makeTabComponent(panel));
} }
return panel; return panel;
} }
CodePanel getSelectedCodePanel() { ContentPanel getSelectedCodePanel() {
return (CodePanel) getSelectedComponent(); return (ContentPanel) getSelectedComponent();
} }
private Component makeTabComponent(final CodePanel codePanel) { private Component makeTabComponent(final ContentPanel contentPanel) {
JClass cls = codePanel.getCls(); JNode node = contentPanel.getNode();
String name = cls.getCls().getFullName(); String name = node.makeLongString();
final JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 3, 0)); final JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 3, 0));
panel.setOpaque(false); panel.setOpaque(false);
final JLabel label = new JLabel(name); final JLabel label = new JLabel(name);
label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10)); label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
label.setIcon(cls.getIcon()); label.setIcon(node.getIcon());
final JButton button = new JButton(); final JButton button = new JButton();
button.setIcon(ICON_CLOSE_INACTIVE); button.setIcon(ICON_CLOSE_INACTIVE);
...@@ -144,7 +144,7 @@ class TabbedPane extends JTabbedPane { ...@@ -144,7 +144,7 @@ class TabbedPane extends JTabbedPane {
button.addActionListener(new ActionListener() { button.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
closeCodePanel(codePanel); closeCodePanel(contentPanel);
} }
}); });
...@@ -152,13 +152,13 @@ class TabbedPane extends JTabbedPane { ...@@ -152,13 +152,13 @@ class TabbedPane extends JTabbedPane {
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isMiddleMouseButton(e)) { if (SwingUtilities.isMiddleMouseButton(e)) {
closeCodePanel(codePanel); closeCodePanel(contentPanel);
} else if (SwingUtilities.isRightMouseButton(e)) { } else if (SwingUtilities.isRightMouseButton(e)) {
JPopupMenu menu = createTabPopupMenu(codePanel); JPopupMenu menu = createTabPopupMenu(contentPanel);
menu.show(panel, e.getX(), e.getY()); menu.show(panel, e.getX(), e.getY());
} else { } else {
// TODO: make correct event delegation to tabbed pane // TODO: make correct event delegation to tabbed pane
setSelectedComponent(codePanel); setSelectedComponent(contentPanel);
} }
} }
}); });
...@@ -169,14 +169,14 @@ class TabbedPane extends JTabbedPane { ...@@ -169,14 +169,14 @@ class TabbedPane extends JTabbedPane {
return panel; return panel;
} }
private JPopupMenu createTabPopupMenu(final CodePanel codePanel) { private JPopupMenu createTabPopupMenu(final ContentPanel contentPanel) {
JPopupMenu menu = new JPopupMenu(); JPopupMenu menu = new JPopupMenu();
JMenuItem closeTab = new JMenuItem(NLS.str("tabs.close")); JMenuItem closeTab = new JMenuItem(NLS.str("tabs.close"));
closeTab.addActionListener(new ActionListener() { closeTab.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
closeCodePanel(codePanel); closeCodePanel(contentPanel);
} }
}); });
menu.add(closeTab); menu.add(closeTab);
...@@ -186,9 +186,9 @@ class TabbedPane extends JTabbedPane { ...@@ -186,9 +186,9 @@ class TabbedPane extends JTabbedPane {
closeOther.addActionListener(new ActionListener() { closeOther.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
List<CodePanel> codePanels = new ArrayList<CodePanel>(openTabs.values()); List<ContentPanel> contentPanels = new ArrayList<ContentPanel>(openTabs.values());
for (CodePanel panel : codePanels) { for (ContentPanel panel : contentPanels) {
if (panel != codePanel) { if (panel != contentPanel) {
closeCodePanel(panel); closeCodePanel(panel);
} }
} }
...@@ -200,8 +200,8 @@ class TabbedPane extends JTabbedPane { ...@@ -200,8 +200,8 @@ class TabbedPane extends JTabbedPane {
closeAll.addActionListener(new ActionListener() { closeAll.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
List<CodePanel> codePanels = new ArrayList<CodePanel>(openTabs.values()); List<ContentPanel> contentPanels = new ArrayList<ContentPanel>(openTabs.values());
for (CodePanel panel : codePanels) { for (ContentPanel panel : contentPanels) {
closeCodePanel(panel); closeCodePanel(panel);
} }
} }
...@@ -209,14 +209,14 @@ class TabbedPane extends JTabbedPane { ...@@ -209,14 +209,14 @@ class TabbedPane extends JTabbedPane {
menu.add(closeAll); menu.add(closeAll);
menu.addSeparator(); menu.addSeparator();
CodePanel selectedCodePanel = getSelectedCodePanel(); ContentPanel selectedContentPanel = getSelectedCodePanel();
for (final Map.Entry<JClass, CodePanel> entry : openTabs.entrySet()) { for (final Map.Entry<JNode, ContentPanel> entry : openTabs.entrySet()) {
final CodePanel cp = entry.getValue(); final ContentPanel cp = entry.getValue();
if (cp == selectedCodePanel) { if (cp == selectedContentPanel) {
continue; continue;
} }
JClass jClass = entry.getKey(); JNode node = entry.getKey();
final String clsName = jClass.getCls().getFullName(); final String clsName = node.makeLongString();
JMenuItem item = new JMenuItem(clsName); JMenuItem item = new JMenuItem(clsName);
item.addActionListener(new ActionListener() { item.addActionListener(new ActionListener() {
@Override @Override
...@@ -224,7 +224,7 @@ class TabbedPane extends JTabbedPane { ...@@ -224,7 +224,7 @@ class TabbedPane extends JTabbedPane {
setSelectedComponent(cp); setSelectedComponent(cp);
} }
}); });
item.setIcon(jClass.getIcon()); item.setIcon(node.getIcon());
menu.add(item); menu.add(item);
} }
} }
......
...@@ -18,6 +18,8 @@ import org.slf4j.LoggerFactory; ...@@ -18,6 +18,8 @@ import org.slf4j.LoggerFactory;
import static java.awt.Desktop.Action; import static java.awt.Desktop.Action;
public class Link extends JLabel implements MouseListener { public class Link extends JLabel implements MouseListener {
private static final long serialVersionUID = 3655322136444908178L;
private static final Logger LOG = LoggerFactory.getLogger(JLabel.class); private static final Logger LOG = LoggerFactory.getLogger(JLabel.class);
private String url; private String url;
......
...@@ -4,6 +4,7 @@ import javax.swing.Icon; ...@@ -4,6 +4,7 @@ import javax.swing.Icon;
import java.awt.Component; import java.awt.Component;
import java.awt.Graphics; import java.awt.Graphics;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
public class OverlayIcon implements Icon { public class OverlayIcon implements Icon {
...@@ -19,6 +20,11 @@ public class OverlayIcon implements Icon { ...@@ -19,6 +20,11 @@ public class OverlayIcon implements Icon {
this.icon = icon; this.icon = icon;
} }
public OverlayIcon(Icon icon, Icon... ovrIcons) {
this.icon = icon;
Collections.addAll(icons, ovrIcons);
}
@Override @Override
public int getIconHeight() { public int getIconHeight() {
return icon.getIconHeight(); return icon.getIconHeight();
......
...@@ -2,23 +2,24 @@ package jadx.gui.utils; ...@@ -2,23 +2,24 @@ package jadx.gui.utils;
import jadx.api.CodePosition; import jadx.api.CodePosition;
import jadx.gui.treemodel.JClass; import jadx.gui.treemodel.JClass;
import jadx.gui.treemodel.JNode;
public class Position { public class Position {
private final JClass cls; private final JNode node;
private final int line; private final int line;
public Position(CodePosition pos) { public Position(CodePosition pos) {
this.cls = new JClass(pos.getJavaClass()); this.node = new JClass(pos.getJavaClass());
this.line = pos.getLine(); this.line = pos.getLine();
} }
public Position(JClass cls, int line) { public Position(JNode node, int line) {
this.cls = cls; this.node = node;
this.line = line; this.line = line;
} }
public JClass getCls() { public JNode getNode() {
return cls; return node;
} }
public int getLine() { public int getLine() {
...@@ -34,16 +35,16 @@ public class Position { ...@@ -34,16 +35,16 @@ public class Position {
return false; return false;
} }
Position position = (Position) obj; Position position = (Position) obj;
return line == position.line && cls.equals(position.cls); return line == position.line && node.equals(position.node);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return 31 * cls.hashCode() + line; return 31 * node.hashCode() + line;
} }
@Override @Override
public String toString() { public String toString() {
return "Position: " + cls + " : " + line; return "Position: " + node + " : " + line;
} }
} }
...@@ -16,15 +16,19 @@ import org.junit.Test; ...@@ -16,15 +16,19 @@ import org.junit.Test;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class JRootTest { public class JSourcesTest {
private JRoot root; private JSources sources;
private JadxDecompiler decompiler; private JadxDecompiler decompiler;
@Before @Before
public void init() { public void init() {
root = new JRoot(mock(JadxWrapper.class)); JRoot root = mock(JRoot.class);
when(root.isFlatPackages()).thenReturn(false);
JadxWrapper wrapper = mock(JadxWrapper.class);
sources = new JSources(root, wrapper);
decompiler = new JadxDecompiler(mock(IJadxArgs.class)); decompiler = new JadxDecompiler(mock(IJadxArgs.class));
} }
...@@ -33,7 +37,7 @@ public class JRootTest { ...@@ -33,7 +37,7 @@ public class JRootTest {
String pkgName = "a.b.c.d.e"; String pkgName = "a.b.c.d.e";
List<JavaPackage> packages = Arrays.asList(newPkg(pkgName)); List<JavaPackage> packages = Arrays.asList(newPkg(pkgName));
List<JPackage> out = root.getHierarchyPackages(packages); List<JPackage> out = sources.getHierarchyPackages(packages);
assertEquals(out.size(), 1); assertEquals(out.size(), 1);
JPackage jpkg = out.get(0); JPackage jpkg = out.get(0);
...@@ -48,7 +52,7 @@ public class JRootTest { ...@@ -48,7 +52,7 @@ public class JRootTest {
newPkg("a.c"), newPkg("a.c"),
newPkg("a.d") newPkg("a.d")
); );
List<JPackage> out = root.getHierarchyPackages(packages); List<JPackage> out = sources.getHierarchyPackages(packages);
assertEquals(out.size(), 1); assertEquals(out.size(), 1);
JPackage jpkg = out.get(0); JPackage jpkg = out.get(0);
...@@ -64,7 +68,7 @@ public class JRootTest { ...@@ -64,7 +68,7 @@ public class JRootTest {
newPkg("a.b.p2"), newPkg("a.b.p2"),
newPkg("a.b.p3") newPkg("a.b.p3")
); );
List<JPackage> out = root.getHierarchyPackages(packages); List<JPackage> out = sources.getHierarchyPackages(packages);
assertEquals(out.size(), 1); assertEquals(out.size(), 1);
JPackage jpkg = out.get(0); JPackage jpkg = out.get(0);
...@@ -82,7 +86,7 @@ public class JRootTest { ...@@ -82,7 +86,7 @@ public class JRootTest {
newPkg("d.e"), newPkg("d.e"),
newPkg("d.f.a") newPkg("d.f.a")
); );
List<JPackage> out = root.getHierarchyPackages(packages); List<JPackage> out = sources.getHierarchyPackages(packages);
assertEquals(out.size(), 2); assertEquals(out.size(), 2);
assertEquals(out.get(0).getName(), "a"); assertEquals(out.get(0).getName(), "a");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册