Files
window-axis-innovators-box/README.md
2025-10-05 17:06:26 +08:00

635 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AxisInnovatorsBoxWindowApi
[项目链接](http://103.97.57.30:3000/tzdwindows7/AxisInnovatorsBoxWindowApi) | 简体中文
---
## 项目概述
`AxisInnovatorsBoxWindowApi` 是一个为 **AxisInnovatorsBox** 平台设计的管理API接口库开发者可通过此API创建自定义插件实现窗口管理、事件交互等核心功能。该仓库提供了接口定义、类说明文档及插件开发示例代码帮助开发者快速接入AxisInnovatorsBox生态系统。
---
## 功能特性
- 🖥️ **窗口生命周期管理** - 创建/销毁窗口、调整窗口状态(最小化/最大化)
- 🎮 **事件驱动交互** - 支持窗口事件监听与自定义事件触发
- 📦 **跨语言插件支持** - 基于 Java 平台无缝加载 Python 插件提供标准插件基类Java/Python实现快速扩展
- 📄 **动态配置管理** - 通过 properties 配置文件灵活加载多语言插件(支持 Java/Python 插件声明)
- 📊 **统一日志追踪** - 集成 Java 平台日志系统,同步记录 Python 插件的运行状态与异常信息
---
## 插件加载系统说明
- 插件加载系统核心组件。
- 插件加载系统由 **程序内部** 完成
### 注册Jar插件
- Jar插件在/plug-in中添加
```java
@PluginMeta(id = "test", name = "测试插件",
supportedVersions = {"0.0.2"},
description = "测试插件",
icon = "",
registeredName = "test")
public class Template {
public static PluginDescriptor INSTANCE = null;
public Template() {
GlobalEventBus.EVENT_BUS.register(this);
}
@SubscribeEvent
public void onStartup(StartupEvent event) {
MainWindow.ToolCategory category = new MainWindow.ToolCategory("测试插件", "test", "测试插件");
event.main().getRegistrationTool().addToolCategory(
category,
INSTANCE,
"templatePlugin"
);
}
}
```
- 插件加载系统会自动填充 **INSTANCE** 内容
- 使用PluginMeta注册插件信息
### Python插件注册
- Python插件在/plug-in/python中添加
- Python可以直接调用Java类实现对插件系统的控制
- 插件还需要单独的放在一个子文件夹中,如/plug-in/python/Examples
- Python插件需要声明一个metadata.json文件
```json
{
"id": "testing",
"name": "测试",
"version": "0.0.1",
"description": "测试插件",
"author": "tzdwindows 7",
"dependencies": [],
"_comment": {
"warning": "本文件为插件元数据配置,修改后需重启应用生效",
"path": "插件资源应放置在plugins/{id}/目录下"
}
}
```
- Python插件需要声明一个main.py文件做为插件的主脚本
```python
"""
工具模块初始化脚本
功能向Axis Innovators Box注册自定义工具类别和工具项
作者tzdwindows 7
版本1.1
"""
from com.axis.innovators.box.python import PyLocalSide
from javax.swing import AbstractAction
class MyAction(AbstractAction):
def actionPerformed(self, event):
"""工具项点击事件处理"""
print("[DEBUG] Tool item clicked! Event source:", event.getSource())
def onStartup():
"""
系统启动时自动执行的初始化逻辑
功能:
1. 创建工具类别
2. 创建工具项并绑定动作
3. 注册到系统全局工具集
"""
print('[INFO] 正在初始化自定义工具...')
# --------------------------
# 创建工具类别(参数顺序:显示名称,图标资源名,描述)
# --------------------------
tool_category = PyLocalSide.getToolCategory(
u"数据分析工具", # 显示名称GUI可见
u"analytics_icon.png", # 图标文件名(需存在于资源目录)
u"高级数据分析功能集合" # 悬停提示描述
)
# --------------------------
# 创建工具项参数顺序显示名称图标描述ID动作对象
# --------------------------
tool_action = MyAction()
tool_item = PyLocalSide.getToolItem(
u"数据可视化", # 工具项显示名称
u"chart_icon.png", # 工具项图标
u"生成交互式数据图表", # 工具项描述
1001, # 工具项唯一ID需在配置中统一管理
tool_action # 点击触发的动作
)
tool_category.addTool(tool_item)
# --------------------------
# 注册工具类别到系统(参数:类别对象,全局唯一注册名称)
# --------------------------
PyLocalSide.addToolCategory(
tool_category,
u"custom_module::data_analysis_tools" # 推荐命名规则:模块名::功能名
)
print('[SUCCESS] 工具类别注册成功')
if __name__ == '__main__':
result = 0
errorResult = ""
# 确保Jython运行时可以访问onStartup函数
# 原理:将函数显式绑定到全局字典
globals()['onStartup'] = onStartup
```
### 声明CorePlugins
* CorePlugins核心组件可以修改部分模块的字节码。
* CorePlugins需要在jar的属性中添加 **CorePlugins: CorePlugins类位置**
* 自动化构建在build.gradle中添加如下代码
```groovy
jar {
manifest {
attributes 'CorePlugin': 'com.axis.core.template.TemplateLoadingCorePlugin'
}
}
```
* CorePlugins核心组件需要实现 **CorePlugins** 接口,如:
```java
package com.axis.core.template;
import com.axis.innovators.box.plugins.LoadingCorePlugin;
import com.axis.innovators.template.Template;
/**
* 注册core插件
*/
public class TemplateLoadingCorePlugin implements LoadingCorePlugin {
@Override
public String getMainClass() {
// 返回主类名
return Template.class.getName();
}
@Override
public String[] getASMTransformerClass() {
// 返回字节码转换器类名
return new String[]{TemplateTransformer.class.getName()};
}
}
```
* IClassTransformer的实现
```java
package com.axis.core.template;
import com.axis.innovators.box.plugins.IClassTransformer;
import org.objectweb.asm.*;
/**
* core plugin transformer
* @author tzdwindows 7
*/
public class TemplateTransformer implements IClassTransformer {
@Override
public byte[] transform(String s, String s1, byte[] bytes) {
ClassReader classReader = new ClassReader(bytes);
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM5, classWriter) {
@Override
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
if ((access & Opcodes.ACC_PRIVATE) != 0) {
access = (access & ~Opcodes.ACC_PRIVATE) | Opcodes.ACC_PUBLIC;
System.out.println("Changing field access to public: " + name);
}
return super.visitField(access, name, descriptor, signature, value);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
System.out.println(name + " , descriptor:" + descriptor);
if ((access & Opcodes.ACC_PRIVATE) != 0) {
access = (access & ~Opcodes.ACC_PRIVATE) | Opcodes.ACC_PUBLIC;
System.out.println("Changing method access to public: " + name);
}
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
};
classReader.accept(classVisitor, 0);
return classWriter.toByteArray();
}
}
```
## 事件系统说明
- 事件驱动架构核心组件
- 事件总线系统支持跨模块通信
- 事件总线由 **EventBus & GlobalEventBus** 实现
### 1.. EventBus & GlobalEventBus 说明
应用程序内的事件驱动架构核心组件
```java
package com.axis.innovators.box.events;
/**
* 事件总线系统(支持多总线实例隔离)
*/
public class EventBus {
// 核心方法
public void register(Object listener); // 注册监听器
public void unregister(Object target); // 注销监听器
public boolean post(Object event); // 发布事件
public void shutdown(); // 关闭总线
}
public class GlobalEventBus {
public static final EventBus EVENT_BUS = new EventBus(); // 全局单例总线
}
```
- **EventBus**:用于处理应用程序内各个模块之间的事件通信。
- **GlobalEventBus**:用于处理应用程序内各个模块之间的事件通信,支持多总线实例隔离。
### 2. EventBus & GlobalEventBus 使用示例
#### 示例1基础事件处理
```java
// 1. 定义事件类型
public class UserLoginEvent {
private final String username;
private boolean cancelled;
public UserLoginEvent(String username) {
this.username = username;
}
// Getter/Setter...
}
// 2. 创建监听器类
public class SecurityLogger {
@SubscribeEvent
public void logLoginAttempt(UserLoginEvent event) {
System.out.println("[安全审计] 登录尝试: " + event.getUsername());
}
}
// 3. 使用全局总线
public class Main {
public static void main(String[] args) {
// 注册监听器
GlobalEventBus.EVENT_BUS.register(new SecurityLogger());
// 模拟用户登录
UserLoginEvent loginEvent = new UserLoginEvent("admin");
GlobalEventBus.EVENT_BUS.post(loginEvent);
}
}
```
- 示例2事件取消机制
```java
// 1. 定义可取消事件
public class FileDeleteEvent {
private final Path filePath;
private boolean cancelled;
// 构造方法/getters/setters...
}
// 2. 创建权限校验监听器
public class PermissionValidator {
@SubscribeEvent
public void validateDeletePermission(FileDeleteEvent event) {
if (!checkAdminAccess()) {
event.setCancelled(true);
System.out.println("文件删除被拒绝:权限不足");
}
}
private boolean checkAdminAccess() {
// 权限校验逻辑
return false;
}
}
// 3. 主业务流程
public class FileManager {
public void deleteFile(Path path) {
FileDeleteEvent event = new FileDeleteEvent(path);
GlobalEventBus.EVENT_BUS.post(event);
if (!event.isCancelled()) {
// 执行删除操作
System.out.println("正在删除文件: " + path);
}
}
}
```
### 3.所有系统所支持的事件
- `com.axis.innovators.box.events.CategoryRenderingEvent`: 分类栏的渲染事件
- `com.axis.innovators.box.events.MainWindowEvents`: 主窗口事件
- `com.axis.innovators.box.events.OpenFileEvents`: 接收文件事件
- `com.axis.innovators.box.events.SettingsLoadEvents`: 程序初始化事件
- `com.axis.innovators.box.events.StartupEvent`: 程序启动事件
- `com.axis.innovators.box.events.TABUIEvents`: 选项卡Ui属性事件
## HTML窗口集成指南
我们实现了一套高性能的HTML渲染系统通过Java Chromium Embedded Framework (JCEF) 将HTML内容无缝集成到Java桌面应用中底层基于[jcefmaven](https://github.com/jcefmaven/jcefmaven)项目。
### 核心实现步骤
#### 1. 创建HTML窗口
```java
// 创建窗口引用
AtomicReference<BrowserWindowJDialog> htmlWindow = new AtomicReference<>();
SwingUtilities.invokeLater(() -> {
// 通过窗口注册表创建子窗口
WindowRegistry.getInstance().createNewChildWindow("main", builder -> {
htmlWindow.set(builder
.title("Axis Innovators Box AI 工具箱") // 窗口标题
.parentFrame(parentFrame) // 父级窗口
.icon(getApplicationIcon()) // 应用图标
.size(1280, 720) // 初始尺寸
.htmlPath(getHtmlResourcePath()) // HTML文件路径
.operationHandler(createOperationHandler()) // 自定义操作处理器
.build());
});
// 配置消息路由
configureMessageRouter(htmlWindow.get());
});
```
#### 2. 辅助方法
```java
// 获取应用图标
private Image getApplicationIcon() {
return new ImageIcon(Objects.requireNonNull(
MainApplication.class.getClassLoader()
.getResource("icons/logo.png")
)).getImage();
}
// 获取HTML资源路径
private String getHtmlResourcePath() {
return FolderCreator.getJavaScriptFolder() + "/AIaToolbox_dark.html";
}
```
#### 3. 配置消息路由器
```java
private void configureMessageRouter(BrowserWindowJDialog window) {
CefMessageRouter msgRouter = window.getMsgRouter();
if (msgRouter == null) return;
msgRouter.addHandler(new CefMessageRouterHandlerAdapter() {
@Override
public boolean onQuery(CefBrowser browser, CefFrame frame, long queryId,
String request, boolean persistent, CefQueryCallback callback) {
// 处理来自HTML的请求
handleBrowserRequest(request, callback);
return true; // 表示已处理该请求
}
@Override
public void onQueryCanceled(CefBrowser browser, CefFrame frame, long queryId) {
// 处理请求取消逻辑
System.out.println("请求被取消: " + queryId);
}
}, true); // true表示优先处理
}
```
### 窗口管理系统说明
通过`WindowRegistry`统一管理应用窗口:
| 方法 | 说明 |
|------|------|
| `createNewWindow(String id, Consumer<Builder> config)` | 创建主窗口 |
| `createNewChildWindow(String id, Consumer<Builder> config)` | 创建模态子窗口 |
| `getWindow(String id)` | 获取已注册窗口 |
| `unregisterWindow(String id)` | 关闭指定窗口 |
### CefMessageRouter 使用指南
实现Java与JavaScript双向通信的核心组件
1. **消息处理流程**
- JavaScript → Java: 通过`window.cefQuery()`发送请求
- Java → JavaScript: 使用`CefFrame.executeJavaScript()`执行脚本
2. **核心方法**
```java
// JavaScript调用示例
function callJavaMethod(data) {
window.cefQuery({
request: JSON.stringify(data),
onSuccess: response => console.log("Success:", response),
onFailure: (err, msg) => console.error("Error:", msg)
});
}
```
3. **最佳实践**
- 使用JSON格式进行数据交换
- 为不同功能模块使用独立的路由处理器
- 在窗口关闭前移除所有路由处理器
### 生命周期管理
```java
// 关闭窗口时清理资源
htmlWindow.get().addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
window.getMsgRouter().dispose();
CefApp.getInstance().dispose();
}
});
```
## 核心类说明
### 1. AxisInnovatorsBox
窗口实例的核心操作类,提供以下功能:
- `getMain()`: 获取当前AxisInnovatorsBox实例
- `getMainWindow()`: 获取主窗口实例
- `quit()`: 退出程序
- `organizingCrashReports(Exception)`: 组织崩溃报告,用于在应用程序发生异常时生成崩溃报告。
- `popupWindow(WindowsJDialog)`: 弹出新的窗口,并将其添加到窗口列表中。
- `isWindowStartup(WindowsJDialog)`: 判断指定的窗口是否已经启动。
- `clearWindow(WindowsJDialog)`: 清除指定的窗口,并将其从窗口列表中移除。
- `reloadAllWindow()`: 重新加载窗口。
- `getRegistrationTool()`: 获取注册工具实例。
- `getArgs()`: 获取命令行参数。
- `isWindow()`: 判断窗口是否已经启动。
- `getVersion()`: 获取应用程序的版本号。
- `getRegistrationTopic()`: 获取注册主题实例。
- `getAuthor()`: 获取应用程序的作者信息。
- `getStateManager()`: 获取状态管理器实例。
### 2. RegistrationTool
负责在 **应用程序启动阶段** 注册和管理工具分类的核心组件,具备插件系统集成能力:
```java
package com.axis.innovators.box.register;
/**
* 工具分类注册中心(窗口启动前必须完成注册)
*/
public class RegistrationTool {
// 构造方法关联主程序实例
public RegistrationTool(AxisInnovatorsBox main) { ... }
// 核心功能方法
public boolean addToolCategory(ToolCategory category, String regName);
public void addToolCategory(ToolCategory category, PluginDescriptor descriptor, String regName);
public ToolCategory getToolCategory(UUID id);
public UUID getUUID(String registeredName);
}
```
- `addToolCategory(ToolCategory category, String regName)`: 向工具分类注册中心添加一个新的工具分类。
- `addToolCategory(ToolCategory category, PluginDescriptor descriptor, String regName)`: 向工具分类注册中心添加一个新的工具分类,同时关联插件描述符。
- `getToolCategory(UUID id)`: 通过UUID获取工具分类。
- `getUUID(String registeredName)`: 通过注册名称获取UUID。
#### 注册示例
```java
// 创建调试工具分类
MainWindow.ToolCategory debugCategory = new MainWindow.ToolCategory(
"逆向分析工具",
"icons/debugger.png",
"二进制逆向分析工具集"
);
// 添加工具项(带点击事件)
debugCategory.addTool(new MainWindow.ToolItem(
"内存分析器",
"icons/memory.png",
"实时查看进程内存映射",
1,
new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "启动内存分析模块...");
}
}
));
// 注册到系统(必须在窗口初始化前完成)
try {
registrationTool.addToolCategory(debugCategory, "system:reverseEngineering");
} catch (RegistrationError ex) {
System.err.println("注册失败: " + ex.getMessage());
}
```
### 3. RegistrationTopic
负责在 **应用程序初始化阶段** 统一管理UI主题注册的核心组件支持类名/LookAndFeel双模式主题注入
```java
package com.axis.innovators.box.register;
/**
* 主题注册中心(窗口初始化前必须完成注册)
*/
public class RegistrationTopic {
// 核心注册方法
public void addTopic(String topicClass, String name, String tip, Icon icon, String regName);
public void addTopic(LookAndFeel laf, String name, String tip, Icon icon, String regName);
// 状态管理方法
public boolean isLoading(String themeName);
public void setLoading(String themeName);
}
```
- `addTopic(String topicClass, String name, String tip, Icon icon, String regName)`: 向主题注册中心添加一个新的主题。
- `addTopic(LookAndFeel laf, String name, String tip, Icon icon, String regName)`: 向主题注册中心添加一个新的主题同时关联LookAndFeel。
- `isLoading(String themeName)`: 判断指定主题是否正在加载。
- `setLoading(String themeName)`: 设置指定主题为正在加载状态。
#### 注册示例
```java
try {
// 重复注册相同名称
topicRegistry.addTopic("com.axis.light.MaterialTheme",
"质感浅色",
"Material Design风格",
materialIcon,
"theme:light"); // 已存在同名注册
} catch (RegistrationError ex) {
// 捕获异常并提示theme:light duplicate registered names
JOptionPane.showMessageDialog(null, ex.getMessage());
}
```
### 4. StateManager
应用程序状态管理工具类,提供跨会话的配置持久化能力:
```java
package com.axis.innovators.box.tools;
/**
* 状态持久化管理器(线程安全)
*/
public class StateManager {
// 构造方法
public StateManager(); // 默认使用toolbox.properties
public StateManager(String customFileName); // 自定义状态文件名
// 核心操作方法
public void saveState(String key, [int|long|boolean...] value);
public [String|int|boolean...] getStateAs[Type](String key);
}
```
- `saveState(String key, [int|long|boolean...] value)`: 保存状态到配置文件。
- `getStateAs[Type](String key)`: 从配置文件获取状态。
- `[String|int|boolean...]`: 支持多种数据类型保存到配置文件,并支持多种数据类型从配置文件获取。
### 5. RegistrationSettingsItem
负责管理系统 **设置中心** 的配置面板注册,支持插件化扩展设置项的核心组件:
```java
package com.axis.innovators.box.register;
/**
* 设置项注册中心(集成插件配置扩展能力)
*/
public class RegistrationSettingsItem extends WindowsJDialog {
// 核心注册方法
public void addSettings(JPanel panel, String title, Icon icon, String tip, String regName);
public void addSettings(JPanel panel, String title, Icon icon, String tip,
PluginDescriptor plugin, String regName);
// 查询方法
public static List<RegistrationSettingsItem> getRegistrationsByPlugin(PluginDescriptor plugin);
}
```
- `addSettings(JPanel panel, String title, Icon icon, String tip, String regName)`: 向设置项注册中心添加一个新的设置项。
- `addSettings(JPanel panel, String title, Icon icon, String tip, PluginDescriptor plugin, String regName)`: 向设置项注册中心添加一个新的设置项,同时关联插件描述符。
- `getRegistrationsByPlugin(PluginDescriptor plugin)`: 通过插件描述符获取关联的设置项列表。
### 6. LanguageManager
应用程序多语言管理核心组件,支持动态加载与合并多语言资源:
```java
package com.axis.innovators.box.register;
/**
* 国际化语言管理中心(支持插件扩展语言包)
*/
public class LanguageManager {
// 核心操作方法
public static void addLanguage(Language lang);
public static void loadLanguage(String regName);
public static Language getLoadedLanguages();
public static Language getLanguage(String identifier);
}
```
- `addLanguage(Language lang)`: 向语言管理中心添加一个新的语言包。
- `loadLanguage(String regName)`: 加载指定语言包。
- `getLoadedLanguages()`: 获取当前系统加载的语言包。
- `getLanguage(String identifier)`: 通过标识符获取语言包。