Skip to content
This repository was archived by the owner on Jan 2, 2023. It is now read-only.

Commit 18bf251

Browse files
committed
node
1 parent a8be18a commit 18bf251

19 files changed

+374
-96
lines changed

src/main/java/cn/enaium/joe/gui/panel/file/tree/FileTreeCellRenderer.java

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,14 @@
1616

1717
package cn.enaium.joe.gui.panel.file.tree;
1818

19-
import cn.enaium.joe.gui.panel.file.tree.node.ClassTreeNode;
20-
import cn.enaium.joe.gui.panel.file.tree.node.FieldTreeNode;
21-
import cn.enaium.joe.gui.panel.file.tree.node.MethodTreeNode;
22-
import cn.enaium.joe.gui.panel.file.tree.node.PackageTreeNode;
19+
import cn.enaium.joe.gui.panel.file.tree.node.*;
2320
import com.formdev.flatlaf.extras.FlatSVGIcon;
24-
import com.formdev.flatlaf.extras.FlatSVGUtils;
2521
import org.objectweb.asm.Opcodes;
2622
import org.objectweb.asm.tree.ClassNode;
2723

2824
import javax.swing.*;
2925
import javax.swing.tree.DefaultTreeCellRenderer;
3026
import java.awt.*;
31-
import java.awt.image.BufferedImage;
32-
import java.util.Objects;
3327

