From 701dfcfb4769bc823e736d73f2ea1f7466393ccf Mon Sep 17 00:00:00 2001 From: tzdwindows 7 <3076584115@qq.com> Date: Fri, 21 Feb 2025 20:55:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(box):=20=E6=B7=BB=E5=8A=A0=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E8=A1=8C=E6=96=87=E4=BB=B6=E8=A7=A3=E6=9E=90=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=B9=B6=E4=BC=98=E5=8C=96=E4=B8=BB=E9=A2=98=E5=92=8C?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E7=AE=A1=E7=90=86-=20=E6=96=B0=E5=A2=9E=20Ar?= =?UTF-8?q?gsParser=20=E7=B1=BB=E7=94=A8=E4=BA=8E=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E8=A1=8C=E5=8F=82=E6=95=B0=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E8=B7=AF=E5=BE=84=20-=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=20OpenFileEvents=20=E4=BA=8B=E4=BB=B6=E7=B1=BB=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E5=A4=84=E7=90=86=E6=89=93=E5=BC=80=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=20-=20=E6=9B=B4=E6=96=B0=20AxisInnovatorsBox?= =?UTF-8?q?=20=E7=B1=BB=EF=BC=8C=E6=94=AF=E6=8C=81=E5=91=BD=E4=BB=A4?= =?UTF-8?q?=E8=A1=8C=E6=96=87=E4=BB=B6=E8=A7=A3=E6=9E=90=20-=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=20LanguageManager=20=E7=B1=BB=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E8=AF=AD=E8=A8=80=E5=90=88=E5=B9=B6=E5=92=8C=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E9=80=BB=E8=BE=91=20-=20=E6=9B=B4=E6=96=B0=20MainWind?= =?UTF-8?q?ow=20=E7=B1=BB=EF=BC=8C=E6=94=B9=E8=BF=9B=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E5=92=8C=E6=BB=9A=E5=8A=A8=E6=9D=A1UI=20-=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=20PluginDescriptor=20=E7=B1=BB=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B3=A8=E5=86=8C=E5=90=8D=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 8 +- language/EnglishLanguage.properties | 99 ------------ language/SimplifiedChineseLanguage.properties | 99 ------------ .../TraditionalChineseLanguage.properties | 99 ------------ language/saved_language.properties | 3 - .../innovators/box/AxisInnovatorsBox.java | 96 +++++++---- .../java/com/axis/innovators/box/Main.java | 7 +- .../innovators/box/events/OpenFileEvents.java | 53 +++++++ .../axis/innovators/box/gui/MainWindow.java | 150 ++++++++++-------- .../box/plugins/PluginDescriptor.java | 3 + .../innovators/box/plugins/PluginLoader.java | 116 +++++++++++++- .../box/plugins/PluginLoadingError.java | 17 ++ .../innovators/box/plugins/PluginMeta.java | 21 ++- .../box/register/LanguageManager.java | 121 ++++++++++++-- .../register/RegistrationSettingsItem.java | 46 +++++- .../box/register/RegistrationTool.java | 20 ++- .../axis/innovators/box/tools/ArgsParser.java | 83 ++++++++++ .../innovators/box/tools/StateManager.java | 4 +- src/main/java/org/tzd/lm/LM.java | 2 +- statestate_management.properties | 3 + 20 files changed, 614 insertions(+), 436 deletions(-) delete mode 100644 language/EnglishLanguage.properties delete mode 100644 language/SimplifiedChineseLanguage.properties delete mode 100644 language/TraditionalChineseLanguage.properties delete mode 100644 language/saved_language.properties create mode 100644 src/main/java/com/axis/innovators/box/events/OpenFileEvents.java create mode 100644 src/main/java/com/axis/innovators/box/plugins/PluginLoadingError.java create mode 100644 src/main/java/com/axis/innovators/box/tools/ArgsParser.java diff --git a/build.gradle b/build.gradle index a02d609..6c220a3 100644 --- a/build.gradle +++ b/build.gradle @@ -42,8 +42,12 @@ dependencies { implementation 'com.google.code.gson:gson:2.8.9' - implementation 'com.formdev:flatlaf:0.26' - implementation 'commons-io:commons-io:2.11.0' + //implementation 'com.formdev:flatlaf:0.26' + implementation 'commons-io:commons-io:2.14.0' + + implementation 'com.formdev:flatlaf:3.2.1' // FlatLaf核心 + implementation 'com.formdev:flatlaf-extras:3.2.1' // 扩展组件 + implementation 'com.formdev:flatlaf-intellij-themes:3.2.1' // 官方主题包 } // 分离依赖项到 libs 目录 diff --git a/language/EnglishLanguage.properties b/language/EnglishLanguage.properties deleted file mode 100644 index 8abb1bc..0000000 --- a/language/EnglishLanguage.properties +++ /dev/null @@ -1,99 +0,0 @@ -default_theme.system.topicName=Default Theme -default_theme.default.tip=Default theme -metal_theme.system.topicName=Metal Style -metal_theme.default.tip=Metal style -motif_theme.system.topicName=Motif Style -motif_theme.default.tip=Motif style -flatLightLaf_theme.system.topicName=flatLightLaf Style -flatLightLaf_theme.default.tip=flatLightLaf style - -mainWindow.title=Axis Creation Toolbox v1.0 -mainWindow.title.2=Axis Creation Toolbox -mainWindow.settings.title=System Settings - -andShow.title=Program Crash Report -andShow.title.2=

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 deleted file mode 100644 index 4ecd818..0000000 --- a/language/SimplifiedChineseLanguage.properties +++ /dev/null @@ -1,99 +0,0 @@ -default_theme.system.topicName=\u9ED8\u8BA4\u4E3B\u9898 -default_theme.default.tip=\u9ED8\u8BA4\u7684\u4E3B\u9898 -metal_theme.system.topicName=Metal\u98CE\u683C -metal_theme.default.tip=Metal\u98CE\u683C -motif_theme.system.topicName=Motif\u98CE\u683C -motif_theme.default.tip=Motif\u98CE\u683C -flatLightLaf_theme.system.topicName=flatLightLaf\u98CE\u683C -flatLightLaf_theme.default.tip=flatLightLaf\u98CE\u683C - -mainWindow.title=\u8F74\u521B\u5DE5\u5177\u7BB1 v1.0 -mainWindow.title.2=\u8F74\u521B\u5DE5\u5177\u7BB1 -mainWindow.settings.title=\u7CFB\u7EDF\u8BBE\u7F6E - -andShow.title=\u7A0B\u5E8F\u5D29\u6E83\u62A5\u544A -andShow.title.2=

\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 deleted file mode 100644 index 8b754fe..0000000 --- a/language/TraditionalChineseLanguage.properties +++ /dev/null @@ -1,99 +0,0 @@ -default_theme.system.topicName=\u9810\u8A2D\u4E3B\u984C -default_theme.default.tip=\u9810\u8A2D\u7684\u4E3B\u984C -metal_theme.system.topicName=Metal\u98A8\u683C -metal_theme.default.tip=Metal\u98A8\u683C -motif_theme.system.topicName=Motif\u98A8\u683C -motif_theme.default.tip=Motif\u98A8\u683C -flatLightLaf_theme.system.topicName=flatLightLaf\u98A8\u683C -flatLightLaf_theme.default.tip=flatLightLaf\u98A8\u683C - -mainWindow.title=\u8EF8\u5275\u5DE5\u5177\u7BB1 v1.0 -mainWindow.title.2=\u8EF8\u5275\u5DE5\u5177\u7BB1 -mainWindow.settings.title=\u7CFB\u7D71\u8A2D\u7F6E - -andShow.title=\u7A0B\u5F0F\u5D29\u6F70\u5831\u544A -andShow.title.2=

\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 deleted file mode 100644 index 060dcf8..0000000 --- a/language/saved_language.properties +++ /dev/null @@ -1,3 +0,0 @@ -#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 index 43247e2..2c44ff2 100644 --- a/src/main/java/com/axis/innovators/box/AxisInnovatorsBox.java +++ b/src/main/java/com/axis/innovators/box/AxisInnovatorsBox.java @@ -1,6 +1,7 @@ package com.axis.innovators.box; import com.axis.innovators.box.events.GlobalEventBus; +import com.axis.innovators.box.events.OpenFileEvents; import com.axis.innovators.box.events.StartupEvent; import com.axis.innovators.box.gui.*; import com.axis.innovators.box.plugins.PluginDescriptor; @@ -9,6 +10,7 @@ import com.axis.innovators.box.register.RegistrationSettingsItem; import com.axis.innovators.box.register.RegistrationTool; import com.axis.innovators.box.register.RegistrationTopic; import com.axis.innovators.box.register.LanguageManager; +import com.axis.innovators.box.tools.ArgsParser; import com.axis.innovators.box.tools.LibraryLoad; import com.axis.innovators.box.tools.StateManager; import com.axis.innovators.box.tools.SystemInfoUtil; @@ -22,7 +24,9 @@ import java.awt.*; import java.awt.event.ActionEvent; import java.io.*; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Map; /** * 主类 @@ -52,13 +56,14 @@ public class AxisInnovatorsBox { private final List windowsJDialogList = new ArrayList<>(); private final StateManager stateManager = new StateManager(); - public AxisInnovatorsBox(String[] args){ + public AxisInnovatorsBox(String[] args) { this.args = args; } static { try { LibraryLoad.loadLibrary("FridaNative"); + LibraryLoad.loadLibrary("ThrowSafely"); LM.loadLibrary(LM.CUDA); } catch (Exception e) { logger.error("Failed to load the 'FridaNative' library", e); @@ -218,6 +223,9 @@ public class AxisInnovatorsBox { dialog.setVisible(true); } + /** + * 初始化Log4j2 + */ public void initLog4j2() { Log4j2OutputStream.redirectSystemStreams(); @@ -235,9 +243,11 @@ public class AxisInnovatorsBox { logger.info("ClassLoader.getSystemClassLoader(): {}", ClassLoader.getSystemClassLoader()); } + /** + * 设置主题 + */ private void setTopic() { try { - main.registrationTopic.addTopic(UIManager.getSystemLookAndFeelClassName(), LanguageManager.getLoadedLanguages().getText("default_theme.system.topicName"), LanguageManager.getLoadedLanguages().getText("default_theme.default.tip"), @@ -317,43 +327,59 @@ public class AxisInnovatorsBox { isWindow = true; } - - public static void main(String[] args) { + public static void run(String[] args) { main = new AxisInnovatorsBox(args); - main.initLog4j2(); - main.setTopic(); + try { + 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"); + List> validFiles = ArgsParser.parseArgs(args); - 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); + for (Map fileInfo : validFiles) { + OpenFileEvents openFileEvents = new OpenFileEvents(fileInfo.get("path"), fileInfo.get("extension")); + GlobalEventBus.EVENT_BUS.post(openFileEvents); + if (!openFileEvents.isContinue()) { + return; + } } - }); - main.thread.setName("Main Thread"); - main.thread.start(); + + 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(); + } catch (Exception e) { + logger.error("In unexpected errors", e); + main.ex.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + main.organizingCrashReports(e); + throw new RuntimeException(e); + } } public void runWindow() { diff --git a/src/main/java/com/axis/innovators/box/Main.java b/src/main/java/com/axis/innovators/box/Main.java index c8b2d8b..6d09fc5 100644 --- a/src/main/java/com/axis/innovators/box/Main.java +++ b/src/main/java/com/axis/innovators/box/Main.java @@ -10,7 +10,12 @@ import com.axis.innovators.box.register.LanguageManager; public class Main { public static void main(String[] args) { FolderCleaner.cleanFolder(FolderCreator.getLogsFolder(), 10); + LanguageManager.loadSavedLanguage(); - AxisInnovatorsBox.main(args); + if (LanguageManager.getLoadedLanguages() == null){ + LanguageManager.loadLanguage("system:zh_CN"); + } + + AxisInnovatorsBox.run(args); } } diff --git a/src/main/java/com/axis/innovators/box/events/OpenFileEvents.java b/src/main/java/com/axis/innovators/box/events/OpenFileEvents.java new file mode 100644 index 0000000..d87301e --- /dev/null +++ b/src/main/java/com/axis/innovators/box/events/OpenFileEvents.java @@ -0,0 +1,53 @@ +package com.axis.innovators.box.events; + + +import java.io.File; + +/** + * 当程序接受到了文件时触发 + * @author tzdwindows 7 + */ +public class OpenFileEvents { + private final File filePath; + private final String extension; + private boolean isContinue; + + /** + * 构造函数 + * @param filePath 文件路径 + * @param extension 文件后缀 + */ + public OpenFileEvents(String filePath, String extension) { + this.filePath = new File(filePath); + this.extension = extension; + isContinue = true; + } + + /** + * 获取文件路径 + * @return 文件路径 + */ + public File getFilePath() { + return filePath; + } + + /** + * 获取文件后缀 + * @return 文件后缀 + */ + public String getExtension() { + return extension; + } + + public boolean isContinue() { + return isContinue; + } + + /** + * 希望程序继续执行后面的操作 + * @param isContinue 是否继续 + */ + public void setContinue(boolean isContinue) { + this.isContinue = isContinue; + } +} 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 2175880..757de91 100644 --- a/src/main/java/com/axis/innovators/box/gui/MainWindow.java +++ b/src/main/java/com/axis/innovators/box/gui/MainWindow.java @@ -4,6 +4,8 @@ import com.axis.innovators.box.AxisInnovatorsBox; import com.axis.innovators.box.events.*; import com.axis.innovators.box.register.RegistrationSettingsItem; import com.axis.innovators.box.register.LanguageManager; +import com.formdev.flatlaf.FlatClientProperties; +import com.formdev.flatlaf.FlatLaf; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -13,9 +15,7 @@ import javax.swing.plaf.PanelUI; import javax.swing.plaf.basic.BasicScrollBarUI; import javax.swing.plaf.basic.BasicTabbedPaneUI; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; +import java.awt.event.*; import java.awt.image.BufferedImage; import java.awt.image.ConvolveOp; import java.awt.image.Kernel; @@ -30,16 +30,22 @@ public class MainWindow extends JFrame { private static final Logger logger = LogManager.getLogger(MainWindow.class); private final Map cardScales = new HashMap<>(); private final Map cardElevations = new HashMap<>(); - // 选项卡颜色 private final Color CARD_COLOR = Color.WHITE; private final List categories = new ArrayList<>(); - // 是否启用背景图片 private final boolean isBackground = true; - // 启动背景图片后是否启动背景模糊 private final boolean isBlur = true; public MainWindow() { setIconImage(LoadIcon.loadIcon("logo.png", 32).getImage()); + addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + for (JComponent card : cardScales.keySet()) { + cardScales.put(card, 1.0f); + card.repaint(); + } + } + }); } /** @@ -52,18 +58,13 @@ public class MainWindow extends JFrame { public void initUI() { - // 设置窗口属性 - setTitle(LanguageManager.getLoadedLanguages().getText("mainWindow.title")); setDefaultCloseOperation(EXIT_ON_CLOSE); setSize(1200, 800); setLocationRelativeTo(null); - // 设置窗口和内容面板透明 - //setBackground(new Color(0, 0, 0, 0)); getContentPane().setBackground(new Color(0, 0, 0, 0)); - // 自定义面板 JPanel mainPanel = new JPanel() { @Override protected void paintComponent(Graphics g) { @@ -96,24 +97,18 @@ public class MainWindow extends JFrame { logger.error("Failed to load background image", e); } } - - } }; - // 强制面板不透明 mainPanel.setOpaque(true); mainPanel.putClientProperty("FlatLaf.style", "background: null;"); - // 设置布局和边距 mainPanel.setLayout(new BorderLayout(20, 20)); mainPanel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30)); - // 添加其他组件 mainPanel.add(createHeader(), BorderLayout.NORTH); mainPanel.add(createCategoryTabs(), BorderLayout.CENTER); - // 添加主面板到窗口 add(mainPanel); } @@ -208,6 +203,10 @@ public class MainWindow extends JFrame { private JComponent createCategoryTabs() { JTabbedPane tabbedPane = new JTabbedPane(); + //tabbedPane.putClientProperty(FlatClientProperties.TABBED_PANE_TAB_AREA_ALIGN, Component.LEFT_ALIGNMENT); + tabbedPane.putClientProperty(FlatClientProperties.TABBED_PANE_TAB_HEIGHT, 40); + tabbedPane.putClientProperty(FlatClientProperties.TABBED_PANE_TAB_ICON_PLACEMENT, SwingConstants.TOP); + tabbedPane.setOpaque(false); tabbedPane.setBackground(new Color(0, 0, 0, 0)); tabbedPane.setBorder(null); @@ -236,7 +235,7 @@ public class MainWindow extends JFrame { } tabbedPane.addTab( category.getName(), - LoadIcon.loadIcon(category.getIcon(), 24), + LoadIcon.loadIcon(category.getIcon(), 12), scrollPane ); } @@ -246,7 +245,7 @@ public class MainWindow extends JFrame { private JPanel createToolsPanel(ToolCategory category) { JPanel panel = new JPanel(new GridLayout(0, 3, 20, 20)); - for (ToolItem tool : category.getTools()) { + for (ToolItem tool : category.getTools()) { panel.add(createToolCard(tool)); } panel.setOpaque(false); @@ -264,16 +263,14 @@ public class MainWindow extends JFrame { title.setFont(new Font("微软雅黑", Font.BOLD, 28)); title.setForeground(new Color(44, 62, 80)); - //JLabel iconLabel = new JLabel(LoadIcon.loadIcon("logo.png", 28)); - //iconLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); - JButton settings = new JButton(LoadIcon.loadIcon("settings.png", 32)); + settings.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_BORDERLESS); + settings.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); settings.setContentAreaFilled(false); settings.addActionListener(e -> showSettings()); JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); titlePanel.setOpaque(false); - //titlePanel.add(iconLabel); titlePanel.add(title); header.add(titlePanel, BorderLayout.WEST); @@ -323,7 +320,6 @@ public class MainWindow extends JFrame { JPanel card = new JPanel() { @Override protected void paintComponent(Graphics g) { - Graphics2D g2d = (Graphics2D) g.create(); // 毛玻璃效果 @@ -350,7 +346,8 @@ public class MainWindow extends JFrame { g2d.dispose(); } }; - + card.setPreferredSize(new Dimension(200, 150)); + card.setMinimumSize(new Dimension(100, 75)); card.setLayout(new BorderLayout(15, 15)); card.setBackground(CARD_COLOR); card.setBorder(BorderFactory.createCompoundBorder( @@ -395,7 +392,6 @@ public class MainWindow extends JFrame { card.add(iconLabel, BorderLayout.NORTH); card.add(textPanel, BorderLayout.CENTER); - // 鼠标悬停动画 card.addMouseListener(new CardMouseAdapter(card, tool)); card.addMouseListener(new MouseAdapter() { @Override @@ -418,6 +414,19 @@ public class MainWindow extends JFrame { super.update(g, c); } }); + + card.addMouseListener(new CardMouseAdapter(card, tool) { + @Override + public void mouseEntered(MouseEvent e) { + cardElevations.put(card, 8); + animateCardElevation(card, 8); + } + + @Override + public void mouseExited(MouseEvent e) { + animateCardElevation(card, 2); + } + }); return card; } @@ -429,7 +438,25 @@ public class MainWindow extends JFrame { ""; } - // 工具类别内部类 + private void animateCardElevation(JComponent card, int targetElevation) { + new Timer(10, new AbstractAction() { + private int currentElevation = cardElevations.getOrDefault(card, 2); + + @Override + public void actionPerformed(ActionEvent e) { + if (currentElevation < targetElevation) currentElevation++; + else if (currentElevation > targetElevation) currentElevation--; + + cardElevations.put(card, currentElevation); + card.repaint(); + + if (currentElevation == targetElevation) { + ((Timer)e.getSource()).stop(); + } + } + }).start(); + } + public static class ToolCategory { private final String name; private final String icon; @@ -687,52 +714,41 @@ public class MainWindow extends JFrame { public static class CustomScrollBarUI extends BasicScrollBarUI { @Override - protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) { - Graphics2D g2d = (Graphics2D) g; - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + protected void configureScrollBarColors() { + this.thumbColor = new Color(90, 90, 120); + this.trackColor = new Color(50, 50, 70); + } - // 设置轨道背景颜色 - Color trackColor = new Color(240, 240, 240); - g2d.setColor(trackColor); - g2d.fillRoundRect( - trackBounds.x, - trackBounds.y, - trackBounds.width - 1, - trackBounds.height - 1, - 5, 5 // 圆角半径 - ); + @Override + protected JButton createDecreaseButton(int orientation) { + return createInvisibleButton(); + } + + @Override + protected JButton createIncreaseButton(int orientation) { + return createInvisibleButton(); + } + + private JButton createInvisibleButton() { + JButton btn = new JButton(); + btn.setPreferredSize(new Dimension(0, 0)); + btn.setMinimumSize(new Dimension(0, 0)); + btn.setMaximumSize(new Dimension(0, 0)); + return btn; } @Override protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) { - Graphics2D g2d = (Graphics2D) g; - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - Color thumbColor = new Color(180, 180, 180); - g2d.setColor(thumbColor); - g2d.fillRoundRect( - thumbBounds.x, - thumbBounds.y, - thumbBounds.width - 1, - thumbBounds.height - 1, - 5, 5 - ); - - Color borderColor = new Color(160, 160, 160); - g2d.setColor(borderColor); - g2d.drawRoundRect( - thumbBounds.x, - thumbBounds.y, - thumbBounds.width - 1, - thumbBounds.height - 1, - 5, 5 + Graphics2D g2 = (Graphics2D)g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setColor(thumbColor); + g2.fillRoundRect( + thumbBounds.x + 2, + thumbBounds.y + 2, + thumbBounds.width - 4, + thumbBounds.height - 4, + 8, 8 ); } - - @Override - protected void paintDecreaseHighlight(Graphics g) {} - - @Override - protected void paintIncreaseHighlight(Graphics g) {} } } \ 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 939795e..f481514 100644 --- a/src/main/java/com/axis/innovators/box/plugins/PluginDescriptor.java +++ b/src/main/java/com/axis/innovators/box/plugins/PluginDescriptor.java @@ -13,6 +13,7 @@ public class PluginDescriptor { private String description; private Object instance; private String transformers; + private String registrationName; // Getters and Setters public String getId() { return id; } @@ -29,4 +30,6 @@ public class PluginDescriptor { public void setInstance(Object instance) { this.instance = instance; } public String getTransformers() {return transformers;} public void setTransformers(String transformers) {this.transformers = transformers;} + public String getRegistrationName() {return registrationName;} + public void setRegistrationName(String registrationName) {this.registrationName = registrationName;} } 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 5a391c1..0235fe5 100644 --- a/src/main/java/com/axis/innovators/box/plugins/PluginLoader.java +++ b/src/main/java/com/axis/innovators/box/plugins/PluginLoader.java @@ -1,12 +1,16 @@ package com.axis.innovators.box.plugins; import com.axis.innovators.box.AxisInnovatorsBox; +import com.axis.innovators.box.register.LanguageManager; +import com.axis.innovators.box.register.RegistrationTool; import com.axis.innovators.box.tools.FolderCreator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.*; +import java.lang.reflect.Field; import java.net.*; +import java.nio.charset.StandardCharsets; import java.util.*; import java.util.jar.*; @@ -20,7 +24,8 @@ public class PluginLoader { private static final List loadedPlugins = new ArrayList<>(); private static final List transformers = new ArrayList<>(); private static final List corePluginMainClass = new ArrayList<>(); - public static void loadPlugins() throws IOException { + private static final List pluginRegisteredName = new ArrayList<>(); + public static void loadPlugins() throws IOException, PluginLoadingError { logger = LogManager.getLogger(PluginLoader.class); File pluginDir = null; if (PLUGIN_PATH != null) { @@ -43,7 +48,7 @@ public class PluginLoader { } } - private static void processJarFile(File jarFile, boolean isCorePlugin) throws IOException { + private static void processJarFile(File jarFile, boolean isCorePlugin) throws IOException, PluginLoadingError { try (JarFile jar = new JarFile(jarFile)) { // Check for CorePlugin in MANIFEST.MF if (isCorePlugin) { @@ -80,7 +85,11 @@ public class PluginLoader { return; } for (File jar : jars) { - processJarFile(jar, true); + try { + processJarFile(jar, true); + } catch (PluginLoadingError e) { + throw new RuntimeException(e); + } } } @@ -122,7 +131,8 @@ public class PluginLoader { //} } - private static void processWithManifest(JarFile jar, JarEntry entry, File jarFile) throws IOException { + private static void processWithManifest(JarFile jar, JarEntry entry, File jarFile) + throws IOException, PluginLoadingError { Properties props = new Properties(); try (InputStream is = jar.getInputStream(entry)) { props.load(is); @@ -139,27 +149,92 @@ public class PluginLoader { descriptor.setSupportedVersions( Arrays.asList(props.getProperty("supportedVersions").split(",")) ); + String registrationName = props.getProperty("registrationName"); + verifyRegisteredNameValid(descriptor, registrationName); + logger.info("Loaded plugin: {}", descriptor.getName()); loadMainClass(props.getProperty("mainClass"), jarFile, descriptor); Attributes attributes = jar.getManifest().getMainAttributes(); String corePluginClass = attributes.getValue("CorePlugin"); descriptor.setTransformers(corePluginClass); + loadPluginLanguages(jarFile, descriptor); } - private static void processWithAnnotations(JarFile jar, File jarFile) { + private static void verifyRegisteredNameValid(PluginDescriptor descriptor, String registrationName) throws PluginLoadingError { + if (registrationName != null && !registrationName.isEmpty() + && !pluginRegisteredName.contains(registrationName)) { + pluginRegisteredName.add(registrationName); + } else { + if (registrationName == null || registrationName.isEmpty()) { + throw new PluginLoadingError("Invalid registration name"); + } + throw new PluginLoadingError("When the \" " + + descriptor.getName() + + "\" plugin is loaded, this plugin contains the same registered name as the previously loaded plugin"); + } + + descriptor.setRegistrationName(registrationName); + } + + private static void processWithAnnotations(JarFile jar, File jarFile) throws PluginLoadingError { URLClassLoader classLoader = createClassLoader(jarFile); Enumeration entries = jar.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); if (entry.getName().endsWith(".class")) { if (classLoader != null) { - processClassEntry(entry, jar,classLoader); + processClassEntry(entry, jar,classLoader,jarFile); + } } } } + private static void loadPluginLanguages(File jarFile, PluginDescriptor plugin) { + try (JarFile jar = new JarFile(jarFile)) { + Enumeration entries = jar.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + if (entry.getName().startsWith("lang/") && + entry.getName().endsWith(".properties")) { + processLanguageFile(jar, entry, plugin); + } + } + } catch (IOException e) { + logger.error("Failed to load language files for plugin: {}", plugin.getName(), e); + } + } + + private static void processLanguageFile(JarFile jar, JarEntry entry, PluginDescriptor plugin) { + String fileName = entry.getName().substring(entry.getName().lastIndexOf("/") + 1); + String[] parts = fileName.split("[_.]"); + if (parts.length < 3) { + return; + } + String langCode = parts[parts.length-1].replace(".properties", ""); + String langName = plugin.getName() + " " + langCode.toUpperCase(); + String registeredName = plugin.getRegistrationName() + "_" + langCode; + try (InputStream is = jar.getInputStream(entry)) { + Properties properties2 = new Properties(); + properties2.load(new InputStreamReader(is, StandardCharsets.UTF_8)); + LanguageManager.Language language = new LanguageManager.Language( + langName, + registeredName, + null + ) { + @Override + public void loadLanguageFile(String languageFile) { + this.properties.putAll(properties2); + } + }; + LanguageManager.addLanguage(language); + logger.info("Loaded plugin language: {} ({})", langName, registeredName); + } catch (IOException e) { + logger.error("Failed to load language file: {}", entry.getName(), e); + } + } + private static URLClassLoader createClassLoader(File jarFile) { try { return new URLClassLoader( @@ -172,7 +247,9 @@ public class PluginLoader { return null; } - private static void processClassEntry(JarEntry entry,JarFile jar, URLClassLoader classLoader) { + private static void processClassEntry(JarEntry entry,JarFile jar, + URLClassLoader classLoader, + File jarFile) throws PluginLoadingError { String className = entry.getName() .replace("/", ".") .replace(".class", ""); @@ -188,14 +265,27 @@ public class PluginLoader { descriptor.setIcon(meta.icon()); descriptor.setSupportedVersions(Arrays.asList(meta.supportedVersions())); + String registrationName = meta.registeredName(); + verifyRegisteredNameValid(descriptor, registrationName); + try { Object instance = clazz.getDeclaredConstructor().newInstance(); descriptor.setInstance(instance); - loadedPlugins.add(descriptor); + try { + Field pluginInstance = instance.getClass().getDeclaredField("INSTANCE"); + pluginInstance.setAccessible(true); + pluginInstance.set(null, descriptor); + } catch (NoSuchFieldException | IllegalArgumentException + | SecurityException | IllegalAccessException e) { + logger.warn("Failed to set plugin instance: {}", instance.getClass(), e); + } + + loadedPlugins.add(descriptor); Attributes attributes = jar.getManifest().getMainAttributes(); String corePluginClass = attributes.getValue("CorePlugin"); descriptor.setTransformers(corePluginClass); + loadPluginLanguages(jarFile, descriptor); logger.info("Loaded plugin: {}", descriptor.getName()); } catch (Exception e) { logger.error("Failed to instantiate plugin class: {}", className, e); @@ -208,6 +298,7 @@ public class PluginLoader { private static void loadMainClass(String mainClassName, File jarFile, PluginDescriptor descriptor) { if (mainClassName == null || mainClassName.isEmpty()) { + logger.error("Invalid main class name: {}", mainClassName); return; } @@ -218,6 +309,15 @@ public class PluginLoader { Class mainClass = classLoader.loadClass(mainClassName); Object instance = mainClass.getDeclaredConstructor().newInstance(); descriptor.setInstance(instance); + + try { + Field pluginInstance = mainClass.getDeclaredField("INSTANCE"); + pluginInstance.setAccessible(true); + pluginInstance.set(null, descriptor); + } catch (NoSuchFieldException | IllegalArgumentException + | SecurityException | IllegalAccessException e) { + logger.warn("Failed to set plugin instance: {}", mainClassName, e); + } } catch (Exception e) { logger.error("Failed to load main class: {}", mainClassName, e); } diff --git a/src/main/java/com/axis/innovators/box/plugins/PluginLoadingError.java b/src/main/java/com/axis/innovators/box/plugins/PluginLoadingError.java new file mode 100644 index 0000000..d9ba154 --- /dev/null +++ b/src/main/java/com/axis/innovators/box/plugins/PluginLoadingError.java @@ -0,0 +1,17 @@ +package com.axis.innovators.box.plugins; + +/** + * 当加载插件时发生的错误 + * @author tzdwindows 7 + */ +public class PluginLoadingError extends Exception{ + public PluginLoadingError(String message) + { + super(message); + } + + public PluginLoadingError(String message, Throwable cause) + { + super(message, cause); + } +} diff --git a/src/main/java/com/axis/innovators/box/plugins/PluginMeta.java b/src/main/java/com/axis/innovators/box/plugins/PluginMeta.java index ca2a19d..a33b322 100644 --- a/src/main/java/com/axis/innovators/box/plugins/PluginMeta.java +++ b/src/main/java/com/axis/innovators/box/plugins/PluginMeta.java @@ -6,15 +6,34 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * + * 这是创建基础参数的注解 * @author tzdwindows 7 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface PluginMeta { + /** + * 插件ID + */ String id(); + /** + * 创建显示名称 + */ String name(); + /** + * 支持的版本 + */ String[] supportedVersions(); + /** + * 插件描述 + */ String description(); + /** + * 插件图标 + */ String icon() default ""; + /** + * 插件注册名称(确保其唯一性) + */ + String registeredName() default "no_registration"; } \ No newline at end of file diff --git a/src/main/java/com/axis/innovators/box/register/LanguageManager.java b/src/main/java/com/axis/innovators/box/register/LanguageManager.java index f9d03be..699571d 100644 --- a/src/main/java/com/axis/innovators/box/register/LanguageManager.java +++ b/src/main/java/com/axis/innovators/box/register/LanguageManager.java @@ -1,13 +1,14 @@ package com.axis.innovators.box.register; +import com.axis.innovators.box.plugins.PluginLoader; import com.axis.innovators.box.tools.FolderCreator; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.io.*; +import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Properties; +import java.util.*; /** * 语言管理器 @@ -18,27 +19,106 @@ public class LanguageManager { private static final String LANGUAGE_PATH = FolderCreator.getLanguageFolder(); private static final List LANGUAGES = new ArrayList<>(); private static final String SAVED_LANGUAGE_FILE = LANGUAGE_PATH + "\\saved_language.properties"; + private static final Logger logger = LogManager.getLogger(PluginLoader.class); static { - LANGUAGES.add(new Language("简体中文", "Zh","SimplifiedChineseLanguage")); - LANGUAGES.add(new Language("繁體中文", "TC","TraditionalChineseLanguage")); - LANGUAGES.add(new Language("English", "En","EnglishLanguage")); + LANGUAGES.add(new Language("简体中文", "system:zh_CN", "sys_zh_CN")); + LANGUAGES.add(new Language("繁體中文(台灣)", "system:zh_TW", "sys_zh_TW")); + LANGUAGES.add(new Language("English (International)", "system:en_US", "sys_en_US")); + LANGUAGES.add(new Language("日本語", "system:ja_JP", "sys_ja_JP")); } + /** - * 添加语言 - * @param language 语言 + * 添加/合并语言资源 + * @param language 要添加的语言对象 + * 处理规则: + * 1. 注册名相同时保留原有基础信息 + * 2. 相同键值的新内容覆盖旧内容 + * 3. 详细记录新增、更新的键值数量 + * 4. 提供关键示例用于调试 */ public static void addLanguage(Language language) { - for (int i = 0; i < LANGUAGES.size(); i++) { - Language language1 = LANGUAGES.get(i); - if (Objects.equals(language1.getRegisteredName(), language.getRegisteredName())){ - LANGUAGES.set(i, language); + for (Language existing : LANGUAGES) { + if (existing.getRegisteredName().equals(language.getRegisteredName())) { + try { + int added = 0; + int updated = 0; + Set sampleAddedKeys = new LinkedHashSet<>(); + Set sampleUpdatedKeys = new LinkedHashSet<>(); + for (String key : language.properties.stringPropertyNames()) { + String newValue = language.properties.getProperty(key); + + if (existing.properties.containsKey(key)) { + updated++; + if (sampleUpdatedKeys.size() < 5) { + sampleUpdatedKeys.add(key); + } + } else { + added++; + if (sampleAddedKeys.size() < 5) { + sampleAddedKeys.add(key); + } + } + existing.properties.setProperty(key, newValue); + } + + String logDetail = buildMergeLogDetails(added, updated, sampleAddedKeys, sampleUpdatedKeys); + + logger.info("【语言合并报告】\n" + + "▌合并目标:{} ({})\n" + + "▌变更统计:新增 {} 条 / 更新 {} 条\n" + + "▌当前总量:{} 条\n" + + "▌关键示例:\n{}", + existing.getLanguageName(), + existing.getRegisteredName(), + added, + updated, + existing.properties.size(), + logDetail); + + return; + } catch (Exception e) { + logger.error("语言合并异常!注册名:{} - {}", + existing.getRegisteredName(), + e.getClass().getSimpleName(), + e); + } return; } } + LANGUAGES.add(language); + logger.info("【新增语言】{} ({}) 初始加载 {} 条", + language.getLanguageName(), + language.getRegisteredName(), + language.properties.size()); } + private static String buildMergeLogDetails(int added, int updated, + Set sampleAdded, Set sampleUpdated) { + StringBuilder sb = new StringBuilder(); + + if (added > 0) { + sb.append("✦ 新增条目:\n"); + sampleAdded.forEach(k -> sb.append(" ▸ ").append(k).append("\n")); + if (added > 5) { + sb.append(" ...(共").append(added).append("条)\n"); + } + } + + if (updated > 0) { + sb.append("✦ 更新条目:\n"); + sampleUpdated.forEach(k -> sb.append(" ▸ ").append(k).append("\n")); + if (updated > 5) { + sb.append(" ...(共").append(updated).append("条)\n"); + } + } + + return sb.toString().isEmpty() ? "无内容变更" : sb.toString(); + } + + + /** * 加载语言 * @param languageName 语言注册名 @@ -120,7 +200,7 @@ public class LanguageManager { private final String languageName; private final String registeredName; private final String languageFile; - private final Properties properties; + protected final Properties properties; public Language(String languageName, String registeredName, @@ -133,14 +213,14 @@ public class LanguageManager { this.languageFile = LANGUAGE_PATH + "\\" + languageFileName + ".properties"; } this.properties = new Properties(); - loadLanguageFile(); + loadLanguageFile(languageFile); } /** * 加载语言文件 */ - private void loadLanguageFile() { - try (InputStreamReader reader = new InputStreamReader(new FileInputStream(this.languageFile), + public void loadLanguageFile(String languageFile) { + try (InputStreamReader reader = new InputStreamReader(new FileInputStream(languageFile), StandardCharsets.UTF_8)) { properties.load(reader); } catch (IOException e) { @@ -161,6 +241,13 @@ public class LanguageManager { return properties.getProperty(key); } + /** + * 添加文本 + */ + public void addText(String key, String value) { + properties.setProperty(key, value); + } + public String getLanguageName() { return languageName; } diff --git a/src/main/java/com/axis/innovators/box/register/RegistrationSettingsItem.java b/src/main/java/com/axis/innovators/box/register/RegistrationSettingsItem.java index e87e19f..9543b30 100644 --- a/src/main/java/com/axis/innovators/box/register/RegistrationSettingsItem.java +++ b/src/main/java/com/axis/innovators/box/register/RegistrationSettingsItem.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.UUID; +import java.util.stream.Collectors; /** * 用于注册设置项的类 @@ -563,7 +564,7 @@ public class RegistrationSettingsItem extends WindowsJDialog { * @param tip 描述 * @param registeredName 注册名(必须是唯一的) */ - public void addSettings(JPanel tabbedPanesSettings, + private void addSettings(JPanel tabbedPanesSettings, String title, Icon icon, String tip, @@ -579,6 +580,49 @@ public class RegistrationSettingsItem extends WindowsJDialog { } } + /** + * 注册设置项 + * @param tabbedPanesSettings 设置页面 + * @param title 标题 + * @param icon 显示图标(可为null) + * @param tip 描述 + * @param plugin 插件 + * @param registeredName 注册名(必须是唯一的) + */ + public void addSettings(JPanel tabbedPanesSettings, + String title, + Icon icon, + String tip, + PluginDescriptor plugin, + String registeredName) { + if (mainWindow != null) { + if (!mainWindow.isWindow()) { + registrationItem(tabbedPanesSettings, title, icon, tip,plugin.getRegistrationName() + + ":" + + registeredName); + } else { + logger.warn("Wrong time to add tools"); + } + } else { + registrationItem(tabbedPanesSettings, title, icon, tip, registeredName); + } + } + + /** + * 通过 PluginDescriptor 查询整个插件装载的注册项 + * @param plugin 插件描述符 + * @return List 与指定插件相关的注册设置项列表 + */ + public static List getRegistrationsByPlugin(PluginDescriptor plugin) { + return registrationSettingsItemList.stream() + .filter(item -> + item.getRegisteredNameList().stream() + .anyMatch(name -> + name.startsWith(plugin.getRegistrationName() + ":")) + ) + .collect(Collectors.toList()); + } + private void registrationItem(JPanel tabbedPanesSettings, String title, Icon icon, String tip, String registeredName) { if (registeredNameList.contains(registeredName)) { throw new RegistrationError(registeredName + " duplicate registered names"); 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 ca9732b..7cd448b 100644 --- a/src/main/java/com/axis/innovators/box/register/RegistrationTool.java +++ b/src/main/java/com/axis/innovators/box/register/RegistrationTool.java @@ -4,6 +4,7 @@ import com.axis.innovators.box.AxisInnovatorsBox; import com.axis.innovators.box.gui.FridaWindow; import com.axis.innovators.box.gui.LocalWindow; import com.axis.innovators.box.gui.MainWindow; +import com.axis.innovators.box.plugins.PluginDescriptor; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -24,6 +25,7 @@ public class RegistrationTool { private final AxisInnovatorsBox main; private final List uuidList = new ArrayList<>(); private final List registeredNameList = new ArrayList<>(); + private final List pluginDescriptors = new ArrayList<>(); public RegistrationTool(AxisInnovatorsBox main) { this.main = main; @@ -66,7 +68,7 @@ public class RegistrationTool { * 注册ToolCategory * @param toolCategory ToolCategory */ - public void addToolCategory(MainWindow.ToolCategory toolCategory, + private boolean addToolCategory(MainWindow.ToolCategory toolCategory, String registeredName) { if (!main.isWindow()) { if (registeredNameList.contains(registeredName)) { @@ -75,8 +77,24 @@ public class RegistrationTool { uuidList.add(toolCategory.getId()); registeredNameList.add(registeredName); toolCategories.add(toolCategory); + return true; } else { logger.warn("Wrong time to add tools"); + return false; + } + } + + /** + * 注册ToolCategory + * @param toolCategory ToolCategory + */ + public void addToolCategory(MainWindow.ToolCategory toolCategory, + PluginDescriptor pluginDescriptor, + String registeredName) { + if (addToolCategory(toolCategory, + pluginDescriptor.getRegistrationName() + ":" + + registeredName)) { + pluginDescriptors.add(pluginDescriptor); } } diff --git a/src/main/java/com/axis/innovators/box/tools/ArgsParser.java b/src/main/java/com/axis/innovators/box/tools/ArgsParser.java new file mode 100644 index 0000000..d958a12 --- /dev/null +++ b/src/main/java/com/axis/innovators/box/tools/ArgsParser.java @@ -0,0 +1,83 @@ +package com.axis.innovators.box.tools; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * ArgsParser 类用于解析命令行参数,并返回包含合法文件信息的列表。 + * @author tzdwindows 7 + */ +public class ArgsParser { + + /** + * 判断路径是否合法(存在且是文件) + * + * @param path 文件路径 + * @return 是否合法 + */ + private static boolean isValidPath(String path) { + File file = new File(path); + return file.exists() && file.isFile(); + } + + /** + * 获取文件的后缀名 + * + * @param path 文件路径 + * @return 文件后缀名(如 ".txt") + */ + private static String getFileExtension(String path) { + int lastDotIndex = path.lastIndexOf('.'); + if (lastDotIndex == -1) { + return ""; // 没有后缀名 + } + return path.substring(lastDotIndex); + } + + /** + * 解析 args 参数并保存合法的文件路径 + * + * @param args main 方法的参数 + * @return 包含合法文件信息的列表,每个元素是一个 Map,包含 "extension" 和 "path" + */ + public static List> parseArgs(String[] args) { + List> validFiles = new ArrayList<>(); + + for (String arg : args) { + if (isValidPath(arg)) { + String extension = getFileExtension(arg); + + Map fileInfo = new HashMap<>(); + fileInfo.put("extension", extension); + fileInfo.put("path", arg); + + validFiles.add(fileInfo); + } + } + + return validFiles; + } + + public static void main(String[] args) { + // 模拟 main 方法的 args 参数 + String[] testArgs = { + "C:\\Program Files\\test.txt", // 合法文件 + "C:\\invalid_file.exe", // 不存在的文件 + "D:\\Documents\\report.pdf", // 合法文件 + "not_a_path", // 无效路径 + "C:\\Windows\\system32" // 目录,不是文件 + }; + + // 解析 args 参数 + List> validFiles = parseArgs(testArgs); + + // 输出结果 + System.out.println("Valid files:"); + for (Map fileInfo : validFiles) { + System.out.println("Extension: " + fileInfo.get("extension") + ", Path: " + fileInfo.get("path")); + } + } +} diff --git a/src/main/java/com/axis/innovators/box/tools/StateManager.java b/src/main/java/com/axis/innovators/box/tools/StateManager.java index 6988042..a08f963 100644 --- a/src/main/java/com/axis/innovators/box/tools/StateManager.java +++ b/src/main/java/com/axis/innovators/box/tools/StateManager.java @@ -22,7 +22,7 @@ public class StateManager { * @param statusName 状态文件名 */ public StateManager(String statusName) { - statusFile = FolderCreator.getConfigurationFolder() + statusName + ".properties"; + statusFile = FolderCreator.getConfigurationFolder() + "\\" + statusName + ".properties"; configMap = new HashMap<>(); properties = new Properties(); loadConfiguration(); @@ -32,7 +32,7 @@ public class StateManager { * 默认构造函数 */ public StateManager() { - statusFile = FolderCreator.getConfigurationFolder() + "state_management.properties"; + statusFile = FolderCreator.getConfigurationFolder() + "\\toolbox.properties"; configMap = new HashMap<>(); properties = new Properties(); loadConfiguration(); diff --git a/src/main/java/org/tzd/lm/LM.java b/src/main/java/org/tzd/lm/LM.java index d41cfb2..bce8855 100644 --- a/src/main/java/org/tzd/lm/LM.java +++ b/src/main/java/org/tzd/lm/LM.java @@ -10,7 +10,7 @@ import org.apache.logging.log4j.Logger; * @author tzdwindows 7 */ public class LM { - public static boolean CUDA = true; + public static boolean CUDA = false; public final static String DEEP_SEEK = FolderCreator.getModelFolder() + "\\DeepSeek-R1-Distill-Qwen-1.5B-Q8_0.gguf"; private static final Logger logger = LogManager.getLogger(LM.class); diff --git a/statestate_management.properties b/statestate_management.properties index e69de29..41c60c9 100644 --- a/statestate_management.properties +++ b/statestate_management.properties @@ -0,0 +1,3 @@ +#Updated configuration +#Fri Feb 14 09:55:41 CST 2025 +isWindow=false