From 43e775653fd3e5c7f3954e1978edc06c86c8487d Mon Sep 17 00:00:00 2001 From: hupan Date: Wed, 20 Nov 2019 21:17:36 +0800 Subject: [PATCH] =?UTF-8?q?add=20feature:=20context=20menu=20(remove|expan?= =?UTF-8?q?d|collapse)=20support=20fixbug=EF=BC=9Afiles=20are=20hidden=20w?= =?UTF-8?q?hen=20select=20and=20click=20"-"=20button?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- .../gui/FileNavigationPane.java | 139 ++++++++++++------ .../bytecodeviewer/util/LazyNameUtil.java | 98 ++++++++++-- 3 files changed, 183 insertions(+), 57 deletions(-) diff --git a/.gitignore b/.gitignore index 0d008861..6fa47a36 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ .classpath .project .DS_Store -*.iml \ No newline at end of file +*.iml +/out/ diff --git a/src/the/bytecode/club/bytecodeviewer/gui/FileNavigationPane.java b/src/the/bytecode/club/bytecodeviewer/gui/FileNavigationPane.java index 448dc10f..0aeb5414 100644 --- a/src/the/bytecode/club/bytecodeviewer/gui/FileNavigationPane.java +++ b/src/the/bytecode/club/bytecodeviewer/gui/FileNavigationPane.java @@ -1,50 +1,25 @@ package the.bytecode.club.bytecodeviewer.gui; -import java.awt.BorderLayout; -import java.awt.font.FontRenderContext; -import java.awt.geom.*; -import java.awt.Color; -import java.awt.Component; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.Map.Entry; - -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextField; -import javax.swing.JTree; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeCellRenderer; -import javax.swing.tree.MutableTreeNode; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; - +import com.sun.java.swing.plaf.windows.WindowsTreeUI; import org.objectweb.asm.tree.ClassNode; - -import the.bytecode.club.bytecodeviewer.*; +import the.bytecode.club.bytecodeviewer.BytecodeViewer; +import the.bytecode.club.bytecodeviewer.Resources; import the.bytecode.club.bytecodeviewer.util.FileChangeNotifier; import the.bytecode.club.bytecodeviewer.util.FileContainer; import the.bytecode.club.bytecodeviewer.util.FileDrop; +import the.bytecode.club.bytecodeviewer.util.LazyNameUtil; + +import javax.swing.*; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.font.FontRenderContext; +import java.awt.geom.Rectangle2D; +import java.io.File; +import java.util.*; +import java.util.Map.Entry; /*************************************************************************** * Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite * @@ -195,6 +170,60 @@ public class FileNavigationPane extends VisibleComponent implements } }; + private void showPopMenu(MyTree tree, TreePath selPath, int x, int y) { + if (selPath == null) { + return; + } + + final JPopupMenu pop = new JPopupMenu(); + pop.add(new AbstractAction("Remove") { + @Override + public void actionPerformed(ActionEvent e) { + TreePath selPath = FileNavigationPane.this.tree.getPathForLocation(x, y); + DefaultMutableTreeNode selectNode = (DefaultMutableTreeNode) selPath.getLastPathComponent(); + Enumeration enumeration = treeRoot.children(); + while (enumeration.hasMoreElements()) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) enumeration.nextElement(); + if (node.isNodeAncestor(selectNode)) { + DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot(); + root.remove(node); + for (FileContainer fileContainer : BytecodeViewer.files) { + if (fileContainer.name.equals(selectNode.toString())) { + removeFile(fileContainer); + break; + } + } + updateTree(); + return; + } + } + } + }); + + pop.add(new AbstractAction("Expand", WindowsTreeUI.ExpandedIcon.createExpandedIcon()) { + @Override + public void actionPerformed(ActionEvent e) { + TreePath selPath = FileNavigationPane.this.tree.getPathForLocation(x, y); + expandAll(tree, selPath, true); + } + }); + + pop.add(new AbstractAction("Collapse", WindowsTreeUI.CollapsedIcon.createCollapsedIcon()) { + @Override + public void actionPerformed(ActionEvent e) { + TreePath selPath = FileNavigationPane.this.tree.getPathForLocation(x, y); + expandAll(tree, selPath, false); + } + }); + + pop.show(this.tree, x, y); + } + + private void removeFile(FileContainer fileContainer) { + BytecodeViewer.files.remove(fileContainer); + LazyNameUtil.removeName(fileContainer.name); + } + public FileNavigationPane(final FileChangeNotifier fcn) { super("ClassNavigation"); this.fcn = fcn; @@ -203,6 +232,30 @@ public class FileNavigationPane extends VisibleComponent implements quickSearch.setForeground(Color.gray); setTitle("Files"); + tree.addMouseListener(new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent e) { + if (e.isMetaDown()) { + MyTree tree = (MyTree) e.getSource(); + TreePath selPath = FileNavigationPane.this.tree.getPathForLocation(e.getX(), e.getY()); + if (selPath == null) { + return; + } + + DefaultMutableTreeNode selectNode = (DefaultMutableTreeNode) selPath.getLastPathComponent(); + Enumeration enumeration = treeRoot.children(); + while (enumeration.hasMoreElements()) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) enumeration.nextElement(); + if (node.isNodeAncestor(selectNode)) { + // pop.show(tree, e.getX(), e.getY()); + showPopMenu(tree, selPath, e.getX(), e.getY()); + break; + } + } + } + } + }); + this.open.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -513,6 +566,7 @@ public class FileNavigationPane extends VisibleComponent implements return hash; } }; + } /** @@ -556,8 +610,9 @@ public class FileNavigationPane extends VisibleComponent implements public void openPath(TreePath path) { - if (path == null) + if (path == null || path.getPathCount() == 1) { return; + } final StringBuilder nameBuffer = new StringBuilder(); for (int i = 2; i < path.getPathCount(); i++) { diff --git a/src/the/bytecode/club/bytecodeviewer/util/LazyNameUtil.java b/src/the/bytecode/club/bytecodeviewer/util/LazyNameUtil.java index 4dcbcff4..ad1cdc0e 100644 --- a/src/the/bytecode/club/bytecodeviewer/util/LazyNameUtil.java +++ b/src/the/bytecode/club/bytecodeviewer/util/LazyNameUtil.java @@ -19,6 +19,7 @@ package the.bytecode.club.bytecodeviewer.util; ***************************************************************************/ import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; import java.util.HashMap; @@ -29,31 +30,100 @@ public class LazyNameUtil { public static boolean SAME_NAME_JAR_WORKSPACE = false; - private static final HashMap nameMap = new HashMap<>(); + private static final HashMap nameMap = new HashMap<>(); public static void reset() { nameMap.clear(); } - public static String applyNameChanges(String name) - { - if(nameMap.containsKey(name)) - { - if(!SAME_NAME_JAR_WORKSPACE) + public static String applyNameChanges(String name) { + if (nameMap.containsKey(name)) { + if (!SAME_NAME_JAR_WORKSPACE) { SAME_NAME_JAR_WORKSPACE = true; + } - int counter = nameMap.get(name)+1; - nameMap.put(name, counter); - - return FilenameUtils.removeExtension(name)+"#"+counter+"."+FilenameUtils.getExtension(name); - } - else - { - nameMap.put(name, 1); + SeqAndCount seqAndCount = nameMap.get(name); + nameMap.put(name, seqAndCount.incrSeqAndCount()); + return FilenameUtils.removeExtension(name) + "#" + seqAndCount.getSeq() + "." + FilenameUtils.getExtension(name); + } else { + nameMap.put(name, SeqAndCount.init()); } return name; } + public static void removeName(String name) { + if (StringUtils.isBlank(name)) { + return; + } + + if (name.contains("#")) { + name = name.substring(0, name.indexOf("#")) + name.substring(name.indexOf(".")); + } + + SeqAndCount seqAndCount = nameMap.get(name); + if (seqAndCount == null) { + return; + } + + // sequence remain the same and decrease the count + // still the count become 1 + if (seqAndCount.getCount() == 1) { + nameMap.remove(name); + } else { + nameMap.put(name, seqAndCount.decrCount()); + } + } + } + + +class SeqAndCount { + Integer seq; + Integer count; + + public static SeqAndCount init() { + SeqAndCount seqAndCount = new SeqAndCount(); + seqAndCount.setSeq(1); + seqAndCount.setCount(1); + return seqAndCount; + } + + public SeqAndCount incrSeq() { + seq = seq + 1; + return this; + } + + public SeqAndCount incrCount() { + count = count + 1; + return this; + } + + public SeqAndCount decrCount() { + count = count - 1; + return this; + } + + public SeqAndCount incrSeqAndCount() { + seq = seq + 1; + count = count + 1; + return this; + } + + public Integer getSeq() { + return seq; + } + + public void setSeq(Integer seq) { + this.seq = seq; + } + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } +} \ No newline at end of file