diff --git a/build.gradle b/build.gradle index 03f2c4a..a02d609 100644 --- a/build.gradle +++ b/build.gradle @@ -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 目录 diff --git a/language/EnglishLanguage.properties b/language/EnglishLanguage.properties new file mode 100644 index 0000000..8abb1bc --- /dev/null +++ b/language/EnglishLanguage.properties @@ -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=

A serious error occurred in the program

+andShow.title.3=

Please report it to us!

+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 diff --git a/language/SimplifiedChineseLanguage.properties b/language/SimplifiedChineseLanguage.properties new file mode 100644 index 0000000..4ecd818 --- /dev/null +++ b/language/SimplifiedChineseLanguage.properties @@ -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=

\u7A0B\u5E8F\u53D1\u751F\u4E25\u91CD\u9519\u8BEF

+andShow.title.3=

\u8BF7\u5411\u6211\u4EEC\u53CD\u9988\uFF01

+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 \ No newline at end of file diff --git a/language/TraditionalChineseLanguage.properties b/language/TraditionalChineseLanguage.properties new file mode 100644 index 0000000..8b754fe --- /dev/null +++ b/language/TraditionalChineseLanguage.properties @@ -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=

\u7A0B\u5F0F\u767C\u751F\u56B4\u91CD\u932F\u8AA4

+andShow.title.3=

\u8ACB\u5411\u6211\u5011\u53CD\u994B\uFF01

