feat(box): 添加命令行文件解析功能并优化主题和语言管理- 新增 ArgsParser 类用于解析命令行参数中的文件路径

- 添加 OpenFileEvents 事件类用于处理打开文件请求
- 更新 AxisInnovatorsBox 类,支持命令行文件解析
- 重构 LanguageManager 类,优化语言合并和加载逻辑
- 更新 MainWindow 类,改进界面样式和滚动条UI
- 修改 PluginDescriptor 类,增加注册名字段
This commit is contained in:
tzdwindows 7
2025-02-21 20:55:10 +08:00
parent 97b071ece8
commit 701dfcfb47
20 changed files with 614 additions and 436 deletions

View File

@@ -42,8 +42,12 @@ dependencies {
implementation 'com.google.code.gson:gson:2.8.9'
implementation 'com.formdev:flatlaf:0.26'
implementation 'commons-io:commons-io:2.11.0'
//implementation 'com.formdev:flatlaf:0.26'
implementation 'commons-io:commons-io:2.14.0'
implementation 'com.formdev:flatlaf:3.2.1' // FlatLaf核心
implementation 'com.formdev:flatlaf-extras:3.2.1' // 扩展组件
implementation 'com.formdev:flatlaf-intellij-themes:3.2.1' // 官方主题包
}
// 分离依赖项到 libs 目录

View File

@@ -1,99 +0,0 @@
default_theme.system.topicName=Default Theme
default_theme.default.tip=Default theme
metal_theme.system.topicName=Metal Style
metal_theme.default.tip=Metal style
motif_theme.system.topicName=Motif Style
motif_theme.default.tip=Motif style
flatLightLaf_theme.system.topicName=flatLightLaf Style
flatLightLaf_theme.default.tip=flatLightLaf style
mainWindow.title=Axis Creation Toolbox v1.0
mainWindow.title.2=Axis Creation Toolbox
mainWindow.settings.title=System Settings
andShow.title=Program Crash Report
andShow.title.2=<html><h2 style='color: #D32F2F;'>A serious error occurred in the program</h2></html>
andShow.title.3=<html><h3 style='color: #FF0000;'>Please report it to us!</h3></html>
andShow.pluginInfo.title==== Loaded Plugins ===
andShow.pluginInfo.title.1=Plugin Name:
andShow.pluginInfo.title.2=Plugin Description:
andShow.pluginInfo.title.3=Supported Versions:
andShow.pluginInfo.exportButton=Export Report
andShow.pluginInfo.closeButton=Close
andShow.pluginInfo.writer=The report has been saved to:
andShow.pluginInfo.writer.title=Export Successful
andShow.pluginInfo.writer.error=Export Failed:
andShow.pluginInfo.error.writer.title=Error
progressBarManager.title=Loading...
fridaWindow.title=Frida Injection Tool
fridaWindow.pidField=Enter Process PID
fridaWindow.browseButton=Select Process
fridaWindow.panel=Script Editor
fridaWindow.injectButton=Inject Script
fridaWindow.panel.log=Log Output
fridaWindow.processSelectionWindow=Select Process
fridaWindow.processSelectionWindow.search=Search Process
fridaWindow.processSelectionWindow.columns.1=Process Name
fridaWindow.processSelectionWindow.columns.2=Process ID
fridaWindow.processSelectionWindow.selectButton=Select
localWindow.newBtn=New Conversation
localWindow.saveBtn=Save Record
localWindow.cudaCheck=Enable CUDA
localWindow.searchBtn=Start Search
localWindow.searchBtn.1=Close Search
localWindow.searchBtn.appendMessage=Search functionality is enabled
localWindow.searchBtn.appendMessage.1=Search functionality is disabled
localWindow.sendButton=Send
localWindow.prompt.system=You are a helpful AI assistant. Please respond to user questions in a friendly and natural tone. Users may provide search results, and you should integrate those results into your answers.
localWindow.prompt.system.2=You are a search-focused assistant. Users will provide links, summaries, titles, and scraped content, and your job is to output the most relevant content to the user's question.
localWindow.prompt.name=[User]
settings.1.title=Plugins
settings.2.title=Basic Settings
settings.3.title=About
settings.4.title=Themes
settings.1.tip=Plugin Management
settings.2.tip=Appearance Settings
settings.3.tip=Version Information
settings.4.tip=Theme Management
settings.1.columns.1=Plugin Name
settings.1.columns.2=Supported Versions
settings.1.columns.3=Description
settings.1.scrollPane=Loaded Plugin List
settings.2.color=Interface Theme Color:
settings.2.colorBtn=Select Color
settings.2.colorBtn.color=Select Theme Color
settings.2.font=Interface Font:
settings.2.fontBtn=Select Font
settings.2.showConfirmDialog=Select Font
settings.2.cuda=Use CUDA for AI Inference:
settings.2.cudaCheckBox=Enable CUDA Acceleration
settings.2.cuda.error=Unable to reload AI inference library, please check the CUDA environment
settings.2.cuda.error.1=Error
settings.2.language=Interface Language:
settings.2.language.error=Unknown Language
settings.3.infoArea.1=Software Version:
settings.3.infoArea.2=Developer:
settings.4.no_theme=No available themes
settings.4.search=Search
settings.4.search_empty=Please enter search content!
settings.4.search_empty_title=Prompt
settings.4.search_not_found=No matching themes found!
settings.4.search_not_found_title=Prompt
settings.4.loading=This theme has already been loaded, no need to load again!
settings.4.loading_title=Prompt
settings.4.load=Load Theme
settings.4.info=Theme Class:
settings.4.info.1=Theme Name:
settings.4.info.2=Tip:
settings.4.info.3=Register Name:
settings.4.load_theme_success=Theme '
settings.4.load_theme_success.2=' loaded successfully!
settings.4.load_theme_success.3=Success
settings.4.load_theme_error=Failed to load theme:
settings.4.load_theme_error.title=Error

View File

