feat(i18n): 添加多语言支持并优化用户界面
- 新增 LanguageManager 类实现语言管理功能 - 在 FridaWindow 中添加多语言支持 - 优化 LoadIcon 类的图片加载逻辑- 更新 BoxClassLoader 和 AxisInnovatorsBox 类以支持新功能- 添加 FolderCleaner 工具类用于清理日志文件 - 更新构建配置,添加新的依赖项
This commit is contained in:
@@ -37,6 +37,13 @@ dependencies {
|
||||
implementation 'org.ow2.asm:asm-analysis:7.1'
|
||||
implementation 'org.ow2.asm:asm-util:7.0'
|
||||
implementation 'org.ow2.asm:asm-tree:7.1'
|
||||
|
||||
implementation 'org.jsoup:jsoup:1.17.2'
|
||||
|
||||
implementation 'com.google.code.gson:gson:2.8.9'
|
||||
|
||||
implementation 'com.formdev:flatlaf:0.26'
|
||||
implementation 'commons-io:commons-io:2.11.0'
|
||||
}
|
||||
|
||||
// 分离依赖项到 libs 目录
|
||||
|
||||
99
language/EnglishLanguage.properties
Normal file
99
language/EnglishLanguage.properties
Normal file
@@ -0,0 +1,99 @@
|
||||
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
|
||||
99
language/SimplifiedChineseLanguage.properties
Normal file
99
language/SimplifiedChineseLanguage.properties
Normal file
@@ -0,0 +1,99 @@
|
||||
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
|
||||
99
language/TraditionalChineseLanguage.properties
Normal file
99
language/TraditionalChineseLanguage.properties
Normal file
@@ -0,0 +1,99 @@
|
||||
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
|
||||
3
language/saved_language.properties
Normal file
3
language/saved_language.properties
Normal file
@@ -0,0 +1,3 @@
|
||||
#Current Loaded Language
|
||||
#Fri Feb 14 09:23:44 CST 2025
|
||||
loadedLanguage=Zh
|
||||
417
src/main/java/com/axis/innovators/box/AxisInnovatorsBox.java
Normal file
417
src/main/java/com/axis/innovators/box/AxisInnovatorsBox.java
Normal file
@@ -0,0 +1,417 @@
|
||||
package com.axis.innovators.box;
|
||||
|
||||
import com.axis.innovators.box.events.GlobalEventBus;
|
||||
import com.axis.innovators.box.events.StartupEvent;
|
||||
import com.axis.innovators.box.gui.*;
|
||||
import com.axis.innovators.box.plugins.PluginDescriptor;
|
||||
import com.axis.innovators.box.plugins.PluginLoader;
|
||||
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.LibraryLoad;
|
||||
import com.axis.innovators.box.tools.StateManager;
|
||||
import com.axis.innovators.box.tools.SystemInfoUtil;
|
||||
import com.formdev.flatlaf.FlatLightLaf;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.tzd.lm.LM;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 主类
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class AxisInnovatorsBox {
|
||||
private static final Logger logger = LogManager.getLogger(AxisInnovatorsBox.class);
|
||||
private static final String VERSIONS = "0.0.1";
|
||||
private static final String[] AUTHOR = new String[]{
|
||||
"tzdwindows 7"
|
||||
};
|
||||
|
||||
/** 我是总任务数 **/
|
||||
public int totalTasks = 1;
|
||||
/** 我是当前任务数 **/
|
||||
private int completedTasks = 0;
|
||||
public ProgressBarManager progressBarManager = new ProgressBarManager(
|
||||
LanguageManager.getLoadedLanguages().getText("progressBarManager.title"),
|
||||
totalTasks);
|
||||
private static AxisInnovatorsBox main;
|
||||
private MainWindow ex;
|
||||
private Thread thread;
|
||||
private final String[] args;
|
||||
private boolean isWindow = false;
|
||||
private RegistrationTool registrationTool = new RegistrationTool(this);
|
||||
private final RegistrationTopic registrationTopic = new RegistrationTopic(this);
|
||||
private final List<WindowsJDialog> windowsJDialogList = new ArrayList<>();
|
||||
private final StateManager stateManager = new StateManager();
|
||||
|
||||
public AxisInnovatorsBox(String[] args){
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
LibraryLoad.loadLibrary("FridaNative");
|
||||
LM.loadLibrary(LM.CUDA);
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to load the 'FridaNative' library", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取主类
|
||||
* @return 主类
|
||||
*/
|
||||
public static AxisInnovatorsBox getMain() {
|
||||
return main;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取主窗口
|
||||
* @return 主窗口
|
||||
*/
|
||||
public MainWindow getMainWindow() {
|
||||
return ex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出程序
|
||||
*/
|
||||
public void quit() {
|
||||
logger.info("Application is shutting down...");
|
||||
thread.interrupt();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 组织崩溃报告
|
||||
*/
|
||||
public void organizingCrashReports(Exception e) {
|
||||
String systemOut = Log4j2OutputStream.systemOutContent.toString();
|
||||
String systemErr = Log4j2OutputStream.systemErrContent.toString();
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
String stackTrace = sw.toString();
|
||||
|
||||
String report = "========== 系统标准输出 ==========\n" + systemOut +
|
||||
"\n========== 系统错误输出 ==========\n" + systemErr +
|
||||
"\n========== 异常堆栈跟踪 ==========\n" + stackTrace;
|
||||
|
||||
SwingUtilities.invokeLater(() -> createAndShowGUI(report));
|
||||
}
|
||||
|
||||
private void createAndShowGUI(String reportContent) {
|
||||
JDialog dialog = new JDialog((Frame) null,
|
||||
LanguageManager.getLoadedLanguages().getText("andShow.title"), true);
|
||||
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
||||
dialog.setLayout(new BorderLayout(10, 10));
|
||||
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
JPanel topPanel = new JPanel(new BorderLayout(10, 10));
|
||||
Icon errorIcon = UIManager.getIcon("OptionPane.errorIcon");
|
||||
JLabel iconLabel = new JLabel(errorIcon);
|
||||
|
||||
JLabel titleLabel = new JLabel(LanguageManager.getLoadedLanguages().getText("andShow.title.2"));
|
||||
|
||||
JLabel feedbackLabel = new JLabel(LanguageManager.getLoadedLanguages().getText("andShow.title.3"));
|
||||
feedbackLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
|
||||
JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 10));
|
||||
titlePanel.add(iconLabel);
|
||||
titlePanel.add(titleLabel);
|
||||
|
||||
topPanel.add(titlePanel, BorderLayout.NORTH);
|
||||
topPanel.add(feedbackLabel, BorderLayout.CENTER);
|
||||
topPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
|
||||
JTextArea contentArea = new JTextArea(reportContent);
|
||||
contentArea.setEditable(false);
|
||||
contentArea.setFont(new Font("Monospaced", Font.PLAIN, 12));
|
||||
|
||||
StringBuilder pluginInfo = new StringBuilder();
|
||||
pluginInfo.append(
|
||||
LanguageManager.getLoadedLanguages().getText("andShow.pluginInfo.title"))
|
||||
.append("\n");
|
||||
|
||||
List<PluginDescriptor> corePluginList = new ArrayList<>();
|
||||
for (PluginDescriptor plugin : PluginLoader.getLoadedPlugins()) {
|
||||
pluginInfo.append(LanguageManager.getLoadedLanguages().getText("andShow.pluginInfo.title.1")).append(plugin.getName()).append("\n");
|
||||
pluginInfo.append(LanguageManager.getLoadedLanguages().getText("andShow.pluginInfo.title.2")).append(plugin.getDescription()).append("\n");
|
||||
pluginInfo.append(LanguageManager.getLoadedLanguages().getText("andShow.pluginInfo.title.3")).append(plugin.getSupportedVersions()).append("\n\n");
|
||||
if (plugin.getTransformers() != null) {
|
||||
corePluginList.add(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
pluginInfo.append("=== 核心插件 ===\n");
|
||||
for (PluginDescriptor corePlugin : corePluginList) {
|
||||
pluginInfo.append("核心插件主类: ").append(corePlugin.getName()).append("\n");
|
||||
pluginInfo.append("核心转换器位置: ").append(corePlugin.getTransformers()).append("\n");
|
||||
}
|
||||
|
||||
contentArea.append("\n\n=== 插件信息 ===\n");
|
||||
contentArea.append(pluginInfo.toString());
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane(contentArea);
|
||||
scrollPane.setBorder(BorderFactory.createTitledBorder("错误详细信息"));
|
||||
|
||||
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 10));
|
||||
JButton exportButton = new JButton(LanguageManager.getLoadedLanguages().getText("andShow.pluginInfo.exportButton"));
|
||||
JButton closeButton = new JButton(LanguageManager.getLoadedLanguages().getText("andShow.pluginInfo.closeButton"));
|
||||
|
||||
exportButton.setForeground(Color.BLACK);
|
||||
closeButton.setForeground(Color.BLACK);
|
||||
|
||||
exportButton.setBackground(new Color(0, 120, 215));
|
||||
exportButton.setFocusPainted(false);
|
||||
closeButton.setBackground(new Color(79, 79, 79));
|
||||
closeButton.setFocusPainted(false);
|
||||
|
||||
exportButton.addActionListener((ActionEvent e) -> {
|
||||
JFileChooser fileChooser = new JFileChooser();
|
||||
fileChooser.setDialogTitle("保存崩溃报告");
|
||||
fileChooser.setSelectedFile(new File("crash_report.txt"));
|
||||
|
||||
int userSelection = fileChooser.showSaveDialog(dialog);
|
||||
if (userSelection == JFileChooser.APPROVE_OPTION) {
|
||||
File fileToSave = fileChooser.getSelectedFile();
|
||||
try (FileWriter writer = new FileWriter(fileToSave)) {
|
||||
writer.write(reportContent + "\n" + pluginInfo);
|
||||
JOptionPane.showMessageDialog(dialog,
|
||||
LanguageManager.getLoadedLanguages().getText("andShow.pluginInfo.writer")
|
||||
+ "\n" + fileToSave.getAbsolutePath(),
|
||||
LanguageManager.getLoadedLanguages().getText("andShow.pluginInfo.writer.title"),
|
||||
JOptionPane.INFORMATION_MESSAGE);
|
||||
} catch (IOException ex) {
|
||||
JOptionPane.showMessageDialog(dialog,
|
||||
LanguageManager.getLoadedLanguages().getText("andShow.pluginInfo.writer.error")
|
||||
+ "\n" + ex.getMessage(),
|
||||
LanguageManager.getLoadedLanguages().getText("andShow.pluginInfo.error.writer.title"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
closeButton.addActionListener(e -> quit());
|
||||
|
||||
buttonPanel.add(exportButton);
|
||||
buttonPanel.add(closeButton);
|
||||
|
||||
dialog.add(topPanel, BorderLayout.NORTH);
|
||||
dialog.add(scrollPane, BorderLayout.CENTER);
|
||||
dialog.add(buttonPanel, BorderLayout.SOUTH);
|
||||
|
||||
dialog.setSize(800, 600);
|
||||
dialog.setLocationRelativeTo(null);
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
|
||||
public void initLog4j2() {
|
||||
Log4j2OutputStream.redirectSystemStreams();
|
||||
|
||||
logger.info("Application Version: {}", VERSIONS);
|
||||
logger.info("Authors: {}", String.join(", ", AUTHOR));
|
||||
|
||||
logger.info("Operating System: {}", SystemInfoUtil.getOSName());
|
||||
logger.info("OS Architecture: {}", SystemInfoUtil.getOSArch());
|
||||
logger.info("CPU: {}", SystemInfoUtil.getCPUInfo());
|
||||
logger.info("GPU: {}", SystemInfoUtil.getGPUInfo());
|
||||
logger.info("Java Version: {}", System.getProperty("java.version"));
|
||||
logger.info("Java Vendor: {}", System.getProperty("java.vendor"));
|
||||
logger.info("Java Home: {}", System.getProperty("java.home"));
|
||||
logger.info("Java Class Path: {}", System.getProperty("java.class.path"));
|
||||
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"),
|
||||
LoadIcon.loadIcon(MainWindow.class, "logo.png", 64),
|
||||
"system:default_theme");
|
||||
main.registrationTopic.setLoading("system:default_theme");
|
||||
|
||||
main.registrationTopic.addTopic("javax.swing.plaf.metal.MetalLookAndFeel",
|
||||
LanguageManager.getLoadedLanguages().getText("metal_theme.system.topicName"),
|
||||
LanguageManager.getLoadedLanguages().getText("metal_theme.default.tip"),
|
||||
LoadIcon.loadIcon(MainWindow.class, "logo.png", 64),
|
||||
"system:metal_theme");
|
||||
|
||||
main.registrationTopic.addTopic("com.sun.java.swing.plaf.motif.MotifLookAndFeel",
|
||||
LanguageManager.getLoadedLanguages().getText("motif_theme.system.topicName"),
|
||||
LanguageManager.getLoadedLanguages().getText("motif_theme.default.tip"),
|
||||
LoadIcon.loadIcon(MainWindow.class, "logo.png", 64),
|
||||
"system:motif_theme");
|
||||
|
||||
main.registrationTopic.addTopic(new FlatLightLaf(),
|
||||
LanguageManager.getLoadedLanguages().getText("flatLightLaf_theme.system.topicName"),
|
||||
LanguageManager.getLoadedLanguages().getText("flatLightLaf_theme.default.tip"),
|
||||
LoadIcon.loadIcon(MainWindow.class, "logo.png", 64),
|
||||
"system:flatLightLaf_theme");
|
||||
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (Exception e) {
|
||||
logger.warn("Failed to load the system facade class", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 弹出窗口
|
||||
* @param windowsJDialog 窗口
|
||||
*/
|
||||
public void popupWindow(WindowsJDialog windowsJDialog) {
|
||||
windowsJDialogList.add(windowsJDialog);
|
||||
windowsJDialog.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断窗口是否启动
|
||||
* @param windowsJDialog 窗口
|
||||
*/
|
||||
public boolean isWindowStartup(WindowsJDialog windowsJDialog) {
|
||||
return windowsJDialogList.contains(windowsJDialog);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除窗口
|
||||
* @param windowsJDialog 窗口
|
||||
*/
|
||||
public void clearWindow(WindowsJDialog windowsJDialog){
|
||||
windowsJDialogList.remove(windowsJDialog);
|
||||
windowsJDialog.revalidate();
|
||||
windowsJDialog.repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新加载窗口
|
||||
*/
|
||||
public void reloadAllWindow() {
|
||||
isWindow = false;
|
||||
ex.getContentPane().removeAll();
|
||||
ex.revalidate();
|
||||
ex.repaint();
|
||||
registrationTool = new RegistrationTool(this);
|
||||
for (WindowsJDialog windowsJDialog : windowsJDialogList) {
|
||||
windowsJDialog.getContentPane().removeAll();
|
||||
windowsJDialog.initUI();
|
||||
windowsJDialog.revalidate();
|
||||
windowsJDialog.repaint();
|
||||
}
|
||||
ex.initUI();
|
||||
ex.revalidate();
|
||||
RegistrationSettingsItem.overloading();
|
||||
isWindow = true;
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
main = new AxisInnovatorsBox(args);
|
||||
main.initLog4j2();
|
||||
main.setTopic();
|
||||
|
||||
main.thread = new Thread(() -> {
|
||||
try {
|
||||
// 主任务1:加载插件
|
||||
logger.info("Loaded plugins Started");
|
||||
main.progressBarManager.updateMainProgress(++main.completedTasks);
|
||||
PluginLoader.loadPlugins();
|
||||
logger.info("Loaded plugins End");
|
||||
|
||||
main.progressBarManager.close();
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
try {
|
||||
main.ex = new MainWindow();
|
||||
GlobalEventBus.EVENT_BUS.post(new StartupEvent(main));
|
||||
main.runWindow();
|
||||
} catch (Exception e) {
|
||||
logger.error("There was a problem starting the main thread", e);
|
||||
main.ex.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
main.organizingCrashReports(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to load plugins", e);
|
||||
main.ex.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
main.organizingCrashReports(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
main.thread.setName("Main Thread");
|
||||
main.thread.start();
|
||||
}
|
||||
|
||||
public void runWindow() {
|
||||
progressBarManager.updateMainProgress(++completedTasks);
|
||||
|
||||
if (!registrationTool.getToolCategories().isEmpty()) {
|
||||
for (int i = 0; i < registrationTool.getToolCategories()
|
||||
.size(); i++) {
|
||||
ex.addToolCategory(registrationTool.getToolCategories()
|
||||
.get(i));
|
||||
progressBarManager.updateSubProgress(
|
||||
"add tools", i,
|
||||
registrationTool.getToolCategories().size());
|
||||
}
|
||||
}
|
||||
|
||||
ex.initUI();
|
||||
isWindow = true;
|
||||
ex.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取注册工具
|
||||
* @return 注册工具
|
||||
*/
|
||||
public RegistrationTool getRegistrationTool() {
|
||||
return registrationTool;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取命令行参数
|
||||
* @return 命令行参数
|
||||
*/
|
||||
public String[] getArgs() {
|
||||
return args;
|
||||
}
|
||||
|
||||
public boolean isWindow() {
|
||||
return isWindow;
|
||||
}
|
||||
|
||||
public static String getVersion() {
|
||||
return VERSIONS;
|
||||
}
|
||||
|
||||
public RegistrationTopic getRegistrationTopic() {
|
||||
return registrationTopic;
|
||||
}
|
||||
|
||||
public static String[] getAuthor() {
|
||||
return AUTHOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取状态管理器
|
||||
* @return 状态管理器
|
||||
*/
|
||||
public StateManager getStateManager() {
|
||||
return stateManager;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.axis.innovators.box;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
@@ -12,14 +13,17 @@ import java.io.PrintStream;
|
||||
*/
|
||||
public class Log4j2OutputStream extends OutputStream {
|
||||
private static final Logger logger = LogManager.getLogger();
|
||||
|
||||
public static final ByteArrayOutputStream systemOutContent = new ByteArrayOutputStream();
|
||||
public static final ByteArrayOutputStream systemErrContent = new ByteArrayOutputStream();
|
||||
@Override
|
||||
public void write(int b) {
|
||||
systemOutContent.write(b);
|
||||
logger.info(String.valueOf((char) b));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) {
|
||||
systemOutContent.write(b, off, len);
|
||||
String message = new String(b, off, len).trim();
|
||||
logger.info(message);
|
||||
}
|
||||
|
||||
@@ -1,384 +1,16 @@
|
||||
package com.axis.innovators.box;
|
||||
|
||||
import com.axis.innovators.box.events.GlobalEventBus;
|
||||
import com.axis.innovators.box.events.SettingsLoadEvents;
|
||||
import com.axis.innovators.box.events.StartupEvent;
|
||||
import com.axis.innovators.box.events.SubscribeEvent;
|
||||
import com.axis.innovators.box.gui.*;
|
||||
import com.axis.innovators.box.plugins.PluginDescriptor;
|
||||
import com.axis.innovators.box.plugins.PluginLoader;
|
||||
import com.axis.innovators.box.register.RegistrationTool;
|
||||
import com.axis.innovators.box.tools.LibraryLoad;
|
||||
import com.axis.innovators.box.tools.SystemInfoUtil;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.tzd.lm.LM;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import com.axis.innovators.box.tools.FolderCleaner;
|
||||
import com.axis.innovators.box.tools.FolderCreator;
|
||||
import com.axis.innovators.box.register.LanguageManager;
|
||||
|
||||
/**
|
||||
* 主类
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class Main {
|
||||
private static final Logger logger = LogManager.getLogger(Main.class);
|
||||
private static final String VERSIONS = "0.0.1";
|
||||
private static final String[] AUTHOR = new String[]{
|
||||
"tzdwindows 7"
|
||||
};
|
||||
|
||||
/** 我是总任务数 **/
|
||||
public int totalTasks = 1;
|
||||
/** 我是当前任务数 **/
|
||||
private int completedTasks = 0;
|
||||
public ProgressBarManager progressBarManager = new ProgressBarManager("加载中...", totalTasks);
|
||||
private static Main main;
|
||||
private MainWindow ex;
|
||||
private Thread thread;
|
||||
private final String[] args;
|
||||
private boolean isWindow = false;
|
||||
private final RegistrationTool registrationTool = new RegistrationTool(this);
|
||||
|
||||
public Main(String[] args){
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
LibraryLoad.loadLibrary("FridaNative");
|
||||
LM.loadLibrary(LM.CUDA);
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to load the 'FridaNative' library", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取主类
|
||||
* @return 主类
|
||||
*/
|
||||
public static Main getMain() {
|
||||
return main;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取主窗口
|
||||
* @return 主窗口
|
||||
*/
|
||||
public MainWindow getMainWindow() {
|
||||
return ex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出程序
|
||||
*/
|
||||
public void quit() {
|
||||
logger.info("Application is shutting down...");
|
||||
thread.interrupt();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
public void initLog4j2() {
|
||||
Log4j2OutputStream.redirectSystemStreams();
|
||||
// 输出版本和作者信息
|
||||
logger.info("Application Version: {}", VERSIONS);
|
||||
logger.info("Authors: {}", String.join(", ", AUTHOR));
|
||||
|
||||
// 输出系统信息
|
||||
logger.info("Operating System: {}", SystemInfoUtil.getOSName());
|
||||
logger.info("OS Architecture: {}", SystemInfoUtil.getOSArch());
|
||||
logger.info("CPU: {}", SystemInfoUtil.getCPUInfo());
|
||||
logger.info("GPU: {}", SystemInfoUtil.getGPUInfo());
|
||||
logger.info("Java Version: {}", System.getProperty("java.version"));
|
||||
logger.info("Java Vendor: {}", System.getProperty("java.vendor"));
|
||||
logger.info("Java Home: {}", System.getProperty("java.home"));
|
||||
logger.info("Java Class Path: {}", System.getProperty("java.class.path"));
|
||||
logger.info("ClassLoader.getSystemClassLoader(): {}", ClassLoader.getSystemClassLoader());
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onSettingsLoad(SettingsLoadEvents event) {
|
||||
JTabbedPane tabbedPane = new JTabbedPane();
|
||||
|
||||
JPanel pluginPanel = createPluginSettingsPanel();
|
||||
tabbedPane.addTab("插件", null, pluginPanel, "插件管理");
|
||||
|
||||
JPanel generalPanel = createGeneralSettingsPanel();
|
||||
tabbedPane.addTab("基础设置", null, generalPanel, "外观设置");
|
||||
|
||||
JPanel aboutPanel = createAboutPanel();
|
||||
tabbedPane.addTab("关于", null, aboutPanel, "版本信息");
|
||||
|
||||
event.content().add(tabbedPane, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
private JPanel createAboutPanel() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
JTextArea infoArea = new JTextArea();
|
||||
infoArea.setEditable(false);
|
||||
infoArea.setLineWrap(true);
|
||||
infoArea.setWrapStyleWord(true);
|
||||
infoArea.append("软件版本: " + Main.VERSIONS + "\n\n");
|
||||
infoArea.append("开发作者:\n");
|
||||
for (String author : Main.AUTHOR) {
|
||||
infoArea.append("• " + author + "\n");
|
||||
}
|
||||
|
||||
panel.add(new JScrollPane(infoArea), BorderLayout.CENTER);
|
||||
return panel;
|
||||
}
|
||||
|
||||
// 字体选择器内部类
|
||||
private static class FontChooser extends JPanel {
|
||||
private final JComboBox<String> fontFamilyCombo;
|
||||
private final JSpinner fontSizeSpinner;
|
||||
|
||||
public FontChooser(Font currentFont) {
|
||||
setLayout(new GridLayout(2, 2, 5, 5));
|
||||
|
||||
// 字体族选择
|
||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
String[] fontFamilies = ge.getAvailableFontFamilyNames();
|
||||
fontFamilyCombo = new JComboBox<>(fontFamilies);
|
||||
fontFamilyCombo.setSelectedItem(currentFont.getFamily());
|
||||
|
||||
// 字体大小选择
|
||||
SpinnerNumberModel sizeModel = new SpinnerNumberModel(
|
||||
currentFont.getSize(), 8, 48, 1
|
||||
);
|
||||
fontSizeSpinner = new JSpinner(sizeModel);
|
||||
|
||||
add(new JLabel("字体:"));
|
||||
add(fontFamilyCombo);
|
||||
add(new JLabel("大小:"));
|
||||
add(fontSizeSpinner);
|
||||
}
|
||||
|
||||
public Font getSelectedFont() {
|
||||
return new Font(
|
||||
(String) fontFamilyCombo.getSelectedItem(),
|
||||
Font.PLAIN,
|
||||
(Integer) fontSizeSpinner.getValue()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 应用主题颜色
|
||||
private void applyThemeColor(Color color) {
|
||||
// 更新全局颜色设置
|
||||
UIManager.put("Panel.background", color);
|
||||
UIManager.put("TabbedPane.background", color);
|
||||
|
||||
// 更新现有界面
|
||||
SwingUtilities.updateComponentTreeUI(Main.getMain().getMainWindow());
|
||||
}
|
||||
|
||||
private JPanel createPluginSettingsPanel() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
|
||||
// 表格列配置
|
||||
String[] columns = {"插件名称", "版本支持", "描述"};
|
||||
DefaultTableModel model = new DefaultTableModel(columns, 0) {
|
||||
@Override
|
||||
public boolean isCellEditable(int row, int column) {
|
||||
return false; // 禁止编辑
|
||||
}
|
||||
};
|
||||
|
||||
// 从PluginLoader获取插件数据
|
||||
List<PluginDescriptor> plugins = PluginLoader.getLoadedPlugins();
|
||||
for (PluginDescriptor plugin : plugins) {
|
||||
model.addRow(new Object[]{
|
||||
plugin.getName(),
|
||||
String.join(", ", plugin.getSupportedVersions()),
|
||||
plugin.getDescription()
|
||||
});
|
||||
}
|
||||
|
||||
JTable table = new JTable(model);
|
||||
table.setRowHeight(30);
|
||||
table.getTableHeader().setFont(new Font("微软雅黑", Font.BOLD, 14));
|
||||
|
||||
// 添加滚动面板
|
||||
JScrollPane scrollPane = new JScrollPane(table);
|
||||
scrollPane.setBorder(BorderFactory.createTitledBorder("已加载插件列表"));
|
||||
panel.add(scrollPane, BorderLayout.CENTER);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private JPanel createGeneralSettingsPanel() {
|
||||
JPanel panel = new JPanel(new GridBagLayout());
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
gbc.insets = new Insets(5, 5, 5, 5);
|
||||
gbc.anchor = GridBagConstraints.WEST;
|
||||
|
||||
// 颜色选择组件
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy = 0;
|
||||
panel.add(new JLabel("界面主题颜色:"), gbc);
|
||||
|
||||
JButton colorBtn = new JButton("选择颜色");
|
||||
colorBtn.addActionListener(e -> {
|
||||
Color color = JColorChooser.showDialog(panel, "选择主题颜色", Color.WHITE);
|
||||
if (color != null) {
|
||||
applyThemeColor(color);
|
||||
}
|
||||
});
|
||||
gbc.gridx = 1;
|
||||
panel.add(colorBtn, gbc);
|
||||
|
||||
// 字体选择组件
|
||||
gbc.gridy++;
|
||||
gbc.gridx = 0;
|
||||
panel.add(new JLabel("界面字体:"), gbc);
|
||||
|
||||
JButton fontBtn = new JButton("选择字体");
|
||||
fontBtn.addActionListener(e -> {
|
||||
Font currentFont = UIManager.getFont("Label.font");
|
||||
FontChooser fontChooser = new FontChooser(currentFont);
|
||||
int result = JOptionPane.showConfirmDialog(
|
||||
panel,
|
||||
fontChooser,
|
||||
"选择字体",
|
||||
JOptionPane.OK_CANCEL_OPTION
|
||||
);
|
||||
|
||||
if (result == JOptionPane.OK_OPTION) {
|
||||
applyUIFont(fontChooser.getSelectedFont());
|
||||
}
|
||||
});
|
||||
gbc.gridx = 1;
|
||||
panel.add(fontBtn, gbc);
|
||||
|
||||
// 添加CUDA选项
|
||||
gbc.gridy++;
|
||||
gbc.gridx = 0;
|
||||
panel.add(new JLabel("AI推理时使用CUDA:"), gbc);
|
||||
|
||||
JCheckBox cudaCheckBox = new JCheckBox("启用CUDA加速", LM.CUDA);
|
||||
cudaCheckBox.addActionListener(e -> {
|
||||
boolean useCUDA = cudaCheckBox.isSelected();
|
||||
LM.CUDA = useCUDA;
|
||||
logger.info("CUDA加速设置已更新: " + (useCUDA ? "启用" : "禁用"));
|
||||
|
||||
try {
|
||||
LM.loadLibrary(useCUDA);
|
||||
logger.info("AI推理库已重新加载");
|
||||
} catch (Exception ex) {
|
||||
logger.error("无法重新加载AI推理库", ex);
|
||||
JOptionPane.showMessageDialog(panel, "无法重新加载AI推理库,请检查CUDA环境", "错误", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
gbc.gridx = 1;
|
||||
panel.add(cudaCheckBox, gbc);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
// 应用全局字体
|
||||
private void applyUIFont(Font font) {
|
||||
Enumeration<Object> keys = UIManager.getLookAndFeelDefaults().keys();
|
||||
while (keys.hasMoreElements()) {
|
||||
Object key = keys.nextElement();
|
||||
Object value = UIManager.get(key);
|
||||
if (value instanceof Font) {
|
||||
Font derived = font.deriveFont(((Font)value).getStyle());
|
||||
UIManager.put(key, derived);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新所有窗口
|
||||
for (Window window : Window.getWindows()) {
|
||||
SwingUtilities.updateComponentTreeUI(window);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
main = new Main(args);
|
||||
// 注册事件
|
||||
GlobalEventBus.EVENT_BUS.register(main);
|
||||
|
||||
main.initLog4j2();
|
||||
|
||||
// 设置系统外观
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (Exception e) {
|
||||
logger.warn("Failed to load the system facade class", e);
|
||||
}
|
||||
main.thread = new Thread(() -> {
|
||||
try {
|
||||
// 主任务1:加载插件
|
||||
logger.info("Loaded plugins Started");
|
||||
main.progressBarManager.updateMainProgress(++main.completedTasks);
|
||||
PluginLoader.loadPlugins();
|
||||
logger.info("Loaded plugins End");
|
||||
|
||||
main.progressBarManager.close();
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
try {
|
||||
main.ex = new MainWindow();
|
||||
GlobalEventBus.EVENT_BUS.post(new StartupEvent(main));
|
||||
main.runWindow();
|
||||
} catch (Exception e) {
|
||||
logger.error("There was a problem starting the main thread", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to load plugins", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
main.thread.setName("Main Thread");
|
||||
main.thread.start();
|
||||
FolderCleaner.cleanFolder(FolderCreator.getLogsFolder(), 10);
|
||||
LanguageManager.loadSavedLanguage();
|
||||
AxisInnovatorsBox.main(args);
|
||||
}
|
||||
|
||||
public void runWindow() {
|
||||
progressBarManager.updateMainProgress(++completedTasks);
|
||||
|
||||
if (!registrationTool.getToolCategories().isEmpty()) {
|
||||
for (int i = 0; i < registrationTool.getToolCategories()
|
||||
.size(); i++) {
|
||||
ex.addToolCategory(registrationTool.getToolCategories()
|
||||
.get(i));
|
||||
progressBarManager.updateSubProgress(
|
||||
"add tools", i,
|
||||
registrationTool.getToolCategories().size());
|
||||
}
|
||||
}
|
||||
|
||||
ex.initUI();
|
||||
isWindow = true;
|
||||
ex.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取注册工具
|
||||
* @return 注册工具
|
||||
*/
|
||||
public RegistrationTool getRegistrationTool() {
|
||||
return registrationTool;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取命令行参数
|
||||
* @return 命令行参数
|
||||
*/
|
||||
public String[] getArgs() {
|
||||
return args;
|
||||
}
|
||||
|
||||
public boolean isWindow() {
|
||||
return isWindow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.axis.innovators.box.events;
|
||||
|
||||
import com.axis.innovators.box.gui.WindowsJDialog;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
@@ -8,5 +10,5 @@ import javax.swing.*;
|
||||
*
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public record SettingsLoadEvents(JDialog dialog, JPanel content) {
|
||||
public record SettingsLoadEvents(WindowsJDialog dialog, JPanel content) {
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.axis.innovators.box.events;
|
||||
|
||||
import com.axis.innovators.box.Main;
|
||||
import com.axis.innovators.box.AxisInnovatorsBox;
|
||||
|
||||
/**
|
||||
* 当程序启动时触发
|
||||
*
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public record StartupEvent(Main main) {
|
||||
public record StartupEvent(AxisInnovatorsBox main) {
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.axis.innovators.box.gui;
|
||||
|
||||
import com.axis.innovators.box.register.LanguageManager;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.tzd.frida.windows.Frida;
|
||||
@@ -21,7 +22,7 @@ import java.util.List;
|
||||
* Frida注入工具窗口
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class FridaWindow extends JDialog {
|
||||
public class FridaWindow extends WindowsJDialog {
|
||||
private static final Logger logger = LogManager.getLogger(FridaWindow.class);
|
||||
private JTextArea scriptArea;
|
||||
private JTextArea logArea;
|
||||
@@ -29,11 +30,13 @@ public class FridaWindow extends JDialog {
|
||||
private boolean isRepetition = false;
|
||||
|
||||
public FridaWindow(Window owner) {
|
||||
super(owner, "Frida 注入工具", ModalityType.APPLICATION_MODAL);
|
||||
initializeUI();
|
||||
super(owner, language.getText("fridaWindow.title"), ModalityType.APPLICATION_MODAL);
|
||||
initUI();
|
||||
}
|
||||
|
||||
private void initializeUI() {
|
||||
@Override
|
||||
public void initUI() {
|
||||
super.initUI();
|
||||
setSize(800, 600);
|
||||
setLocationRelativeTo(getOwner());
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
@@ -73,18 +76,15 @@ public class FridaWindow extends JDialog {
|
||||
JPanel panel = new JPanel(new GridLayout(1, 3, 10, 10));
|
||||
panel.setOpaque(false);
|
||||
|
||||
pidField = new JTextField("请输入进程PID");
|
||||
|
||||
pidField = new JTextField(language.getText("fridaWindow.pidField"));
|
||||
pidField.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
||||
pidField.setBorder(BorderFactory.createCompoundBorder(
|
||||
BorderFactory.createLineBorder(new Color(57, 56, 56)),
|
||||
BorderFactory.createEmptyBorder(5, 10, 5, 10)
|
||||
));
|
||||
|
||||
//JButton attachButton = new JButton("附加进程");
|
||||
//styleButton(attachButton, new Color(70, 130, 180));
|
||||
//attachButton.setEnabled(false);
|
||||
|
||||
JButton browseButton = new JButton("选择进程");
|
||||
JButton browseButton = new JButton(language.getText("fridaWindow.browseButton"));
|
||||
styleButton(browseButton, new Color(60, 179, 113));
|
||||
browseButton.addActionListener(this::openProcessSelectionWindow);
|
||||
panel.add(pidField);
|
||||
@@ -97,7 +97,7 @@ public class FridaWindow extends JDialog {
|
||||
private JPanel createScriptPanel() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.setOpaque(false);
|
||||
panel.setBorder(BorderFactory.createTitledBorder("脚本编辑器"));
|
||||
panel.setBorder(BorderFactory.createTitledBorder(language.getText("fridaWindow.panel")));
|
||||
|
||||
scriptArea = new JTextArea();
|
||||
scriptArea.setFont(new Font("Consolas", Font.PLAIN, 14));
|
||||
@@ -107,7 +107,7 @@ public class FridaWindow extends JDialog {
|
||||
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 5));
|
||||
buttonPanel.setOpaque(false);
|
||||
|
||||
JButton injectButton = new JButton("注入脚本");
|
||||
JButton injectButton = new JButton(language.getText("fridaWindow.injectButton"));
|
||||
styleButton(injectButton, new Color(220, 20, 60));
|
||||
injectButton.addActionListener(this::handleInject);
|
||||
|
||||
@@ -122,7 +122,7 @@ public class FridaWindow extends JDialog {
|
||||
private JPanel createLogPanel() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.setPreferredSize(new Dimension(0, 150));
|
||||
panel.setBorder(BorderFactory.createTitledBorder("日志输出"));
|
||||
panel.setBorder(BorderFactory.createTitledBorder(language.getText("fridaWindow.panel.log")));
|
||||
panel.setOpaque(false);
|
||||
|
||||
logArea = new JTextArea();
|
||||
@@ -187,7 +187,7 @@ public class FridaWindow extends JDialog {
|
||||
private JTable table;
|
||||
|
||||
public ProcessSelectionWindow(Window owner) {
|
||||
super(owner, "选择进程", ModalityType.APPLICATION_MODAL);
|
||||
super(owner, language.getText("fridaWindow.processSelectionWindow"), ModalityType.APPLICATION_MODAL);
|
||||
setSize(600, 400);
|
||||
setLocationRelativeTo(owner);
|
||||
initializeUI();
|
||||
@@ -220,21 +220,22 @@ public class FridaWindow extends JDialog {
|
||||
filterProcesses(searchField.getText());
|
||||
}
|
||||
});
|
||||
searchPanel.add(new JLabel("搜索进程: "), BorderLayout.WEST);
|
||||
searchPanel.add(new JLabel(language.getText("fridaWindow.processSelectionWindow.search")), BorderLayout.WEST);
|
||||
searchPanel.add(searchField, BorderLayout.CENTER);
|
||||
panel.add(searchPanel, BorderLayout.NORTH);
|
||||
|
||||
String[] columns = {"进程名称", "进程ID"};
|
||||
String[] columns = {language.getText("fridaWindow.processSelectionWindow.columns.1"),
|
||||
language.getText("fridaWindow.processSelectionWindow.columns.2")};
|
||||
Object[][] data = getTableData(processList);
|
||||
table = new JTable(data, columns);
|
||||
JScrollPane scrollPane = new JScrollPane(table);
|
||||
panel.add(scrollPane, BorderLayout.CENTER);
|
||||
|
||||
JButton selectButton = new JButton("选择");
|
||||
JButton selectButton = new JButton(language.getText("fridaWindow.processSelectionWindow.selectButton"));
|
||||
selectButton.addActionListener(e -> {
|
||||
int selectedRow = table.getSelectedRow();
|
||||
if (selectedRow >= 0) {
|
||||
long selectedPid = (Long) table.getValueAt(selectedRow, 1); // 注意这里获取的是PID列
|
||||
long selectedPid = (Long) table.getValueAt(selectedRow, 1);
|
||||
((FridaWindow) getOwner()).pidField.setText(String.valueOf(selectedPid));
|
||||
dispose();
|
||||
}
|
||||
|
||||
@@ -28,20 +28,6 @@ public class LoadIcon {
|
||||
return loadIcon(LoadIcon.class, filename, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* 专门留给插件的加载图片方法
|
||||
* @param filename 图片在resources中的位置
|
||||
* @param size 图片大小
|
||||
* @return ImageIcon对象
|
||||
*/
|
||||
public static ImageIcon pluginsLoadIcon(String filename, int size) {
|
||||
for (int i = 0; i < PluginLoader.getLoadedPlugins().size(); i++) {
|
||||
PluginDescriptor plugin = PluginLoader.getLoadedPlugins().get(i);
|
||||
return loadIcon(plugin.getInstance().getClass(), filename, size);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载图片
|
||||
* @param clazz resources包所在的jar
|
||||
@@ -51,6 +37,9 @@ public class LoadIcon {
|
||||
*/
|
||||
public static ImageIcon loadIcon(Class<?> clazz ,String filename, int size) {
|
||||
try {
|
||||
if (filename.isEmpty()){
|
||||
return createPlaceholderIcon(size);
|
||||
}
|
||||
String fullPath = ICON_PATH + filename;
|
||||
URL imgUrl = clazz.getResource(fullPath);
|
||||
if (imgUrl == null) {
|
||||
@@ -64,6 +53,30 @@ public class LoadIcon {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载图片,另一个版本
|
||||
* @param clazz resources包所在的jar
|
||||
* @param filename 图片名
|
||||
* @param size 图片大小
|
||||
* @return ImageIcon对象
|
||||
*/
|
||||
public static ImageIcon loadIcon0(Class<?> clazz ,String filename, int size) {
|
||||
try {
|
||||
if (filename.isEmpty()){
|
||||
return createPlaceholderIcon(size);
|
||||
}
|
||||
URL imgUrl = clazz.getResource(filename);
|
||||
if (imgUrl == null) {
|
||||
return createPlaceholderIcon(size);
|
||||
}
|
||||
Image image = new ImageIcon(imgUrl).getImage();
|
||||
return new ImageIcon(image.getScaledInstance(size, size, Image.SCALE_SMOOTH));
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to load icon image path '{}'", filename, e);
|
||||
return createPlaceholderIcon(size);
|
||||
}
|
||||
}
|
||||
|
||||
private static ImageIcon createPlaceholderIcon(int size) {
|
||||
BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g2d = img.createGraphics();
|
||||
|
||||
@@ -1,21 +1,29 @@
|
||||
package com.axis.innovators.box.gui;
|
||||
|
||||
import com.axis.innovators.box.register.LanguageManager;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.tzd.lm.LM;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
/**
|
||||
* 本地AI执行工具
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class LocalWindow extends JDialog {
|
||||
public class LocalWindow extends WindowsJDialog {
|
||||
private static final Logger logger = LogManager.getLogger(LocalWindow.class);
|
||||
private final Color bgColor = new Color(45, 45, 48);
|
||||
private final Color textColor = new Color(240, 240, 240);
|
||||
@@ -31,14 +39,17 @@ public class LocalWindow extends JDialog {
|
||||
private long currentModelHandle = -1;
|
||||
|
||||
private JSpinner tempSpinner;
|
||||
private boolean searchEnabled = false;
|
||||
|
||||
public LocalWindow(Window owner) {
|
||||
super(owner, "本地AI执行工具", ModalityType.APPLICATION_MODAL);
|
||||
initializeUI();
|
||||
initUI();
|
||||
loadModelAsync();
|
||||
}
|
||||
|
||||
private void initializeUI() {
|
||||
@Override
|
||||
public void initUI() {
|
||||
super.initUI();
|
||||
JPanel mainPanel = getjPanel();
|
||||
|
||||
// 聊天区域
|
||||
@@ -97,17 +108,17 @@ public class LocalWindow extends JDialog {
|
||||
toolBar.setBackground(bgColor);
|
||||
|
||||
// 新对话按钮
|
||||
JButton newBtn = new JButton("新对话");
|
||||
JButton newBtn = new JButton(language.getText("localWindow.newBtn"));
|
||||
styleButton(newBtn);
|
||||
newBtn.addActionListener(e -> createNewContext());
|
||||
|
||||
// 保存记录按钮
|
||||
JButton saveBtn = new JButton("保存记录");
|
||||
JButton saveBtn = new JButton(language.getText("localWindow.saveBtn"));
|
||||
styleButton(saveBtn);
|
||||
saveBtn.addActionListener(e -> saveConversation());
|
||||
|
||||
// CUDA切换
|
||||
JCheckBox cudaCheck = new JCheckBox("启用CUDA", LM.CUDA);
|
||||
JCheckBox cudaCheck = new JCheckBox(language.getText("localWindow.cudaCheck"), LM.CUDA);
|
||||
cudaCheck.setFont(mainFont);
|
||||
cudaCheck.setBackground(Color.lightGray);
|
||||
cudaCheck.setForeground(Color.black);
|
||||
@@ -118,13 +129,28 @@ public class LocalWindow extends JDialog {
|
||||
contextBox.setBackground(bgColor);
|
||||
contextBox.setForeground(textColor);
|
||||
|
||||
// 搜索功能按钮
|
||||
JButton searchBtn = new JButton(language.getText("localWindow.searchBtn"));
|
||||
styleButton(searchBtn);
|
||||
searchBtn.addActionListener(e -> {
|
||||
searchEnabled = !searchEnabled;
|
||||
searchBtn.setText(searchEnabled ? language.getText("localWindow.searchBtn.1")
|
||||
: language.getText("localWindow.searchBtn"));
|
||||
if (searchEnabled) {
|
||||
appendMessage(language.getText("localWindow.searchBtn.appendMessage"));
|
||||
} else {
|
||||
appendMessage(language.getText("localWindow.searchBtn.appendMessage.1"));
|
||||
}
|
||||
});
|
||||
|
||||
toolBar.add(newBtn);
|
||||
toolBar.add(saveBtn);
|
||||
toolBar.addSeparator();
|
||||
toolBar.add(cudaCheck);
|
||||
toolBar.addSeparator();
|
||||
|
||||
toolBar.add(contextBox);
|
||||
toolBar.addSeparator();
|
||||
toolBar.add(searchBtn);
|
||||
|
||||
return toolBar;
|
||||
}
|
||||
@@ -138,7 +164,7 @@ public class LocalWindow extends JDialog {
|
||||
inputField.setForeground(Color.black);
|
||||
inputField.setBackground(Color.white);
|
||||
|
||||
JButton sendButton = new JButton("发送");
|
||||
JButton sendButton = new JButton(language.getText("localWindow.sendButton"));
|
||||
styleButton(sendButton);
|
||||
sendButton.addActionListener(this::handleSendMessage);
|
||||
|
||||
@@ -204,38 +230,155 @@ public class LocalWindow extends JDialog {
|
||||
if (!prompt.isEmpty()) {
|
||||
appendMessage(prompt);
|
||||
inputField.setText("");
|
||||
new SwingWorker<String, String>() {
|
||||
@Override
|
||||
protected String doInBackground() {
|
||||
float temperature = ((Number) tempSpinner.getValue()).floatValue();
|
||||
return LM.inference(
|
||||
currentModelHandle,
|
||||
contextHandles.getLast(),
|
||||
temperature,
|
||||
prompt,
|
||||
"你是一个乐于助人的AI助手,请用友好自然的语气回答用户问题。",
|
||||
this::publish
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process(java.util.List<String> chunks) {
|
||||
chunks.forEach(msg -> appendAIMessage(msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
String result = get();
|
||||
logger.info(result);
|
||||
} catch (Exception ex) {
|
||||
logger.error("SwingWorker execution error: ", ex);
|
||||
if (searchEnabled) {
|
||||
// 如果搜索功能开启,先进行搜索
|
||||
new SwingWorker<String, Void>() {
|
||||
@Override
|
||||
protected String doInBackground() {
|
||||
return searchWeb(prompt);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
String searchResult = get();
|
||||
logger.info("Search result: {}", searchResult);
|
||||
if (searchResult.isEmpty()) {
|
||||
while (true){
|
||||
searchResult = searchWeb(prompt);
|
||||
if (!searchResult.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
seekAI(prompt, searchResult);
|
||||
return;
|
||||
}
|
||||
seekAI(prompt, searchResult);
|
||||
} catch (Exception ex) {
|
||||
logger.error("Search failed: ", ex);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
} else {
|
||||
analyzeWithAI(prompt, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String searchWeb(String query) {
|
||||
int maxRetries = 2;
|
||||
int retry = 0;
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
// 设置请求 URL
|
||||
String url = "https://cn.bing.com/search?q=" + URLEncoder.encode(query, StandardCharsets.UTF_8);
|
||||
|
||||
// 设置请求头和 Cookies
|
||||
Document doc = Jsoup.connect(url)
|
||||
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36")
|
||||
.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
|
||||
.header("Accept-Language", "zh-CN,zh;q=0.9")
|
||||
.header("Accept-Encoding", "gzip, deflate, br")
|
||||
.header("Connection", "keep-alive")
|
||||
.cookie("MUID", "你的MUID值")
|
||||
.cookie("SRCHD", "你的SRCHD值")
|
||||
.timeout(10000)
|
||||
.get();
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
Elements items = doc.select("li.b_algo");
|
||||
|
||||
for (Element item : items) {
|
||||
String title = item.select("h2").text();
|
||||
String urlLink = item.select("a").attr("href");
|
||||
String snippet = item.select("div.b_caption p").text();
|
||||
String urlContent = "未爬取";
|
||||
|
||||
result.append("标题: ").append(title)
|
||||
.append("\n链接: ").append(urlLink)
|
||||
.append("\n摘要: ").append(snippet)
|
||||
.append("\n爬取到的内容: ").append(urlContent)
|
||||
.append("\n\n");
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
} catch (IOException e) {
|
||||
retry++;
|
||||
if (retry > maxRetries) {
|
||||
System.err.println("搜索失败(重试 " + maxRetries + " 次): " + e.getMessage());
|
||||
return "搜索失败: " + e.getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void analyzeWithAI(String prompt, String searchResult) {
|
||||
new SwingWorker<String, String>() {
|
||||
@Override
|
||||
protected String doInBackground() {
|
||||
float temperature = ((Number) tempSpinner.getValue()).floatValue();
|
||||
String fullPrompt = searchResult != null ? ("\n\n搜索结果:\n" + searchResult + "。") + prompt : prompt;
|
||||
return LM.inference(
|
||||
currentModelHandle,
|
||||
contextHandles.getLast(),
|
||||
temperature,
|
||||
fullPrompt,
|
||||
language.getText("localWindow.prompt.system"),
|
||||
this::publish
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process(java.util.List<String> chunks) {
|
||||
chunks.forEach(msg -> appendAIMessage(msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
String result = get();
|
||||
logger.info(result);
|
||||
} catch (Exception ex) {
|
||||
logger.error("SwingWorker execution error: ", ex);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private void seekAI(String prompt, String searchResult) {
|
||||
new SwingWorker<String, String>() {
|
||||
@Override
|
||||
protected String doInBackground() {
|
||||
float temperature = ((Number) tempSpinner.getValue()).floatValue();
|
||||
String fullPrompt = searchResult != null ? ("\n\n搜索结果:\n" + searchResult + "。") + prompt : prompt;
|
||||
return LM.inference(
|
||||
currentModelHandle,
|
||||
contextHandles.getLast(),
|
||||
temperature,
|
||||
fullPrompt,
|
||||
language.getText("localWindow.prompt.system.2"),
|
||||
this::publish
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process(java.util.List<String> chunks) {
|
||||
chunks.forEach(msg -> appendAIMessage(msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
String result = get();
|
||||
logger.info(result);
|
||||
} catch (Exception ex) {
|
||||
logger.error("SwingWorker execution error: ", ex);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
static boolean isTemporary = true;
|
||||
private void appendAIMessage(String message) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
@@ -256,7 +399,7 @@ public class LocalWindow extends JDialog {
|
||||
private void appendMessage(String message) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
logger.info("\n【用户】\n{}", message);
|
||||
chatArea.append("\n【用户】\n" + message + "\n\n");
|
||||
chatArea.append("\n"+ language.getText("localWindow.prompt.user")+"\n" + message + "\n\n");
|
||||
chatArea.setCaretPosition(chatArea.getDocument().getLength());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.axis.innovators.box.gui;
|
||||
|
||||
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 org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@@ -47,18 +50,26 @@ public class MainWindow extends JFrame {
|
||||
categories.add(category);
|
||||
}
|
||||
|
||||
|
||||
public void initUI() {
|
||||
setTitle("轴创工具箱 v1.0");
|
||||
// 设置窗口属性
|
||||
|
||||
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) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
Color color1 = new Color(235, 241, 250);
|
||||
Color color2 = new Color(255, 255, 255);
|
||||
GradientPaint gp = new GradientPaint(0, 0, color1, getWidth(), getHeight(), color2);
|
||||
@@ -80,23 +91,29 @@ public class MainWindow extends JFrame {
|
||||
int y = (getHeight() - backgroundImage.getIconHeight()) / 2;
|
||||
g2d.drawImage(backgroundImage.getImage(), x, y, this);
|
||||
}
|
||||
|
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
|
||||
} catch (Exception e) {
|
||||
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);
|
||||
|
||||
GlobalEventBus.EVENT_BUS.post(new MainWindowEvents.initialize(this, mainPanel));
|
||||
|
||||
// 添加主面板到窗口
|
||||
add(mainPanel);
|
||||
}
|
||||
|
||||
@@ -243,7 +260,7 @@ public class MainWindow extends JFrame {
|
||||
header.setBorder(BorderFactory.createEmptyBorder(15, 30, 15, 30));
|
||||
|
||||
// 创建标题
|
||||
JLabel title = new JLabel("轴创工具箱");
|
||||
JLabel title = new JLabel(LanguageManager.getLoadedLanguages().getText("mainWindow.title.2"));
|
||||
title.setFont(new Font("微软雅黑", Font.BOLD, 28));
|
||||
title.setForeground(new Color(44, 62, 80));
|
||||
|
||||
@@ -272,28 +289,50 @@ public class MainWindow extends JFrame {
|
||||
super.update(g);
|
||||
}
|
||||
|
||||
private void showSettings() {
|
||||
JDialog dialog = new JDialog(this, "系统设置", true);
|
||||
private WindowsJDialog dialog;
|
||||
public void showSettings() {
|
||||
if (dialog == null || !AxisInnovatorsBox.getMain().isWindowStartup(dialog)) {
|
||||
dialog = new WindowsJDialog(this,
|
||||
LanguageManager.getLoadedLanguages().getText("mainWindow.settings.title"), true);
|
||||
}
|
||||
dialog.setTitle(LanguageManager.getLoadedLanguages().getText("mainWindow.settings.title"));
|
||||
dialog.setSize(600, 400);
|
||||
dialog.setLocationRelativeTo(this);
|
||||
|
||||
JPanel content = new JPanel(new BorderLayout());
|
||||
content.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
JTabbedPane tabbedPane = new JTabbedPane();
|
||||
|
||||
List<RegistrationSettingsItem> registrationSettingsItemList
|
||||
= RegistrationSettingsItem.getRegistrationSettingsItemList();
|
||||
for (RegistrationSettingsItem registrationSettingsItem : registrationSettingsItemList) {
|
||||
registrationSettingsItem.registration(tabbedPane);
|
||||
}
|
||||
|
||||
content.add(tabbedPane, BorderLayout.CENTER);
|
||||
GlobalEventBus.EVENT_BUS.post(new SettingsLoadEvents(dialog, content));
|
||||
|
||||
dialog.add(content);
|
||||
dialog.setVisible(true);
|
||||
dialog.revalidate();
|
||||
if (!AxisInnovatorsBox.getMain().isWindowStartup(dialog)) {
|
||||
AxisInnovatorsBox.getMain().popupWindow(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private JPanel createToolCard(ToolItem tool) {
|
||||
JPanel card = new JPanel() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
|
||||
Graphics2D g2d = (Graphics2D) g.create();
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
// 毛玻璃效果
|
||||
BufferedImage background = new BufferedImage(
|
||||
getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
|
||||
super.paintComponent(background.getGraphics());
|
||||
BufferedImage blurred = applyGaussianBlur(background, 5);
|
||||
|
||||
g2d.drawImage(blurred, 0, 0, null);
|
||||
|
||||
// 绘制阴影
|
||||
int elevation = cardElevations.getOrDefault(this, 2);
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.util.Map;
|
||||
* 启动窗口的任务系统
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class ProgressBarManager {
|
||||
public class ProgressBarManager extends WindowsJDialog {
|
||||
private JFrame loadingFrame;
|
||||
private JProgressBar mainProgressBar;
|
||||
private JProgressBar subProgressBar;
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.axis.innovators.box.gui;
|
||||
|
||||
import com.axis.innovators.box.AxisInnovatorsBox;
|
||||
import com.axis.innovators.box.register.LanguageManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
/**
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class WindowsJDialog extends JDialog {
|
||||
public static LanguageManager.Language language = LanguageManager.getLoadedLanguages();
|
||||
|
||||
public WindowsJDialog() {}
|
||||
|
||||
public WindowsJDialog(Window owner, String title, Dialog.ModalityType modalityType) {
|
||||
super(owner, title, modalityType);
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public WindowsJDialog(Frame owner, String title, boolean modal) {
|
||||
super(owner, title, modal);
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void initUI() {
|
||||
language = LanguageManager.getLoadedLanguages();
|
||||
}
|
||||
|
||||
public void dispose_() {
|
||||
super.dispose();
|
||||
}
|
||||
@Override
|
||||
public void dispose() {
|
||||
AxisInnovatorsBox.getMain().clearWindow(this);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package com.axis.innovators.box.plugins;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
@@ -32,14 +34,10 @@ public class BoxClassLoader extends URLClassLoader {
|
||||
try {
|
||||
PluginLoader.loadCorePlugin();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to load core plugin", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public BoxClassLoader(URL[] urls, ClassLoader parent) {
|
||||
super(urls, parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addURL(URL url) {
|
||||
super.addURL(url);
|
||||
@@ -49,7 +47,9 @@ public class BoxClassLoader extends URLClassLoader {
|
||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||
synchronized (getClassLoadingLock(name)) {
|
||||
Class<?> loadedClass = findLoadedClass(name);
|
||||
if (loadedClass != null) return loadedClass;
|
||||
if (loadedClass != null) {
|
||||
return loadedClass;
|
||||
}
|
||||
|
||||
if (isBlacklisted(name)) {
|
||||
return getParent().loadClass(name);
|
||||
@@ -57,7 +57,9 @@ public class BoxClassLoader extends URLClassLoader {
|
||||
|
||||
try {
|
||||
Class<?> c = findClass(name);
|
||||
if (resolve) resolveClass(c);
|
||||
if (resolve) {
|
||||
resolveClass(c);
|
||||
}
|
||||
return c;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return super.loadClass(name, resolve);
|
||||
@@ -107,6 +109,10 @@ public class BoxClassLoader extends URLClassLoader {
|
||||
CLASS_TRANSFORMS.add(transformer);
|
||||
}
|
||||
|
||||
public static List<IClassTransformer> getClassTransforms() {
|
||||
return CLASS_TRANSFORMS;
|
||||
}
|
||||
|
||||
public static List<Class<?>> getClassList() {
|
||||
return CLASS_LOADING_LIST_OBJECT;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
package com.axis.innovators.box.plugins;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Core插件接口
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public interface LoadingCorePlugin {
|
||||
String[] getLibraryRequestClass();
|
||||
/**
|
||||
* 获取主类
|
||||
* @return 请返回插件主类
|
||||
*/
|
||||
String getMainClass();
|
||||
|
||||
/**
|
||||
* 获取ASM转换器
|
||||
* @return 请返回ASM转换器
|
||||
*/
|
||||
String[] getASMTransformerClass();
|
||||
String getSetupClass();
|
||||
void injectData(Map<String, Object> data);
|
||||
}
|
||||
@@ -12,6 +12,7 @@ public class PluginDescriptor {
|
||||
private String icon;
|
||||
private String description;
|
||||
private Object instance;
|
||||
private String transformers;
|
||||
|
||||
// Getters and Setters
|
||||
public String getId() { return id; }
|
||||
@@ -26,4 +27,6 @@ public class PluginDescriptor {
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
public Object getInstance() { return instance; }
|
||||
public void setInstance(Object instance) { this.instance = instance; }
|
||||
public String getTransformers() {return transformers;}
|
||||
public void setTransformers(String transformers) {this.transformers = transformers;}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.axis.innovators.box.plugins;
|
||||
|
||||
import com.axis.innovators.box.Main;
|
||||
import com.axis.innovators.box.AxisInnovatorsBox;
|
||||
import com.axis.innovators.box.tools.FolderCreator;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -19,6 +19,7 @@ public class PluginLoader {
|
||||
public static final String PLUGIN_PATH = FolderCreator.getPluginFolder();
|
||||
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 {
|
||||
logger = LogManager.getLogger(PluginLoader.class);
|
||||
File pluginDir = null;
|
||||
@@ -35,7 +36,7 @@ public class PluginLoader {
|
||||
}
|
||||
for (int i = 0; i < jars.length; i++) {
|
||||
processJarFile(jars[i],false);
|
||||
Main.getMain().progressBarManager.updateSubProgress(
|
||||
AxisInnovatorsBox.getMain().progressBarManager.updateSubProgress(
|
||||
"Loading Plugin " + i,
|
||||
i,
|
||||
jars.length);
|
||||
@@ -84,14 +85,14 @@ public class PluginLoader {
|
||||
}
|
||||
|
||||
private static void processCorePlugin(File jarFile, String corePluginClass) {
|
||||
try (URLClassLoader classLoader = new URLClassLoader(
|
||||
try (URLClassLoader urlClassLoader = new URLClassLoader(
|
||||
new URL[]{jarFile.toURI().toURL()},
|
||||
PluginLoader.class.getClassLoader())
|
||||
) {
|
||||
Class<?> coreClass = classLoader.loadClass(corePluginClass);
|
||||
Class<?> coreClass = urlClassLoader.loadClass(corePluginClass);
|
||||
if (LoadingCorePlugin.class.isAssignableFrom(coreClass)) {
|
||||
LoadingCorePlugin corePlugin = (LoadingCorePlugin) coreClass.getDeclaredConstructor().newInstance();
|
||||
registerTransformers(corePlugin, classLoader);
|
||||
registerTransformers(corePlugin, urlClassLoader);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to load core plugin: {}", corePluginClass, e);
|
||||
@@ -99,24 +100,29 @@ public class PluginLoader {
|
||||
}
|
||||
|
||||
private static void registerTransformers(LoadingCorePlugin corePlugin, ClassLoader classLoader) {
|
||||
String[] transformerClasses = corePlugin.getASMTransformerClass();
|
||||
if (transformerClasses != null) {
|
||||
for (String transformerClass : transformerClasses) {
|
||||
try {
|
||||
Class<?> transformerClazz = classLoader.loadClass(transformerClass);
|
||||
if (IClassTransformer.class.isAssignableFrom(transformerClazz)) {
|
||||
IClassTransformer transformer = (IClassTransformer) transformerClazz.getDeclaredConstructor().newInstance();
|
||||
transformers.add(transformer);
|
||||
BoxClassLoader.addClassTransformer(transformer);
|
||||
//if (corePlugin.getMainClass() != null) {
|
||||
corePluginMainClass.add(corePlugin.getMainClass());
|
||||
String[] transformerClasses = corePlugin.getASMTransformerClass();
|
||||
if (transformerClasses != null) {
|
||||
for (String transformerClass : transformerClasses) {
|
||||
try {
|
||||
Class<?> transformerClazz = classLoader.loadClass(transformerClass);
|
||||
if (IClassTransformer.class.isAssignableFrom(transformerClazz)) {
|
||||
IClassTransformer transformer = (IClassTransformer) transformerClazz.getDeclaredConstructor().newInstance();
|
||||
transformers.add(transformer);
|
||||
BoxClassLoader.addClassTransformer(transformer);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to register transformer: {}", transformerClass, e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to register transformer: {}", transformerClass, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
//} else {
|
||||
// logger.error("Failed to load core plugin: {}", corePlugin.getClass().getName());
|
||||
//}
|
||||
}
|
||||
|
||||
private static void processWithManifest(JarFile jar, JarEntry entry, File jarFile) {
|
||||
private static void processWithManifest(JarFile jar, JarEntry entry, File jarFile) throws IOException {
|
||||
Properties props = new Properties();
|
||||
try (InputStream is = jar.getInputStream(entry)) {
|
||||
props.load(is);
|
||||
@@ -133,11 +139,12 @@ public class PluginLoader {
|
||||
descriptor.setSupportedVersions(
|
||||
Arrays.asList(props.getProperty("supportedVersions").split(","))
|
||||
);
|
||||
|
||||
logger.info("Loaded plugin: {}", descriptor.getName());
|
||||
loadMainClass(props.getProperty("mainClass"), jarFile, descriptor);
|
||||
if (descriptor.getInstance() != null) {
|
||||
loadedPlugins.add(descriptor);
|
||||
}
|
||||
|
||||
Attributes attributes = jar.getManifest().getMainAttributes();
|
||||
String corePluginClass = attributes.getValue("CorePlugin");
|
||||
descriptor.setTransformers(corePluginClass);
|
||||
}
|
||||
|
||||
private static void processWithAnnotations(JarFile jar, File jarFile) {
|
||||
@@ -147,7 +154,7 @@ public class PluginLoader {
|
||||
JarEntry entry = entries.nextElement();
|
||||
if (entry.getName().endsWith(".class")) {
|
||||
if (classLoader != null) {
|
||||
processClassEntry(entry, classLoader);
|
||||
processClassEntry(entry, jar,classLoader);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -165,7 +172,7 @@ public class PluginLoader {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void processClassEntry(JarEntry entry, URLClassLoader classLoader) {
|
||||
private static void processClassEntry(JarEntry entry,JarFile jar, URLClassLoader classLoader) {
|
||||
String className = entry.getName()
|
||||
.replace("/", ".")
|
||||
.replace(".class", "");
|
||||
@@ -185,6 +192,11 @@ public class PluginLoader {
|
||||
Object instance = clazz.getDeclaredConstructor().newInstance();
|
||||
descriptor.setInstance(instance);
|
||||
loadedPlugins.add(descriptor);
|
||||
|
||||
Attributes attributes = jar.getManifest().getMainAttributes();
|
||||
String corePluginClass = attributes.getValue("CorePlugin");
|
||||
descriptor.setTransformers(corePluginClass);
|
||||
logger.info("Loaded plugin: {}", descriptor.getName());
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to instantiate plugin class: {}", className, e);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
package com.axis.innovators.box.register;
|
||||
|
||||
import com.axis.innovators.box.tools.FolderCreator;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* 语言管理器
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class LanguageManager {
|
||||
private static Language loadedLanguages;
|
||||
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";
|
||||
|
||||
static {
|
||||
LANGUAGES.add(new Language("简体中文", "Zh","SimplifiedChineseLanguage"));
|
||||
LANGUAGES.add(new Language("繁體中文", "TC","TraditionalChineseLanguage"));
|
||||
LANGUAGES.add(new Language("English", "En","EnglishLanguage"));
|
||||
}
|
||||
/**
|
||||
* 添加语言
|
||||
* @param language 语言
|
||||
*/
|
||||
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);
|
||||
return;
|
||||
}
|
||||
}
|
||||
LANGUAGES.add(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载语言
|
||||
* @param languageName 语言注册名
|
||||
*/
|
||||
public static void loadLanguage(String languageName) {
|
||||
loadedLanguages = LanguageManager.getLanguage(languageName);
|
||||
saveCurrentLanguageToFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将当前加载的语言保存到配置文件中
|
||||
*/
|
||||
private static void saveCurrentLanguageToFile() {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("loadedLanguage", loadedLanguages.getRegisteredName());
|
||||
|
||||
try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(SAVED_LANGUAGE_FILE), StandardCharsets.UTF_8)) {
|
||||
properties.store(writer, "Current Loaded Language");
|
||||
} catch (IOException e) {
|
||||
System.err.println("Failed to save current language to file: " + SAVED_LANGUAGE_FILE);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从配置文件中加载保存的语言
|
||||
*/
|
||||
public static void loadSavedLanguage() {
|
||||
Properties properties = new Properties();
|
||||
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(SAVED_LANGUAGE_FILE), StandardCharsets.UTF_8)) {
|
||||
properties.load(reader);
|
||||
String loadedLanguageName = properties.getProperty("loadedLanguage");
|
||||
if (loadedLanguageName != null) {
|
||||
loadedLanguages = LanguageManager.getLanguage(loadedLanguageName);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("Failed to load saved language from file: " + SAVED_LANGUAGE_FILE);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已加载的语言
|
||||
* @return 已加载的语言
|
||||
*/
|
||||
public static Language getLoadedLanguages() {
|
||||
return loadedLanguages;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取语言
|
||||
* @param languageName 语言注册名,或者语言名称
|
||||
* @return 语言对象
|
||||
*/
|
||||
public static Language getLanguage(String languageName) {
|
||||
for (Language language : LANGUAGES) {
|
||||
if (language.getRegisteredName().equals(languageName)) {
|
||||
return language;
|
||||
}
|
||||
}
|
||||
|
||||
for (Language language : LANGUAGES) {
|
||||
if (language.getLanguageName().equals(languageName)) {
|
||||
return language;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有语言
|
||||
* @return 所有语言
|
||||
*/
|
||||
public static List<Language> getLanguages() {
|
||||
return LANGUAGES;
|
||||
}
|
||||
|
||||
public static class Language {
|
||||
private final String languageName;
|
||||
private final String registeredName;
|
||||
private final String languageFile;
|
||||
private final Properties properties;
|
||||
|
||||
public Language(String languageName,
|
||||
String registeredName,
|
||||
String languageFileName) {
|
||||
this.languageName = languageName;
|
||||
this.registeredName = registeredName;
|
||||
if (languageFileName == null) {
|
||||
this.languageFile = LANGUAGE_PATH + "\\" + registeredName + ".properties";
|
||||
} else {
|
||||
this.languageFile = LANGUAGE_PATH + "\\" + languageFileName + ".properties";
|
||||
}
|
||||
this.properties = new Properties();
|
||||
loadLanguageFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载语言文件
|
||||
*/
|
||||
private void loadLanguageFile() {
|
||||
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(this.languageFile),
|
||||
StandardCharsets.UTF_8)) {
|
||||
properties.load(reader);
|
||||
} catch (IOException e) {
|
||||
System.err.println("Failed to load language file: " + this.languageFile);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定键的文本
|
||||
* @param key 键
|
||||
* @return 对应的文本,如果键不存在则返回 null
|
||||
*/
|
||||
public String getText(String key) {
|
||||
if (!properties.containsKey(key)) {
|
||||
return key;
|
||||
}
|
||||
return properties.getProperty(key);
|
||||
}
|
||||
|
||||
public String getLanguageName() {
|
||||
return languageName;
|
||||
}
|
||||
|
||||
public String getRegisteredName() {
|
||||
return registeredName;
|
||||
}
|
||||
|
||||
public File getLanguageFile() {
|
||||
return new File(languageFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,8 @@ package com.axis.innovators.box.register;
|
||||
* 当工具注册失败时抛出此错误
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class ToolsRegistrationError extends Error{
|
||||
public ToolsRegistrationError(String message) {
|
||||
public class RegistrationError extends Error{
|
||||
public RegistrationError(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,679 @@
|
||||
package com.axis.innovators.box.register;
|
||||
|
||||
|
||||
import com.axis.innovators.box.AxisInnovatorsBox;
|
||||
import com.axis.innovators.box.gui.LoadIcon;
|
||||
import com.axis.innovators.box.gui.WindowsJDialog;
|
||||
import com.axis.innovators.box.plugins.PluginDescriptor;
|
||||
import com.axis.innovators.box.plugins.PluginLoader;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.tzd.lm.LM;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 用于注册设置项的类
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class RegistrationSettingsItem extends WindowsJDialog {
|
||||
private static final List<RegistrationSettingsItem> registrationSettingsItemList = new ArrayList<>();
|
||||
private static final Logger logger = LogManager.getLogger(RegistrationSettingsItem.class);
|
||||
private static RegistrationTopic registrationTopic;
|
||||
private final List<UUID> uuidList = new ArrayList<>();
|
||||
private final List<String> registeredNameList = new ArrayList<>();
|
||||
private final List<JPanel> tabbedPanesSettings = new ArrayList<>();
|
||||
private final List<String> titleList = new ArrayList<>();
|
||||
private final List<Icon> iconList = new ArrayList<>();
|
||||
private final List<String> tipList = new ArrayList<>();
|
||||
private boolean isEmpty = true;
|
||||
private final AxisInnovatorsBox mainWindow;
|
||||
|
||||
static {
|
||||
RegistrationSettingsItem registrationSettingsItem = new RegistrationSettingsItem();
|
||||
JPanel pluginPanel = createPluginSettingsPanel();
|
||||
JPanel generalPanel = createGeneralSettingsPanel();
|
||||
JPanel aboutPanel = createAboutPanel();
|
||||
JPanel themePanel = createThemePanel();
|
||||
|
||||
registrationSettingsItem.addSettings(
|
||||
pluginPanel, language.getText("settings.1.title"),
|
||||
null, language.getText("settings.1.tip"), "system:settings_plugins_item"
|
||||
);
|
||||
registrationSettingsItem.addSettings(
|
||||
generalPanel, language.getText("settings.2.title"),
|
||||
null, language.getText("settings.2.tip"), "system:settings_appearance_item"
|
||||
);
|
||||
registrationSettingsItem.addSettings(
|
||||
aboutPanel, language.getText("settings.3.title"),
|
||||
null, language.getText("settings.3.tip"), "system:settings_information_item"
|
||||
);
|
||||
registrationSettingsItem.addSettings(
|
||||
themePanel, language.getText("settings.4.title"),
|
||||
null, language.getText("settings.4.tip"), "system:settings_theme_item"
|
||||
);
|
||||
|
||||
registrationSettingsItemList.add(
|
||||
registrationSettingsItem
|
||||
);
|
||||
}
|
||||
|
||||
public static void overloading() {
|
||||
language = LanguageManager.getLoadedLanguages();
|
||||
registrationSettingsItemList.clear();
|
||||
RegistrationSettingsItem registrationSettingsItem = new RegistrationSettingsItem();
|
||||
JPanel pluginPanel = createPluginSettingsPanel();
|
||||
JPanel generalPanel = createGeneralSettingsPanel();
|
||||
JPanel aboutPanel = createAboutPanel();
|
||||
JPanel themePanel = createThemePanel();
|
||||
|
||||
registrationSettingsItem.addSettings(
|
||||
pluginPanel, language.getText("settings.1.title"),
|
||||
null, language.getText("settings.1.tip"), "system:settings_plugins_item"
|
||||
);
|
||||
registrationSettingsItem.addSettings(
|
||||
generalPanel, language.getText("settings.2.title"),
|
||||
null, language.getText("settings.2.tip"), "system:settings_appearance_item"
|
||||
);
|
||||
registrationSettingsItem.addSettings(
|
||||
aboutPanel, language.getText("settings.3.title"),
|
||||
null, language.getText("settings.3.tip"), "system:settings_information_item"
|
||||
);
|
||||
registrationSettingsItem.addSettings(
|
||||
themePanel, language.getText("settings.4.title"),
|
||||
null, language.getText("settings.4.tip"), "system:settings_theme_item"
|
||||
);
|
||||
|
||||
registrationSettingsItemList.add(
|
||||
registrationSettingsItem
|
||||
);
|
||||
|
||||
AxisInnovatorsBox.getMain().getMainWindow().showSettings();
|
||||
}
|
||||
|
||||
private static JPanel createThemePanel() {
|
||||
JPanel themePanel = new JPanel(new BorderLayout());
|
||||
|
||||
RegistrationTopic registrationTopic = getRegistrationTopic();
|
||||
|
||||
if (registrationTopic.isEmpty()) {
|
||||
themePanel.add(new JLabel(language.getText("settings.4.no_theme"), SwingConstants.CENTER), BorderLayout.CENTER);
|
||||
return themePanel;
|
||||
}
|
||||
|
||||
// 创建搜索栏
|
||||
JPanel searchPanel = new JPanel(new BorderLayout());
|
||||
JTextField searchField = new JTextField();
|
||||
JButton searchButton = new JButton(language.getText("settings.4.search"));
|
||||
searchPanel.add(searchField, BorderLayout.CENTER);
|
||||
searchPanel.add(searchButton, BorderLayout.EAST);
|
||||
searchPanel.setVisible(false);
|
||||
|
||||
// 将搜索栏添加到主题面板的顶部
|
||||
themePanel.add(searchPanel, BorderLayout.NORTH);
|
||||
|
||||
DefaultListModel<JPanel> listModel = new DefaultListModel<>();
|
||||
JList<JPanel> themeList = new JList<>(listModel);
|
||||
|
||||
themeList.setCellRenderer(new DefaultListCellRenderer() {
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
JPanel itemPanel = (JPanel) value;
|
||||
|
||||
if (registrationTopic.isLoading(registrationTopic.getRegisteredNameList().get(index))) {
|
||||
itemPanel.setEnabled(false);
|
||||
itemPanel.setBackground(Color.LIGHT_GRAY);
|
||||
} else {
|
||||
itemPanel.setEnabled(true);
|
||||
itemPanel.setBackground(isSelected ? list.getSelectionBackground() : list.getBackground());
|
||||
}
|
||||
|
||||
return itemPanel;
|
||||
}
|
||||
});
|
||||
|
||||
// 监听键盘事件
|
||||
themeList.addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_F) {
|
||||
searchPanel.setVisible(true);
|
||||
searchField.requestFocusInWindow();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
searchButton.addActionListener(e -> {
|
||||
String searchText = searchField.getText().trim().toLowerCase();
|
||||
if (searchText.isEmpty()) {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
language.getText("settings.4.search_empty"),
|
||||
language.getText("settings.4.search_empty_title"), JOptionPane.INFORMATION_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < registrationTopic.getTopicsClasses().size(); i++) {
|
||||
String topicName = registrationTopic.getTopicsName().get(i).toLowerCase();
|
||||
if (topicName.contains(searchText)) {
|
||||
themeList.setSelectedIndex(i);
|
||||
themeList.ensureIndexIsVisible(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JOptionPane.showMessageDialog(null,
|
||||
language.getText("settings.4.search_not_found"),
|
||||
language.getText("settings.4.search_not_found_title"), JOptionPane.INFORMATION_MESSAGE);
|
||||
});
|
||||
|
||||
themeList.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.getClickCount() == 2) {
|
||||
int index = themeList.locationToIndex(e.getPoint());
|
||||
if (index >= 0) {
|
||||
if (registrationTopic.isLoading(registrationTopic.getRegisteredNameList().get(index))) {
|
||||
JOptionPane.showMessageDialog(null, language.getText("settings.4.loading"),
|
||||
language.getText("settings.4.loading_title"), JOptionPane.INFORMATION_MESSAGE);
|
||||
return;
|
||||
}
|
||||
loadTheme(registrationTopic, index, themeList);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JPopupMenu popupMenu = new JPopupMenu();
|
||||
JMenuItem loadMenuItem = new JMenuItem(language.getText("settings.4.load"));
|
||||
loadMenuItem.addActionListener(e -> {
|
||||
int index = themeList.getSelectedIndex();
|
||||
if (index >= 0) {
|
||||
if (registrationTopic.isLoading(registrationTopic.getRegisteredNameList().get(index))) {
|
||||
JOptionPane.showMessageDialog(null, language.getText("settings.4.loading"),
|
||||
language.getText("settings.4.loading_title"), JOptionPane.INFORMATION_MESSAGE);
|
||||
return;
|
||||
}
|
||||
loadTheme(registrationTopic, index, themeList);
|
||||
}
|
||||
});
|
||||
popupMenu.add(loadMenuItem);
|
||||
|
||||
themeList.setComponentPopupMenu(popupMenu);
|
||||
|
||||
for (int i = 0; i < registrationTopic.getTopicsClasses().size(); i++) {
|
||||
JPanel itemPanel = new JPanel(new BorderLayout());
|
||||
itemPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
||||
|
||||
JLabel iconLabel = new JLabel(registrationTopic.getIconList().get(i));
|
||||
itemPanel.add(iconLabel, BorderLayout.WEST);
|
||||
|
||||
JPanel infoPanel = new JPanel(new GridLayout(0, 1));
|
||||
String tip = registrationTopic.getTipList().get(i);
|
||||
if (tip == null) {
|
||||
tip = registrationTopic.getTopicsClassesLookAndFeel().get(i).getName();
|
||||
}
|
||||
infoPanel.add(new JLabel(language.getText("settings.4.info") + tip));
|
||||
infoPanel.add(new JLabel(language.getText("settings.4.info.1") + registrationTopic.getTopicsName().get(i)));
|
||||
infoPanel.add(new JLabel(language.getText("settings.4.info.2") + registrationTopic.getTipList().get(i)));
|
||||
infoPanel.add(new JLabel(language.getText("settings.4.info.3") + registrationTopic.getRegisteredNameList().get(i)));
|
||||
itemPanel.add(infoPanel, BorderLayout.CENTER);
|
||||
|
||||
listModel.addElement(itemPanel);
|
||||
}
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane(themeList);
|
||||
themePanel.add(scrollPane, BorderLayout.CENTER);
|
||||
|
||||
return themePanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载主题
|
||||
*/
|
||||
private static void loadTheme(RegistrationTopic registrationTopic, int index, JList<JPanel> themeList) {
|
||||
String themeClass = registrationTopic.getTopicsClasses().get(index);
|
||||
String themeName = registrationTopic.getTopicsName().get(index);
|
||||
String registeredName = registrationTopic.getRegisteredNameList().get(index);
|
||||
try {
|
||||
if (themeClass != null) {
|
||||
UIManager.setLookAndFeel(themeClass);
|
||||
} else {
|
||||
LookAndFeel theme = registrationTopic.getTopicsClassesLookAndFeel().get(index);
|
||||
UIManager.setLookAndFeel(theme);
|
||||
}
|
||||
JOptionPane.showMessageDialog(null, language.getText("settings.4.load_theme_success")
|
||||
+ themeName + language.getText("settings.4.load_theme_success.2"),
|
||||
language.getText("settings.4.load_theme_success.3"), JOptionPane.INFORMATION_MESSAGE);
|
||||
registrationTopic.setLoading(registeredName);
|
||||
themeList.repaint();
|
||||
} catch (Exception e) {
|
||||
JOptionPane.showMessageDialog(null, language.getText("settings.4.load_theme_error")
|
||||
+ e.getMessage(),
|
||||
language.getText("settings.4.load_theme_error.title"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private static RegistrationTopic getRegistrationTopic() {
|
||||
return registrationTopic;
|
||||
}
|
||||
|
||||
private static JPanel createAboutPanel() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
JTextArea infoArea = new JTextArea();
|
||||
infoArea.setEditable(false);
|
||||
infoArea.setLineWrap(true);
|
||||
infoArea.setWrapStyleWord(true);
|
||||
infoArea.append(language.getText("settings.3.infoArea.1") + AxisInnovatorsBox.getVersion() + "\n\n");
|
||||
infoArea.append(language.getText("settings.3.infoArea.2") + "\n");
|
||||
for (String author : AxisInnovatorsBox.getAuthor()) {
|
||||
infoArea.append("• " + author + "\n");
|
||||
}
|
||||
|
||||
panel.add(new JScrollPane(infoArea), BorderLayout.CENTER);
|
||||
return panel;
|
||||
}
|
||||
|
||||
private static class FontChooser extends JPanel {
|
||||
private final JComboBox<String> fontFamilyCombo;
|
||||
private final JSpinner fontSizeSpinner;
|
||||
|
||||
public FontChooser(Font currentFont) {
|
||||
setLayout(new GridLayout(2, 2, 5, 5));
|
||||
|
||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
String[] fontFamilies = ge.getAvailableFontFamilyNames();
|
||||
fontFamilyCombo = new JComboBox<>(fontFamilies);
|
||||
fontFamilyCombo.setSelectedItem(currentFont.getFamily());
|
||||
|
||||
SpinnerNumberModel sizeModel = new SpinnerNumberModel(
|
||||
currentFont.getSize(), 8, 48, 1
|
||||
);
|
||||
fontSizeSpinner = new JSpinner(sizeModel);
|
||||
|
||||
add(new JLabel("字体:"));
|
||||
add(fontFamilyCombo);
|
||||
add(new JLabel("大小:"));
|
||||
add(fontSizeSpinner);
|
||||
}
|
||||
|
||||
public Font getSelectedFont() {
|
||||
return new Font(
|
||||
(String) fontFamilyCombo.getSelectedItem(),
|
||||
Font.PLAIN,
|
||||
(Integer) fontSizeSpinner.getValue()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyThemeColor(Color color) {
|
||||
UIManager.put("Panel.background", color);
|
||||
UIManager.put("TabbedPane.background", color);
|
||||
|
||||
SwingUtilities.updateComponentTreeUI(AxisInnovatorsBox.getMain().getMainWindow());
|
||||
}
|
||||
|
||||
private static JPanel createPluginSettingsPanel() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
|
||||
String[] columns = {
|
||||
language.getText("settings.1.columns.1"),
|
||||
language.getText("settings.1.columns.2"),
|
||||
language.getText("settings.1.columns.3")
|
||||
};
|
||||
DefaultTableModel model = new DefaultTableModel(columns, 0) {
|
||||
@Override
|
||||
public boolean isCellEditable(int row, int column) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
List<PluginDescriptor> plugins = PluginLoader.getLoadedPlugins();
|
||||
for (PluginDescriptor plugin : plugins) {
|
||||
model.addRow(new Object[]{
|
||||
plugin.getName(),
|
||||
String.join(", ", plugin.getSupportedVersions()),
|
||||
plugin.getDescription()
|
||||
});
|
||||
}
|
||||
|
||||
JTable table = new JTable(model);
|
||||
table.setRowHeight(30);
|
||||
table.getTableHeader().setFont(new Font("微软雅黑", Font.BOLD, 14));
|
||||
|
||||
table.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.getClickCount() == 2) {
|
||||
int selectedRow = table.getSelectedRow();
|
||||
if (selectedRow >= 0) {
|
||||
PluginDescriptor selectedPlugin = plugins.get(selectedRow);
|
||||
showPluginDetails(selectedPlugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane(table);
|
||||
scrollPane.setBorder(BorderFactory.createTitledBorder(language.getText("settings.1.scrollPane")));
|
||||
panel.add(scrollPane, BorderLayout.CENTER);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private static void showPluginDetails(PluginDescriptor plugin) {
|
||||
JDialog dialog = new JDialog(AxisInnovatorsBox.getMain().getMainWindow(), "插件详细信息", true);
|
||||
dialog.setLayout(new BorderLayout());
|
||||
dialog.setSize(500, 400);
|
||||
dialog.setLocationRelativeTo(AxisInnovatorsBox.getMain().getMainWindow());
|
||||
|
||||
JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
|
||||
mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
|
||||
JPanel iconPanel = new JPanel();
|
||||
|
||||
ImageIcon icon = LoadIcon.loadIcon(plugin.getInstance().getClass(), plugin.getIcon(), 64);
|
||||
JLabel iconLabel = new JLabel(icon);
|
||||
iconPanel.add(iconLabel);
|
||||
mainPanel.add(iconPanel, BorderLayout.WEST);
|
||||
|
||||
JPanel infoPanel = new JPanel(new GridLayout(0, 1, 5, 5));
|
||||
infoPanel.setBorder(BorderFactory.createTitledBorder("插件信息"));
|
||||
|
||||
infoPanel.add(new JLabel("插件名称: " + plugin.getName()));
|
||||
|
||||
String classFilePath = plugin.getClass().getResource(plugin.getClass().getSimpleName() + ".class").toString();
|
||||
if (classFilePath.startsWith("jar:")) {
|
||||
classFilePath = classFilePath.substring("jar:".length(), classFilePath.indexOf("!"));
|
||||
} else if (classFilePath.startsWith("file:")) {
|
||||
classFilePath = classFilePath.substring("file:".length(), classFilePath.indexOf(plugin.getClass().getSimpleName() + ".class"));
|
||||
}
|
||||
|
||||
JTextArea locationTextArea = new JTextArea("插件位置: " + classFilePath);
|
||||
locationTextArea.setLineWrap(true);
|
||||
locationTextArea.setWrapStyleWord(true);
|
||||
locationTextArea.setEditable(false);
|
||||
locationTextArea.setBackground(infoPanel.getBackground());
|
||||
infoPanel.add(new JScrollPane(locationTextArea));
|
||||
|
||||
infoPanel.add(new JLabel("主类: " + plugin.getInstance().getClass()));
|
||||
if (plugin.getTransformers() != null) {
|
||||
infoPanel.add(new JLabel("核心转换器: " + plugin.getTransformers()));
|
||||
} else {
|
||||
infoPanel.add(new JLabel("核心转换器: 无"));
|
||||
}
|
||||
infoPanel.add(new JLabel("描述: " + plugin.getDescription()));
|
||||
|
||||
mainPanel.add(infoPanel, BorderLayout.CENTER);
|
||||
|
||||
JButton closeButton = new JButton("关闭");
|
||||
closeButton.addActionListener(e -> dialog.dispose());
|
||||
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
|
||||
buttonPanel.add(closeButton);
|
||||
mainPanel.add(buttonPanel, BorderLayout.SOUTH);
|
||||
|
||||
dialog.add(mainPanel);
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
|
||||
private static JPanel createGeneralSettingsPanel() {
|
||||
JPanel panel = new JPanel(new GridBagLayout());
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
gbc.insets = new Insets(5, 5, 5, 5);
|
||||
gbc.anchor = GridBagConstraints.WEST;
|
||||
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy = 0;
|
||||
panel.add(new JLabel(language.getText("settings.2.color")), gbc);
|
||||
|
||||
JButton colorBtn = new JButton(language.getText("settings.2.colorBtn"));
|
||||
colorBtn.addActionListener(e -> {
|
||||
Color color = JColorChooser.showDialog(panel,
|
||||
language.getText("settings.2.colorBtn.color"), Color.WHITE);
|
||||
if (color != null) {
|
||||
applyThemeColor(color);
|
||||
}
|
||||
});
|
||||
gbc.gridx = 1;
|
||||
panel.add(colorBtn, gbc);
|
||||
|
||||
// 界面字体设置
|
||||
gbc.gridy++;
|
||||
gbc.gridx = 0;
|
||||
panel.add(new JLabel(language.getText("settings.2.font")), gbc);
|
||||
|
||||
JButton fontBtn = new JButton(language.getText("settings.2.fontBtn"));
|
||||
fontBtn.addActionListener(e -> {
|
||||
Font currentFont = UIManager.getFont("Label.font");
|
||||
FontChooser fontChooser = new FontChooser(currentFont);
|
||||
int result = JOptionPane.showConfirmDialog(
|
||||
panel,
|
||||
fontChooser,
|
||||
language.getText("settings.2.showConfirmDialog"),
|
||||
JOptionPane.OK_CANCEL_OPTION
|
||||
);
|
||||
|
||||
if (result == JOptionPane.OK_OPTION) {
|
||||
applyUIFont(fontChooser.getSelectedFont());
|
||||
}
|
||||
});
|
||||
gbc.gridx = 1;
|
||||
panel.add(fontBtn, gbc);
|
||||
|
||||
// CUDA 设置
|
||||
gbc.gridy++;
|
||||
gbc.gridx = 0;
|
||||
panel.add(new JLabel(language.getText("settings.2.cuda")), gbc);
|
||||
|
||||
JCheckBox cudaCheckBox = new JCheckBox(language.getText("settings.2.cudaCheckBox"), LM.CUDA);
|
||||
cudaCheckBox.addActionListener(e -> {
|
||||
boolean useCUDA = cudaCheckBox.isSelected();
|
||||
LM.CUDA = useCUDA;
|
||||
logger.info("CUDA加速设置已更新: " + (useCUDA ? "启用" : "禁用"));
|
||||
|
||||
try {
|
||||
LM.loadLibrary(useCUDA);
|
||||
logger.info("AI推理库已重新加载");
|
||||
} catch (Exception ex) {
|
||||
logger.error("无法重新加载AI推理库", ex);
|
||||
JOptionPane.showMessageDialog(panel, language.getText("settings.2.cuda.error"),
|
||||
language.getText("settings.2.cuda.error.1"), JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
gbc.gridx = 1;
|
||||
panel.add(cudaCheckBox, gbc);
|
||||
|
||||
// 语言设置
|
||||
gbc.gridy++;
|
||||
gbc.gridx = 0;
|
||||
panel.add(new JLabel(language.getText("settings.2.language")), gbc);
|
||||
|
||||
List<LanguageManager.Language> languages = LanguageManager.getLanguages();
|
||||
String[] languageNames = languages.stream()
|
||||
.map(LanguageManager.Language::getLanguageName)
|
||||
.toArray(String[]::new);
|
||||
|
||||
JComboBox<String> languageComboBox = new JComboBox<>(languageNames);
|
||||
if (LanguageManager.getLoadedLanguages() != null) {
|
||||
languageComboBox.setSelectedItem(LanguageManager.getLoadedLanguages().getLanguageName());
|
||||
} else {
|
||||
languageComboBox.setSelectedItem(language.getText("settings.2.language.error"));
|
||||
}
|
||||
languageComboBox.addActionListener(e -> {
|
||||
String selectedLanguageName = (String) languageComboBox.getSelectedItem();
|
||||
LanguageManager.Language selectedLanguage = LanguageManager.getLanguage(selectedLanguageName);
|
||||
if (selectedLanguage != null) {
|
||||
LanguageManager.loadLanguage(selectedLanguage.getRegisteredName());
|
||||
logger.info("语言已切换为: " + selectedLanguage.getLanguageName());
|
||||
AxisInnovatorsBox.getMain().reloadAllWindow();
|
||||
|
||||
} else {
|
||||
logger.error("无法切换语言: " + selectedLanguageName);
|
||||
}
|
||||
});
|
||||
gbc.gridx = 1;
|
||||
panel.add(languageComboBox, gbc);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private static void applyUIFont(Font font) {
|
||||
Enumeration<Object> keys = UIManager.getLookAndFeelDefaults().keys();
|
||||
while (keys.hasMoreElements()) {
|
||||
Object key = keys.nextElement();
|
||||
Object value = UIManager.get(key);
|
||||
if (value instanceof Font) {
|
||||
Font derived = font.deriveFont(((Font)value).getStyle());
|
||||
UIManager.put(key, derived);
|
||||
}
|
||||
}
|
||||
|
||||
for (Window window : Window.getWindows()) {
|
||||
SwingUtilities.updateComponentTreeUI(window);
|
||||
}
|
||||
}
|
||||
|
||||
RegistrationSettingsItem() {
|
||||
this.mainWindow = null;
|
||||
registrationTopic = AxisInnovatorsBox.getMain().getRegistrationTopic();
|
||||
}
|
||||
|
||||
public RegistrationSettingsItem(AxisInnovatorsBox main) {
|
||||
this.mainWindow = main;
|
||||
registrationTopic = main.getRegistrationTopic();
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册设置项
|
||||
* @param tabbedPanesSettings 设置页面
|
||||
* @param title 标题
|
||||
* @param icon 显示图标(可为null)
|
||||
* @param tip 描述
|
||||
* @param registeredName 注册名(必须是唯一的)
|
||||
*/
|
||||
public void addSettings(JPanel tabbedPanesSettings,
|
||||
String title,
|
||||
Icon icon,
|
||||
String tip,
|
||||
String registeredName) {
|
||||
if (mainWindow != null) {
|
||||
if (!mainWindow.isWindow()) {
|
||||
registrationItem(tabbedPanesSettings, title, icon, tip, registeredName);
|
||||
} else {
|
||||
logger.warn("Wrong time to add tools");
|
||||
}
|
||||
} else {
|
||||
registrationItem(tabbedPanesSettings, title, icon, tip, registeredName);
|
||||
}
|
||||
}
|
||||
|
||||
private void registrationItem(JPanel tabbedPanesSettings, String title, Icon icon, String tip, String registeredName) {
|
||||
if (registeredNameList.contains(registeredName)) {
|
||||
throw new RegistrationError(registeredName + " duplicate registered names");
|
||||
}
|
||||
this.isEmpty = false;
|
||||
this.uuidList.add(UUID.randomUUID());
|
||||
this.tabbedPanesSettings.add(tabbedPanesSettings);
|
||||
this.titleList.add(title);
|
||||
this.iconList.add(icon);
|
||||
this.tipList.add(tip);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设置项
|
||||
* @param id id
|
||||
* @return JPanel对象
|
||||
*/
|
||||
public JPanel getSettings(UUID id) {
|
||||
for (int i = 0; i < uuidList.size(); i++) {
|
||||
if (uuidList.get(i).equals(id)) {
|
||||
return tabbedPanesSettings.get(i);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过注册名获取UUID
|
||||
* @param registeredName 注册名
|
||||
* @return UUID
|
||||
*/
|
||||
public UUID getUUID(String registeredName) {
|
||||
for (int i = 0; i < registeredNameList.size(); i++) {
|
||||
if (registeredNameList.get(i).equals(registeredName)) {
|
||||
return uuidList.get(i);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册设置项
|
||||
* @param registrationSettingsItem 注册设置项
|
||||
*/
|
||||
public void addRegistrationSettingsItem(RegistrationSettingsItem registrationSettingsItem) {
|
||||
if (registrationSettingsItem.isEmpty()) {
|
||||
logger.warn("Empty registration settings item");
|
||||
return;
|
||||
}
|
||||
registrationSettingsItemList.add(registrationSettingsItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册设置项
|
||||
* @param tabbedPane JTabbedPane
|
||||
*/
|
||||
public void registration(JTabbedPane tabbedPane) {
|
||||
for (int i = 0; i < tabbedPanesSettings.size(); i++) {
|
||||
tabbedPane.addTab(titleList.get(i), iconList.get(i), tabbedPanesSettings.get(i), tipList.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有注册设置项
|
||||
* @return List<RegistrationSettingsItem>
|
||||
*/
|
||||
public static List<RegistrationSettingsItem> getRegistrationSettingsItemList() {
|
||||
return registrationSettingsItemList;
|
||||
}
|
||||
|
||||
public List<UUID> getUUIDList() {
|
||||
return uuidList;
|
||||
}
|
||||
|
||||
public List<String> getRegisteredNameList() {
|
||||
return registeredNameList;
|
||||
}
|
||||
|
||||
public List<JPanel> getTabbedPanesSettings() {
|
||||
return tabbedPanesSettings;
|
||||
}
|
||||
|
||||
public List<String> getTitleList() {
|
||||
return titleList;
|
||||
}
|
||||
|
||||
public List<Icon> getIconList() {
|
||||
return iconList;
|
||||
}
|
||||
|
||||
public List<String> getTipList() {
|
||||
return tipList;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return isEmpty;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.axis.innovators.box.register;
|
||||
|
||||
import com.axis.innovators.box.Main;
|
||||
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;
|
||||
@@ -21,12 +21,12 @@ import java.util.UUID;
|
||||
public class RegistrationTool {
|
||||
private static final Logger logger = LogManager.getLogger(RegistrationTool.class);
|
||||
private final List<MainWindow.ToolCategory> toolCategories = new ArrayList<>();
|
||||
private final Main main;
|
||||
private final AxisInnovatorsBox main;
|
||||
private final List<UUID> uuidList = new ArrayList<>();
|
||||
private final List<String> registeredNameList = new ArrayList<>();
|
||||
|
||||
public RegistrationTool(Main mainWindow) {
|
||||
this.main = mainWindow;
|
||||
public RegistrationTool(AxisInnovatorsBox main) {
|
||||
this.main = main;
|
||||
int id = 0;
|
||||
MainWindow.ToolCategory debugCategory = new MainWindow.ToolCategory("调试工具",
|
||||
"debug/debug.png",
|
||||
@@ -39,7 +39,7 @@ public class RegistrationTool {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Window owner = SwingUtilities.windowForComponent((Component) e.getSource());
|
||||
FridaWindow fridaWindow = new FridaWindow(owner);
|
||||
fridaWindow.setVisible(true);
|
||||
main.popupWindow(fridaWindow);
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -54,7 +54,7 @@ public class RegistrationTool {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Window owner = SwingUtilities.windowForComponent((Component) e.getSource());
|
||||
LocalWindow dialog = new LocalWindow(owner);
|
||||
dialog.setVisible(true);
|
||||
main.popupWindow(dialog);
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -70,7 +70,7 @@ public class RegistrationTool {
|
||||
String registeredName) {
|
||||
if (!main.isWindow()) {
|
||||
if (registeredNameList.contains(registeredName)) {
|
||||
throw new ToolsRegistrationError(registeredName + " duplicate registered names");
|
||||
throw new RegistrationError(registeredName + " duplicate registered names");
|
||||
}
|
||||
uuidList.add(toolCategory.getId());
|
||||
registeredNameList.add(registeredName);
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
package com.axis.innovators.box.register;
|
||||
|
||||
import com.axis.innovators.box.AxisInnovatorsBox;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 注册主题
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class RegistrationTopic {
|
||||
private final Logger logger = LogManager.getLogger(RegistrationTopic.class);
|
||||
private final List<String> topicsClasses = new ArrayList<>();
|
||||
private final List<LookAndFeel> topicsClassesLookAndFeel = new ArrayList<>();
|
||||
private final List<String> topicsName = new ArrayList<>();
|
||||
private final List<String> registeredNameList = new ArrayList<>();
|
||||
private final List<Icon> iconList = new ArrayList<>();
|
||||
private final List<String> tipList = new ArrayList<>();
|
||||
private final AxisInnovatorsBox axisInnovatorsBox;
|
||||
private String loadTopics = "";
|
||||
|
||||
public RegistrationTopic(AxisInnovatorsBox axisInnovatorsBox) {
|
||||
this.axisInnovatorsBox = axisInnovatorsBox;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册主题
|
||||
* @param topicClass 主题类
|
||||
* @param topicName 主题名
|
||||
* @param icon 显示图标
|
||||
* @param registeredName 注册名
|
||||
*/
|
||||
public void addTopic(String topicClass, String topicName, String tip ,Icon icon, String registeredName) {
|
||||
if (!axisInnovatorsBox.isWindow()) {
|
||||
if (registeredNameList.contains(registeredName)) {
|
||||
throw new RegistrationError(registeredName + " duplicate registered names");
|
||||
}
|
||||
topicsClasses.add(topicClass);
|
||||
topicsClassesLookAndFeel.add(null);
|
||||
topicsName.add(topicName);
|
||||
tipList.add(tip);
|
||||
iconList.add(icon);
|
||||
registeredNameList.add(registeredName);
|
||||
} else {
|
||||
logger.warn("Wrong time to add topics");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册主题
|
||||
* @param topicClass 主题类
|
||||
* @param topicName 主题名
|
||||
* @param icon 显示图标
|
||||
* @param registeredName 注册名
|
||||
*/
|
||||
public void addTopic(LookAndFeel topicClass, String topicName, String tip ,Icon icon, String registeredName) {
|
||||
if (!axisInnovatorsBox.isWindow()) {
|
||||
if (registeredNameList.contains(registeredName)) {
|
||||
throw new RegistrationError(registeredName + " duplicate registered names");
|
||||
}
|
||||
topicsClasses.add(null);
|
||||
topicsClassesLookAndFeel.add(topicClass);
|
||||
topicsName.add(topicName);
|
||||
tipList.add(tip);
|
||||
iconList.add(icon);
|
||||
registeredNameList.add(registeredName);
|
||||
} else {
|
||||
logger.warn("Wrong time to add topics");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否已经加载
|
||||
* @return 是否已经加载
|
||||
*/
|
||||
public boolean isLoading(String loading) {
|
||||
if (loadTopics.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(loading, loadTopics);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否加载
|
||||
* @param loading 是否加载
|
||||
*/
|
||||
public void setLoading(String loading) {
|
||||
loadTopics = loading;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为空
|
||||
* @return 是否为空
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return registeredNameList.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取主题类
|
||||
* @return 主题类
|
||||
*/
|
||||
public List<String> getTopicsClasses() {
|
||||
return topicsClasses;
|
||||
}
|
||||
|
||||
public AxisInnovatorsBox getAxisInnovatorsBox() {
|
||||
return axisInnovatorsBox;
|
||||
}
|
||||
|
||||
public List<LookAndFeel> getTopicsClassesLookAndFeel() {
|
||||
return topicsClassesLookAndFeel;
|
||||
}
|
||||
|
||||
public List<Icon> getIconList() {
|
||||
return iconList;
|
||||
}
|
||||
|
||||
public List<String> getRegisteredNameList() {
|
||||
return registeredNameList;
|
||||
}
|
||||
|
||||
public List<String> getTipList() {
|
||||
return tipList;
|
||||
}
|
||||
|
||||
public List<String> getTopicsName() {
|
||||
return topicsName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.axis.innovators.box.tools;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class FolderCleaner {
|
||||
|
||||
/**
|
||||
* 清理文件夹中的文件
|
||||
*
|
||||
* @param folderPath 文件夹路径
|
||||
* @param maxFiles 最大文件数量
|
||||
*/
|
||||
public static void cleanFolder(String folderPath, int maxFiles) {
|
||||
File folder = new File(folderPath);
|
||||
|
||||
// 检查文件夹是否存在
|
||||
if (!folder.exists() || !folder.isDirectory()) {
|
||||
System.out.println("文件夹不存在或不是一个有效的文件夹: " + folderPath);
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取文件夹中的文件列表
|
||||
File[] files = folder.listFiles();
|
||||
if (files == null) {
|
||||
System.out.println("无法读取文件夹内容: " + folderPath);
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果文件数量未超过最大值,直接返回
|
||||
if (files.length <= maxFiles) {
|
||||
System.out.println("文件数量未超过最大值,无需清理。");
|
||||
return;
|
||||
}
|
||||
|
||||
// 按文件最后修改时间排序(从旧到新)
|
||||
Arrays.sort(files, Comparator.comparingLong(File::lastModified));
|
||||
|
||||
// 删除最旧的文件,直到文件数量不超过最大值
|
||||
for (int i = 0; i < files.length - maxFiles; i++) {
|
||||
File fileToDelete = files[i];
|
||||
|
||||
// 检查文件是否未被占用
|
||||
if (isFileUnlocked(fileToDelete)) {
|
||||
if (fileToDelete.delete()) {
|
||||
System.out.println("已删除文件: " + fileToDelete.getName());
|
||||
} else {
|
||||
System.out.println("无法删除文件: " + fileToDelete.getName());
|
||||
}
|
||||
} else {
|
||||
System.out.println("文件被占用,跳过删除: " + fileToDelete.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文件是否未被占用
|
||||
*
|
||||
* @param file 文件
|
||||
* @return 如果文件未被占用返回 true,否则返回 false
|
||||
*/
|
||||
private static boolean isFileUnlocked(File file) {
|
||||
File tempFile = new File(file.getParentFile(), file.getName() + ".tmp");
|
||||
if (file.renameTo(tempFile)) {
|
||||
tempFile.renameTo(file);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String folderPath = "C:/path/to/your/folder";
|
||||
int maxFiles = 10;
|
||||
|
||||
cleanFolder(folderPath, maxFiles);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,25 @@ public class FolderCreator {
|
||||
public static final String LIBRARY_NAME = "library";
|
||||
public static final String MODEL_PATH = "model";
|
||||
public static final String PLUGIN_PATH = "plug-in";
|
||||
|
||||
public static final String LOGS_PATH = "logs";
|
||||
public static final String LANGUAGE_PATH = "language";
|
||||
public static final String CONFIGURATION_PATH = "state";
|
||||
public static String getConfigurationFolder() {
|
||||
String folder = createFolder(CONFIGURATION_PATH);
|
||||
if (folder == null) {
|
||||
logger.error("Plugin folder creation failed, please use administrator privileges to execute this procedure");
|
||||
return null;
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
public static String getLanguageFolder() {
|
||||
String folder = createFolder(LANGUAGE_PATH);
|
||||
if (folder == null) {
|
||||
logger.error("Plugin folder creation failed, please use administrator privileges to execute this procedure");
|
||||
return null;
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
public static String getPluginFolder() {
|
||||
String folder = createFolder(PLUGIN_PATH);
|
||||
if (folder == null) {
|
||||
@@ -36,6 +54,18 @@ public class FolderCreator {
|
||||
return folder;
|
||||
}
|
||||
|
||||
public static String getLogsFolder() {
|
||||
String folder = createFolder(LOGS_PATH);
|
||||
if (folder == null) {
|
||||
if (logger == null) {
|
||||
logger = LogManager.getLogger();
|
||||
}
|
||||
logger.error("Library folder creation failed, please use administrator privileges to execute this procedure");
|
||||
return null;
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
|
||||
public static String getLibraryFolder() {
|
||||
String folder = createFolder(LIBRARY_NAME);
|
||||
if (folder == null) {
|
||||
|
||||
163
src/main/java/com/axis/innovators/box/tools/StateManager.java
Normal file
163
src/main/java/com/axis/innovators/box/tools/StateManager.java
Normal file
@@ -0,0 +1,163 @@
|
||||
package com.axis.innovators.box.tools;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* 对状态进行管理
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class StateManager {
|
||||
private final String statusFile;
|
||||
private final Map<String, String> configMap;
|
||||
private final Properties properties;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param statusName 状态文件名
|
||||
*/
|
||||
public StateManager(String statusName) {
|
||||
statusFile = FolderCreator.getConfigurationFolder() + statusName + ".properties";
|
||||
configMap = new HashMap<>();
|
||||
properties = new Properties();
|
||||
loadConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认构造函数
|
||||
*/
|
||||
public StateManager() {
|
||||
statusFile = FolderCreator.getConfigurationFolder() + "state_management.properties";
|
||||
configMap = new HashMap<>();
|
||||
properties = new Properties();
|
||||
loadConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载配置文件内容到Map中
|
||||
* 如果文件不存在,则创建该文件
|
||||
*/
|
||||
private void loadConfiguration() {
|
||||
File configFile = new File(statusFile);
|
||||
|
||||
if (!configFile.exists()) {
|
||||
try {
|
||||
configFile.getParentFile().mkdirs();
|
||||
configFile.createNewFile();
|
||||
System.out.println("The configuration file does not exist, a new one has been created: " + statusFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try (FileInputStream fis = new FileInputStream(configFile)) {
|
||||
properties.load(fis);
|
||||
for (String key : properties.stringPropertyNames()) {
|
||||
configMap.put(key, properties.getProperty(key));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存状态到Map和配置文件中
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
*/
|
||||
public void saveState(String key, String value) {
|
||||
configMap.put(key, value);
|
||||
properties.setProperty(key, value);
|
||||
saveToFile();
|
||||
}
|
||||
|
||||
public void saveState(String key, int value) {
|
||||
saveState(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public void saveState(String key, long value) {
|
||||
saveState(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public void saveState(String key, float value) {
|
||||
saveState(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public void saveState(String key, boolean value) {
|
||||
saveState(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public void saveState(String key, double value) {
|
||||
saveState(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public void saveState(String key, char value) {
|
||||
saveState(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public void saveState(String key, byte value) {
|
||||
saveState(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public void saveState(String key, short value) {
|
||||
saveState(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将当前状态保存到配置文件中
|
||||
*/
|
||||
private void saveToFile() {
|
||||
try (FileOutputStream fos = new FileOutputStream(statusFile)) {
|
||||
properties.store(fos, "Updated configuration");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Map中获取状态值
|
||||
* @param key 键
|
||||
* @return 值
|
||||
*/
|
||||
public String getState(String key) {
|
||||
return configMap.get(key);
|
||||
}
|
||||
|
||||
public int getStateAsInt(String key) {
|
||||
return Integer.parseInt(configMap.get(key));
|
||||
}
|
||||
|
||||
public long getStateAsLong(String key) {
|
||||
return Long.parseLong(configMap.get(key));
|
||||
}
|
||||
|
||||
public float getStateAsFloat(String key) {
|
||||
return Float.parseFloat(configMap.get(key));
|
||||
}
|
||||
|
||||
public boolean getStateAsBoolean(String key) {
|
||||
return Boolean.parseBoolean(configMap.get(key));
|
||||
}
|
||||
|
||||
public double getStateAsDouble(String key) {
|
||||
return Double.parseDouble(configMap.get(key));
|
||||
}
|
||||
|
||||
public char getStateAsChar(String key) {
|
||||
return configMap.get(key).charAt(0);
|
||||
}
|
||||
|
||||
public byte getStateAsByte(String key) {
|
||||
return Byte.parseByte(configMap.get(key));
|
||||
}
|
||||
|
||||
public short getStateAsShort(String key) {
|
||||
return Short.parseShort(configMap.get(key));
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package org.tzd.frida;
|
||||
|
||||
import org.tzd.frida.windows.CallbackMessage;
|
||||
import org.tzd.frida.windows.Frida;
|
||||
import org.tzd.frida.windows.FridaRunnable;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
/**
|
||||
* Main 类用于启动和执行 Frida 注入操作。
|
||||
*
|
||||
* <p>此类主要包含一个入口方法 <code>main</code>,用于加载必要的本地库并初始化 Frida 对象。</p>
|
||||
* <p>它会通过调用 <code>getProcessPid</code> 方法获取指定进程的 PID,并将 JavaScript 代码注入到目标进程中。</p>
|
||||
*
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
/**
|
||||
* 程序入口方法。
|
||||
*
|
||||
* <p>此方法加载本地 DLL 库并创建一个 <code>Frida</code> 实例。接着通过 <code>run</code> 和 <code>execute</code> 方法执行指定的任务。</p>
|
||||
* <p>执行期间,会将回调函数添加到 <code>Frida</code> 实例中,接收并打印消息。</p>
|
||||
*
|
||||
* @param args 命令行参数
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// 加载本地 DLL 文件
|
||||
System.load("C:\\Users\\Administrator\\source\\repos\\FridaNative\\x64\\Release\\FridaNative.dll");
|
||||
|
||||
// 创建 Frida 实例并传入 JavaScript 代码及进程 PID
|
||||
Frida frida = new Frida("console.log('Hello, Frida!');", getProcessPid("java.exe"));
|
||||
|
||||
// 执行 Frida 任务,注入代码并注册回调函数
|
||||
frida.run(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// 在此处添加要执行的代码
|
||||
}
|
||||
}).execute(new FridaRunnable() {
|
||||
@Override
|
||||
public void run(Frida frida) {
|
||||
// 注册回调消息,接收到消息时打印
|
||||
frida.addCallbackMessage(new CallbackMessage() {
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
System.out.println(message); // 打印收到的消息
|
||||
}
|
||||
});
|
||||
}
|
||||
}).start(); // 启动线程
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定进程的 PID。
|
||||
*
|
||||
* <p>此方法通过运行 Windows 命令 <code>tasklist</code> 获取系统中所有正在运行的进程,并查找指定进程名。</p>
|
||||
* <p>一旦找到匹配的进程,它将提取进程的 PID 并返回。</p>
|
||||
*
|
||||
* @param processName 要查找的进程名称。
|
||||
* @return 目标进程的 PID,如果未找到则返回 -1。
|
||||
*/
|
||||
public static long getProcessPid(String processName) {
|
||||
long pid = -1;
|
||||
try {
|
||||
ProcessBuilder builder = new ProcessBuilder("tasklist");
|
||||
builder.redirectErrorStream(true);
|
||||
Process process = builder.start();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
String line;
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (line.contains(processName)) {
|
||||
String[] parts = line.split("\\s+");
|
||||
pid = Long.parseLong(parts[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ public class LM {
|
||||
|
||||
public static long createContext(long modelHandle){
|
||||
return createContext(modelHandle,
|
||||
4096,
|
||||
100000,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
||||
0
statestate_management.properties
Normal file
0
statestate_management.properties
Normal file
Reference in New Issue
Block a user