+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 diff --git a/language/saved_language.properties b/language/saved_language.properties new file mode 100644 index 0000000..060dcf8 --- /dev/null +++ b/language/saved_language.properties @@ -0,0 +1,3 @@ +#Current Loaded Language +#Fri Feb 14 09:23:44 CST 2025 +loadedLanguage=Zh diff --git a/src/main/java/com/axis/innovators/box/AxisInnovatorsBox.java b/src/main/java/com/axis/innovators/box/AxisInnovatorsBox.java new file mode 100644 index 0000000..43247e2 --- /dev/null +++ b/src/main/java/com/axis/innovators/box/AxisInnovatorsBox.java @@ -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 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 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; + } +} \ No newline at end of file diff --git a/src/main/java/com/axis/innovators/box/Log4j2OutputStream.java b/src/main/java/com/axis/innovators/box/Log4j2OutputStream.java index e90a2e1..6f95af6 100644 --- a/src/main/java/com/axis/innovators/box/Log4j2OutputStream.java +++ b/src/main/java/com/axis/innovators/box/Log4j2OutputStream.java @@ -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); } diff --git a/src/main/java/com/axis/innovators/box/Main.java b/src/main/java/com/axis/innovators/box/Main.java index 9411c22..c8b2d8b 100644 --- a/src/main/java/com/axis/innovators/box/Main.java +++ b/src/main/java/com/axis/innovators/box/Main.java @@ -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 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 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 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; - } -} \ No newline at end of file +} diff --git a/src/main/java/com/axis/innovators/box/events/SettingsLoadEvents.java b/src/main/java/com/axis/innovators/box/events/SettingsLoadEvents.java index 8fb948b..40279c1 100644 --- a/src/main/java/com/axis/innovators/box/events/SettingsLoadEvents.java +++ b/src/main/java/com/axis/innovators/box/events/SettingsLoadEvents.java @@ -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) { } diff --git a/src/main/java/com/axis/innovators/box/events/StartupEvent.java b/src/main/java/com/axis/innovators/box/events/StartupEvent.java index 9b19b75..385e3b7 100644 --- a/src/main/java/com/axis/innovators/box/events/StartupEvent.java +++ b/src/main/java/com/axis/innovators/box/events/StartupEvent.java @@ -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) { } \ No newline at end of file diff --git a/src/main/java/com/axis/innovators/box/gui/FridaWindow.java b/src/main/java/com/axis/innovators/box/gui/FridaWindow.java index 0571193..e242988 100644 --- a/src/main/java/com/axis/innovators/box/gui/FridaWindow.java +++ b/src/main/java/com/axis/innovators/box/gui/FridaWindow.java @@ -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(); } diff --git a/src/main/java/com/axis/innovators/box/gui/LoadIcon.java b/src/main/java/com/axis/innovators/box/gui/LoadIcon.java index cba0da3..9c20243 100644 --- a/src/main/java/com/axis/innovators/box/gui/LoadIcon.java +++ b/src/main/java/com/axis/innovators/box/gui/LoadIcon.java @@ -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(); diff --git a/src/main/java/com/axis/innovators/box/gui/LocalWindow.java b/src/main/java/com/axis/innovators/box/gui/LocalWindow.java index 541f3b6..c211566 100644 --- a/src/main/java/com/axis/innovators/box/gui/LocalWindow.java +++ b/src/main/java/com/axis/innovators/box/gui/LocalWindow.java @@ -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() { - @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 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() { + @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() { + @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 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() { + @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 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()); }); } diff --git a/src/main/java/com/axis/innovators/box/gui/MainWindow.java b/src/main/java/com/axis/innovators/box/gui/MainWindow.java index cff3d3c..2175880 100644 --- a/src/main/java/com/axis/innovators/box/gui/MainWindow.java +++ b/src/main/java/com/axis/innovators/box/gui/MainWindow.java @@ -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 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); diff --git a/src/main/java/com/axis/innovators/box/gui/ProgressBarManager.java b/src/main/java/com/axis/innovators/box/gui/ProgressBarManager.java index 83e843d..6fa9c88 100644 --- a/src/main/java/com/axis/innovators/box/gui/ProgressBarManager.java +++ b/src/main/java/com/axis/innovators/box/gui/ProgressBarManager.java @@ -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; diff --git a/src/main/java/com/axis/innovators/box/gui/WindowsJDialog.java b/src/main/java/com/axis/innovators/box/gui/WindowsJDialog.java new file mode 100644 index 0000000..fce1005 --- /dev/null +++ b/src/main/java/com/axis/innovators/box/gui/WindowsJDialog.java @@ -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(); + } +} diff --git a/src/main/java/com/axis/innovators/box/plugins/BoxClassLoader.java b/src/main/java/com/axis/innovators/box/plugins/BoxClassLoader.java index d730ce0..02d4932 100644 --- a/src/main/java/com/axis/innovators/box/plugins/BoxClassLoader.java +++ b/src/main/java/com/axis/innovators/box/plugins/BoxClassLoader.java @@ -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 getClassTransforms() { + return CLASS_TRANSFORMS; + } + public static List> getClassList() { return CLASS_LOADING_LIST_OBJECT; } diff --git a/src/main/java/com/axis/innovators/box/plugins/LoadingCorePlugin.java b/src/main/java/com/axis/innovators/box/plugins/LoadingCorePlugin.java index bf12e64..ec4d51f 100644 --- a/src/main/java/com/axis/innovators/box/plugins/LoadingCorePlugin.java +++ b/src/main/java/com/axis/innovators/box/plugins/LoadingCorePlugin.java @@ -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 data); } \ No newline at end of file diff --git a/src/main/java/com/axis/innovators/box/plugins/PluginDescriptor.java b/src/main/java/com/axis/innovators/box/plugins/PluginDescriptor.java index a14947f..939795e 100644 --- a/src/main/java/com/axis/innovators/box/plugins/PluginDescriptor.java +++ b/src/main/java/com/axis/innovators/box/plugins/PluginDescriptor.java @@ -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;} } diff --git a/src/main/java/com/axis/innovators/box/plugins/PluginLoader.java b/src/main/java/com/axis/innovators/box/plugins/PluginLoader.java index 17d6935..5a391c1 100644 --- a/src/main/java/com/axis/innovators/box/plugins/PluginLoader.java +++ b/src/main/java/com/axis/innovators/box/plugins/PluginLoader.java @@ -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 loadedPlugins = new ArrayList<>(); private static final List transformers = new ArrayList<>(); + private static final List 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); } diff --git a/src/main/java/com/axis/innovators/box/register/LanguageManager.java b/src/main/java/com/axis/innovators/box/register/LanguageManager.java new file mode 100644 index 0000000..f9d03be --- /dev/null +++ b/src/main/java/com/axis/innovators/box/register/LanguageManager.java @@ -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 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 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); + } + } +} diff --git a/src/main/java/com/axis/innovators/box/register/ToolsRegistrationError.java b/src/main/java/com/axis/innovators/box/register/RegistrationError.java similarity index 59% rename from src/main/java/com/axis/innovators/box/register/ToolsRegistrationError.java rename to src/main/java/com/axis/innovators/box/register/RegistrationError.java index da117eb..17c2c96 100644 --- a/src/main/java/com/axis/innovators/box/register/ToolsRegistrationError.java +++ b/src/main/java/com/axis/innovators/box/register/RegistrationError.java @@ -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); } diff --git a/src/main/java/com/axis/innovators/box/register/RegistrationSettingsItem.java b/src/main/java/com/axis/innovators/box/register/RegistrationSettingsItem.java new file mode 100644 index 0000000..e87e19f --- /dev/null +++ b/src/main/java/com/axis/innovators/box/register/RegistrationSettingsItem.java @@ -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 registrationSettingsItemList = new ArrayList<>(); + private static final Logger logger = LogManager.getLogger(RegistrationSettingsItem.class); + private static RegistrationTopic registrationTopic; + private final List uuidList = new ArrayList<>(); + private final List registeredNameList = new ArrayList<>(); + private final List tabbedPanesSettings = new ArrayList<>(); + private final List titleList = new ArrayList<>(); + private final List iconList = new ArrayList<>(); + private final List 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 listModel = new DefaultListModel<>(); + JList 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 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 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 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 languages = LanguageManager.getLanguages(); + String[] languageNames = languages.stream() + .map(LanguageManager.Language::getLanguageName) + .toArray(String[]::new); + + JComboBox 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 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 + */ + public static List getRegistrationSettingsItemList() { + return registrationSettingsItemList; + } + + public List getUUIDList() { + return uuidList; + } + + public List getRegisteredNameList() { + return registeredNameList; + } + + public List getTabbedPanesSettings() { + return tabbedPanesSettings; + } + + public List getTitleList() { + return titleList; + } + + public List getIconList() { + return iconList; + } + + public List getTipList() { + return tipList; + } + + public boolean isEmpty() { + return isEmpty; + } +} diff --git a/src/main/java/com/axis/innovators/box/register/RegistrationTool.java b/src/main/java/com/axis/innovators/box/register/RegistrationTool.java index 212a190..ca9732b 100644 --- a/src/main/java/com/axis/innovators/box/register/RegistrationTool.java +++ b/src/main/java/com/axis/innovators/box/register/RegistrationTool.java @@ -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 toolCategories = new ArrayList<>(); - private final Main main; + private final AxisInnovatorsBox main; private final List uuidList = new ArrayList<>(); private final List 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); diff --git a/src/main/java/com/axis/innovators/box/register/RegistrationTopic.java b/src/main/java/com/axis/innovators/box/register/RegistrationTopic.java new file mode 100644 index 0000000..e8b5fc1 --- /dev/null +++ b/src/main/java/com/axis/innovators/box/register/RegistrationTopic.java @@ -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 topicsClasses = new ArrayList<>(); + private final List topicsClassesLookAndFeel = new ArrayList<>(); + private final List topicsName = new ArrayList<>(); + private final List registeredNameList = new ArrayList<>(); + private final List iconList = new ArrayList<>(); + private final List 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 getTopicsClasses() { + return topicsClasses; + } + + public AxisInnovatorsBox getAxisInnovatorsBox() { + return axisInnovatorsBox; + } + + public List getTopicsClassesLookAndFeel() { + return topicsClassesLookAndFeel; + } + + public List getIconList() { + return iconList; + } + + public List getRegisteredNameList() { + return registeredNameList; + } + + public List getTipList() { + return tipList; + } + + public List getTopicsName() { + return topicsName; + } +} diff --git a/src/main/java/com/axis/innovators/box/tools/FolderCleaner.java b/src/main/java/com/axis/innovators/box/tools/FolderCleaner.java new file mode 100644 index 0000000..fc26d0f --- /dev/null +++ b/src/main/java/com/axis/innovators/box/tools/FolderCleaner.java @@ -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); + } +} diff --git a/src/main/java/com/axis/innovators/box/tools/FolderCreator.java b/src/main/java/com/axis/innovators/box/tools/FolderCreator.java index 4ab7b5d..1ea9c79 100644 --- a/src/main/java/com/axis/innovators/box/tools/FolderCreator.java +++ b/src/main/java/com/axis/innovators/box/tools/FolderCreator.java @@ -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) { diff --git a/src/main/java/com/axis/innovators/box/tools/StateManager.java b/src/main/java/com/axis/innovators/box/tools/StateManager.java new file mode 100644 index 0000000..6988042 --- /dev/null +++ b/src/main/java/com/axis/innovators/box/tools/StateManager.java @@ -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 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)); + } +} \ No newline at end of file diff --git a/src/main/java/org/tzd/frida/Main.java b/src/main/java/org/tzd/frida/Main.java deleted file mode 100644 index 1c53626..0000000 --- a/src/main/java/org/tzd/frida/Main.java +++ /dev/null @@ -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 注入操作。 - * - *