3428
/**
3529
* @author Enaium
@@ -38,31 +32,42 @@ public class FileTreeCellRenderer extends DefaultTreeCellRenderer {
3832
@Override
3933
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
4034
super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
41-
final PackageTreeNode packageTreeNode = (PackageTreeNode) value;
35+
final DefaultTreeNode defaultTreeNode = (DefaultTreeNode) value;
4236

43-
if (packageTreeNode.getChildCount() > 0) {
37+
if (defaultTreeNode.toString().equals("classes")) {
38+
setIcon(new FlatSVGIcon("icons/classesRoot.svg"));
39+
} else if (defaultTreeNode.toString().equals("resources")) {
40+
setIcon(new FlatSVGIcon("icons/resourceRoot.svg"));
41+
} else if (defaultTreeNode instanceof PackageTreeNode) {
4442
setIcon(new FlatSVGIcon("icons/package.svg"));
45-
}
43+
PackageTreeNode packageTreeNode = (PackageTreeNode) defaultTreeNode;
44+
if (packageTreeNode instanceof ClassTreeNode) {
45+
ClassNode classNode = ((ClassTreeNode) packageTreeNode).classNode;
46+
if (classNode.access == (Opcodes.ACC_PUBLIC | Opcodes.ACC_ANNOTATION | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE)) {
47+
setIcon(new FlatSVGIcon("icons/annotation.svg"));
48+
} else if (classNode.access == (Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE)) {
49+
setIcon(new FlatSVGIcon("icons/interface.svg"));
50+
} else if (classNode.access == (Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_ABSTRACT)) {
51+
setIcon(new FlatSVGIcon("icons/abstractClass.svg"));
52+
} else if (classNode.access == (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_SUPER | Opcodes.ACC_ENUM)) {
53+
setIcon(new FlatSVGIcon("icons/enum.svg"));
54+
} else if (classNode.access == (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_SUPER)) {
55+
setIcon(new FlatSVGIcon("icons/finalClass.svg"));
56+
} else {
57+
setIcon(new FlatSVGIcon("icons/class.svg"));
58+
}
59+
} else if (packageTreeNode instanceof MethodTreeNode) {
60+
setIcon(new FlatSVGIcon("icons/method.svg"));
61+
} else if (packageTreeNode instanceof FieldTreeNode) {
62+
setIcon(new FlatSVGIcon("icons/field.svg"));
63+
}
64+
} else if (defaultTreeNode instanceof FolderTreeNode) {
65+
setIcon(new FlatSVGIcon("icons/folder.svg"));
4666

47-
if (packageTreeNode instanceof ClassTreeNode) {
48-
ClassNode classNode = ((ClassTreeNode) packageTreeNode).classNode;
49-
if (classNode.access == (Opcodes.ACC_PUBLIC | Opcodes.ACC_ANNOTATION | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE)) {
50-
setIcon(new FlatSVGIcon("icons/annotation.svg"));
51-
} else if (classNode.access == (Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE)) {
52-
setIcon(new FlatSVGIcon("icons/interface.svg"));
53-
} else if (classNode.access == (Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_ABSTRACT)) {
54-
setIcon(new FlatSVGIcon("icons/abstractClass.svg"));
55-
} else if (classNode.access == (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_SUPER | Opcodes.ACC_ENUM)) {
56-
setIcon(new FlatSVGIcon("icons/enum.svg"));
57-
} else if (classNode.access == (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_SUPER)) {
58-
setIcon(new FlatSVGIcon("icons/finalClass.svg"));
59-
} else {
60-
setIcon(new FlatSVGIcon("icons/class.svg"));
67+
FolderTreeNode folderTreeNode = (FolderTreeNode) defaultTreeNode;
68+
if (folderTreeNode instanceof FileTreeNode) {
69+
setIcon(new FlatSVGIcon("icons/file.svg"));
6170
}
62-
} else if (packageTreeNode instanceof MethodTreeNode) {
63-
setIcon(new FlatSVGIcon("icons/method.svg"));
64-
} else if (packageTreeNode instanceof FieldTreeNode) {
65-
setIcon(new FlatSVGIcon("icons/field.svg"));
6671
}
6772
return this;
6873
}

src/main/java/cn/enaium/joe/gui/panel/file/tree/FileTreePanel.java

Lines changed: 85 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,37 +19,50 @@
1919
import cn.enaium.joe.gui.JavaOctetEditor;
2020
import cn.enaium.joe.gui.panel.file.FileDropTarget;
2121
import cn.enaium.joe.gui.panel.file.tabbed.tab.FileTabPanel;
22-
import cn.enaium.joe.gui.panel.file.tree.node.ClassTreeNode;
23-
import cn.enaium.joe.gui.panel.file.tree.node.FieldTreeNode;
24-
import cn.enaium.joe.gui.panel.file.tree.node.MethodTreeNode;
25-
import cn.enaium.joe.gui.panel.file.tree.node.PackageTreeNode;
22+
import cn.enaium.joe.gui.panel.file.tree.node.*;
2623
import cn.enaium.joe.jar.Jar;
2724
import cn.enaium.joe.util.ASyncUtil;
25+
import javassist.ClassPool;
26+
import javassist.CtClass;
27+
import javassist.CtMethod;
28+
import javassist.Loader;
29+
import org.objectweb.asm.ClassReader;
2830
import org.objectweb.asm.tree.ClassNode;
2931
import org.objectweb.asm.tree.FieldNode;
3032
import org.objectweb.asm.tree.MethodNode;
33+
import org.objectweb.asm.util.ASMifier;
34+
import org.objectweb.asm.util.TraceClassVisitor;
3135

3236
import javax.swing.*;
3337
import javax.swing.tree.DefaultTreeModel;
34-
import javax.swing.tree.TreePath;
3538
import java.awt.dnd.DnDConstants;
3639
import java.awt.dnd.DropTarget;
40+
import java.awt.event.KeyAdapter;
41+
import java.awt.event.KeyEvent;
3742
import java.io.File;
38-
import java.nio.file.Files;
43+
import java.io.PrintWriter;
44+
import java.io.StringWriter;
3945
import java.util.*;
4046

4147
/**
4248
* @author Enaium
4349
*/
4450
public class FileTreePanel extends JTree {
4551

52+
private static final DefaultTreeNode classesRoot = new DefaultTreeNode("classes");
53+
private static final DefaultTreeNode resourceRoot = new DefaultTreeNode("resources");
54+
4655
public FileTreePanel() {
47-
super(new PackageTreeNode(""));
56+
super(new DefaultTreeNode("") {{
57+
add(classesRoot);
58+
add(resourceRoot);
59+
}});
60+
4861
setRootVisible(false);
4962
setShowsRootHandles(true);
5063
setCellRenderer(new FileTreeCellRenderer());
5164
addTreeSelectionListener(e -> {
52-
PackageTreeNode lastPathComponent = (PackageTreeNode) e.getPath().getLastPathComponent();
65+
DefaultTreeNode lastPathComponent = (DefaultTreeNode) e.getPath().getLastPathComponent();
5366
if (lastPathComponent instanceof ClassTreeNode) {
5467
JavaOctetEditor.getInstance().fileTabbedPanel.addTab(lastPathComponent.toString(), new FileTabPanel(((ClassTreeNode) lastPathComponent).classNode));
5568
JavaOctetEditor.getInstance().fileTabbedPanel.setSelectedIndex(JavaOctetEditor.getInstance().fileTabbedPanel.getTabCount() - 1);
@@ -67,66 +80,102 @@ public FileTreePanel() {
6780
public void refresh(Jar jar) {
6881
DefaultTreeModel model = (DefaultTreeModel) getModel();
6982
model.reload();
70-
PackageTreeNode root = (PackageTreeNode) model.getRoot();
71-
root.removeAllChildren();
83+
classesRoot.removeAllChildren();
84+
resourceRoot.removeAllChildren();
7285

73-
Map<String, PackageTreeNode> hasMap = new HashMap<>();
86+
Map<String, DefaultTreeNode> hasMap = new HashMap<>();
7487

7588

7689
for (ClassNode classNode : jar.classes.values()) {
7790
String[] split = classNode.name.split("/");
78-
PackageTreeNode prev = null;
91+
DefaultTreeNode prev = null;
7992
StringBuilder stringBuilder = new StringBuilder();
8093
int i = 0;
8194
for (String s : split) {
8295
stringBuilder.append(s);
83-
PackageTreeNode fileTreeNode = new PackageTreeNode(s);
96+
PackageTreeNode packageTreeNode = new PackageTreeNode(s);
8497

8598
if (split.length == i + 1) {
86-
fileTreeNode = new ClassTreeNode(classNode);
99+
packageTreeNode = new ClassTreeNode(classNode);
87100
for (MethodNode methodNode : classNode.methods) {
88-
fileTreeNode.add(new MethodTreeNode(classNode, methodNode));
101+
packageTreeNode.add(new MethodTreeNode(classNode, methodNode));
89102
}
90103
for (FieldNode field : classNode.fields) {
91-
fileTreeNode.add(new FieldTreeNode(classNode, field));
104+
packageTreeNode.add(new FieldTreeNode(classNode, field));
92105
}
93106
}
94107

95108
if (prev == null) {
96109
if (!hasMap.containsKey(stringBuilder.toString())) {
97-
root.add(fileTreeNode);
98-
hasMap.put(stringBuilder.toString(), fileTreeNode);
99-
prev = fileTreeNode;
110+
classesRoot.add(packageTreeNode);
111+
hasMap.put(stringBuilder.toString(), packageTreeNode);
112+
prev = packageTreeNode;
100113
} else {
101114
prev = hasMap.get(stringBuilder.toString());
102115
}
103116
} else {
104117
if (!hasMap.containsKey(stringBuilder.toString())) {
105-
prev.add(fileTreeNode);
106-
hasMap.put(stringBuilder.toString(), fileTreeNode);
107-
prev = fileTreeNode;
118+
prev.add(packageTreeNode);
119+
hasMap.put(stringBuilder.toString(), packageTreeNode);
120+
prev = packageTreeNode;
108121
} else {
109122
prev = hasMap.get(stringBuilder.toString());
110123
}
111124
}
112125
i++;
113126
}
114127
}
115-
sort(model, root);
128+
sort(model, classesRoot);
129+
130+
for (Map.Entry<String, byte[]> stringEntry : jar.resources.entrySet()) {
131+
String[] split = stringEntry.getKey().split("/");
132+
DefaultTreeNode prev = null;
133+
StringBuilder stringBuilder = new StringBuilder();
134+
int i = 0;
135+
for (String s : split) {
136+
stringBuilder.append(s);
137+
FolderTreeNode folderTreeNode = new FolderTreeNode(s);
116138

117-
super.expandPath(new TreePath(root.getPath()));
139+
if (split.length == i + 1) {
140+
folderTreeNode = new FileTreeNode(s, stringEntry.getValue());
141+
}
142+
143+
if (prev == null) {
144+
if (!hasMap.containsKey(stringBuilder.toString())) {
145+
resourceRoot.add(folderTreeNode);
146+
hasMap.put(stringBuilder.toString(), folderTreeNode);
147+
prev = folderTreeNode;
148+
} else {
149+
prev = hasMap.get(stringBuilder.toString());
150+
}
151+
} else {
152+
if (!hasMap.containsKey(stringBuilder.toString())) {
153+
prev.add(folderTreeNode);
154+
hasMap.put(stringBuilder.toString(), folderTreeNode);
155+
prev = folderTreeNode;
156+
} else {
157+
prev = hasMap.get(stringBuilder.toString());
158+
}
159+
}
160+
i++;
161+
}
162+
}
163+
sort(model, resourceRoot);
118164
}
119165

120166

121-
public void sort(DefaultTreeModel defaultTreeModel, PackageTreeNode fileTreeNode) {
122-
if (!fileTreeNode.isLeaf()) {
123-
fileTreeNode.getChildren().sort((o1, o2) -> {
167+
public void sort(DefaultTreeModel defaultTreeModel, DefaultTreeNode defaultTreeNode) {
168+
if (!defaultTreeNode.isLeaf()) {
169+
defaultTreeNode.getChildren().sort((o1, o2) -> {
124170
boolean class1 = o1 instanceof ClassTreeNode;
125171
boolean class2 = o2 instanceof ClassTreeNode;
126172

127173
boolean method1 = o1 instanceof MethodTreeNode;
128174
boolean method2 = o2 instanceof MethodTreeNode;
129175

176+
boolean file1 = o1 instanceof FileTreeNode;
177+
boolean file2 = o2 instanceof FileTreeNode;
178+
130179
if (class1 && !class2) {
131180
return 1;
132181
}
@@ -141,10 +190,17 @@ public void sort(DefaultTreeModel defaultTreeModel, PackageTreeNode fileTreeNode
141190
if (!method1 && method2) {
142191
return -1;
143192
}
193+
194+
if (file1 && !file2) {
195+
return 1;
196+
}
197+
if (!file1 && file2) {
198+
return -1;
199+
}
144200
return o1.toString().compareTo(o2.toString());
145201
});
146-
for (int i = 0; i < defaultTreeModel.getChildCount(fileTreeNode); i++) {
147-
PackageTreeNode child = ((PackageTreeNode) defaultTreeModel.getChild(fileTreeNode, i));
202+
for (int i = 0; i < defaultTreeModel.getChildCount(defaultTreeNode); i++) {
203+
DefaultTreeNode child = ((DefaultTreeNode) defaultTreeModel.getChild(defaultTreeNode, i));
148204
sort(defaultTreeModel, child);
149205
}
150206
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2022 Enaium
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package cn.enaium.joe.gui.panel.file.tree.node;
18+
19+
import javax.swing.tree.DefaultMutableTreeNode;
20+
import javax.swing.tree.TreeNode;
21+
import java.util.Vector;
22+
23+
/**
24+
* @author Enaium
25+
*/
26+
public class DefaultTreeNode extends DefaultMutableTreeNode {
27+
public DefaultTreeNode(Object userObject) {
28+
super(userObject);
29+
}
30+
31+
32+
public Vector<TreeNode> getChildren() {
33+
return children;
34+
}
35+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2022 Enaium
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package cn.enaium.joe.gui.panel.file.tree.node;
18+
19+
/**
20+
* @author Enaium
21+
*/
22+
public class FileTreeNode extends FolderTreeNode {
23+
24+
private final byte[] data;
25+
26+
public FileTreeNode(Object userObject, byte[] data) {
27+
super(userObject);
28+
this.data = data;
29+
}
30+
31+
public byte[] getData() {
32+
return data;
33+
}
34+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2022 Enaium
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package cn.enaium.joe.gui.panel.file.tree.node;
18+
19+
/**
20+
* @author Enaium
21+
*/
22+
public class FolderTreeNode extends DefaultTreeNode {
23+
public FolderTreeNode(Object userObject) {
24+
super(userObject);
25+
}
26+
}

0 commit comments

Comments
 (0)