PluginContext provides the APIs plugins use to interact with WebCAD.
import type { PluginContext, CommandOptions } from 'vjcad';
import { Engine, Point2D, LineEnt } from 'vjcad';
// Command class
class DrawCrossCommand {
async main(): Promise<void> {
const size = 50;
const center = new Point2D(0, 0);
const hLine = new LineEnt(
new Point2D(center.x - size, center.y),
new Point2D(center.x + size, center.y)
);
const vLine = new LineEnt(
new Point2D(center.x, center.y - size),
new Point2D(center.x, center.y + size)
);
hLine.setDefaults();
vLine.setDefaults();
Engine.addEntities([hLine, vLine], { recordUndo: true });
Engine.pcanvas.regen();
}
}
// Register in onActivate
async onActivate(context: PluginContext): Promise<void> {
const options = new CommandOptions();
context.registerCommand(
'DRAWCROSS',
'Draw Cross',
DrawCrossCommand,
options
);
}
// Unregister in onDeactivate
async onDeactivate(context: PluginContext): Promise<void> {
context.unregisterCommand('DRAWCROSS');
}
async onActivate(context: PluginContext): Promise<void> {
// Register SVG icon
const svgIcon = `<svg viewBox="0 0 24 24">
<line x1="4" y1="12" x2="20" y2="12" stroke="currentColor" stroke-width="2"/>
<line x1="12" y1="4" x2="12" y2="20" stroke="currentColor" stroke-width="2"/>
</svg>`;
context.registerIcon('DRAWCROSS', svgIcon);
}
import type { RibbonButtonConfig, RibbonGroupConfig, RibbonTabConfig } from 'vjcad';
async onActivate(context: PluginContext): Promise<void> {
// Add button to existing group
const button: RibbonButtonConfig = {
cmd: 'DRAWCROSS',
label: 'Cross',
icon: 'DRAWCROSS',
tooltip: 'Draw cross marker'
};
context.addRibbonButton('home', 'draw', button, 'primary');
}
// Add a new group to an existing tab
const group: RibbonGroupConfig = {
id: 'my-tools',
label: 'My Tools',
primaryButtons: [
{ cmd: 'DRAWCROSS', label: 'Cross' },
{ cmd: 'MYCMD2', label: 'Command 2' }
],
moreButtons: []
};
context.addRibbonGroup('home', group);
// Add a new tab
const tab: RibbonTabConfig = {
id: 'my-plugin-tab',
label: 'My Plugin',
groups: [
{
id: 'main-group',
label: 'Main Features',
primaryButtons: [
{ cmd: 'DRAWCROSS', label: 'Cross' }
]
}
]
};
context.addRibbonTab(tab, 'home'); // Insert after home tab
async onDeactivate(context: PluginContext): Promise<void> {
context.removeRibbonTab('my-plugin-tab');
context.removeRibbonGroup('home', 'my-tools');
context.removeRibbonButton('home', 'draw', 'DRAWCROSS');
}
async onActivate(context: PluginContext): Promise<void> {
// Register command and icon
context.registerCommand('MYCMD', 'My Command', MyCommand);
context.registerIcon('MYCMD', '<svg>...</svg>'); // Menu uses same-name icon
// Add to Tools menu
context.addMenuItem('tool', {
command: 'MYCMD',
shortcut: 'Ctrl+M' // Optional shortcut hint
});
}
async onActivate(context: PluginContext): Promise<void> {
// Create top-level menu (if it does not already exist)
context.addMenu({
id: 'my-tools',
label: 'My Tools',
after: 'tool' // After Tools menu
});
// Add menu items
context.addMenuItem('my-tools', { command: 'MYCMD1' });
context.addMenuItem('my-tools', { command: 'MYCMD2' });
}
async onDeactivate(context: PluginContext): Promise<void> {
context.removeMenuItem('my-tools', 'MYCMD1');
context.removeMenuItem('my-tools', 'MYCMD2');
context.removeMenu('my-tools');
}
For details, see Menu Bar and Ribbon Extension
import { CadEvents } from 'vjcad';
async onActivate(context: PluginContext): Promise<void> {
// Listen for entity-added event
context.on(CadEvents.EntityAdded, (args) => {
console.log('Entity added:', args.entity.type);
});
// Listen for command execution
context.on(CadEvents.CommandStarted, (args) => {
console.log('Command started:', args.commandName);
});
// One-time listener
context.once(CadEvents.DocumentOpened, (args) => {
console.log('Document opened:', args.document.name);
});
}
interface PluginSettings {
defaultSize: number;
autoSave: boolean;
}
async onActivate(context: PluginContext): Promise<void> {
// Read stored settings
const settings = context.getStorageItem<PluginSettings>('settings');
if (settings) {
console.log('Default size:', settings.defaultSize);
}
// Save settings
context.setStorageItem<PluginSettings>('settings', {
defaultSize: 100,
autoSave: true
});
// Delete data
context.removeStorageItem('old-key');
}
| Method | Description |
|---|
registerCommand(name, desc, cls, opt) | Register command |
unregisterCommand(name) | Unregister command |
executeCommand(name) | Execute command |
getRegisteredCommands() | Get registered commands |
| Method | Description |
|---|
addMenu(config) | Add top-level menu (skip if already exists) |
removeMenu(menuId) | Remove top-level menu |
addMenuItem(menuId, config) | Add menu item to specified menu |
removeMenuItem(menuId, command) | Remove menu item |
| Method | Description |
|---|
registerIcon(name, svg) | Register icon |
addRibbonButton(tab, group, btn, type) | Add button |
removeRibbonButton(tab, group, cmd) | Remove button |
addRibbonGroup(tab, group) | Add group |
removeRibbonGroup(tab, groupId) | Remove group |
addRibbonTab(tab, afterId) | Add tab (skip if already exists) |
removeRibbonTab(tabId) | Remove tab |
| Method | Description |
|---|
on(event, handler) | Listen to event |
off(event, handler) | Remove listener |
once(event, handler) | One-time listener |
| Method | Description |
|---|
getStorageItem<T>(key) | Read data |
setStorageItem<T>(key, value) | Save data |
removeStorageItem(key) | Delete data |