perf(core): cache ribbon_groups() with OnceLock, avoid per-frame tree allocations

Change CadModule::ribbon_groups() from -> Vec<RibbonGroup> to -> &[RibbonGroup],
backed by a per-module OnceLock cache. The ribbon group tree is static data
(&'static str, Copy enums) that was being fully reconstructed — Vecs, String
clones, enum discriminants — on every call, including all three per-frame
call sites (view(), dropdown_overlay(), style_combo_overlay()).

- 7 built-in modules + 2 plugin templates cache via function-local OnceLock.
  Safe because each is a unit struct with exactly one instance per process
  (plugins run in isolated child processes; see PluginProcess::spawn()).
- SharedCadModule avoids the static pattern entirely, storing groups in an
  instance field (owned.rs).
- IPC runner converts &RibbonGroup -> OwnedRibbonGroup directly via new
  From<&T> impls, avoiding an intermediate clone.
- render_small/render_large and the two make_tool_row closures now borrow
  (&RibbonItem, &[ToolDef]) instead of taking ownership, so the view loop
  doesn't need to clone items to satisfy the old by-value signatures.
- Various match-ergonomics deref fixes (*id, *default, *icon, etc.) from
  the &RibbonItem pattern change.
This commit is contained in:
Karim Jerbi committed 2026-07-02 21:00:57 +01:00
1 parent 8164e14a19
commit 73b05e1dec
14 files changed
+947 -690

No files matched your search

+89 -86
View File
@@ -35,91 +35,94 @@ impl CadModule for InsertModule {
"Insert"
}
fn ribbon_groups(&self) -> Vec<RibbonGroup> {
vec![
// ── Reference ────────────────────────────────────────────────────
RibbonGroup {
title: "Reference",
tools: vec![
RibbonItem::LargeTool(xattach::tool()),
RibbonItem::LargeTool(xclip::tool()),
RibbonItem::LargeTool(xadjust::tool()),
RibbonItem::Tool(underlay_layers::tool()),
RibbonItem::Dropdown {
id: "FRAMES_DROPDOWN",
icon: IconKind::Svg(include_bytes!(
"../../../assets/icons/underlay_frames.svg"
)),
items: vec![
(
"FRAMES0",
"Frames Off",
IconKind::Svg(include_bytes!(
"../../../assets/icons/underlay_frames.svg"
)),
),
(
"FRAMES1",
"Frames On",
IconKind::Svg(include_bytes!(
"../../../assets/icons/underlay_frames.svg"
)),
),
(
"FRAMES2",
"Frames & Print",
IconKind::Svg(include_bytes!(
"../../../assets/icons/underlay_frames.svg"
)),
),
],
default: "FRAMES1",
},
RibbonItem::Tool(snap_underlays::tool()),
],
},
// ── Point Cloud ───────────────────────────────────────────────────
RibbonGroup {
title: "Point Cloud",
tools: vec![RibbonItem::LargeTool(pc_attach::tool())],
},
// ── Block ─────────────────────────────────────────────────────────
RibbonGroup {
title: "Block",
tools: vec![
RibbonItem::LargeTool(mview_block::tool()),
RibbonItem::LargeTool(insert_block::tool()),
RibbonItem::Tool(create_block::tool()),
RibbonItem::Tool(edit_block::tool()),
RibbonItem::Tool(base_point::tool()),
],
},
// ── Attributes ────────────────────────────────────────────────────
RibbonGroup {
title: "Attributes",
tools: vec![
RibbonItem::LargeTool(attdef::tool()),
RibbonItem::LargeTool(attedit::tool()),
RibbonItem::Tool(attman::tool()),
RibbonItem::Tool(attsync::tool()),
],
},
// ── Import ────────────────────────────────────────────────────────
RibbonGroup {
title: "Import",
tools: vec![
RibbonItem::LargeTool(open_obj::tool()),
RibbonItem::LargeTool(landxml::tool()),
],
},
// ── Content ───────────────────────────────────────────────────────
RibbonGroup {
title: "Content",
tools: vec![
RibbonItem::LargeTool(content_browser::tool()),
RibbonItem::LargeTool(design_center::tool()),
],
},
]
fn ribbon_groups(&self) -> &[RibbonGroup] {
static GROUPS: std::sync::OnceLock<Vec<RibbonGroup>> = std::sync::OnceLock::new();
GROUPS.get_or_init(|| {
vec![
// ── Reference ────────────────────────────────────────────────────
RibbonGroup {
title: "Reference",
tools: vec![
RibbonItem::LargeTool(xattach::tool()),
RibbonItem::LargeTool(xclip::tool()),
RibbonItem::LargeTool(xadjust::tool()),
RibbonItem::Tool(underlay_layers::tool()),
RibbonItem::Dropdown {
id: "FRAMES_DROPDOWN",
icon: IconKind::Svg(include_bytes!(
"../../../assets/icons/underlay_frames.svg"
)),
items: vec![
(
"FRAMES0",
"Frames Off",
IconKind::Svg(include_bytes!(
"../../../assets/icons/underlay_frames.svg"
)),
),
(
"FRAMES1",
"Frames On",
IconKind::Svg(include_bytes!(
"../../../assets/icons/underlay_frames.svg"
)),
),
(
"FRAMES2",
"Frames & Print",
IconKind::Svg(include_bytes!(
"../../../assets/icons/underlay_frames.svg"
)),
),
],
default: "FRAMES1",
},
RibbonItem::Tool(snap_underlays::tool()),
],
},
// ── Point Cloud ───────────────────────────────────────────────────
RibbonGroup {
title: "Point Cloud",
tools: vec![RibbonItem::LargeTool(pc_attach::tool())],
},
// ── Block ─────────────────────────────────────────────────────────
RibbonGroup {
title: "Block",
tools: vec![
RibbonItem::LargeTool(mview_block::tool()),
RibbonItem::LargeTool(insert_block::tool()),
RibbonItem::Tool(create_block::tool()),
RibbonItem::Tool(edit_block::tool()),
RibbonItem::Tool(base_point::tool()),
],
},
// ── Attributes ────────────────────────────────────────────────────
RibbonGroup {
title: "Attributes",
tools: vec![
RibbonItem::LargeTool(attdef::tool()),
RibbonItem::LargeTool(attedit::tool()),
RibbonItem::Tool(attman::tool()),
RibbonItem::Tool(attsync::tool()),
],
},
// ── Import ────────────────────────────────────────────────────────
RibbonGroup {
title: "Import",
tools: vec![
RibbonItem::LargeTool(open_obj::tool()),
RibbonItem::LargeTool(landxml::tool()),
],
},
// ── Content ───────────────────────────────────────────────────────
RibbonGroup {
title: "Content",
tools: vec![
RibbonItem::LargeTool(content_browser::tool()),
RibbonItem::LargeTool(design_center::tool()),
],
},
]
})
}
}