refactor(plugin): extract ocs_plugin_api crate for the stable add-on contract

Move the dependency-free, semver-versioned half of the plugin contract into a
standalone workspace crate `crates/ocs_plugin_api`:

- manifest types: PluginManifest, ApiVersion, API_VERSION
- ribbon vocabulary: CadModule trait + ToolDef/RibbonGroup/RibbonItem/IconKind/
  ModuleEvent/StyleKey

The host re-exports them from `crate::plugin::manifest` and `crate::modules`, so
every existing call site is unchanged. The acadrust-typed runtime surface
(HostSession) stays in the host binary; lifting it behind a HostApi trait in the
same crate is the remaining phase-1b step.

Part of #100. Docs updated in docs/plugin-architecture.md.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-06-15 01:36:04 +03:00
1 parent 7a4ddbc62e
commit 72ec1146df
9 files changed
+280 -154

No files matched your search

+8 -118
View File
@@ -13,124 +13,14 @@
// - mod.rs : module definition (ribbon groups + tool layout)
// - <tool>.rs : one file per tool (ribbon def + future command logic)
// ── Events ────────────────────────────────────────────────────────────────
/// Events a module tool can emit to the host application.
#[derive(Debug, Clone)]
pub enum ModuleEvent {
/// Fire a named CAD command (e.g. "LINE", "CIRCLE").
Command(String),
/// Open the OS file dialog.
OpenFileDialog,
/// Remove all loaded models from the scene.
#[allow(dead_code)]
ClearModels,
/// Toggle wireframe rendering.
SetWireframe(bool),
/// Toggle the layer manager panel.
ToggleLayers,
}
// ── Data types ────────────────────────────────────────────────────────────
/// Icon source for a ribbon tool button.
#[derive(Clone, Copy)]
pub enum IconKind {
/// Unicode glyph rendered as text (fast, no file needed).
Glyph(&'static str),
/// Raw SVG bytes embedded at compile time via `include_bytes!`.
Svg(&'static [u8]),
}
/// A single tool button shown in the ribbon.
#[derive(Clone)]
pub struct ToolDef {
/// Unique command id, e.g. "LINE".
pub id: &'static str,
/// Short label shown under the icon.
pub label: &'static str,
/// Icon — either a unicode glyph or embedded SVG bytes.
pub icon: IconKind,
/// Event emitted when the tool is clicked.
pub event: ModuleEvent,
}
/// One item in a ribbon group — plain button or dropdown, in small (1-row) or large (3-row) size.
#[derive(Clone)]
pub enum RibbonItem {
/// 1-row button — icon only, no label.
Tool(ToolDef),
/// 3-row button — icon + label below; full ribbon height.
LargeTool(ToolDef),
/// 1-row dropdown — icon + ▾ on right, no label.
Dropdown {
id: &'static str,
icon: IconKind,
items: Vec<(&'static str, &'static str, IconKind)>,
default: &'static str,
},
/// 3-row dropdown — icon + label + ▾ below label; full ribbon height.
LargeDropdown {
id: &'static str,
label: &'static str,
icon: IconKind,
items: Vec<(&'static str, &'static str, IconKind)>,
default: &'static str,
},
/// Layer combo + two rows of small tools below.
/// row2: operates on the layer of a selected object (off/freeze/lock/make-current)
/// row3: all-layers operations + match (on/thaw/unlock/match)
LayerComboGroup {
row2: Vec<ToolDef>,
row3: Vec<ToolDef>,
},
/// Match Properties (large button) + Color / Linetype / Lineweight combos on the right.
PropertiesGroup { match_prop: ToolDef },
/// A style selector combobox (text / dim / mleader / table style) with
/// optional small tool rows below it.
StyleComboGroup {
/// Which style domain this combo controls.
style_key: StyleKey,
/// Unique dropdown id (must be unique across the ribbon).
combo_id: &'static str,
/// Optional command to run when the user opens the style manager.
manager_cmd: Option<&'static str>,
/// Small tool rows rendered below the combo (0–2 rows).
rows: Vec<Vec<ToolDef>>,
},
}
/// Identifies which style list a `StyleComboGroup` refers to.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum StyleKey {
TextStyle,
DimStyle,
MLeaderStyle,
TableStyle,
}
impl From<ToolDef> for RibbonItem {
fn from(t: ToolDef) -> Self {
RibbonItem::Tool(t)
}
}
/// A named group of tool buttons shown together in the ribbon.
pub struct RibbonGroup {
pub title: &'static str,
pub tools: Vec<RibbonItem>,
}
// ── Trait ─────────────────────────────────────────────────────────────────
/// A CAD module owns a set of ribbon groups shown when its tab is active.
/// Each module is a stateless unit struct — all UI state lives in Ribbon.
pub trait CadModule: Send + Sync {
#[allow(dead_code)]
fn id(&self) -> &'static str;
fn title(&self) -> &'static str;
fn ribbon_groups(&self) -> Vec<RibbonGroup>;
}
// ── Ribbon vocabulary (CadModule, ToolDef, RibbonGroup, …) ─────────────────
//
// These types moved to the dependency-free `ocs_plugin_api` crate so add-ons
// can target a semver-stable contract. Re-exported here to keep the long-used
// `crate::modules::{CadModule, ToolDef, …}` paths stable across the codebase.
pub use ocs_plugin_api::ribbon::{
CadModule, IconKind, ModuleEvent, RibbonGroup, RibbonItem, StyleKey, ToolDef,
};
// ── Module declarations ───────────────────────────────────────────────────