refactor(jar): 重构 ModernJarViewer 并优化文件打开逻辑

- 将 ModernJarViewer从 JDialog 改为 JFrame,独立运行
- 优化文件打开逻辑,支持从命令行参数直接打开 jar 文件
- 改进搜索功能,支持增量搜索和循环搜索
- 调整 UI 样式,支持中文菜单- 移除冗余代码,提高代码可维护性
This commit is contained in:
tzdwindows 7
2025-02-23 14:05:23 +08:00
parent e422d31b85
commit f62db0f91d
3 changed files with 116 additions and 48 deletions

View File

@@ -340,19 +340,6 @@ public class AxisInnovatorsBox {
for (Map<String, String> fileInfo : validFiles) { for (Map<String, String> fileInfo : validFiles) {
String extension = fileInfo.get("extension"); String extension = fileInfo.get("extension");
String path = fileInfo.get("path"); 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); OpenFileEvents openFileEvents = new OpenFileEvents(path, extension);
GlobalEventBus.EVENT_BUS.post(openFileEvents); GlobalEventBus.EVENT_BUS.post(openFileEvents);
if (!openFileEvents.isContinue()) { if (!openFileEvents.isContinue()) {

View File

@@ -1,10 +1,17 @@
package com.axis.innovators.box; 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.FolderCleaner;
import com.axis.innovators.box.tools.FolderCreator; import com.axis.innovators.box.tools.FolderCreator;
import com.axis.innovators.box.register.LanguageManager; import com.axis.innovators.box.register.LanguageManager;
import javax.swing.*;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import java.util.Map;
/** /**
* @author tzdwindows 7 * @author tzdwindows 7
@@ -18,7 +25,23 @@ public class Main {
LanguageManager.loadLanguage("system:zh_CN"); LanguageManager.loadLanguage("system:zh_CN");
} }
System.out.println(Arrays.toString(args)); List<Map<String, String>> validFiles = ArgsParser.parseArgs(args);
for (Map<String, String> 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); AxisInnovatorsBox.run(args);
} }
} }

View File

@@ -2,6 +2,7 @@ package com.axis.innovators.box.decompilation.gui;
import com.axis.innovators.box.gui.LoadIcon; import com.axis.innovators.box.gui.LoadIcon;
import com.axis.innovators.box.gui.WindowsJDialog; import com.axis.innovators.box.gui.WindowsJDialog;
import com.axis.innovators.box.register.LanguageManager;
import com.github.javaparser.JavaParser; import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseResult; import com.github.javaparser.ParseResult;
import com.github.javaparser.Position; import com.github.javaparser.Position;
@@ -18,6 +19,7 @@ import java.awt.event.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import javax.swing.*; import javax.swing.*;
import javax.swing.Timer;
import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkEvent;
import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener; import javax.swing.event.TreeSelectionListener;
@@ -39,7 +41,7 @@ import java.util.regex.Pattern;
/** /**
* @author tzdwindows 7 * @author tzdwindows 7
*/ */
public class ModernJarViewer extends WindowsJDialog { public class ModernJarViewer extends JFrame {
private final DefaultListModel<SearchResult> globalSearchResults = new DefaultListModel<>(); private final DefaultListModel<SearchResult> globalSearchResults = new DefaultListModel<>();
private JTree fileTree; private JTree fileTree;
private JTabbedPane contentPane; private JTabbedPane contentPane;
@@ -52,40 +54,40 @@ public class ModernJarViewer extends WindowsJDialog {
private DefaultMutableTreeNode root; private DefaultMutableTreeNode root;
public ModernJarViewer(Frame owner) { public ModernJarViewer(Frame owner) {
super(owner, "Jar反编译工具", true); setTitle("Jar反编译工具");
setDefaultCloseOperation(EXIT_ON_CLOSE);
initComponents(); initComponents();
} }
/****/ /****/
public ModernJarViewer(Frame owner, String jarFile) { public ModernJarViewer(Frame owner, String jarFile) {
super(owner, "Jar反编译工具", true); setTitle("Jar反编译工具");
setDefaultCloseOperation(EXIT_ON_CLOSE);
initComponents(); initComponents();
loadJar(new File(jarFile)); loadJar(new File(jarFile));
} }
/****/
private void initComponents() { private void initComponents() {
setSize(1280, 800); setSize(1280, 800);
setLayout(new BorderLayout()); setLayout(new BorderLayout());
setLocationRelativeTo(null);
setIconImage(LoadIcon.loadIcon("logo.png", 32).getImage()); setIconImage(LoadIcon.loadIcon("logo.png", 32).getImage());
// 初始化菜单
JMenuBar menuBar = new JMenuBar(); JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File"); JMenu fileMenu = new JMenu("文件");
JMenuItem openItem = new JMenuItem("Open"); JMenuItem openItem = new JMenuItem("打开");
openItem.addActionListener(e -> openJarFile()); openItem.addActionListener(e -> openJarFile());
fileMenu.add(openItem); fileMenu.add(openItem);
menuBar.add(fileMenu); menuBar.add(fileMenu);
setJMenuBar(menuBar); setJMenuBar(menuBar);
// 初始化文件树 root = new DefaultMutableTreeNode("根目录");
root = new DefaultMutableTreeNode("Root");
fileTree = new JTree(new DefaultTreeModel(root)); fileTree = new JTree(new DefaultTreeModel(root));
fileTree.addTreeSelectionListener(new TreeSelectionHandler()); fileTree.addTreeSelectionListener(new TreeSelectionHandler());
JScrollPane treeScroll = new JScrollPane(fileTree); JScrollPane treeScroll = new JScrollPane(fileTree);
// 初始化代码编辑器
codeArea = new RSyntaxTextArea(); codeArea = new RSyntaxTextArea();
codeArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); codeArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
codeArea.setCodeFoldingEnabled(true); codeArea.setCodeFoldingEnabled(true);
@@ -104,13 +106,11 @@ public class ModernJarViewer extends WindowsJDialog {
}); });
codeArea.setToolTipSupplier((textArea, mouseEvent) -> { codeArea.setToolTipSupplier((textArea, mouseEvent) -> {
// 优先检查方法链接
currentHoveredMethod = findMethodUnderCursor(mouseEvent.getPoint()); currentHoveredMethod = findMethodUnderCursor(mouseEvent.getPoint());
if (currentHoveredMethod != null) { if (currentHoveredMethod != null) {
return buildMethodTooltip(currentHoveredMethod); return buildMethodTooltip(currentHoveredMethod);
} }
// 回退到Javadoc检查
String javadoc = getJavadocAtCursor(); String javadoc = getJavadocAtCursor();
return javadoc != null ? formatJavadoc(javadoc) : null; return javadoc != null ? formatJavadoc(javadoc) : null;
}); });
@@ -141,18 +141,16 @@ public class ModernJarViewer extends WindowsJDialog {
codeArea.setCurrentLineHighlightColor(new Color(0x323232)); codeArea.setCurrentLineHighlightColor(new Color(0x323232));
// 使用 RTextScrollPane 支持代码折叠
RTextScrollPane codeScrollPane = new RTextScrollPane(codeArea); RTextScrollPane codeScrollPane = new RTextScrollPane(codeArea);
codeScrollPane.setLineNumbersEnabled(true); codeScrollPane.setLineNumbersEnabled(true);
codeScrollPane.setFoldIndicatorEnabled(true); codeScrollPane.setFoldIndicatorEnabled(true);
// 初始化图片预览
imageLabel = new JLabel(); imageLabel = new JLabel();
JScrollPane imageScrollPane = new JScrollPane(imageLabel); JScrollPane imageScrollPane = new JScrollPane(imageLabel);
contentPane = new JTabbedPane(); contentPane = new JTabbedPane();
contentPane.addTab("Code", codeScrollPane); contentPane.addTab("代码", codeScrollPane);
contentPane.addTab("Image", imageScrollPane); contentPane.addTab("图片", imageScrollPane);
codeArea.setCodeFoldingEnabled(true); codeArea.setCodeFoldingEnabled(true);
Font ideaFont = new Font("JetBrains Mono", Font.PLAIN, 13); 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() { private void setupKeyBindings() {
// 本地文件搜索 // 本地文件搜索
KeyStroke ctrlF = KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_DOWN_MASK); KeyStroke ctrlF = KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_DOWN_MASK);
@@ -245,11 +245,25 @@ public class ModernJarViewer extends WindowsJDialog {
} }
private void showLocalSearchDialog() { 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); JTextField searchField = new JTextField(20);
JButton nextButton = new JButton("下一个"); JButton nextButton = new JButton("下一个");
JButton prevButton = 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)); nextButton.addActionListener(e -> searchInText(searchField.getText(), true));
prevButton.addActionListener(e -> searchInText(searchField.getText(), false)); prevButton.addActionListener(e -> searchInText(searchField.getText(), false));
@@ -258,10 +272,32 @@ public class ModernJarViewer extends WindowsJDialog {
panel.add(prevButton); panel.add(prevButton);
panel.add(nextButton); panel.add(nextButton);
searchDialog.add(panel); currentSearchDialog.add(panel);
searchDialog.pack(); currentSearchDialog.pack();
searchDialog.setLocationRelativeTo(this); currentSearchDialog.setLocationRelativeTo(this);
searchDialog.setVisible(true);
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) { private void searchInText(String pattern, boolean forward) {
@@ -272,60 +308,82 @@ public class ModernJarViewer extends WindowsJDialog {
int index = text.indexOf(pattern, caret); int index = text.indexOf(pattern, caret);
if (index != -1) { if (index != -1) {
codeArea.select(index, index + pattern.length()); 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 { } else {
int index = text.lastIndexOf(pattern, caret - pattern.length()); int index = text.lastIndexOf(pattern, caret - pattern.length());
if (index != -1) { if (index != -1) {
codeArea.select(index, index + pattern.length()); 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() { 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); JTextField searchField = new JTextField(30);
JButton searchButton = new JButton("搜索"); JButton searchButton = new JButton("搜索");
DefaultListModel<SearchResult> listModel = new DefaultListModel<>(); DefaultListModel<SearchResult> listModel = new DefaultListModel<>();
JList<SearchResult> resultList = new JList<>(listModel); JList<SearchResult> resultList = new JList<>(listModel);
// 添加搜索按钮的监听器
searchButton.addActionListener(e -> { searchButton.addActionListener(e -> {
// 在后台线程中执行搜索操作
new SwingWorker<Void, SearchResult>() { new SwingWorker<Void, SearchResult>() {
@Override @Override
protected Void doInBackground() throws Exception { protected Void doInBackground() throws Exception {
searchInJar(searchField.getText(), listModel); // 耗时的搜索操作 searchInJar(searchField.getText(), listModel);
return null; return null;
} }
@Override @Override
protected void done() { protected void done() {
// 搜索完成后更新 UI JOptionPane.showMessageDialog(currentGlobalSearchDialog, "搜索完成!");
JOptionPane.showMessageDialog(globalDialog, "搜索完成!");
} }
}.execute(); }.execute();
}); });
// 添加结果列表的监听器
resultList.addListSelectionListener(e -> { resultList.addListSelectionListener(e -> {
SearchResult result = resultList.getSelectedValue(); SearchResult result = resultList.getSelectedValue();
if (result != null) { if (result != null) {
navigateToSearchResult(result); // 跳转到搜索结果 navigateToSearchResult(result);
} }
}); });
// 设置布局
JPanel panel = new JPanel(new BorderLayout()); JPanel panel = new JPanel(new BorderLayout());
panel.add(searchField, BorderLayout.NORTH); panel.add(searchField, BorderLayout.NORTH);
panel.add(new JScrollPane(resultList), BorderLayout.CENTER); panel.add(new JScrollPane(resultList), BorderLayout.CENTER);
panel.add(searchButton, BorderLayout.SOUTH); panel.add(searchButton, BorderLayout.SOUTH);
globalDialog.add(panel); currentGlobalSearchDialog.addWindowListener(new WindowAdapter() {
globalDialog.setSize(500, 400); @Override
globalDialog.setLocationRelativeTo(this); public void windowClosing(WindowEvent e) {
globalDialog.setVisible(true); // 显示对话框 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) { private void navigateToSearchResult(SearchResult result) {
expandTreeToClass(result.filePath); expandTreeToClass(result.filePath);