@@ -1,99 +0,0 @@
default_theme.system.topicName=\u9ED8\u8BA4\u4E3B\u9898
default_theme.default.tip=\u9ED8\u8BA4\u7684\u4E3B\u9898
metal_theme.system.topicName=Metal\u98CE\u683C
metal_theme.default.tip=Metal\u98CE\u683C
motif_theme.system.topicName=Motif\u98CE\u683C
motif_theme.default.tip=Motif\u98CE\u683C
flatLightLaf_theme.system.topicName=flatLightLaf\u98CE\u683C
flatLightLaf_theme.default.tip=flatLightLaf\u98CE\u683C
mainWindow.title=\u8F74\u521B\u5DE5\u5177\u7BB1 v1.0
mainWindow.title.2=\u8F74\u521B\u5DE5\u5177\u7BB1
mainWindow.settings.title=\u7CFB\u7EDF\u8BBE\u7F6E
andShow.title=\u7A0B\u5E8F\u5D29\u6E83\u62A5\u544A
andShow.title.2=<html><h2 style='color: #D32F2F;'>\u7A0B\u5E8F\u53D1\u751F\u4E25\u91CD\u9519\u8BEF</h2></html>
andShow.title.3=<html><h3 style='color: #FF0000;'>\u8BF7\u5411\u6211\u4EEC\u53CD\u9988\uFF01</h3></html>
andShow.pluginInfo.title==== \u52A0\u8F7D\u7684\u63D2\u4EF6 ===
andShow.pluginInfo.title.1=\u63D2\u4EF6\u540D\u79F0:
andShow.pluginInfo.title.2=\u63D2\u4EF6\u63CF\u8FF0:
andShow.pluginInfo.title.3=\u652F\u6301\u7684\u7248\u672C:
andShow.pluginInfo.exportButton=\u5BFC\u51FA\u62A5\u544A
andShow.pluginInfo.closeButton=\u5173\u95ED
andShow.pluginInfo.writer=\u62A5\u544A\u5DF2\u4FDD\u5B58\u81F3:
andShow.pluginInfo.writer.title=\u5BFC\u51FA\u6210\u529F
andShow.pluginInfo.writer.error=\u5BFC\u51FA\u5931\u8D25:
andShow.pluginInfo.error.writer.title=\u9519\u8BEF
progressBarManager.title=\u52A0\u8F7D\u4E2D...
fridaWindow.title=Frida \u6CE8\u5165\u5DE5\u5177
fridaWindow.pidField=\u8BF7\u8F93\u5165\u8FDB\u7A0BPID
fridaWindow.browseButton=\u9009\u62E9\u8FDB\u7A0B
fridaWindow.panel=\u811A\u672C\u7F16\u8F91\u5668
fridaWindow.injectButton=\u6CE8\u5165\u811A\u672C
fridaWindow.panel.log=\u65E5\u5FD7\u8F93\u51FA
fridaWindow.processSelectionWindow=\u9009\u62E9\u8FDB\u7A0B
fridaWindow.processSelectionWindow.search=\u641C\u7D22\u8FDB\u7A0B
fridaWindow.processSelectionWindow.columns.1=\u8FDB\u7A0B\u540D\u79F0
fridaWindow.processSelectionWindow.columns.2=\u8FDB\u7A0BID
fridaWindow.processSelectionWindow.selectButton=\u9009\u62E9
localWindow.newBtn=\u65B0\u5BF9\u8BDD
localWindow.saveBtn=\u4FDD\u5B58\u8BB0\u5F55
localWindow.cudaCheck=\u542F\u7528CUDA
localWindow.searchBtn=\u5F00\u542F\u641C\u7D22
localWindow.searchBtn.1=\u5173\u95ED\u641C\u7D22
localWindow.searchBtn.appendMessage=\u641C\u7D22\u529F\u80FD\u5DF2\u5F00\u542F
localWindow.searchBtn.appendMessage.1=\u641C\u7D22\u529F\u80FD\u5DF2\u5173\u95ED
localWindow.sendButton=\u53D1\u9001
localWindow.prompt.system=\u4F60\u662F\u4E00\u4E2A\u4E50\u4E8E\u52A9\u4EBA\u7684AI\u52A9\u624B\uFF0C\u8BF7\u7528\u53CB\u597D\u81EA\u7136\u7684\u8BED\u6C14\u56DE\u7B54\u7528\u6237\u95EE\u9898,\u7528\u6237\u53EF\u80FD\u4F1A\u63D0\u4F9B\u4E00\u4E9B\u641C\u7D22\u7ED3\u679C\u8BF7\u4F60\u7ED3\u5408\u641C\u7D22\u7ED3\u679C\u6765\u56DE\u7B54\u7528\u6237\u3002
localWindow.prompt.system.2=\u4F60\u662F\u4E00\u4E2A\u4E13\u6CE8\u68C0\u7D22\u641C\u7D22\u4FE1\u606F\u7684\u52A9\u624B\uFF0C\u7528\u6237\u5C06\u63D0\u4F9B\u4E00\u4E9B\u94FE\u63A5\u3001\u6458\u8981\u3001\u6807\u9898\u3001\u722C\u53D6\u5230\u7684\u5185\u5BB9\uFF0C\u4F60\u7684\u4F5C\u7528\u5C31\u662F\u8F93\u51FA\u4E3B\u8981\u5185\u5BB9\u4E0E\u7528\u6237\u95EE\u9898\u76F8\u5173\u7684\u5185\u5BB9\u3002
localWindow.prompt.name=\u3010\u7528\u6237\u3011
settings.1.title=\u63D2\u4EF6
settings.2.title=\u57FA\u7840\u8BBE\u7F6E
settings.3.title=\u5173\u4E8E
settings.4.title=\u4E3B\u9898
settings.1.tip=\u63D2\u4EF6\u7BA1\u7406
settings.2.tip=\u5916\u89C2\u8BBE\u7F6E
settings.3.tip=\u7248\u672C\u4FE1\u606F
settings.4.tip=\u4E3B\u9898\u7BA1\u7406
settings.1.columns.1=\u63D2\u4EF6\u540D\u79F0
settings.1.columns.2=\u7248\u672C\u652F\u6301
settings.1.columns.3=\u63CF\u8FF0
settings.1.scrollPane=\u5DF2\u52A0\u8F7D\u63D2\u4EF6\u5217\u8868
settings.2.color=\u754C\u9762\u4E3B\u9898\u989C\u8272\uFF1A
settings.2.colorBtn=\u9009\u62E9\u989C\u8272
settings.2.colorBtn.color=\u9009\u62E9\u4E3B\u9898\u989C\u8272
settings.2.font=\u754C\u9762\u5B57\u4F53\uFF1A
settings.2.fontBtn=\u9009\u62E9\u5B57\u4F53
settings.2.showConfirmDialog=\u9009\u62E9\u5B57\u4F53
settings.2.cuda=AI\u63A8\u7406\u65F6\u4F7F\u7528CUDA\uFF1A
settings.2.cudaCheckBox=\u542F\u7528CUDA\u52A0\u901F
settings.2.cuda.error=\u65E0\u6CD5\u91CD\u65B0\u52A0\u8F7DAI\u63A8\u7406\u5E93\uFF0C\u8BF7\u68C0\u67E5CUDA\u73AF\u5883
settings.2.cuda.error.1=\u9519\u8BEF
settings.2.language=\u754C\u9762\u8BED\u8A00\uFF1A
settings.2.language.error=\u672A\u77E5\u8BED\u8A00
settings.3.infoArea.1=\u8F6F\u4EF6\u7248\u672C:
settings.3.infoArea.2=\u5F00\u53D1\u4F5C\u8005:
settings.4.no_theme=\u6CA1\u6709\u53EF\u7528\u7684\u4E3B\u9898
settings.4.search=\u641C\u7D22
settings.4.search_empty=\u8BF7\u8F93\u5165\u641C\u7D22\u5185\u5BB9\uFF01
settings.4.search_empty_title=\u63D0\u793A
settings.4.search_not_found=\u672A\u627E\u5230\u5339\u914D\u7684\u4E3B\u9898\uFF01
settings.4.search_not_found_title=\u63D0\u793A
settings.4.loading=\u8BE5\u4E3B\u9898\u5DF2\u52A0\u8F7D\uFF0C\u65E0\u9700\u91CD\u590D\u52A0\u8F7D\uFF01
settings.4.loading_title=\u63D0\u793A
settings.4.load=\u52A0\u8F7D\u4E3B\u9898
settings.4.info=\u4E3B\u9898\u7C7B:
settings.4.info.1=\u4E3B\u9898\u540D:
settings.4.info.2=\u63D0\u793A:
settings.4.info.3=\u6CE8\u518C\u540D:
settings.4.load_theme_success=\u4E3B\u9898 '
settings.4.load_theme_success.2=' \u5DF2\u6210\u529F\u52A0\u8F7D\uFF01
settings.4.load_theme_success.3=\u6210\u529F
settings.4.load_theme_error=\u52A0\u8F7D\u4E3B\u9898\u5931\u8D25:
settings.4.load_theme_error.title=\u9519\u8BEF

