feat(gui): 重构主界面并添加新功能
- 重新设计了主窗口布局,增加了侧边栏和内容面板 - 添加了分类按钮和设置按钮 - 实现了内存分析面板的自动补全功能 - 优化了日志文件生成和异常处理机制- 更新了依赖库版本
23
build.gradle
@@ -65,6 +65,8 @@ dependencies {
|
|||||||
//implementation 'com.formdev:flatlaf:0.26'
|
//implementation 'com.formdev:flatlaf:0.26'
|
||||||
implementation 'commons-io:commons-io:2.14.0'
|
implementation 'commons-io:commons-io:2.14.0'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
implementation 'com.formdev:flatlaf:3.2.1' // FlatLaf核心
|
implementation 'com.formdev:flatlaf:3.2.1' // FlatLaf核心
|
||||||
implementation 'com.formdev:flatlaf-extras:3.2.1' // 扩展组件
|
implementation 'com.formdev:flatlaf-extras:3.2.1' // 扩展组件
|
||||||
implementation 'com.formdev:flatlaf-intellij-themes:3.2.1' // 官方主题包
|
implementation 'com.formdev:flatlaf-intellij-themes:3.2.1' // 官方主题包
|
||||||
@@ -74,6 +76,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation files('libs/JNC-1.0-jnc.jar')
|
implementation files('libs/JNC-1.0-jnc.jar')
|
||||||
implementation files('libs/dog api 1.3.jar')
|
implementation files('libs/dog api 1.3.jar')
|
||||||
|
implementation files('libs/DesktopWallpaperSdk-1.0-SNAPSHOT.jar')
|
||||||
|
|
||||||
implementation 'org.fxmisc.richtext:richtextfx:0.11.0' // 更新后的richtextfx
|
implementation 'org.fxmisc.richtext:richtextfx:0.11.0' // 更新后的richtextfx
|
||||||
implementation 'org.bitbucket.mstrobel:procyon-core:0.5.36' // 使用JitPack版本
|
implementation 'org.bitbucket.mstrobel:procyon-core:0.5.36' // 使用JitPack版本
|
||||||
@@ -112,6 +115,21 @@ dependencies {
|
|||||||
//runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.3', // JWT实现
|
//runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.3', // JWT实现
|
||||||
// 'io.jsonwebtoken:jjwt-jackson:0.12.3' // JWT序列化
|
// 'io.jsonwebtoken:jjwt-jackson:0.12.3' // JWT序列化
|
||||||
|
|
||||||
|
implementation 'org.json:json:20230618'
|
||||||
|
|
||||||
|
implementation 'org.lwjgl:lwjgl:3.3.1'
|
||||||
|
implementation 'org.lwjgl:lwjgl-glfw:3.3.1'
|
||||||
|
implementation 'org.lwjgl:lwjgl-opengl:3.3.1'
|
||||||
|
implementation 'org.lwjgl:lwjgl:3.3.1:natives-windows' // Windows natives
|
||||||
|
implementation 'org.lwjgl:lwjgl-glfw:3.3.1:natives-windows'
|
||||||
|
implementation 'org.lwjgl:lwjgl-opengl:3.3.1:natives-windows'
|
||||||
|
|
||||||
|
implementation 'org.bytedeco:javacv-platform:1.5.7' // JavaCV
|
||||||
|
implementation 'org.bytedeco:javacpp-platform:1.5.7' // JavaCPP
|
||||||
|
|
||||||
|
implementation 'com.madgag:animated-gif-lib:1.4'
|
||||||
|
implementation 'org.openjfx:javafx-web:17'
|
||||||
|
|
||||||
|
|
||||||
runtimeOnly 'com.mysql:mysql-connector-j'
|
runtimeOnly 'com.mysql:mysql-connector-j'
|
||||||
|
|
||||||
@@ -136,12 +154,15 @@ dependencies {
|
|||||||
implementation 'me.friwi:jcefmaven:122.1.10'
|
implementation 'me.friwi:jcefmaven:122.1.10'
|
||||||
|
|
||||||
implementation 'com.alphacephei:vosk:0.3.45' // Java API
|
implementation 'com.alphacephei:vosk:0.3.45' // Java API
|
||||||
implementation 'net.java.dev.jna:jna:5.12.1' // 本地库加载
|
implementation 'net.java.dev.jna:jna:5.13.0'
|
||||||
|
implementation 'net.java.dev.jna:jna-platform:5.13.0'
|
||||||
|
|
||||||
// 高性能音频处理
|
// 高性能音频处理
|
||||||
implementation 'org.apache.commons:commons-math3:3.6.1'
|
implementation 'org.apache.commons:commons-math3:3.6.1'
|
||||||
implementation 'com.google.guava:guava:31.1-jre'
|
implementation 'com.google.guava:guava:31.1-jre'
|
||||||
|
|
||||||
|
implementation 'com.github.javaparser:javaparser-symbol-solver-core:3.25.9'
|
||||||
|
|
||||||
// 中文拼音处理
|
// 中文拼音处理
|
||||||
implementation 'com.belerweb:pinyin4j:2.5.1'
|
implementation 'com.belerweb:pinyin4j:2.5.1'
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
#Current Loaded Language
|
#Current Loaded Language
|
||||||
#Sat May 31 10:30:35 CST 2025
|
#Wed Jul 02 20:11:55 CST 2025
|
||||||
loadedLanguage=system\:zh_CN
|
loadedLanguage=system\:zh_CN
|
||||||
|
|||||||
BIN
libs/DesktopWallpaperSdk-1.0-SNAPSHOT.jar
Normal file
@@ -17,6 +17,7 @@ import com.axis.innovators.box.util.Tray;
|
|||||||
import com.axis.innovators.box.util.UserLocalInformation;
|
import com.axis.innovators.box.util.UserLocalInformation;
|
||||||
import com.axis.innovators.box.verification.UserTags;
|
import com.axis.innovators.box.verification.UserTags;
|
||||||
import com.formdev.flatlaf.FlatLightLaf;
|
import com.formdev.flatlaf.FlatLightLaf;
|
||||||
|
import com.sun.management.HotSpotDiagnosticMXBean;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.logging.log4j.core.Appender;
|
import org.apache.logging.log4j.core.Appender;
|
||||||
@@ -78,6 +79,10 @@ public class AxisInnovatorsBox {
|
|||||||
public AxisInnovatorsBox(String[] args, boolean isDebug) {
|
public AxisInnovatorsBox(String[] args, boolean isDebug) {
|
||||||
this.args = args;
|
this.args = args;
|
||||||
this.isDebug = isDebug;
|
this.isDebug = isDebug;
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
|
||||||
|
organizingCrashReports(throwable instanceof Exception ?
|
||||||
|
(Exception) throwable : new Exception(throwable));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -358,7 +363,7 @@ public class AxisInnovatorsBox {
|
|||||||
if (appender instanceof FileAppender fileAppender) {
|
if (appender instanceof FileAppender fileAppender) {
|
||||||
String fileName = fileAppender.getFileName();
|
String fileName = fileAppender.getFileName();
|
||||||
if (fileName != null && !addedFiles.contains(fileName)) {
|
if (fileName != null && !addedFiles.contains(fileName)) {
|
||||||
addFileToZip(zos, new File(fileName), "logs/");
|
addFileToZip(zos, new File(fileName), "logs/" + new File(fileName).getName());
|
||||||
addedFiles.add(fileName);
|
addedFiles.add(fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -387,7 +392,7 @@ public class AxisInnovatorsBox {
|
|||||||
for (File file : logFiles) {
|
for (File file : logFiles) {
|
||||||
String absolutePath = file.getAbsolutePath();
|
String absolutePath = file.getAbsolutePath();
|
||||||
if (!addedFiles.contains(absolutePath)) {
|
if (!addedFiles.contains(absolutePath)) {
|
||||||
addFileToZip(zos, file, "logs/");
|
addFileToZip(zos, file, "logs/" + file.getName());
|
||||||
addedFiles.add(absolutePath);
|
addedFiles.add(absolutePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -436,6 +441,24 @@ public class AxisInnovatorsBox {
|
|||||||
addFileToZip(zos, generateSystemProperties(), "debug_files/system_properties.txt");
|
addFileToZip(zos, generateSystemProperties(), "debug_files/system_properties.txt");
|
||||||
// 7. 添加环境变量
|
// 7. 添加环境变量
|
||||||
addFileToZip(zos, generateEnvironmentVariables(), "debug_files/environment_variables.txt");
|
addFileToZip(zos, generateEnvironmentVariables(), "debug_files/environment_variables.txt");
|
||||||
|
// 8.生成dump文件
|
||||||
|
addFileToZip(zos, generateFileDump(), "debug_files/dump.hprof");
|
||||||
|
}
|
||||||
|
|
||||||
|
private File generateFileDump() throws IOException {
|
||||||
|
final String javaLibraryPath = System.getProperty("java.library.path");
|
||||||
|
String jvmFolder = javaLibraryPath.contains(";")
|
||||||
|
? javaLibraryPath.substring(0, javaLibraryPath.indexOf(';'))
|
||||||
|
: javaLibraryPath;
|
||||||
|
logger.info("JVM folder: {}", jvmFolder);
|
||||||
|
File dumpFile = File.createTempFile("dump", ".hprof");
|
||||||
|
String dumpFilePath = dumpFile.getAbsolutePath();
|
||||||
|
if (!dumpFile.delete()) {
|
||||||
|
throw new IOException("Failed to delete temporary placeholder file");
|
||||||
|
}
|
||||||
|
HotSpotDiagnosticMXBean bean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
|
||||||
|
bean.dumpHeap(dumpFilePath, true);
|
||||||
|
return new File(dumpFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private File generateClassLoaderInfo() throws IOException {
|
private File generateClassLoaderInfo() throws IOException {
|
||||||
@@ -606,8 +629,7 @@ public class AxisInnovatorsBox {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String entryName = entryPath + file.getName();
|
ZipEntry zipEntry = new ZipEntry(entryPath);
|
||||||
ZipEntry zipEntry = new ZipEntry(entryName);
|
|
||||||
zos.putNextEntry(zipEntry);
|
zos.putNextEntry(zipEntry);
|
||||||
|
|
||||||
try (FileInputStream fis = new FileInputStream(file)) {
|
try (FileInputStream fis = new FileInputStream(file)) {
|
||||||
@@ -805,6 +827,22 @@ public class AxisInnovatorsBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void run(String[] args, boolean isDebug) {
|
public static void run(String[] args, boolean isDebug) {
|
||||||
|
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
|
||||||
|
if (main != null) {
|
||||||
|
main.organizingCrashReports(throwable instanceof Exception ?
|
||||||
|
(Exception) throwable : new Exception(throwable));
|
||||||
|
} else {
|
||||||
|
// 如果主类尚未初始化,创建临时实例处理崩溃
|
||||||
|
new AxisInnovatorsBox(args, isDebug)
|
||||||
|
.organizingCrashReports(throwable instanceof Exception ?
|
||||||
|
(Exception) throwable : new Exception(throwable));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 设置EDT(事件调度线程)的异常处理器
|
||||||
|
System.setProperty("sun.awt.exception.handler", EDTCrashHandler.class.getName());
|
||||||
|
|
||||||
main = new AxisInnovatorsBox(args,isDebug);
|
main = new AxisInnovatorsBox(args,isDebug);
|
||||||
try {
|
try {
|
||||||
main.initLog4j2();
|
main.initLog4j2();
|
||||||
@@ -880,7 +918,6 @@ public class AxisInnovatorsBox {
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}, "TrayThread").start();
|
}, "TrayThread").start();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("Failed to load plugins", e);
|
logger.error("Failed to load plugins", e);
|
||||||
if (main.ex != null) {
|
if (main.ex != null) {
|
||||||
@@ -972,4 +1009,16 @@ public class AxisInnovatorsBox {
|
|||||||
public StateManager getStateManager() {
|
public StateManager getStateManager() {
|
||||||
return stateManager;
|
return stateManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 专门处理EDT线程异常的处理器
|
||||||
|
*/
|
||||||
|
public static class EDTCrashHandler {
|
||||||
|
public void handle(Throwable throwable) {
|
||||||
|
if (main != null) {
|
||||||
|
main.organizingCrashReports(throwable instanceof Exception ?
|
||||||
|
(Exception) throwable : new Exception(throwable));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -126,10 +126,7 @@ public class Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加JVM关闭钩子确保锁释放
|
|
||||||
static {
|
static {
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
Runtime.getRuntime().addShutdownHook(new Thread(Main::releaseLock));
|
||||||
releaseLock();
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ public class CefAppManager {
|
|||||||
private static void initializeDefaultSettings() {
|
private static void initializeDefaultSettings() {
|
||||||
initLock.lock();
|
initLock.lock();
|
||||||
try {
|
try {
|
||||||
settings.windowless_rendering_enabled = false;
|
settings.windowless_rendering_enabled = true;
|
||||||
settings.javascript_flags = "--expose-gc";
|
settings.javascript_flags = "--expose-gc";
|
||||||
settings.cache_path = FolderCreator.getLibraryFolder() + "/jcef/cache";
|
settings.cache_path = FolderCreator.getLibraryFolder() + "/jcef/cache";
|
||||||
settings.root_cache_path = FolderCreator.getLibraryFolder() + "/jcef/cache";
|
settings.root_cache_path = FolderCreator.getLibraryFolder() + "/jcef/cache";
|
||||||
|
|||||||
@@ -1,138 +0,0 @@
|
|||||||
package com.axis.innovators.box.events;
|
|
||||||
|
|
||||||
import com.axis.innovators.box.gui.MainWindow;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分类栏的渲染事件
|
|
||||||
* @author tzdwindows 7
|
|
||||||
*/
|
|
||||||
public class CategoryRenderingEvent {
|
|
||||||
private final MainWindow.CustomTabbedPaneUI ui;
|
|
||||||
private final Graphics graphics;
|
|
||||||
private final int tabPlacement;
|
|
||||||
private final int tabIndex;
|
|
||||||
private final int x;
|
|
||||||
private final int y;
|
|
||||||
private final int width;
|
|
||||||
private final int height;
|
|
||||||
private final boolean isSelected;
|
|
||||||
private boolean isEnd = false;
|
|
||||||
|
|
||||||
public CategoryRenderingEvent(MainWindow.CustomTabbedPaneUI ui, Graphics graphics, int tabPlacement, int tabIndex, int x, int y, int width, int height, boolean isSelected) {
|
|
||||||
this.ui = ui;
|
|
||||||
this.graphics = graphics;
|
|
||||||
this.tabPlacement = tabPlacement;
|
|
||||||
this.tabIndex = tabIndex;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.isSelected = isSelected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MainWindow.CustomTabbedPaneUI getUi() {
|
|
||||||
return ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Graphics getGraphics() {
|
|
||||||
return graphics;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTabPlacement() {
|
|
||||||
return tabPlacement;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTabIndex() {
|
|
||||||
return tabIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getX() {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getY() {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWidth() {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeight() {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSelected() {
|
|
||||||
return isSelected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEnd() {
|
|
||||||
return isEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEnd(boolean end) {
|
|
||||||
isEnd = end;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class paintTabBorder {
|
|
||||||
private final MainWindow.CustomTabbedPaneUI event;
|
|
||||||
private final Graphics graphics;
|
|
||||||
private final int tabPlacement;
|
|
||||||
private final int tabIndex;
|
|
||||||
private final int x;
|
|
||||||
private final int y;
|
|
||||||
private final int width;
|
|
||||||
private final int height;
|
|
||||||
private final boolean isSelected;
|
|
||||||
|
|
||||||
public paintTabBorder(MainWindow.CustomTabbedPaneUI event, Graphics graphics, int tabPlacement, int tabIndex, int x, int y, int width, int height, boolean isSelected) {
|
|
||||||
this.event = event;
|
|
||||||
this.graphics = graphics;
|
|
||||||
this.tabPlacement = tabPlacement;
|
|
||||||
this.tabIndex = tabIndex;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.isSelected = isSelected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MainWindow.CustomTabbedPaneUI getEvent() {
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Graphics getGraphics() {
|
|
||||||
return graphics;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTabPlacement() {
|
|
||||||
return tabPlacement;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTabIndex() {
|
|
||||||
return tabIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getX() {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getY() {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWidth() {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeight() {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSelected() {
|
|
||||||
return isSelected;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -34,6 +34,7 @@ public class MainWindow extends JFrame {
|
|||||||
private final Color CARD_COLOR = Color.WHITE;
|
private final Color CARD_COLOR = Color.WHITE;
|
||||||
private final List<ToolCategory> categories = new ArrayList<>();
|
private final List<ToolCategory> categories = new ArrayList<>();
|
||||||
private SystemTray systemTray;
|
private SystemTray systemTray;
|
||||||
|
private JPanel contentPanel;
|
||||||
//private TrayIcon trayIcon;
|
//private TrayIcon trayIcon;
|
||||||
|
|
||||||
public MainWindow() {
|
public MainWindow() {
|
||||||
@@ -67,7 +68,7 @@ public class MainWindow extends JFrame {
|
|||||||
|
|
||||||
getContentPane().setBackground(new Color(0, 0, 0, 0));
|
getContentPane().setBackground(new Color(0, 0, 0, 0));
|
||||||
|
|
||||||
JPanel mainPanel = new JPanel();
|
JPanel mainPanel = new JPanel(new BorderLayout());
|
||||||
|
|
||||||
mainPanel.setOpaque(true);
|
mainPanel.setOpaque(true);
|
||||||
|
|
||||||
@@ -86,8 +87,87 @@ public class MainWindow extends JFrame {
|
|||||||
setVisible(false);
|
setVisible(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
JPanel sideBar = createSideBar();
|
||||||
|
mainPanel.add(sideBar, BorderLayout.WEST);
|
||||||
|
|
||||||
|
contentPanel = new JPanel(new BorderLayout());
|
||||||
|
contentPanel.setOpaque(false);
|
||||||
|
mainPanel.add(contentPanel, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
mainPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
|
||||||
|
|
||||||
|
add(mainPanel);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JPanel createSideBar() {
|
||||||
|
JPanel sidebar = new JPanel();
|
||||||
|
sidebar.setLayout(new BoxLayout(sidebar, BoxLayout.Y_AXIS));
|
||||||
|
sidebar.setBackground(new Color(35, 35, 35));
|
||||||
|
sidebar.setPreferredSize(new Dimension(180, getHeight()));
|
||||||
|
|
||||||
|
// 添加分类按钮
|
||||||
|
for (ToolCategory category : categories) {
|
||||||
|
JButton button = new JButton(category.getName());
|
||||||
|
button.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
|
button.setMaximumSize(new Dimension(160, 40));
|
||||||
|
button.setForeground(Color.WHITE);
|
||||||
|
button.setBackground(new Color(60, 60, 60));
|
||||||
|
button.setFocusPainted(false);
|
||||||
|
button.setBorderPainted(false);
|
||||||
|
button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||||
|
|
||||||
|
button.addActionListener(e -> {
|
||||||
|
JPanel toolsPanel = createToolsPanel(category);
|
||||||
|
toolsPanel.setOpaque(false);
|
||||||
|
contentPanel.removeAll();
|
||||||
|
JScrollPane scrollPane = new JScrollPane(toolsPanel);
|
||||||
|
scrollPane.setBorder(null);
|
||||||
|
scrollPane.setOpaque(false);
|
||||||
|
scrollPane.getViewport().setOpaque(false);
|
||||||
|
scrollPane.getVerticalScrollBar().setUI(new CustomScrollBarUI());
|
||||||
|
contentPanel.add(scrollPane, BorderLayout.CENTER);
|
||||||
|
contentPanel.revalidate();
|
||||||
|
contentPanel.repaint();
|
||||||
|
});
|
||||||
|
|
||||||
|
sidebar.add(Box.createVerticalStrut(10));
|
||||||
|
sidebar.add(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加设置按钮
|
||||||
|
JButton settingsButton = new JButton("设置");
|
||||||
|
settingsButton.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
|
settingsButton.setMaximumSize(new Dimension(160, 40));
|
||||||
|
settingsButton.setForeground(Color.WHITE);
|
||||||
|
settingsButton.setBackground(new Color(45, 45, 45));
|
||||||
|
settingsButton.setFocusPainted(false);
|
||||||
|
settingsButton.setBorderPainted(false);
|
||||||
|
settingsButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||||
|
settingsButton.addActionListener(e -> showSettings());
|
||||||
|
sidebar.add(Box.createVerticalGlue());
|
||||||
|
sidebar.add(settingsButton);
|
||||||
|
|
||||||
|
// 添加关于按钮
|
||||||
|
JButton aboutButton = new JButton("关于");
|
||||||
|
aboutButton.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
|
aboutButton.setMaximumSize(new Dimension(160, 40));
|
||||||
|
aboutButton.setForeground(Color.WHITE);
|
||||||
|
aboutButton.setBackground(new Color(45, 45, 45));
|
||||||
|
aboutButton.setFocusPainted(false);
|
||||||
|
aboutButton.setBorderPainted(false);
|
||||||
|
aboutButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||||
|
aboutButton.addActionListener(e -> JOptionPane.showMessageDialog(this, "作者: tzdwindows7"));
|
||||||
|
sidebar.add(Box.createVerticalStrut(10));
|
||||||
|
sidebar.add(aboutButton);
|
||||||
|
|
||||||
|
return sidebar;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private JPanel createFooter() {
|
private JPanel createFooter() {
|
||||||
JPanel footer = new JPanel();
|
JPanel footer = new JPanel();
|
||||||
footer.setLayout(new BoxLayout(footer, BoxLayout.X_AXIS));
|
footer.setLayout(new BoxLayout(footer, BoxLayout.X_AXIS));
|
||||||
@@ -652,11 +732,6 @@ public class MainWindow extends JFrame {
|
|||||||
protected void paintTabBackground(Graphics g, int tabPlacement,
|
protected void paintTabBackground(Graphics g, int tabPlacement,
|
||||||
int tabIndex, int x, int y, int w, int h,
|
int tabIndex, int x, int y, int w, int h,
|
||||||
boolean isSelected) {
|
boolean isSelected) {
|
||||||
CategoryRenderingEvent event = new CategoryRenderingEvent(this, g, tabPlacement, tabIndex, x, y, w, h, isSelected);
|
|
||||||
GlobalEventBus.EVENT_BUS.post(event);
|
|
||||||
if (event.isEnd()){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Graphics2D g2d = (Graphics2D) g.create();
|
Graphics2D g2d = (Graphics2D) g.create();
|
||||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
|
||||||
@@ -669,15 +744,6 @@ public class MainWindow extends JFrame {
|
|||||||
g2d.fillRoundRect(x + 2, y + 2, w - 4, h - 4, 10, 10);
|
g2d.fillRoundRect(x + 2, y + 2, w - 4, h - 4, 10, 10);
|
||||||
g2d.dispose();
|
g2d.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void paintTabBorder(Graphics g, int tabPlacement,
|
|
||||||
int tabIndex, int x, int y, int w, int h,
|
|
||||||
boolean isSelected) {
|
|
||||||
GlobalEventBus.EVENT_BUS.post(new CategoryRenderingEvent.paintTabBorder(this, g,
|
|
||||||
tabPlacement,
|
|
||||||
tabIndex, x, y, w, h, isSelected));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CardMouseAdapter extends MouseAdapter {
|
private class CardMouseAdapter extends MouseAdapter {
|
||||||
|
|||||||
@@ -14,9 +14,7 @@ import javax.swing.table.DefaultTableModel;
|
|||||||
import javax.swing.table.JTableHeader;
|
import javax.swing.table.JTableHeader;
|
||||||
import javax.swing.table.TableRowSorter;
|
import javax.swing.table.TableRowSorter;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.*;
|
||||||
import java.awt.event.MouseAdapter;
|
|
||||||
import java.awt.event.MouseEvent;
|
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
@@ -30,7 +28,7 @@ import java.text.DecimalFormat;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CancellationException;
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
public class MemoryAnalysisPanel extends JPanel {
|
public class MemoryAnalysisPanel extends JPanel {
|
||||||
private static final DecimalFormat MB_FORMAT = new DecimalFormat("#,##0.00");
|
private static final DecimalFormat MB_FORMAT = new DecimalFormat("#,##0.00");
|
||||||
@@ -92,6 +90,14 @@ public class MemoryAnalysisPanel extends JPanel {
|
|||||||
private final JTable specificClassInstanceTable;
|
private final JTable specificClassInstanceTable;
|
||||||
private final DefaultTableModel specificClassInstanceModel;
|
private final DefaultTableModel specificClassInstanceModel;
|
||||||
|
|
||||||
|
// 自动补全相关组件
|
||||||
|
private JPopupMenu autoCompletePopup;
|
||||||
|
private JList<String> autoCompleteList;
|
||||||
|
private DefaultListModel<String> autoCompleteModel;
|
||||||
|
private ScheduledExecutorService autoCompleteExecutor;
|
||||||
|
private final Map<String, List<String>> classCache = new ConcurrentHashMap<>();
|
||||||
|
private final Set<String> loadedPackages = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
// 特定类分析面板组件
|
// 特定类分析面板组件
|
||||||
private JPanel visualizationPanel;
|
private JPanel visualizationPanel;
|
||||||
private JLabel ratioLabel;
|
private JLabel ratioLabel;
|
||||||
@@ -99,6 +105,10 @@ public class MemoryAnalysisPanel extends JPanel {
|
|||||||
private JTextField instanceSearchField;
|
private JTextField instanceSearchField;
|
||||||
private TableRowSorter<DefaultTableModel> instanceSorter;
|
private TableRowSorter<DefaultTableModel> instanceSorter;
|
||||||
|
|
||||||
|
// 可调整大小的分割面板
|
||||||
|
private JSplitPane mainSplitPane;
|
||||||
|
private JSplitPane infoVisualizationSplitPane;
|
||||||
|
private JSplitPane visualizationInstanceSplitPane;
|
||||||
|
|
||||||
public MemoryAnalysisPanel() {
|
public MemoryAnalysisPanel() {
|
||||||
super(new BorderLayout());
|
super(new BorderLayout());
|
||||||
@@ -280,6 +290,231 @@ public class MemoryAnalysisPanel extends JPanel {
|
|||||||
// 初始刷新 - 只加载内存使用和内存池数据
|
// 初始刷新 - 只加载内存使用和内存池数据
|
||||||
showLoadingDialog("正在初始化内存数据...");
|
showLoadingDialog("正在初始化内存数据...");
|
||||||
refreshInitialData();
|
refreshInitialData();
|
||||||
|
|
||||||
|
// 初始化自动补全系统
|
||||||
|
initAutoCompleteSystem();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initAutoCompleteSystem() {
|
||||||
|
// 创建自动补全组件
|
||||||
|
autoCompleteModel = new DefaultListModel<>();
|
||||||
|
autoCompleteList = new JList<>(autoCompleteModel);
|
||||||
|
autoCompleteList.setFont(DebugWindow.MONOSPACE_FONT);
|
||||||
|
autoCompleteList.setBackground(new Color(50, 50, 50));
|
||||||
|
autoCompleteList.setForeground(FOREGROUND);
|
||||||
|
autoCompleteList.setSelectionBackground(ACCENT);
|
||||||
|
autoCompleteList.setSelectionForeground(FOREGROUND);
|
||||||
|
autoCompleteList.setFixedCellHeight(25);
|
||||||
|
|
||||||
|
autoCompletePopup = new JPopupMenu();
|
||||||
|
autoCompletePopup.setBorder(BorderFactory.createLineBorder(new Color(80, 80, 80)));
|
||||||
|
autoCompletePopup.add(new JScrollPane(autoCompleteList));
|
||||||
|
|
||||||
|
// 添加选择监听器
|
||||||
|
autoCompleteList.addMouseListener(new MouseAdapter() {
|
||||||
|
@Override
|
||||||
|
public void mouseClicked(MouseEvent e) {
|
||||||
|
if (e.getClickCount() == 1) {
|
||||||
|
selectAutoCompleteItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加键盘监听器
|
||||||
|
specificClassField.addKeyListener(new KeyAdapter() {
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyEvent e) {
|
||||||
|
handleAutoCompleteKeyPress(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加文档监听器
|
||||||
|
specificClassField.getDocument().addDocumentListener(new DocumentListener() {
|
||||||
|
@Override
|
||||||
|
public void insertUpdate(DocumentEvent e) {
|
||||||
|
scheduleAutoCompleteUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeUpdate(DocumentEvent e) {
|
||||||
|
scheduleAutoCompleteUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void changedUpdate(DocumentEvent e) {
|
||||||
|
scheduleAutoCompleteUpdate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化线程池
|
||||||
|
autoCompleteExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scheduleAutoCompleteUpdate() {
|
||||||
|
// 取消之前的任务
|
||||||
|
autoCompleteExecutor.shutdownNow();
|
||||||
|
autoCompleteExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
|
||||||
|
// 安排新任务
|
||||||
|
autoCompleteExecutor.schedule(() -> {
|
||||||
|
SwingUtilities.invokeLater(this::updateAutoCompleteSuggestions);
|
||||||
|
}, 300, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateAutoCompleteSuggestions() {
|
||||||
|
String text = specificClassField.getText().trim();
|
||||||
|
if (text.isEmpty()) {
|
||||||
|
autoCompletePopup.setVisible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取或加载建议
|
||||||
|
List<String> suggestions = getAutoCompleteSuggestions(text);
|
||||||
|
autoCompleteModel.clear();
|
||||||
|
|
||||||
|
if (suggestions.isEmpty()) {
|
||||||
|
autoCompletePopup.setVisible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加到模型
|
||||||
|
for (String suggestion : suggestions) {
|
||||||
|
autoCompleteModel.addElement(suggestion);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示弹出菜单
|
||||||
|
if (!autoCompletePopup.isVisible()) {
|
||||||
|
showAutoCompletePopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择第一个项目
|
||||||
|
autoCompleteList.setSelectedIndex(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getAutoCompleteSuggestions(String input) {
|
||||||
|
String packagePrefix = input.contains(".") ?
|
||||||
|
input.substring(0, input.lastIndexOf('.') + 1) :
|
||||||
|
"";
|
||||||
|
|
||||||
|
// 如果包名部分发生变化,重新加载该包下的类
|
||||||
|
if (!classCache.containsKey(packagePrefix) || !loadedPackages.contains(packagePrefix)) {
|
||||||
|
loadPackageClasses(packagePrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> allClasses = classCache.getOrDefault(packagePrefix, new ArrayList<>());
|
||||||
|
String searchTerm = input.toLowerCase();
|
||||||
|
|
||||||
|
// 过滤匹配的类
|
||||||
|
List<String> suggestions = new ArrayList<>();
|
||||||
|
for (String className : allClasses) {
|
||||||
|
if (className.toLowerCase().contains(searchTerm)) {
|
||||||
|
suggestions.add(className);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 限制数量
|
||||||
|
if (suggestions.size() >= 100) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按匹配度排序
|
||||||
|
suggestions.sort((s1, s2) -> {
|
||||||
|
int pos1 = s1.toLowerCase().indexOf(searchTerm);
|
||||||
|
int pos2 = s2.toLowerCase().indexOf(searchTerm);
|
||||||
|
return Integer.compare(pos1, pos2);
|
||||||
|
});
|
||||||
|
|
||||||
|
return suggestions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadPackageClasses(String packageName) {
|
||||||
|
// 对于根包的特殊处理
|
||||||
|
if (packageName.isEmpty()) {
|
||||||
|
packageName = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> classes = new ArrayList<>();
|
||||||
|
Class<?>[] allClasses = instrumentation.getAllLoadedClasses();
|
||||||
|
|
||||||
|
for (Class<?> clazz : allClasses) {
|
||||||
|
String className = clazz.getName();
|
||||||
|
|
||||||
|
// 只处理包匹配的类
|
||||||
|
if (packageName.isEmpty() || className.startsWith(packageName)) {
|
||||||
|
classes.add(className);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缓存结果
|
||||||
|
classCache.put(packageName, classes);
|
||||||
|
loadedPackages.add(packageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showAutoCompletePopup() {
|
||||||
|
if (specificClassField.isShowing()) {
|
||||||
|
// 计算弹出位置
|
||||||
|
Point location = specificClassField.getLocationOnScreen();
|
||||||
|
location.y += specificClassField.getHeight();
|
||||||
|
|
||||||
|
// 设置弹出大小
|
||||||
|
int width = Math.max(specificClassField.getWidth(), 400);
|
||||||
|
int height = Math.min(autoCompleteModel.size() * 25, 300);
|
||||||
|
autoCompletePopup.setPopupSize(width, height);
|
||||||
|
|
||||||
|
// 显示弹出菜单
|
||||||
|
autoCompletePopup.show(specificClassField, 0, specificClassField.getHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleAutoCompleteKeyPress(KeyEvent e) {
|
||||||
|
if (!autoCompletePopup.isVisible()) return;
|
||||||
|
|
||||||
|
switch (e.getKeyCode()) {
|
||||||
|
case KeyEvent.VK_UP:
|
||||||
|
moveSelection(-1);
|
||||||
|
e.consume();
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_DOWN:
|
||||||
|
moveSelection(1);
|
||||||
|
e.consume();
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_ENTER:
|
||||||
|
selectAutoCompleteItem();
|
||||||
|
e.consume();
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_ESCAPE:
|
||||||
|
autoCompletePopup.setVisible(false);
|
||||||
|
e.consume();
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_TAB:
|
||||||
|
if (autoCompleteList.getSelectedIndex() >= 0) {
|
||||||
|
selectAutoCompleteItem();
|
||||||
|
e.consume();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void moveSelection(int direction) {
|
||||||
|
int selected = autoCompleteList.getSelectedIndex();
|
||||||
|
int newIndex = selected + direction;
|
||||||
|
|
||||||
|
if (newIndex >= 0 && newIndex < autoCompleteModel.size()) {
|
||||||
|
autoCompleteList.setSelectedIndex(newIndex);
|
||||||
|
autoCompleteList.ensureIndexIsVisible(newIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void selectAutoCompleteItem() {
|
||||||
|
String selected = autoCompleteList.getSelectedValue();
|
||||||
|
if (selected != null) {
|
||||||
|
specificClassField.setText(selected);
|
||||||
|
autoCompletePopup.setVisible(false);
|
||||||
|
specificClassField.requestFocus();
|
||||||
|
|
||||||
|
// 将光标移动到文本末尾
|
||||||
|
specificClassField.setCaretPosition(selected.length());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private JPanel createSpecificClassAnalysisPanel() {
|
private JPanel createSpecificClassAnalysisPanel() {
|
||||||
@@ -316,41 +551,44 @@ public class MemoryAnalysisPanel extends JPanel {
|
|||||||
inputPanel.add(classLabel, BorderLayout.WEST);
|
inputPanel.add(classLabel, BorderLayout.WEST);
|
||||||
inputPanel.add(fieldPanel, BorderLayout.CENTER);
|
inputPanel.add(fieldPanel, BorderLayout.CENTER);
|
||||||
|
|
||||||
// 主内容面板 (使用网格袋布局)
|
// 使用分割面板替代网格袋布局
|
||||||
JPanel mainContentPanel = new JPanel(new GridBagLayout());
|
mainSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
|
||||||
mainContentPanel.setBackground(BACKGROUND);
|
mainSplitPane.setDividerLocation(0.4); // 初始比例为40%
|
||||||
GridBagConstraints gbc = new GridBagConstraints();
|
mainSplitPane.setResizeWeight(0.4);
|
||||||
gbc.fill = GridBagConstraints.BOTH;
|
mainSplitPane.setBorder(BorderFactory.createEmptyBorder());
|
||||||
gbc.weightx = 1.0;
|
mainSplitPane.setContinuousLayout(true);
|
||||||
gbc.insets = new Insets(5, 5, 5, 5);
|
mainSplitPane.setDividerSize(5);
|
||||||
|
mainSplitPane.setBackground(BACKGROUND);
|
||||||
|
|
||||||
// 类信息面板
|
// 上半部分:类信息面板
|
||||||
JPanel infoPanel = createClassInfoPanel();
|
JPanel infoPanel = createClassInfoPanel();
|
||||||
gbc.gridx = 0;
|
infoPanel.setMinimumSize(new Dimension(100, 100));
|
||||||
gbc.gridy = 0;
|
|
||||||
gbc.gridwidth = 2;
|
// 下半部分:可视化+实例列表
|
||||||
gbc.weighty = 0.4;
|
JSplitPane bottomSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
|
||||||
mainContentPanel.add(infoPanel, gbc);
|
bottomSplitPane.setDividerLocation(0.3); // 初始比例为30%
|
||||||
|
bottomSplitPane.setResizeWeight(0.3);
|
||||||
|
bottomSplitPane.setContinuousLayout(true);
|
||||||
|
bottomSplitPane.setDividerSize(5);
|
||||||
|
bottomSplitPane.setBackground(BACKGROUND);
|
||||||
|
|
||||||
// 可视化面板
|
// 可视化面板
|
||||||
visualizationPanel = createVisualizationPanel();
|
visualizationPanel = createVisualizationPanel();
|
||||||
gbc.gridx = 0;
|
visualizationPanel.setMinimumSize(new Dimension(100, 100));
|
||||||
gbc.gridy = 1;
|
|
||||||
gbc.gridwidth = 1;
|
|
||||||
gbc.weighty = 0.1;
|
|
||||||
mainContentPanel.add(visualizationPanel, gbc);
|
|
||||||
|
|
||||||
// 实例列表面板
|
// 实例列表面板
|
||||||
JPanel instancesPanel = createInstancesPanel();
|
JPanel instancesPanel = createInstancesPanel();
|
||||||
gbc.gridx = 1;
|
instancesPanel.setMinimumSize(new Dimension(100, 100));
|
||||||
gbc.gridy = 1;
|
|
||||||
gbc.gridwidth = 1;
|
bottomSplitPane.setLeftComponent(visualizationPanel);
|
||||||
gbc.weighty = 0.5;
|
bottomSplitPane.setRightComponent(instancesPanel);
|
||||||
mainContentPanel.add(instancesPanel, gbc);
|
|
||||||
|
mainSplitPane.setTopComponent(infoPanel);
|
||||||
|
mainSplitPane.setBottomComponent(bottomSplitPane);
|
||||||
|
|
||||||
// 添加主内容面板到中心
|
// 添加主内容面板到中心
|
||||||
panel.add(inputPanel, BorderLayout.NORTH);
|
panel.add(inputPanel, BorderLayout.NORTH);
|
||||||
panel.add(mainContentPanel, BorderLayout.CENTER);
|
panel.add(mainSplitPane, BorderLayout.CENTER);
|
||||||
|
|
||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import java.nio.file.Paths;
|
|||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
HighAccuracySpeechRecognition recognizer = new HighAccuracySpeechRecognition(
|
//HighAccuracySpeechRecognition recognizer = new HighAccuracySpeechRecognition(
|
||||||
"C:\\Users\\Administrator\\Desktop\\声音识别模型\\vosk-model-cn-0.22",
|
// "C:\\Users\\Administrator\\Desktop\\声音识别模型\\vosk-model-cn-0.22",
|
||||||
"output"
|
// "output"
|
||||||
);
|
//);
|
||||||
|
//
|
||||||
recognizer.processAudio(Paths.get("G:\\鬼畜素材\\工作间\\哪吒-嗵嗵\\哪吒-嗵嗵1.wav"));
|
//recognizer.processAudio(Paths.get("G:\\鬼畜素材\\工作间\\哪吒-嗵嗵\\哪吒-嗵嗵1.wav"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
src/main/java/org/tzd/explorer/DesktopIconRenderer.java
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
package org.tzd.explorer;
|
||||||
|
|
||||||
|
public class DesktopIconRenderer {
|
||||||
|
}
|
||||||
BIN
src/main/resources/icons/programming/JarApiViewer/cfg_file.png
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
src/main/resources/icons/programming/JarApiViewer/exe_file.png
Normal file
|
After Width: | Height: | Size: 108 KiB |
BIN
src/main/resources/icons/programming/JarApiViewer/file.png
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
src/main/resources/icons/programming/JarApiViewer/file_jar.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
src/main/resources/icons/programming/JarApiViewer/java_file.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 92 KiB |
BIN
src/main/resources/icons/programming/JarApiViewer/toml_file.png
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
src/main/resources/icons/programming/JarApiViewer/zip_file.png
Normal file
|
After Width: | Height: | Size: 22 KiB |