UI 与插件系统
大约 4 分钟
UI 与插件系统
Ribbon 工具栏、内置对话框、上下文菜单、插件系统。
如需创建自定义对话框,请参阅 custom-dialog.md。
Ribbon 工具栏
添加自定义标签页
const { RibbonConfigManager, CommandRegistry, CommandDefinition, CommandOptions } = vjcad;
// 1. 先注册命令
class MyToolCommand {
async main() {
console.log('执行我的工具');
}
}
const opt = new CommandOptions();
opt.useAutoComplete = true;
CommandRegistry.regist(new CommandDefinition('MYTOOL', '我的工具', MyToolCommand, opt));
// 2. 创建标签页配置
const newTab = {
id: 'my-tab',
label: '自定义',
groups: [{
id: 'my-tools',
label: '我的工具',
primaryButtons: [
{
cmd: 'MYTOOL',
icon: 'circle',
label: '创建圆',
tooltip: '创建一个圆'
}
],
moreButtons: [
{ cmd: 'ZOOM', icon: 'zoom', label: '缩放' }
]
}]
};
// 3. 添加到配置并刷新
const currentConfig = RibbonConfigManager.getConfig();
currentConfig.tabs.push(newTab);
RibbonConfigManager.refresh();添加到现有标签页
// 添加组到现有标签页
Engine.view.ribbonBar.addGroup('plugins', {
id: 'my-plugin-group',
label: '我的插件',
pinnable: true,
primaryButtons: [
{
icon: 'mygrid',
cmd: 'MYGRID',
prompt: '绘制网格',
type: 'large' // 'large' | 'small'
}
]
});
// 移除组
Engine.view.ribbonBar.removeGroup('plugins', 'my-plugin-group');消息输出
const { writeMessage, message } = vjcad;
// 输出到命令行(支持 HTML)
writeMessage("普通消息");
writeMessage("<br/>换行消息");
writeMessage("<br/><span style='color:red'>红色警告</span>");
writeMessage("<br/><b>粗体消息</b>");
// 信息提示(控制台)
message.info("信息提示");对话框
确认对话框
const { showConfirm, showWarningConfirm, showInfo, showError } = vjcad;
// 简单确认
const result = await showConfirm("确定要删除吗?", "确认删除");
// result: 'yes' | 'no'
// 警告确认
const result = await showWarningConfirm("此操作不可恢复!", "警告");
// 信息提示
await showInfo("操作已完成", "提示");
// 错误提示
await showError("操作失败:文件不存在", "错误");高级确认对话框
const { YesNoDialog, YesNoDialogConfig } = vjcad;
const config = new YesNoDialogConfig({
title: "保存更改",
message: "文件已修改,是否保存更改?",
type: "warning", // 'info' | 'warning' | 'error' | 'confirm'
yesTitle: "保存(S)",
noTitle: "不保存(N)",
showCancel: true,
cancelTitle: "取消"
});
const dialog = new YesNoDialog();
const result = await dialog.showMessageBox(config);
// result: 'yes' | 'no' | 'cancel'输入对话框
const { showPrompt, showInputDialog, showSelectDialog } = vjcad;
// 简单输入
const name = await showPrompt("请输入名称:", "默认值", "输入");
// 返回字符串或 null
// 带验证的输入
const result = await showInputDialog({
title: "设置圆半径",
label: "请输入半径值 (1-100):",
placeholder: "输入数字...",
defaultValue: "25",
required: true,
type: "text", // 'text' | 'password'
validator: (value) => {
const num = parseFloat(value);
if (isNaN(num)) return "请输入有效数字";
if (num < 1 || num > 100) return "半径必须在 1-100 之间";
return null; // null 表示验证通过
},
description: "输入的半径将用于创建新圆形"
});
if (result.confirmed) {
const radius = parseFloat(result.value);
}
// 下拉选择
const result = await showSelectDialog({
title: "选择线型",
label: "请选择线型:",
options: [
{ value: "Continuous", label: "Continuous (实线)" },
{ value: "DASHED", label: "DASHED (虚线)" },
{ value: "CENTER", label: "CENTER (中心线)" }
],
defaultValue: "Continuous",
description: "选择的线型将应用于新创建的直线"
});上下文菜单
基本用法
const { CadEventManager, CadEvents, Engine } = vjcad;
const events = CadEventManager.getInstance();
events.on(CadEvents.ContextMenuOpening, (args) => {
// 在默认菜单之前添加
args.prependItems.push({
label: "我的工具",
icon: "tool",
submenu: [
{
label: "画圆",
icon: "circle",
callback: () => Engine.editor.executerWithOp('CIRCLE')
},
{
label: "画线",
icon: "line",
callback: () => Engine.editor.executerWithOp('LINE')
}
]
});
// 分隔线
args.prependItems.push({ isSeparator: true });
// 在默认菜单之后添加
args.appendItems.push({
label: "缩放全图",
shortcut: "Z+E",
callback: () => Engine.zoomExtents()
});
});根据命令状态定制
events.on(CadEvents.ContextMenuOpening, (args) => {
if (args.isCommandActive) {
// 有命令执行中
if (args.activeCommandName === 'LINE') {
args.appendItems.push({
label: "闭合",
callback: () => writeMessage("<br/>C")
});
}
} else {
// 空闲状态
args.prependItems.push({
label: "快捷命令",
submenu: [
{ label: "画线", command: "LINE" },
{ label: "画圆", command: "CIRCLE" }
]
});
}
});完全自定义菜单
events.on(CadEvents.ContextMenuOpening, (args) => {
args.useDefaultItems = false; // 禁用默认项
args.prependItems.push({
label: "自定义菜单",
callback: () => { /* ... */ }
});
});禁止右键菜单
events.on(CadEvents.ContextMenuOpening, (args) => {
args.cancel = true;
});菜单项属性
| 属性 | 说明 |
|---|---|
label | 菜单文本 |
icon | 图标名称 |
shortcut | 快捷键文本 |
callback | 点击回调函数 |
command | 命令名称 |
submenu | 子菜单数组 |
isSeparator | 是否为分隔线 |
disabled | 是否禁用 |
插件系统
插件基本结构
class MyPlugin {
constructor() {
this.name = "MyPlugin";
this.version = "1.0.0";
this.description = "示例插件";
this.commands = [];
this.eventHandlers = [];
}
install() {
this.registerCommands();
this.addEventListeners();
this.initUI();
}
uninstall() {
// 移除事件监听
this.eventHandlers.forEach(handler => {
Engine.eventManager.off(handler.event, handler.callback);
});
// 注销命令
this.commands.forEach(cmdName => {
CommandRegistry.unregist(cmdName);
});
// 移除 UI
Engine.view.ribbonBar.removeGroup('plugins', 'my-plugin-group');
}
registerCommands() {
class DrawGridCommand {
async main() {
// 绘制网格逻辑
}
}
CommandRegistry.regist(
new CommandDefinition('MYGRID', '绘制网格', DrawGridCommand)
);
this.commands.push('MYGRID');
}
addEventListeners() {
const onEntityAdded = (args) => {
console.log('实体已添加:', args.entity.type);
};
Engine.eventManager.on(CadEvents.EntityAdded, onEntityAdded);
this.eventHandlers.push({
event: CadEvents.EntityAdded,
callback: onEntityAdded
});
}
initUI() {
// 注册图标
IconRegistry.registerCommandIcon('MYGRID', '<svg>...</svg>');
// 添加 Ribbon 组
Engine.view.ribbonBar.addGroup('plugins', {
id: 'my-plugin-group',
label: '我的插件',
primaryButtons: [
{ icon: 'mygrid', cmd: 'MYGRID', prompt: '绘制网格', type: 'large' }
]
});
}
}
// 安装插件
const plugin = new MyPlugin();
plugin.install();标准插件结构(Plugin 接口)
export default {
manifest: {
id: 'my-demo-plugin',
name: '示例插件',
version: '1.0.0',
author: 'vjmap.com',
description: '演示标准插件结构',
keywords: ['demo', 'grid']
},
onLoad(context) {
console.log('插件已加载');
},
onActivate(context) {
// 注册图标
context.registerIcon('MYGRID', '<svg>...</svg>');
// 注册命令
context.registerCommand('MYGRID', '绘制网格', DrawGridCommand);
// 添加菜单项
context.addMenuItem('tool', { command: 'MYGRID' });
// 添加 Ribbon 组
context.addRibbonGroup('plugins', {
id: 'my-demo',
label: '示例工具',
primaryButtons: [
{ icon: 'mygrid', cmd: 'MYGRID', prompt: '绘制网格', type: 'large' }
]
});
},
onDeactivate(context) {
console.log('插件已停用');
},
onUnload(context) {
console.log('插件已卸载');
}
};PluginManager API
const { PluginManager } = vjcad;
const pm = PluginManager.getInstance();
// 加载插件
await pm.loadFromContent(jsContent, cssContent); // 从代码内容
await pm.loadFromUrl(jsUrl, cssUrl); // 从 URL
await pm.loadFromPath(jsPath, cssPath); // 从本地路径
// 插件管理
pm.getLoadedPlugins(); // 获取已加载插件列表
pm.getPluginInfo(id); // 获取指定插件信息
pm.isLoaded(id); // 检查是否已加载
pm.isActive(id); // 检查是否已激活
pm.activate(id); // 激活插件
pm.deactivate(id); // 停用插件
pm.unload(id); // 卸载插件插件生命周期
onLoad- 插件加载时调用(只调用一次)onActivate- 插件激活时调用(可多次调用)onDeactivate- 插件停用时调用(可多次调用)onUnload- 插件卸载时调用(只调用一次)