View File

@@ -1,99 +0,0 @@
default_theme.system.topicName=\u9810\u8A2D\u4E3B\u984C
default_theme.default.tip=\u9810\u8A2D\u7684\u4E3B\u984C
metal_theme.system.topicName=Metal\u98A8\u683C
metal_theme.default.tip=Metal\u98A8\u683C
motif_theme.system.topicName=Motif\u98A8\u683C
motif_theme.default.tip=Motif\u98A8\u683C
flatLightLaf_theme.system.topicName=flatLightLaf\u98A8\u683C
flatLightLaf_theme.default.tip=flatLightLaf\u98A8\u683C
mainWindow.title=\u8EF8\u5275\u5DE5\u5177\u7BB1 v1.0
mainWindow.title.2=\u8EF8\u5275\u5DE5\u5177\u7BB1
mainWindow.settings.title=\u7CFB\u7D71\u8A2D\u7F6E
andShow.title=\u7A0B\u5F0F\u5D29\u6F70\u5831\u544A
andShow.title.2=<html><h2 style='color: #D32F2F;'>\u7A0B\u5F0F\u767C\u751F\u56B4\u91CD\u932F\u8AA4</h2></html>
andShow.title.3=<html><h3 style='color: #FF0000;'>\u8ACB\u5411\u6211\u5011\u53CD\u994B\uFF01</h3></html>
andShow.pluginInfo.title==== \u8F09\u5165\u7684\u63D2\u4EF6 ===
andShow.pluginInfo.title.1=\u63D2\u4EF6\u540D\u7A31:
andShow.pluginInfo.title.2=\u63D2\u4EF6\u63CF\u8FF0:
andShow.pluginInfo.title.3=\u652F\u63F4\u7684\u7248\u672C:
andShow.pluginInfo.exportButton=\u532F\u51FA\u5831\u544A
andShow.pluginInfo.closeButton=\u95DC\u9589
andShow.pluginInfo.writer=\u5831\u544A\u5DF2\u5132\u5B58\u81F3:
andShow.pluginInfo.writer.title=\u532F\u51FA\u6210\u529F
andShow.pluginInfo.writer.error=\u532F\u51FA\u5931\u6557:
andShow.pluginInfo.error.writer.title=\u932F\u8AA4
progressBarManager.title=\u52A0\u8F09\u4E2D...
fridaWindow.title=Frida \u6CE8\u5165\u5DE5\u5177
fridaWindow.pidField=\u8F38\u5165\u9032\u7A0BPID
fridaWindow.browseButton=\u9078\u64C7\u9032\u7A0B
fridaWindow.panel=\u8173\u672C\u7DE8\u8F2F\u5668
fridaWindow.injectButton=\u6CE8\u5165\u8173\u672C
fridaWindow.panel.log=\u65E5\u8A8C\u8F38\u51FA
fridaWindow.processSelectionWindow=\u9078\u64C7\u9032\u7A0B
fridaWindow.processSelectionWindow.search=\u641C\u5C0B\u9032\u7A0B
fridaWindow.processSelectionWindow.columns.1=\u9032\u7A0B\u540D\u7A31
fridaWindow.processSelectionWindow.columns.2=\u9032\u7A0BID
fridaWindow.processSelectionWindow.selectButton=\u9078\u64C7
localWindow.newBtn=\u65B0\u5C0D\u8A71
localWindow.saveBtn=\u4FDD\u5B58\u8A18\u9304
localWindow.cudaCheck=\u555F\u7528CUDA
localWindow.searchBtn=\u958B\u555F\u641C\u5C0B
localWindow.searchBtn.1=\u95DC\u9589\u641C\u5C0B
localWindow.searchBtn.appendMessage=\u641C\u5C0B\u529F\u80FD\u5DF2\u958B\u555F
localWindow.searchBtn.appendMessage.1=\u641C\u5C0B\u529F\u80FD\u5DF2\u95DC\u9589
localWindow.sendButton=\u767C\u9001
localWindow.prompt.system=\u4F60\u662F\u4E00\u4E2A\u4E50\u4E8E\u52A9\u4EBA\u7684AI\u52A9\u624B\uFF0C\u8BF7\u7528\u53CB\u597D\u81EA\u7136\u7684\u8BED\u6C14\u56DE\u7B54\u7528\u6237\u95EE\u9898,\u7528\u6237\u53EF\u80FD\u4F1A\u63D0\u4F9B\u4E00\u4E9B\u641C\u7D22\u7ED3\u679C\u8BF7\u4F60\u7ED3\u5408\u641C\u7D22\u7ED3\u679C\u6765\u56DE\u7B54\u7528\u6237\u3002
localWindow.prompt.system.2=\u4F60\u662F\u4E00\u4E2A\u4E13\u6CE8\u68C0\u7D22\u641C\u7D22\u4FE1\u606F\u7684\u52A9\u624B\uFF0C\u7528\u6237\u5C06\u63D0\u4F9B\u4E00\u4E9B\u94FE\u63A5\u3001\u6458\u8981\u3001\u6807\u9898\u3001\u722C\u53D6\u5230\u7684\u5185\u5BB9\uFF0C\u4F60\u7684\u4F5C\u7528\u5C31\u662F\u8F93\u51FA\u4E3B\u8981\u5185\u5BB9\u4E0E\u7528\u6237\u95EE\u9898\u76F8\u5173\u7684\u5185\u5BB9\u3002
localWindow.prompt.name=[\u7528\u6236]
settings.1.title=\u63D2\u4EF6
settings.2.title=\u57FA\u672C\u8A2D\u7F6E
settings.3.title=\u95DC\u65BC
settings.4.title=\u4E3B\u984C
settings.1.tip=\u63D2\u4EF6\u7BA1\u7406
settings.2.tip=\u5916\u89C0\u8A2D\u7F6E
settings.3.tip=\u7248\u672C\u4FE1\u606F
settings.4.tip=\u4E3B\u984C\u7BA1\u7406
settings.1.columns.1=\u63D2\u4EF6\u540D\u7A31
settings.1.columns.2=\u7248\u672C\u652F\u6301
settings.1.columns.3=\u63CF\u8FF0
settings.1.scrollPane=\u5DF2\u8F09\u5165\u63D2\u4EF6\u5217\u8868
settings.2.color=\u4ECB\u9762\u4E3B\u984C\u984F\u8272\uFF1A
settings.2.colorBtn=\u9078\u64C7\u984F\u8272
settings.2.colorBtn.color=\u9078\u64C7\u4E3B\u984C\u984F\u8272
settings.2.font=\u4ECB\u9762\u5B57\u9AD4\uFF1A
settings.2.fontBtn=\u9078\u64C7\u5B57\u9AD4
settings.2.showConfirmDialog=\u9078\u64C7\u5B57\u9AD4
settings.2.cuda=AI\u63A8\u7406\u6642\u4F7F\u7528CUDA\uFF1A
settings.2.cudaCheckBox=\u555F\u7528CUDA\u52A0\u901F
settings.2.cuda.error=\u7121\u6CD5\u91CD\u65B0\u52A0\u8F09AI\u63A8\u7406\u5EAB\uFF0C\u8ACB\u6AA2\u67E5CUDA\u74B0\u5883
settings.2.cuda.error.1=\u932F\u8AA4
settings.2.language=\u4ECB\u9762\u8A9E\u8A00\uFF1A
settings.2.language.error=\u672A\u77E5\u8A9E\u8A00
settings.3.infoArea.1=\u8EDF\u9AD4\u7248\u672C:
settings.3.infoArea.2=\u958B\u767C\u4F5C\u8005:
settings.4.no_theme=\u6C92\u6709\u53EF\u7528\u7684\u4E3B\u984C
settings.4.search=\u641C\u5C0B
settings.4.search_empty=\u8ACB\u8F38\u5165\u641C\u5C0B\u5167\u5BB9\uFF01
settings.4.search_empty_title=\u63D0\u793A
settings.4.search_not_found=\u672A\u627E\u5230\u5339\u914D\u7684\u4E3B\u984C\uFF01
settings.4.search_not_found_title=\u63D0\u793A
settings.4.loading=\u8A72\u4E3B\u984C\u5DF2\u8F09\u5165\uFF0C\u7121\u9700\u91CD\u8907\u8F09\u5165\uFF01
settings.4.loading_title=\u63D0\u793A
settings.4.load=\u52A0\u8F09\u4E3B\u984C
settings.4.info=\u4E3B\u984C\u985E\u5225:
settings.4.info.1=\u4E3B\u984C\u540D\u7A31:
settings.4.info.2=\u63D0\u793A:
settings.4.info.3=\u8A3B\u518A\u540D\u7A31:
settings.4.load_theme_success=\u4E3B\u984C '
settings.4.load_theme_success.2=' \u5DF2\u6210\u529F\u52A0\u8F09\uFF01
settings.4.load_theme_success.3=\u6210\u529F
settings.4.load_theme_error=\u52A0\u8F09\u4E3B\u984C\u5931\u6557:
settings.4.load_theme_error.title=\u932F\u8AA4

