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) {
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()) {

View File

@@ -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<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);
}
}

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.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<SearchResult> 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<SearchResult> listModel = new DefaultListModel<>();
JList<SearchResult> resultList = new JList<>(listModel);
// 添加搜索按钮的监听器
searchButton.addActionListener(e -> {
// 在后台线程中执行搜索操作
new SwingWorker<Void, SearchResult>() {
@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);