diff --git a/assets/icons/ddedit.svg b/assets/icons/ddedit.svg
new file mode 100644
index 000000000..6c285b694
--- /dev/null
+++ b/assets/icons/ddedit.svg
@@ -0,0 +1,11 @@
+
diff --git a/assets/icons/dim_aligned.svg b/assets/icons/dim_aligned.svg
new file mode 100644
index 000000000..e44f7fb78
--- /dev/null
+++ b/assets/icons/dim_aligned.svg
@@ -0,0 +1,11 @@
+
diff --git a/assets/icons/dim_angular.svg b/assets/icons/dim_angular.svg
new file mode 100644
index 000000000..d837aa0ae
--- /dev/null
+++ b/assets/icons/dim_angular.svg
@@ -0,0 +1,11 @@
+
diff --git a/assets/icons/dim_baseline.svg b/assets/icons/dim_baseline.svg
new file mode 100644
index 000000000..063a74ad1
--- /dev/null
+++ b/assets/icons/dim_baseline.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/icons/dim_continue.svg b/assets/icons/dim_continue.svg
new file mode 100644
index 000000000..8fabc333e
--- /dev/null
+++ b/assets/icons/dim_continue.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/icons/dim_diameter.svg b/assets/icons/dim_diameter.svg
new file mode 100644
index 000000000..db62b45a6
--- /dev/null
+++ b/assets/icons/dim_diameter.svg
@@ -0,0 +1,10 @@
+
diff --git a/assets/icons/dim_linear.svg b/assets/icons/dim_linear.svg
new file mode 100644
index 000000000..80f868048
--- /dev/null
+++ b/assets/icons/dim_linear.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/icons/dim_ordinate.svg b/assets/icons/dim_ordinate.svg
new file mode 100644
index 000000000..fd0b801c0
--- /dev/null
+++ b/assets/icons/dim_ordinate.svg
@@ -0,0 +1,12 @@
+
diff --git a/assets/icons/dim_radius.svg b/assets/icons/dim_radius.svg
new file mode 100644
index 000000000..a2e52734f
--- /dev/null
+++ b/assets/icons/dim_radius.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/icons/leader.svg b/assets/icons/leader.svg
new file mode 100644
index 000000000..c1031b47f
--- /dev/null
+++ b/assets/icons/leader.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/icons/mleader.svg b/assets/icons/mleader.svg
new file mode 100644
index 000000000..25bde637a
--- /dev/null
+++ b/assets/icons/mleader.svg
@@ -0,0 +1,11 @@
+
diff --git a/assets/icons/revcloud.svg b/assets/icons/revcloud.svg
new file mode 100644
index 000000000..d3271788c
--- /dev/null
+++ b/assets/icons/revcloud.svg
@@ -0,0 +1,20 @@
+
diff --git a/assets/icons/table.svg b/assets/icons/table.svg
new file mode 100644
index 000000000..da56b6cd3
--- /dev/null
+++ b/assets/icons/table.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/icons/tolerance.svg b/assets/icons/tolerance.svg
new file mode 100644
index 000000000..94889ee2d
--- /dev/null
+++ b/assets/icons/tolerance.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/icons/wipeout.svg b/assets/icons/wipeout.svg
new file mode 100644
index 000000000..ca9d7b194
--- /dev/null
+++ b/assets/icons/wipeout.svg
@@ -0,0 +1,11 @@
+
diff --git a/src/modules/annotate/aligned_dim.rs b/src/modules/annotate/aligned_dim.rs
index b3903bbf2..df2a066c8 100644
--- a/src/modules/annotate/aligned_dim.rs
+++ b/src/modules/annotate/aligned_dim.rs
@@ -6,8 +6,20 @@ use acadrust::EntityType;
use glam::Vec3;
use crate::command::{CadCommand, CmdResult};
+use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::wire_model::WireModel;
+pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/dim_aligned.svg"));
+
+pub fn tool() -> ToolDef {
+ ToolDef {
+ id: "DIMALIGNED",
+ label: "Aligned",
+ icon: ICON,
+ event: ModuleEvent::Command("DIMALIGNED".to_string()),
+ }
+}
+
enum Step {
First,
Second(Vec3),
diff --git a/src/modules/annotate/angular_dim.rs b/src/modules/annotate/angular_dim.rs
index b25c9a255..b3b2c2dc9 100644
--- a/src/modules/annotate/angular_dim.rs
+++ b/src/modules/annotate/angular_dim.rs
@@ -7,7 +7,7 @@ use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::wire_model::WireModel;
use glam::Vec3;
-pub const ICON: IconKind = IconKind::Glyph("∠");
+pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/dim_angular.svg"));
pub fn tool() -> ToolDef {
ToolDef {
diff --git a/src/modules/annotate/ddedit.rs b/src/modules/annotate/ddedit.rs
index 37567105e..fb03e6eca 100644
--- a/src/modules/annotate/ddedit.rs
+++ b/src/modules/annotate/ddedit.rs
@@ -8,6 +8,18 @@ use acadrust::{EntityType, Handle};
use glam::Vec3;
use crate::command::{CadCommand, CmdResult};
+use crate::modules::{IconKind, ModuleEvent, ToolDef};
+
+pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/ddedit.svg"));
+
+pub fn tool() -> ToolDef {
+ ToolDef {
+ id: "DDEDIT",
+ label: "Edit Text",
+ icon: ICON,
+ event: ModuleEvent::Command("DDEDIT".to_string()),
+ }
+}
enum DdeditStep {
PickEntity,
diff --git a/src/modules/annotate/diameter_dim.rs b/src/modules/annotate/diameter_dim.rs
index bf0215512..c365b2106 100644
--- a/src/modules/annotate/diameter_dim.rs
+++ b/src/modules/annotate/diameter_dim.rs
@@ -6,8 +6,20 @@ use acadrust::EntityType;
use glam::Vec3;
use crate::command::{CadCommand, CmdResult};
+use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::wire_model::WireModel;
+pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/dim_diameter.svg"));
+
+pub fn tool() -> ToolDef {
+ ToolDef {
+ id: "DIMDIAMETER",
+ label: "Diameter",
+ icon: ICON,
+ event: ModuleEvent::Command("DIMDIAMETER".to_string()),
+ }
+}
+
enum Step {
CenterPoint,
ArcPoint(Vec3),
diff --git a/src/modules/annotate/dim_baseline.rs b/src/modules/annotate/dim_baseline.rs
index a715062e1..488b8dd39 100644
--- a/src/modules/annotate/dim_baseline.rs
+++ b/src/modules/annotate/dim_baseline.rs
@@ -12,8 +12,20 @@ use acadrust::EntityType;
use glam::Vec3;
use crate::command::{CadCommand, CmdResult};
+use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::wire_model::WireModel;
+pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/dim_baseline.svg"));
+
+pub fn tool() -> ToolDef {
+ ToolDef {
+ id: "DIMBASELINE",
+ label: "Baseline",
+ icon: ICON,
+ event: ModuleEvent::Command("DIMBASELINE".to_string()),
+ }
+}
+
/// Default stacking increment (world units) between successive baseline dimensions.
const DIMDLI: f32 = 1.5;
diff --git a/src/modules/annotate/dim_continue.rs b/src/modules/annotate/dim_continue.rs
index 8f7dd6e7c..391d502a6 100644
--- a/src/modules/annotate/dim_continue.rs
+++ b/src/modules/annotate/dim_continue.rs
@@ -12,8 +12,20 @@ use acadrust::EntityType;
use glam::Vec3;
use crate::command::{CadCommand, CmdResult};
+use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::wire_model::WireModel;
+pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/dim_continue.svg"));
+
+pub fn tool() -> ToolDef {
+ ToolDef {
+ id: "DIMCONTINUE",
+ label: "Continue",
+ icon: ICON,
+ event: ModuleEvent::Command("DIMCONTINUE".to_string()),
+ }
+}
+
pub struct DimContinueCommand {
/// Fixed first-extension-line origin for the current step (moves each iteration).
chain_p1: Vec3,
diff --git a/src/modules/annotate/leader_cmd.rs b/src/modules/annotate/leader_cmd.rs
index abfcc85b6..0e945f928 100644
--- a/src/modules/annotate/leader_cmd.rs
+++ b/src/modules/annotate/leader_cmd.rs
@@ -15,7 +15,7 @@ use crate::command::{CadCommand, CmdResult};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::wire_model::WireModel;
-pub const ICON: IconKind = IconKind::Glyph("↗");
+pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/leader.svg"));
pub fn tool() -> ToolDef {
ToolDef {
diff --git a/src/modules/annotate/linear_dim.rs b/src/modules/annotate/linear_dim.rs
index 02b33e5cf..3800aba36 100644
--- a/src/modules/annotate/linear_dim.rs
+++ b/src/modules/annotate/linear_dim.rs
@@ -7,7 +7,7 @@ use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::wire_model::WireModel;
use glam::Vec3;
-pub const ICON: IconKind = IconKind::Glyph("⟷");
+pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/dim_linear.svg"));
pub fn tool() -> ToolDef {
ToolDef {
diff --git a/src/modules/annotate/mleader_cmd.rs b/src/modules/annotate/mleader_cmd.rs
index d3c5a413e..c9141dd42 100644
--- a/src/modules/annotate/mleader_cmd.rs
+++ b/src/modules/annotate/mleader_cmd.rs
@@ -14,7 +14,7 @@ use crate::command::{CadCommand, CmdResult};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::wire_model::WireModel;
-pub const ICON: IconKind = IconKind::Glyph("↙");
+pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/mleader.svg"));
pub fn tool() -> ToolDef {
ToolDef {
diff --git a/src/modules/annotate/mod.rs b/src/modules/annotate/mod.rs
index a24c87744..73c08cb10 100644
--- a/src/modules/annotate/mod.rs
+++ b/src/modules/annotate/mod.rs
@@ -1,4 +1,4 @@
-// Annotate module — dimension and text annotation tools.
+// Annotate module — dimension, text, leader, table, and markup tools.
pub mod aligned_dim;
pub mod angular_dim;
@@ -29,54 +29,110 @@ impl CadModule for AnnotateModule {
}
fn ribbon_groups(&self) -> Vec {
+ use crate::modules::home::draw::{wipeout, revcloud};
+
vec![
+ // ── Text ─────────────────────────────────────────────────────
RibbonGroup {
title: "Text",
tools: vec![
RibbonItem::LargeDropdown {
id: "ANNOTATE_TEXT",
label: "Text",
- icon: text::ICON,
+ icon: mtext::ICON,
items: vec![
- (text::tool().id, text::tool().label, text::tool().icon),
(mtext::tool().id, mtext::tool().label, mtext::tool().icon),
+ (text::tool().id, text::tool().label, text::tool().icon),
+ (ddedit::tool().id, ddedit::tool().label, ddedit::tool().icon),
],
- default: "TEXT",
+ default: "MTEXT",
},
],
},
+ // ── Dimensions ───────────────────────────────────────────────
RibbonGroup {
title: "Dimensions",
tools: vec![
RibbonItem::LargeDropdown {
id: "ANNOTATE_DIM",
- label: "Dimensions",
+ label: "Dimension",
icon: linear_dim::ICON,
items: vec![
- (linear_dim::tool().id, linear_dim::tool().label, linear_dim::tool().icon),
- (radius_dim::tool().id, radius_dim::tool().label, radius_dim::tool().icon),
+ (linear_dim::tool().id, linear_dim::tool().label, linear_dim::tool().icon),
+ (aligned_dim::tool().id, aligned_dim::tool().label, aligned_dim::tool().icon),
(angular_dim::tool().id, angular_dim::tool().label, angular_dim::tool().icon),
+ (radius_dim::tool().id, radius_dim::tool().label, radius_dim::tool().icon),
+ (diameter_dim::tool().id, diameter_dim::tool().label, diameter_dim::tool().icon),
(ordinate_dim::tool().id, ordinate_dim::tool().label, ordinate_dim::tool().icon),
],
default: "DIMLINEAR",
},
+ RibbonItem::Tool(dim_continue::tool()),
+ RibbonItem::Tool(dim_baseline::tool()),
+ RibbonItem::Tool(tolerance_cmd::tool()),
],
},
+ // ── Leaders ──────────────────────────────────────────────────
RibbonGroup {
title: "Leaders",
tools: vec![
RibbonItem::LargeDropdown {
id: "ANNOTATE_LEADER",
- label: "Leader",
- icon: leader_cmd::ICON,
+ label: "Multileader",
+ icon: mleader_cmd::ICON,
items: vec![
(mleader_cmd::tool().id, mleader_cmd::tool().label, mleader_cmd::tool().icon),
- (leader_cmd::tool().id, leader_cmd::tool().label, leader_cmd::tool().icon),
+ (leader_cmd::tool().id, leader_cmd::tool().label, leader_cmd::tool().icon),
],
default: "MLEADER",
},
],
},
+ // ── Tables ───────────────────────────────────────────────────
+ RibbonGroup {
+ title: "Tables",
+ tools: vec![
+ RibbonItem::LargeTool(table_cmd::tool()),
+ ],
+ },
+ // ── Markup ───────────────────────────────────────────────────
+ RibbonGroup {
+ title: "Markup",
+ tools: vec![
+ RibbonItem::Tool(wipeout::tool()),
+ RibbonItem::Tool(revcloud::tool()),
+ ],
+ },
+ // ── Annotation Scaling ───────────────────────────────────────
+ RibbonGroup {
+ title: "Annotation Scaling",
+ tools: vec![
+ RibbonItem::Tool(crate::modules::ToolDef {
+ id: "ANNOSCALE",
+ label: "Scale List",
+ icon: crate::modules::IconKind::Glyph("⬡"),
+ event: crate::modules::ModuleEvent::Command("ANNOSCALE".to_string()),
+ }),
+ RibbonItem::Tool(crate::modules::ToolDef {
+ id: "OBJECTSCALE",
+ label: "Add Scale",
+ icon: crate::modules::IconKind::Glyph("⊕"),
+ event: crate::modules::ModuleEvent::Command("OBJECTSCALE".to_string()),
+ }),
+ RibbonItem::Tool(crate::modules::ToolDef {
+ id: "SCALELISTEDIT",
+ label: "Scale Edit",
+ icon: crate::modules::IconKind::Glyph("≡"),
+ event: crate::modules::ModuleEvent::Command("SCALELISTEDIT".to_string()),
+ }),
+ RibbonItem::Tool(crate::modules::ToolDef {
+ id: "SYNCPVIEWPORTS",
+ label: "Sync Scales",
+ icon: crate::modules::IconKind::Glyph("⇄"),
+ event: crate::modules::ModuleEvent::Command("SYNCPVIEWPORTS".to_string()),
+ }),
+ ],
+ },
]
}
}
diff --git a/src/modules/annotate/ordinate_dim.rs b/src/modules/annotate/ordinate_dim.rs
index 88928cf22..e7c0ce58a 100644
--- a/src/modules/annotate/ordinate_dim.rs
+++ b/src/modules/annotate/ordinate_dim.rs
@@ -21,7 +21,7 @@ pub fn tool() -> ToolDef {
ToolDef {
id: "DIMORDINATE",
label: "Ordinate",
- icon: IconKind::Glyph("Φ"),
+ icon: IconKind::Svg(include_bytes!("../../../assets/icons/dim_ordinate.svg")),
event: ModuleEvent::Command("DIMORDINATE".to_string()),
}
}
diff --git a/src/modules/annotate/radius_dim.rs b/src/modules/annotate/radius_dim.rs
index 860c60d0d..109827530 100644
--- a/src/modules/annotate/radius_dim.rs
+++ b/src/modules/annotate/radius_dim.rs
@@ -7,7 +7,7 @@ use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::wire_model::WireModel;
use glam::Vec3;
-pub const ICON: IconKind = IconKind::Glyph("⌀");
+pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/dim_radius.svg"));
pub fn tool() -> ToolDef {
ToolDef {
diff --git a/src/modules/annotate/table_cmd.rs b/src/modules/annotate/table_cmd.rs
index 891bc3e86..ecb52fec3 100644
--- a/src/modules/annotate/table_cmd.rs
+++ b/src/modules/annotate/table_cmd.rs
@@ -13,8 +13,20 @@ use acadrust::EntityType;
use glam::Vec3;
use crate::command::{CadCommand, CmdResult};
+use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::wire_model::WireModel;
+pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/table.svg"));
+
+pub fn tool() -> ToolDef {
+ ToolDef {
+ id: "TABLE",
+ label: "Table",
+ icon: ICON,
+ event: ModuleEvent::Command("TABLE".to_string()),
+ }
+}
+
const DEFAULT_COLS: usize = 3;
const DEFAULT_ROWS: usize = 4;
const COL_WIDTH: f64 = 2.0;
diff --git a/src/modules/annotate/tolerance_cmd.rs b/src/modules/annotate/tolerance_cmd.rs
index 55f3519ce..8e02e8a63 100644
--- a/src/modules/annotate/tolerance_cmd.rs
+++ b/src/modules/annotate/tolerance_cmd.rs
@@ -10,8 +10,20 @@ use acadrust::EntityType;
use glam::Vec3;
use crate::command::{CadCommand, CmdResult};
+use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::wire_model::WireModel;
+pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/tolerance.svg"));
+
+pub fn tool() -> ToolDef {
+ ToolDef {
+ id: "TOLERANCE",
+ label: "Tolerance",
+ icon: ICON,
+ event: ModuleEvent::Command("TOLERANCE".to_string()),
+ }
+}
+
enum Step {
Text,
Insertion { text: String },
diff --git a/src/modules/home/draw/revcloud.rs b/src/modules/home/draw/revcloud.rs
index aca3e22cb..f4b47a1d7 100644
--- a/src/modules/home/draw/revcloud.rs
+++ b/src/modules/home/draw/revcloud.rs
@@ -10,8 +10,20 @@ use acadrust::{EntityType, entities::LwVertex};
use glam::Vec3;
use crate::command::{CadCommand, CmdResult};
+use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::wire_model::WireModel;
+pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../../assets/icons/revcloud.svg"));
+
+pub fn tool() -> ToolDef {
+ ToolDef {
+ id: "REVCLOUD",
+ label: "Rev Cloud",
+ icon: ICON,
+ event: ModuleEvent::Command("REVCLOUD".to_string()),
+ }
+}
+
const DEFAULT_ARC_LEN: f64 = 1.0; // default arc bump length
pub struct RevCloudCommand {
diff --git a/src/modules/home/draw/wipeout.rs b/src/modules/home/draw/wipeout.rs
index 93c17758e..d6afce669 100644
--- a/src/modules/home/draw/wipeout.rs
+++ b/src/modules/home/draw/wipeout.rs
@@ -10,8 +10,20 @@ use acadrust::EntityType;
use glam::Vec3;
use crate::command::{CadCommand, CmdResult};
+use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::wire_model::WireModel;
+pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../../assets/icons/wipeout.svg"));
+
+pub fn tool() -> ToolDef {
+ ToolDef {
+ id: "WIPEOUT",
+ label: "Wipeout",
+ icon: ICON,
+ event: ModuleEvent::Command("WIPEOUT".to_string()),
+ }
+}
+
pub struct WipeoutCommand {
mode: WipeoutMode,
first: Option,