View File

@@ -1,3 +0,0 @@
#Current Loaded Language
#Fri Feb 14 09:23:44 CST 2025
loadedLanguage=Zh

View File

@@ -1,6 +1,7 @@
package com.axis.innovators.box;
import com.axis.innovators.box.events.GlobalEventBus;
import com.axis.innovators.box.events.OpenFileEvents;
import com.axis.innovators.box.events.StartupEvent;
import com.axis.innovators.box.gui.*;
import com.axis.innovators.box.plugins.PluginDescriptor;
@@ -9,6 +10,7 @@ import com.axis.innovators.box.register.RegistrationSettingsItem;
import com.axis.innovators.box.register.RegistrationTool;
import com.axis.innovators.box.register.RegistrationTopic;
import com.axis.innovators.box.register.LanguageManager;
import com.axis.innovators.box.tools.ArgsParser;
import com.axis.innovators.box.tools.LibraryLoad;
import com.axis.innovators.box.tools.StateManager;
import com.axis.innovators.box.tools.SystemInfoUtil;
@@ -22,7 +24,9 @@ import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* 主类
@@ -59,6 +63,7 @@ public class AxisInnovatorsBox {
static {
try {
LibraryLoad.loadLibrary("FridaNative");
LibraryLoad.loadLibrary("ThrowSafely");
LM.loadLibrary(LM.CUDA);
} catch (Exception e) {
logger.error("Failed to load the 'FridaNative' library", e);
@@ -218,6 +223,9 @@ public class AxisInnovatorsBox {
dialog.setVisible(true);
}
/**
* 初始化Log4j2
*/
public void initLog4j2() {
Log4j2OutputStream.redirectSystemStreams();
@@ -235,9 +243,11 @@ public class AxisInnovatorsBox {
logger.info("ClassLoader.getSystemClassLoader(): {}", ClassLoader.getSystemClassLoader());
}
/**
* 设置主题
*/
private void setTopic() {
try {
main.registrationTopic.addTopic(UIManager.getSystemLookAndFeelClassName(),
LanguageManager.getLoadedLanguages().getText("default_theme.system.topicName"),
LanguageManager.getLoadedLanguages().getText("default_theme.default.tip"),
@@ -317,12 +327,22 @@ public class AxisInnovatorsBox {
isWindow = true;
}
public static void main(String[] args) {
public static void run(String[] args) {
main = new AxisInnovatorsBox(args);
try {
main.initLog4j2();
main.setTopic();
List<Map<String, String>> validFiles = ArgsParser.parseArgs(args);
for (Map<String, String> fileInfo : validFiles) {
OpenFileEvents openFileEvents = new OpenFileEvents(fileInfo.get("path"), fileInfo.get("extension"));
GlobalEventBus.EVENT_BUS.post(openFileEvents);
if (!openFileEvents.isContinue()) {
return;
}
}
main.thread = new Thread(() -> {
try {
// 主任务1加载插件
@@ -354,6 +374,12 @@ public class AxisInnovatorsBox {
});
main.thread.setName("Main Thread");
main.thread.start();
} catch (Exception e) {
logger.error("In unexpected errors", e);
main.ex.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.organizingCrashReports(e);
throw new RuntimeException(e);
}
}
public void runWindow() {

View File

@@ -10,7 +10,12 @@ import com.axis.innovators.box.register.LanguageManager;
public class Main {
public static void main(String[] args) {
FolderCleaner.cleanFolder(FolderCreator.getLogsFolder(), 10);
LanguageManager.loadSavedLanguage();
AxisInnovatorsBox.main(args);
if (LanguageManager.getLoadedLanguages() == null){
LanguageManager.loadLanguage("system:zh_CN");
}
AxisInnovatorsBox.run(args);
}
}

View File

@@ -0,0 +1,53 @@
package com.axis.innovators.box.events;
import java.io.File;
/**
* 当程序接受到了文件时触发
* @author tzdwindows 7
*/
public class OpenFileEvents {
private final File filePath;
private final String extension;
private boolean isContinue;
/**
* 构造函数
* @param filePath 文件路径
* @param extension 文件后缀
*/
public OpenFileEvents(String filePath, String extension) {
this.filePath = new File(filePath);
this.extension = extension;
isContinue = true;
}
/**
* 获取文件路径
* @return 文件路径
*/
public File getFilePath() {
return filePath;
}
/**
* 获取文件后缀
* @return 文件后缀
*/
public String getExtension() {
return extension;
}
public boolean isContinue() {
return isContinue;
}
/**
* 希望程序继续执行后面的操作
* @param isContinue 是否继续
*/
public void setContinue(boolean isContinue) {
this.isContinue = isContinue;
}
}

View File

@@ -4,6 +4,8 @@ import com.axis.innovators.box.AxisInnovatorsBox;
import com.axis.innovators.box.events.*;
import com.axis.innovators.box.register.RegistrationSettingsItem;
import com.axis.innovators.box.register.LanguageManager;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatLaf;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -13,9 +15,7 @@ import javax.swing.plaf.PanelUI;
import javax.swing.plaf.basic.BasicScrollBarUI;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
@@ -30,16 +30,22 @@ public class MainWindow extends JFrame {
private static final Logger logger = LogManager.getLogger(MainWindow.class);
private final Map<JComponent, Float> cardScales = new HashMap<>();
private final Map<JComponent, Integer> cardElevations = new HashMap<>();
// 选项卡颜色
private final Color CARD_COLOR = Color.WHITE;
private final List<ToolCategory> categories = new ArrayList<>();
// 是否启用背景图片
private final boolean isBackground = true;
// 启动背景图片后是否启动背景模糊
private final boolean isBlur = true;
public MainWindow() {
setIconImage(LoadIcon.loadIcon("logo.png", 32).getImage());
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
for (JComponent card : cardScales.keySet()) {
cardScales.put(card, 1.0f);
card.repaint();
}
}
});
}
/**
@@ -52,18 +58,13 @@ public class MainWindow extends JFrame {
public void initUI() {
// 设置窗口属性
setTitle(LanguageManager.getLoadedLanguages().getText("mainWindow.title"));
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(1200, 800);
setLocationRelativeTo(null);
// 设置窗口和内容面板透明
//setBackground(new Color(0, 0, 0, 0));
getContentPane().setBackground(new Color(0, 0, 0, 0));
// 自定义面板
JPanel mainPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
@@ -96,24 +97,18 @@ public class MainWindow extends JFrame {
logger.error("Failed to load background image", e);
}
}
}
};
// 强制面板不透明
mainPanel.setOpaque(true);
mainPanel.putClientProperty("FlatLaf.style", "background: null;");
// 设置布局和边距
mainPanel.setLayout(new BorderLayout(20, 20));
mainPanel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30));
// 添加其他组件
mainPanel.add(createHeader(), BorderLayout.NORTH);
mainPanel.add(createCategoryTabs(), BorderLayout.CENTER);
// 添加主面板到窗口
add(mainPanel);
}
@@ -208,6 +203,10 @@ public class MainWindow extends JFrame {
private JComponent createCategoryTabs() {
JTabbedPane tabbedPane = new JTabbedPane();
//tabbedPane.putClientProperty(FlatClientProperties.TABBED_PANE_TAB_AREA_ALIGN, Component.LEFT_ALIGNMENT);
tabbedPane.putClientProperty(FlatClientProperties.TABBED_PANE_TAB_HEIGHT, 40);
tabbedPane.putClientProperty(FlatClientProperties.TABBED_PANE_TAB_ICON_PLACEMENT, SwingConstants.TOP);
tabbedPane.setOpaque(false);
tabbedPane.setBackground(new Color(0, 0, 0, 0));
tabbedPane.setBorder(null);
@@ -236,7 +235,7 @@ public class MainWindow extends JFrame {
}
tabbedPane.addTab(
category.getName(),
LoadIcon.loadIcon(category.getIcon(), 24),
LoadIcon.loadIcon(category.getIcon(), 12),
scrollPane
);
}
@@ -264,16 +263,14 @@ public class MainWindow extends JFrame {
title.setFont(new Font("微软雅黑", Font.BOLD, 28));
title.setForeground(new Color(44, 62, 80));
//JLabel iconLabel = new JLabel(LoadIcon.loadIcon("logo.png", 28));
//iconLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
JButton settings = new JButton(LoadIcon.loadIcon("settings.png", 32));
settings.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_BORDERLESS);
settings.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
settings.setContentAreaFilled(false);
settings.addActionListener(e -> showSettings());
JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
titlePanel.setOpaque(false);
//titlePanel.add(iconLabel);
titlePanel.add(title);
header.add(titlePanel, BorderLayout.WEST);
@@ -323,7 +320,6 @@ public class MainWindow extends JFrame {
JPanel card = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
// 毛玻璃效果
@@ -350,7 +346,8 @@ public class MainWindow extends JFrame {
g2d.dispose();
}
};
card.setPreferredSize(new Dimension(200, 150));
card.setMinimumSize(new Dimension(100, 75));
card.setLayout(new BorderLayout(15, 15));
card.setBackground(CARD_COLOR);
card.setBorder(BorderFactory.createCompoundBorder(
@@ -395,7 +392,6 @@ public class MainWindow extends JFrame {
card.add(iconLabel, BorderLayout.NORTH);
card.add(textPanel, BorderLayout.CENTER);
// 鼠标悬停动画
card.addMouseListener(new CardMouseAdapter(card, tool));
card.addMouseListener(new MouseAdapter() {
@Override
@@ -418,6 +414,19 @@ public class MainWindow extends JFrame {
super.update(g, c);
}
});
card.addMouseListener(new CardMouseAdapter(card, tool) {
@Override
public void mouseEntered(MouseEvent e) {
cardElevations.put(card, 8);
animateCardElevation(card, 8);
}
@Override
public void mouseExited(MouseEvent e) {
animateCardElevation(card, 2);
}
});
return card;
}
@@ -429,7 +438,25 @@ public class MainWindow extends JFrame {
"</body></html>";
}
// 工具类别内部类
private void animateCardElevation(JComponent card, int targetElevation) {
new Timer(10, new AbstractAction() {
private int currentElevation = cardElevations.getOrDefault(card, 2);
@Override
public void actionPerformed(ActionEvent e) {
if (currentElevation < targetElevation) currentElevation++;
else if (currentElevation > targetElevation) currentElevation--;
cardElevations.put(card, currentElevation);
card.repaint();
if (currentElevation == targetElevation) {
((Timer)e.getSource()).stop();
}
}
}).start();
}
public static class ToolCategory {
private final String name;
private final String icon;
@@ -687,52 +714,41 @@ public class MainWindow extends JFrame {
public static class CustomScrollBarUI extends BasicScrollBarUI {
@Override
protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
protected void configureScrollBarColors() {
this.thumbColor = new Color(90, 90, 120);
this.trackColor = new Color(50, 50, 70);
}
// 设置轨道背景颜色
Color trackColor = new Color(240, 240, 240);
g2d.setColor(trackColor);
g2d.fillRoundRect(
trackBounds.x,
trackBounds.y,
trackBounds.width - 1,
trackBounds.height - 1,
5, 5 // 圆角半径
);
@Override
protected JButton createDecreaseButton(int orientation) {
return createInvisibleButton();
}
@Override
protected JButton createIncreaseButton(int orientation) {
return createInvisibleButton();
}
private JButton createInvisibleButton() {
JButton btn = new JButton();
btn.setPreferredSize(new Dimension(0, 0));
btn.setMinimumSize(new Dimension(0, 0));
btn.setMaximumSize(new Dimension(0, 0));
return btn;
}
@Override
protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color thumbColor = new Color(180, 180, 180);
g2d.setColor(thumbColor);
g2d.fillRoundRect(
thumbBounds.x,
thumbBounds.y,
thumbBounds.width - 1,
thumbBounds.height - 1,
5, 5
);
Color borderColor = new Color(160, 160, 160);
g2d.setColor(borderColor);
g2d.drawRoundRect(
thumbBounds.x,
thumbBounds.y,
thumbBounds.width - 1,
thumbBounds.height - 1,
5, 5
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(thumbColor);
g2.fillRoundRect(
thumbBounds.x + 2,
thumbBounds.y + 2,
thumbBounds.width - 4,
thumbBounds.height - 4,
8, 8
);
}
@Override
protected void paintDecreaseHighlight(Graphics g) {}
@Override
protected void paintIncreaseHighlight(Graphics g) {}
}
}

View File

@@ -13,6 +13,7 @@ public class PluginDescriptor {
private String description;
private Object instance;
private String transformers;
private String registrationName;
// Getters and Setters
public String getId() { return id; }
@@ -29,4 +30,6 @@ public class PluginDescriptor {
public void setInstance(Object instance) { this.instance = instance; }
public String getTransformers() {return transformers;}
public void setTransformers(String transformers) {this.transformers = transformers;}
public String getRegistrationName() {return registrationName;}
public void setRegistrationName(String registrationName) {this.registrationName = registrationName;}
}

View File

@@ -1,12 +1,16 @@
package com.axis.innovators.box.plugins;
import com.axis.innovators.box.AxisInnovatorsBox;
import com.axis.innovators.box.register.LanguageManager;
import com.axis.innovators.box.register.RegistrationTool;
import com.axis.innovators.box.tools.FolderCreator;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.*;
import java.lang.reflect.Field;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.jar.*;
@@ -20,7 +24,8 @@ public class PluginLoader {
private static final List<PluginDescriptor> loadedPlugins = new ArrayList<>();
private static final List<IClassTransformer> transformers = new ArrayList<>();
private static final List<String> corePluginMainClass = new ArrayList<>();
public static void loadPlugins() throws IOException {
private static final List<String> pluginRegisteredName = new ArrayList<>();
public static void loadPlugins() throws IOException, PluginLoadingError {
logger = LogManager.getLogger(PluginLoader.class);
File pluginDir = null;
if (PLUGIN_PATH != null) {
@@ -43,7 +48,7 @@ public class PluginLoader {
}
}
private static void processJarFile(File jarFile, boolean isCorePlugin) throws IOException {
private static void processJarFile(File jarFile, boolean isCorePlugin) throws IOException, PluginLoadingError {
try (JarFile jar = new JarFile(jarFile)) {
// Check for CorePlugin in MANIFEST.MF
if (isCorePlugin) {
@@ -80,7 +85,11 @@ public class PluginLoader {
return;
}
for (File jar : jars) {
try {
processJarFile(jar, true);
} catch (PluginLoadingError e) {
throw new RuntimeException(e);
}
}
}
@@ -122,7 +131,8 @@ public class PluginLoader {
//}
}
private static void processWithManifest(JarFile jar, JarEntry entry, File jarFile) throws IOException {
private static void processWithManifest(JarFile jar, JarEntry entry, File jarFile)
throws IOException, PluginLoadingError {
Properties props = new Properties();
try (InputStream is = jar.getInputStream(entry)) {
props.load(is);
@@ -139,27 +149,92 @@ public class PluginLoader {
descriptor.setSupportedVersions(
Arrays.asList(props.getProperty("supportedVersions").split(","))
);
String registrationName = props.getProperty("registrationName");
verifyRegisteredNameValid(descriptor, registrationName);
logger.info("Loaded plugin: {}", descriptor.getName());
loadMainClass(props.getProperty("mainClass"), jarFile, descriptor);
Attributes attributes = jar.getManifest().getMainAttributes();
String corePluginClass = attributes.getValue("CorePlugin");
descriptor.setTransformers(corePluginClass);
loadPluginLanguages(jarFile, descriptor);
}
private static void processWithAnnotations(JarFile jar, File jarFile) {
private static void verifyRegisteredNameValid(PluginDescriptor descriptor, String registrationName) throws PluginLoadingError {
if (registrationName != null && !registrationName.isEmpty()
&& !pluginRegisteredName.contains(registrationName)) {
pluginRegisteredName.add(registrationName);
} else {
if (registrationName == null || registrationName.isEmpty()) {
throw new PluginLoadingError("Invalid registration name");
}
throw new PluginLoadingError("When the \" "
+ descriptor.getName()
+ "\" plugin is loaded, this plugin contains the same registered name as the previously loaded plugin");
}
descriptor.setRegistrationName(registrationName);
}
private static void processWithAnnotations(JarFile jar, File jarFile) throws PluginLoadingError {
URLClassLoader classLoader = createClassLoader(jarFile);
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (entry.getName().endsWith(".class")) {
if (classLoader != null) {
processClassEntry(entry, jar,classLoader);
processClassEntry(entry, jar,classLoader,jarFile);
}
}
}
}
private static void loadPluginLanguages(File jarFile, PluginDescriptor plugin) {
try (JarFile jar = new JarFile(jarFile)) {
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (entry.getName().startsWith("lang/") &&
entry.getName().endsWith(".properties")) {
processLanguageFile(jar, entry, plugin);
}
}
} catch (IOException e) {
logger.error("Failed to load language files for plugin: {}", plugin.getName(), e);
}
}
private static void processLanguageFile(JarFile jar, JarEntry entry, PluginDescriptor plugin) {
String fileName = entry.getName().substring(entry.getName().lastIndexOf("/") + 1);
String[] parts = fileName.split("[_.]");
if (parts.length < 3) {
return;
}
String langCode = parts[parts.length-1].replace(".properties", "");
String langName = plugin.getName() + " " + langCode.toUpperCase();
String registeredName = plugin.getRegistrationName() + "_" + langCode;
try (InputStream is = jar.getInputStream(entry)) {
Properties properties2 = new Properties();
properties2.load(new InputStreamReader(is, StandardCharsets.UTF_8));
LanguageManager.Language language = new LanguageManager.Language(
langName,
registeredName,
null
) {
@Override
public void loadLanguageFile(String languageFile) {
this.properties.putAll(properties2);
}
};
LanguageManager.addLanguage(language);
logger.info("Loaded plugin language: {} ({})", langName, registeredName);
} catch (IOException e) {
logger.error("Failed to load language file: {}", entry.getName(), e);
}
}
private static URLClassLoader createClassLoader(File jarFile) {
try {
return new URLClassLoader(
@@ -172,7 +247,9 @@ public class PluginLoader {
return null;
}
private static void processClassEntry(JarEntry entry,JarFile jar, URLClassLoader classLoader) {
private static void processClassEntry(JarEntry entry,JarFile jar,
URLClassLoader classLoader,
File jarFile) throws PluginLoadingError {
String className = entry.getName()
.replace("/", ".")
.replace(".class", "");
@@ -188,14 +265,27 @@ public class PluginLoader {
descriptor.setIcon(meta.icon());
descriptor.setSupportedVersions(Arrays.asList(meta.supportedVersions()));
String registrationName = meta.registeredName();
verifyRegisteredNameValid(descriptor, registrationName);
try {
Object instance = clazz.getDeclaredConstructor().newInstance();
descriptor.setInstance(instance);
loadedPlugins.add(descriptor);
try {
Field pluginInstance = instance.getClass().getDeclaredField("INSTANCE");
pluginInstance.setAccessible(true);
pluginInstance.set(null, descriptor);
} catch (NoSuchFieldException | IllegalArgumentException
| SecurityException | IllegalAccessException e) {
logger.warn("Failed to set plugin instance: {}", instance.getClass(), e);
}
loadedPlugins.add(descriptor);
Attributes attributes = jar.getManifest().getMainAttributes();
String corePluginClass = attributes.getValue("CorePlugin");
descriptor.setTransformers(corePluginClass);
loadPluginLanguages(jarFile, descriptor);
logger.info("Loaded plugin: {}", descriptor.getName());
} catch (Exception e) {
logger.error("Failed to instantiate plugin class: {}", className, e);
@@ -208,6 +298,7 @@ public class PluginLoader {
private static void loadMainClass(String mainClassName, File jarFile, PluginDescriptor descriptor) {
if (mainClassName == null || mainClassName.isEmpty()) {
logger.error("Invalid main class name: {}", mainClassName);
return;
}
@@ -218,6 +309,15 @@ public class PluginLoader {
Class<?> mainClass = classLoader.loadClass(mainClassName);
Object instance = mainClass.getDeclaredConstructor().newInstance();
descriptor.setInstance(instance);
try {
Field pluginInstance = mainClass.getDeclaredField("INSTANCE");
pluginInstance.setAccessible(true);
pluginInstance.set(null, descriptor);
} catch (NoSuchFieldException | IllegalArgumentException
| SecurityException | IllegalAccessException e) {
logger.warn("Failed to set plugin instance: {}", mainClassName, e);
}
} catch (Exception e) {
logger.error("Failed to load main class: {}", mainClassName, e);
}

View File

@@ -0,0 +1,17 @@
package com.axis.innovators.box.plugins;
/**
* 当加载插件时发生的错误
* @author tzdwindows 7
*/
public class PluginLoadingError extends Exception{
public PluginLoadingError(String message)
{
super(message);
}
public PluginLoadingError(String message, Throwable cause)
{
super(message, cause);
}
}

View File

@@ -6,15 +6,34 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* 这是创建基础参数的注解
* @author tzdwindows 7
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface PluginMeta {
/**
* 插件ID
*/
String id();
/**
* 创建显示名称
*/
String name();
/**
* 支持的版本
*/
String[] supportedVersions();
/**
* 插件描述
*/
String description();
/**
* 插件图标
*/
String icon() default "";
/**
* 插件注册名称(确保其唯一性)
*/
String registeredName() default "no_registration";
}

View File

@@ -1,13 +1,14 @@
package com.axis.innovators.box.register;
import com.axis.innovators.box.plugins.PluginLoader;
import com.axis.innovators.box.tools.FolderCreator;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.*;
/**
* 语言管理器
@@ -18,27 +19,106 @@ public class LanguageManager {
private static final String LANGUAGE_PATH = FolderCreator.getLanguageFolder();
private static final List<Language> LANGUAGES = new ArrayList<>();
private static final String SAVED_LANGUAGE_FILE = LANGUAGE_PATH + "\\saved_language.properties";
private static final Logger logger = LogManager.getLogger(PluginLoader.class);
static {
LANGUAGES.add(new Language("简体中文", "Zh","SimplifiedChineseLanguage"));
LANGUAGES.add(new Language("繁體中文", "TC","TraditionalChineseLanguage"));
LANGUAGES.add(new Language("English", "En","EnglishLanguage"));
LANGUAGES.add(new Language("简体中文", "system:zh_CN", "sys_zh_CN"));
LANGUAGES.add(new Language("繁體中文(台灣)", "system:zh_TW", "sys_zh_TW"));
LANGUAGES.add(new Language("English (International)", "system:en_US", "sys_en_US"));
LANGUAGES.add(new Language("日本語", "system:ja_JP", "sys_ja_JP"));
}
/**
* 添加语言
* @param language 语言
* 添加/合并语言资源
* @param language 要添加的语言对象
* 处理规则:
* 1. 注册名相同时保留原有基础信息
* 2. 相同键值的新内容覆盖旧内容
* 3. 详细记录新增、更新的键值数量
* 4. 提供关键示例用于调试
*/
public static void addLanguage(Language language) {
for (int i = 0; i < LANGUAGES.size(); i++) {
Language language1 = LANGUAGES.get(i);
if (Objects.equals(language1.getRegisteredName(), language.getRegisteredName())){
LANGUAGES.set(i, language);
for (Language existing : LANGUAGES) {
if (existing.getRegisteredName().equals(language.getRegisteredName())) {
try {
int added = 0;
int updated = 0;
Set<String> sampleAddedKeys = new LinkedHashSet<>();
Set<String> sampleUpdatedKeys = new LinkedHashSet<>();
for (String key : language.properties.stringPropertyNames()) {
String newValue = language.properties.getProperty(key);
if (existing.properties.containsKey(key)) {
updated++;
if (sampleUpdatedKeys.size() < 5) {
sampleUpdatedKeys.add(key);
}
} else {
added++;
if (sampleAddedKeys.size() < 5) {
sampleAddedKeys.add(key);
}
}
existing.properties.setProperty(key, newValue);
}
String logDetail = buildMergeLogDetails(added, updated, sampleAddedKeys, sampleUpdatedKeys);
logger.info("【语言合并报告】\n" +
"▌合并目标:{} ({})\n" +
"▌变更统计:新增 {} 条 / 更新 {} 条\n" +
"▌当前总量:{} 条\n" +
"▌关键示例:\n{}",
existing.getLanguageName(),
existing.getRegisteredName(),
added,
updated,
existing.properties.size(),
logDetail);
return;
} catch (Exception e) {
logger.error("语言合并异常!注册名:{} - {}",
existing.getRegisteredName(),
e.getClass().getSimpleName(),
e);
}
return;
}
}
LANGUAGES.add(language);
logger.info("【新增语言】{} ({}) 初始加载 {} 条",
language.getLanguageName(),
language.getRegisteredName(),
language.properties.size());
}
private static String buildMergeLogDetails(int added, int updated,
Set<String> sampleAdded, Set<String> sampleUpdated) {
StringBuilder sb = new StringBuilder();
if (added > 0) {
sb.append("✦ 新增条目:\n");
sampleAdded.forEach(k -> sb.append("").append(k).append("\n"));
if (added > 5) {
sb.append(" ...(共").append(added).append("条)\n");
}
}
if (updated > 0) {
sb.append("✦ 更新条目:\n");
sampleUpdated.forEach(k -> sb.append("").append(k).append("\n"));
if (updated > 5) {
sb.append(" ...(共").append(updated).append("条)\n");
}
}
return sb.toString().isEmpty() ? "无内容变更" : sb.toString();
}
/**
* 加载语言
* @param languageName 语言注册名
@@ -120,7 +200,7 @@ public class LanguageManager {
private final String languageName;
private final String registeredName;
private final String languageFile;
private final Properties properties;
protected final Properties properties;
public Language(String languageName,
String registeredName,
@@ -133,14 +213,14 @@ public class LanguageManager {
this.languageFile = LANGUAGE_PATH + "\\" + languageFileName + ".properties";
}
this.properties = new Properties();
loadLanguageFile();
loadLanguageFile(languageFile);
}
/**
* 加载语言文件
*/
private void loadLanguageFile() {
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(this.languageFile),
public void loadLanguageFile(String languageFile) {
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(languageFile),
StandardCharsets.UTF_8)) {
properties.load(reader);
} catch (IOException e) {
@@ -161,6 +241,13 @@ public class LanguageManager {
return properties.getProperty(key);
}
/**
* 添加文本
*/
public void addText(String key, String value) {
properties.setProperty(key, value);
}
public String getLanguageName() {
return languageName;
}

View File

@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* 用于注册设置项的类
@@ -563,7 +564,7 @@ public class RegistrationSettingsItem extends WindowsJDialog {
* @param tip 描述
* @param registeredName 注册名(必须是唯一的)
*/
public void addSettings(JPanel tabbedPanesSettings,
private void addSettings(JPanel tabbedPanesSettings,
String title,
Icon icon,
String tip,
@@ -579,6 +580,49 @@ public class RegistrationSettingsItem extends WindowsJDialog {
}
}
/**
* 注册设置项
* @param tabbedPanesSettings 设置页面
* @param title 标题
* @param icon 显示图标可为null
* @param tip 描述
* @param plugin 插件
* @param registeredName 注册名(必须是唯一的)
*/
public void addSettings(JPanel tabbedPanesSettings,
String title,
Icon icon,
String tip,
PluginDescriptor plugin,
String registeredName) {
if (mainWindow != null) {
if (!mainWindow.isWindow()) {
registrationItem(tabbedPanesSettings, title, icon, tip,plugin.getRegistrationName()
+ ":" +
registeredName);
} else {
logger.warn("Wrong time to add tools");
}
} else {
registrationItem(tabbedPanesSettings, title, icon, tip, registeredName);
}
}
/**
* 通过 PluginDescriptor 查询整个插件装载的注册项
* @param plugin 插件描述符
* @return List<RegistrationSettingsItem> 与指定插件相关的注册设置项列表
*/
public static List<RegistrationSettingsItem> getRegistrationsByPlugin(PluginDescriptor plugin) {
return registrationSettingsItemList.stream()
.filter(item ->
item.getRegisteredNameList().stream()
.anyMatch(name ->
name.startsWith(plugin.getRegistrationName() + ":"))
)
.collect(Collectors.toList());
}
private void registrationItem(JPanel tabbedPanesSettings, String title, Icon icon, String tip, String registeredName) {
if (registeredNameList.contains(registeredName)) {
throw new RegistrationError(registeredName + " duplicate registered names");

View File

@@ -4,6 +4,7 @@ import com.axis.innovators.box.AxisInnovatorsBox;
import com.axis.innovators.box.gui.FridaWindow;
import com.axis.innovators.box.gui.LocalWindow;
import com.axis.innovators.box.gui.MainWindow;
import com.axis.innovators.box.plugins.PluginDescriptor;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -24,6 +25,7 @@ public class RegistrationTool {
private final AxisInnovatorsBox main;
private final List<UUID> uuidList = new ArrayList<>();
private final List<String> registeredNameList = new ArrayList<>();
private final List<PluginDescriptor> pluginDescriptors = new ArrayList<>();
public RegistrationTool(AxisInnovatorsBox main) {
this.main = main;
@@ -66,7 +68,7 @@ public class RegistrationTool {
* 注册ToolCategory
* @param toolCategory ToolCategory
*/
public void addToolCategory(MainWindow.ToolCategory toolCategory,
private boolean addToolCategory(MainWindow.ToolCategory toolCategory,
String registeredName) {
if (!main.isWindow()) {
if (registeredNameList.contains(registeredName)) {
@@ -75,8 +77,24 @@ public class RegistrationTool {
uuidList.add(toolCategory.getId());
registeredNameList.add(registeredName);
toolCategories.add(toolCategory);
return true;
} else {
logger.warn("Wrong time to add tools");
return false;
}
}
/**
* 注册ToolCategory
* @param toolCategory ToolCategory
*/
public void addToolCategory(MainWindow.ToolCategory toolCategory,
PluginDescriptor pluginDescriptor,
String registeredName) {
if (addToolCategory(toolCategory,
pluginDescriptor.getRegistrationName() + ":" +
registeredName)) {
pluginDescriptors.add(pluginDescriptor);
}
}

View File

@@ -0,0 +1,83 @@
package com.axis.innovators.box.tools;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* ArgsParser 类用于解析命令行参数,并返回包含合法文件信息的列表。
* @author tzdwindows 7
*/
public class ArgsParser {
/**
* 判断路径是否合法(存在且是文件)
*
* @param path 文件路径
* @return 是否合法
*/
private static boolean isValidPath(String path) {
File file = new File(path);
return file.exists() && file.isFile();
}
/**
* 获取文件的后缀名
*
* @param path 文件路径
* @return 文件后缀名(如 ".txt"
*/
private static String getFileExtension(String path) {
int lastDotIndex = path.lastIndexOf('.');
if (lastDotIndex == -1) {
return ""; // 没有后缀名
}
return path.substring(lastDotIndex);
}
/**
* 解析 args 参数并保存合法的文件路径
*
* @param args main 方法的参数
* @return 包含合法文件信息的列表,每个元素是一个 Map包含 "extension" 和 "path"
*/
public static List<Map<String, String>> parseArgs(String[] args) {
List<Map<String, String>> validFiles = new ArrayList<>();
for (String arg : args) {
if (isValidPath(arg)) {
String extension = getFileExtension(arg);
Map<String, String> fileInfo = new HashMap<>();
fileInfo.put("extension", extension);
fileInfo.put("path", arg);
validFiles.add(fileInfo);
}
}
return validFiles;
}
public static void main(String[] args) {
// 模拟 main 方法的 args 参数
String[] testArgs = {
"C:\\Program Files\\test.txt", // 合法文件
"C:\\invalid_file.exe", // 不存在的文件
"D:\\Documents\\report.pdf", // 合法文件
"not_a_path", // 无效路径
"C:\\Windows\\system32" // 目录,不是文件
};
// 解析 args 参数
List<Map<String, String>> validFiles = parseArgs(testArgs);
// 输出结果
System.out.println("Valid files:");
for (Map<String, String> fileInfo : validFiles) {
System.out.println("Extension: " + fileInfo.get("extension") + ", Path: " + fileInfo.get("path"));
}
}
}

View File

@@ -22,7 +22,7 @@ public class StateManager {
* @param statusName 状态文件名
*/
public StateManager(String statusName) {
statusFile = FolderCreator.getConfigurationFolder() + statusName + ".properties";
statusFile = FolderCreator.getConfigurationFolder() + "\\" + statusName + ".properties";
configMap = new HashMap<>();
properties = new Properties();
loadConfiguration();
@@ -32,7 +32,7 @@ public class StateManager {
* 默认构造函数
*/
public StateManager() {
statusFile = FolderCreator.getConfigurationFolder() + "state_management.properties";
statusFile = FolderCreator.getConfigurationFolder() + "\\toolbox.properties";
configMap = new HashMap<>();
properties = new Properties();
loadConfiguration();

View File

@@ -10,7 +10,7 @@ import org.apache.logging.log4j.Logger;
* @author tzdwindows 7
*/
public class LM {
public static boolean CUDA = true;
public static boolean CUDA = false;
public final static String DEEP_SEEK = FolderCreator.getModelFolder() + "\\DeepSeek-R1-Distill-Qwen-1.5B-Q8_0.gguf";
private static final Logger logger = LogManager.getLogger(LM.class);

View File

@@ -0,0 +1,3 @@
#Updated configuration
#Fri Feb 14 09:55:41 CST 2025
isWindow=false