此类主要包含一个入口方法 main,用于加载必要的本地库并初始化 Frida 对象。

- *

它会通过调用 getProcessPid 方法获取指定进程的 PID,并将 JavaScript 代码注入到目标进程中。

- * - * @author tzdwindows 7 - */ -public class Main { - - /** - * 程序入口方法。 - * - *

此方法加载本地 DLL 库并创建一个 Frida 实例。接着通过 runexecute 方法执行指定的任务。

- *

执行期间,会将回调函数添加到 Frida 实例中,接收并打印消息。

- * - * @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。 - * - *

此方法通过运行 Windows 命令 tasklist 获取系统中所有正在运行的进程,并查找指定进程名。

- *

一旦找到匹配的进程,它将提取进程的 PID 并返回。

- * - * @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; - } -} diff --git a/src/main/java/org/tzd/lm/LM.java b/src/main/java/org/tzd/lm/LM.java index ef21063..d41cfb2 100644 --- a/src/main/java/org/tzd/lm/LM.java +++ b/src/main/java/org/tzd/lm/LM.java @@ -80,7 +80,7 @@ public class LM { public static long createContext(long modelHandle){ return createContext(modelHandle, - 4096, + 100000, 0, 0, 0, diff --git a/statestate_management.properties b/statestate_management.properties new file mode 100644 index 0000000..e69de29