From f62db0f91d3e4c3c257bd093cdb362f1cf4d29d4 Mon Sep 17 00:00:00 2001 From: tzdwindows 7 <3076584115@qq.com> Date: Sun, 23 Feb 2025 14:05:23 +0800 Subject: [PATCH] =?UTF-8?q?refactor(jar):=20=E9=87=8D=E6=9E=84=20ModernJar?= =?UTF-8?q?Viewer=20=E5=B9=B6=E4=BC=98=E5=8C=96=E6=96=87=E4=BB=B6=E6=89=93?= =?UTF-8?q?=E5=BC=80=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 ModernJarViewer从 JDialog 改为 JFrame,独立运行 - 优化文件打开逻辑,支持从命令行参数直接打开 jar 文件 - 改进搜索功能,支持增量搜索和循环搜索 - 调整 UI 样式,支持中文菜单- 移除冗余代码,提高代码可维护性 --- .../innovators/box/AxisInnovatorsBox.java | 13 -- .../java/com/axis/innovators/box/Main.java | 25 +++- .../decompilation/gui/ModernJarViewer.java | 126 +++++++++++++----- 3 files changed, 116 insertions(+), 48 deletions(-) diff --git a/src/main/java/com/axis/innovators/box/AxisInnovatorsBox.java b/src/main/java/com/axis/innovators/box/AxisInnovatorsBox.java index 1d7bf8a..4361202 100644 --- a/src/main/java/com/axis/innovators/box/AxisInnovatorsBox.java +++ b/src/main/java/com/axis/innovators/box/AxisInnovatorsBox.java @@ -340,19 +340,6 @@ public class AxisInnovatorsBox { for (Map fileInfo : validFiles) { String extension = fileInfo.get("extension"); String path = fileInfo.get("path"); - if (".jar".equals(extension)){ - SwingUtilities.invokeLater(() -> { - try { - UIManager.setLookAndFeel(new com.formdev.flatlaf.FlatDarculaLaf()); - } catch (Exception ex) { - ex.printStackTrace(); - } - ModernJarViewer viewer = new ModernJarViewer(null, path); - main.popupWindow(viewer); - }); - main.progressBarManager.close(); - return; - } OpenFileEvents openFileEvents = new OpenFileEvents(path, extension); GlobalEventBus.EVENT_BUS.post(openFileEvents); if (!openFileEvents.isContinue()) { diff --git a/src/main/java/com/axis/innovators/box/Main.java b/src/main/java/com/axis/innovators/box/Main.java index e33a86b..cfa3a29 100644 --- a/src/main/java/com/axis/innovators/box/Main.java +++ b/src/main/java/com/axis/innovators/box/Main.java @@ -1,10 +1,17 @@ package com.axis.innovators.box; +import com.axis.innovators.box.decompilation.gui.ModernJarViewer; +import com.axis.innovators.box.events.GlobalEventBus; +import com.axis.innovators.box.events.OpenFileEvents; +import com.axis.innovators.box.tools.ArgsParser; import com.axis.innovators.box.tools.FolderCleaner; import com.axis.innovators.box.tools.FolderCreator; import com.axis.innovators.box.register.LanguageManager; +import javax.swing.*; import java.util.Arrays; +import java.util.List; +import java.util.Map; /** * @author tzdwindows 7 @@ -18,7 +25,23 @@ public class Main { LanguageManager.loadLanguage("system:zh_CN"); } - System.out.println(Arrays.toString(args)); + List> validFiles = ArgsParser.parseArgs(args); + for (Map fileInfo : validFiles) { + String extension = fileInfo.get("extension"); + String path = fileInfo.get("path"); + if (".jar".equals(extension)){ + SwingUtilities.invokeLater(() -> { + try { + UIManager.setLookAndFeel(new com.formdev.flatlaf.FlatDarculaLaf()); + } catch (Exception ex) { + ex.printStackTrace(); + } + ModernJarViewer viewer = new ModernJarViewer(null, path); + viewer.setVisible(true); + }); + return; + } + } AxisInnovatorsBox.run(args); } } diff --git a/src/main/java/com/axis/innovators/box/decompilation/gui/ModernJarViewer.java b/src/main/java/com/axis/innovators/box/decompilation/gui/ModernJarViewer.java index bd9ad35..cfa31fa 100644 --- a/src/main/java/com/axis/innovators/box/decompilation/gui/ModernJarViewer.java +++ b/src/main/java/com/axis/innovators/box/decompilation/gui/ModernJarViewer.java @@ -2,6 +2,7 @@ package com.axis.innovators.box.decompilation.gui; import com.axis.innovators.box.gui.LoadIcon; import com.axis.innovators.box.gui.WindowsJDialog; +import com.axis.innovators.box.register.LanguageManager; import com.github.javaparser.JavaParser; import com.github.javaparser.ParseResult; import com.github.javaparser.Position; @@ -18,6 +19,7 @@ import java.awt.event.*; import java.util.concurrent.ConcurrentHashMap; import javax.swing.*; +import javax.swing.Timer; import javax.swing.event.HyperlinkEvent; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; @@ -39,7 +41,7 @@ import java.util.regex.Pattern; /** * @author tzdwindows 7 */ -public class ModernJarViewer extends WindowsJDialog { +public class ModernJarViewer extends JFrame { private final DefaultListModel globalSearchResults = new DefaultListModel<>(); private JTree fileTree; private JTabbedPane contentPane; @@ -52,40 +54,40 @@ public class ModernJarViewer extends WindowsJDialog { private DefaultMutableTreeNode root; public ModernJarViewer(Frame owner) { - super(owner, "Jar反编译工具", true); + setTitle("Jar反编译工具"); + setDefaultCloseOperation(EXIT_ON_CLOSE); initComponents(); } /****/ public ModernJarViewer(Frame owner, String jarFile) { - super(owner, "Jar反编译工具", true); + setTitle("Jar反编译工具"); + setDefaultCloseOperation(EXIT_ON_CLOSE); initComponents(); loadJar(new File(jarFile)); } - /****/ private void initComponents() { setSize(1280, 800); setLayout(new BorderLayout()); + setLocationRelativeTo(null); + setIconImage(LoadIcon.loadIcon("logo.png", 32).getImage()); - // 初始化菜单 JMenuBar menuBar = new JMenuBar(); - JMenu fileMenu = new JMenu("File"); - JMenuItem openItem = new JMenuItem("Open"); + JMenu fileMenu = new JMenu("文件"); + JMenuItem openItem = new JMenuItem("打开"); openItem.addActionListener(e -> openJarFile()); fileMenu.add(openItem); menuBar.add(fileMenu); setJMenuBar(menuBar); - // 初始化文件树 - root = new DefaultMutableTreeNode("Root"); + root = new DefaultMutableTreeNode("根目录"); fileTree = new JTree(new DefaultTreeModel(root)); fileTree.addTreeSelectionListener(new TreeSelectionHandler()); JScrollPane treeScroll = new JScrollPane(fileTree); - // 初始化代码编辑器 codeArea = new RSyntaxTextArea(); codeArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); codeArea.setCodeFoldingEnabled(true); @@ -104,13 +106,11 @@ public class ModernJarViewer extends WindowsJDialog { }); codeArea.setToolTipSupplier((textArea, mouseEvent) -> { - // 优先检查方法链接 currentHoveredMethod = findMethodUnderCursor(mouseEvent.getPoint()); if (currentHoveredMethod != null) { return buildMethodTooltip(currentHoveredMethod); } - // 回退到Javadoc检查 String javadoc = getJavadocAtCursor(); return javadoc != null ? formatJavadoc(javadoc) : null; }); @@ -141,18 +141,16 @@ public class ModernJarViewer extends WindowsJDialog { codeArea.setCurrentLineHighlightColor(new Color(0x323232)); - // 使用 RTextScrollPane 支持代码折叠 RTextScrollPane codeScrollPane = new RTextScrollPane(codeArea); codeScrollPane.setLineNumbersEnabled(true); codeScrollPane.setFoldIndicatorEnabled(true); - // 初始化图片预览 imageLabel = new JLabel(); JScrollPane imageScrollPane = new JScrollPane(imageLabel); contentPane = new JTabbedPane(); - contentPane.addTab("Code", codeScrollPane); - contentPane.addTab("Image", imageScrollPane); + contentPane.addTab("代码", codeScrollPane); + contentPane.addTab("图片", imageScrollPane); codeArea.setCodeFoldingEnabled(true); Font ideaFont = new Font("JetBrains Mono", Font.PLAIN, 13); @@ -224,6 +222,8 @@ public class ModernJarViewer extends WindowsJDialog { } } + private JDialog currentSearchDialog = null; + private JDialog currentGlobalSearchDialog = null; private void setupKeyBindings() { // 本地文件搜索 KeyStroke ctrlF = KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_DOWN_MASK); @@ -245,11 +245,25 @@ public class ModernJarViewer extends WindowsJDialog { } private void showLocalSearchDialog() { - JDialog searchDialog = new JDialog(this, "查找", false); + if (currentSearchDialog != null && currentSearchDialog.isVisible()) { + currentSearchDialog.setVisible(true); + return; + } + + currentSearchDialog = new JDialog(this, "查找", false); JTextField searchField = new JTextField(20); JButton nextButton = new JButton("下一个"); JButton prevButton = new JButton("上一个"); + searchField.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + searchInText(searchField.getText(), true); + } + } + }); + nextButton.addActionListener(e -> searchInText(searchField.getText(), true)); prevButton.addActionListener(e -> searchInText(searchField.getText(), false)); @@ -258,10 +272,32 @@ public class ModernJarViewer extends WindowsJDialog { panel.add(prevButton); panel.add(nextButton); - searchDialog.add(panel); - searchDialog.pack(); - searchDialog.setLocationRelativeTo(this); - searchDialog.setVisible(true); + currentSearchDialog.add(panel); + currentSearchDialog.pack(); + currentSearchDialog.setLocationRelativeTo(this); + + Point editorLocation = codeArea.getLocationOnScreen(); + int editorWidth = codeArea.getWidth(); + int dialogWidth = currentSearchDialog.getWidth(); + + int offsetX = -5; + int offsetY = 0; + + currentSearchDialog.setLocation(editorLocation.x + editorWidth - dialogWidth - offsetX, editorLocation.y + offsetY); + currentSearchDialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + closeSearchDialog(); + } + }); + currentSearchDialog.setVisible(true); + } + + private void closeSearchDialog() { + if (currentSearchDialog != null) { + currentSearchDialog.dispose(); + currentSearchDialog = null; + } } private void searchInText(String pattern, boolean forward) { @@ -272,60 +308,82 @@ public class ModernJarViewer extends WindowsJDialog { int index = text.indexOf(pattern, caret); if (index != -1) { codeArea.select(index, index + pattern.length()); + } else { + int reverseIndex = text.lastIndexOf(pattern, caret - pattern.length()); + if (reverseIndex != -1) { + codeArea.select(reverseIndex, reverseIndex + pattern.length()); + } } } else { int index = text.lastIndexOf(pattern, caret - pattern.length()); if (index != -1) { codeArea.select(index, index + pattern.length()); + } else { + int forwardIndex = text.indexOf(pattern, caret); + if (forwardIndex != -1) { + codeArea.select(forwardIndex, forwardIndex + pattern.length()); + } } } } private void showGlobalSearchDialog() { - JDialog globalDialog = new JDialog(this, "全局搜索", false); + if (currentGlobalSearchDialog != null && currentGlobalSearchDialog.isVisible()) { + currentGlobalSearchDialog.setVisible(true); + return; + } + currentGlobalSearchDialog = new JDialog(this, "全局搜索", false); JTextField searchField = new JTextField(30); JButton searchButton = new JButton("搜索"); DefaultListModel listModel = new DefaultListModel<>(); JList resultList = new JList<>(listModel); - // 添加搜索按钮的监听器 searchButton.addActionListener(e -> { - // 在后台线程中执行搜索操作 new SwingWorker() { @Override protected Void doInBackground() throws Exception { - searchInJar(searchField.getText(), listModel); // 耗时的搜索操作 + searchInJar(searchField.getText(), listModel); return null; } @Override protected void done() { - // 搜索完成后更新 UI - JOptionPane.showMessageDialog(globalDialog, "搜索完成!"); + JOptionPane.showMessageDialog(currentGlobalSearchDialog, "搜索完成!"); } }.execute(); }); - // 添加结果列表的监听器 resultList.addListSelectionListener(e -> { SearchResult result = resultList.getSelectedValue(); if (result != null) { - navigateToSearchResult(result); // 跳转到搜索结果 + navigateToSearchResult(result); } }); - // 设置布局 JPanel panel = new JPanel(new BorderLayout()); panel.add(searchField, BorderLayout.NORTH); panel.add(new JScrollPane(resultList), BorderLayout.CENTER); panel.add(searchButton, BorderLayout.SOUTH); - globalDialog.add(panel); - globalDialog.setSize(500, 400); - globalDialog.setLocationRelativeTo(this); - globalDialog.setVisible(true); // 显示对话框 + currentGlobalSearchDialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + closeGlobalSearchDialog(); + } + }); + + currentGlobalSearchDialog.add(panel); + currentGlobalSearchDialog.setSize(500, 400); + currentGlobalSearchDialog.setLocationRelativeTo(this); + currentGlobalSearchDialog.setVisible(true); } + private void closeGlobalSearchDialog() { + if (currentGlobalSearchDialog != null) { + currentGlobalSearchDialog.dispose(); + currentGlobalSearchDialog = null; + } + } private void navigateToSearchResult(SearchResult result) { expandTreeToClass(result.filePath);