diff --git a/assets/icons/cascade.svg b/assets/icons/cascade.svg new file mode 100644 index 000000000..ce7f11b19 --- /dev/null +++ b/assets/icons/cascade.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/icons/data_extract.svg b/assets/icons/data_extract.svg new file mode 100644 index 000000000..ddcb26568 --- /dev/null +++ b/assets/icons/data_extract.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/icons/data_link.svg b/assets/icons/data_link.svg new file mode 100644 index 000000000..ff265870b --- /dev/null +++ b/assets/icons/data_link.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/icons/file_tabs.svg b/assets/icons/file_tabs.svg new file mode 100644 index 000000000..e33a0acd1 --- /dev/null +++ b/assets/icons/file_tabs.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/icons/layout_tabs.svg b/assets/icons/layout_tabs.svg new file mode 100644 index 000000000..4758ae242 --- /dev/null +++ b/assets/icons/layout_tabs.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/icons/navbar.svg b/assets/icons/navbar.svg new file mode 100644 index 000000000..75c94d7ae --- /dev/null +++ b/assets/icons/navbar.svg @@ -0,0 +1,10 @@ + + + + + + + + + N + diff --git a/assets/icons/properties.svg b/assets/icons/properties.svg new file mode 100644 index 000000000..76cc8b652 --- /dev/null +++ b/assets/icons/properties.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/icons/sheetset.svg b/assets/icons/sheetset.svg new file mode 100644 index 000000000..41ec42d8d --- /dev/null +++ b/assets/icons/sheetset.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/icons/tile_horiz.svg b/assets/icons/tile_horiz.svg new file mode 100644 index 000000000..0b9c0308d --- /dev/null +++ b/assets/icons/tile_horiz.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/icons/tile_vert.svg b/assets/icons/tile_vert.svg new file mode 100644 index 000000000..3c14ed76b --- /dev/null +++ b/assets/icons/tile_vert.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/icons/tool_palettes.svg b/assets/icons/tool_palettes.svg new file mode 100644 index 000000000..474f76b64 --- /dev/null +++ b/assets/icons/tool_palettes.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/icons/ucs_icon.svg b/assets/icons/ucs_icon.svg new file mode 100644 index 000000000..ff12a0b39 --- /dev/null +++ b/assets/icons/ucs_icon.svg @@ -0,0 +1,10 @@ + + + + + X + + + + Y + diff --git a/assets/icons/viewcube.svg b/assets/icons/viewcube.svg new file mode 100644 index 000000000..071fcf9f7 --- /dev/null +++ b/assets/icons/viewcube.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/icons/vports_config.svg b/assets/icons/vports_config.svg new file mode 100644 index 000000000..ae1132b36 --- /dev/null +++ b/assets/icons/vports_config.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/icons/vports_join.svg b/assets/icons/vports_join.svg new file mode 100644 index 000000000..208e25e03 --- /dev/null +++ b/assets/icons/vports_join.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/icons/vports_named.svg b/assets/icons/vports_named.svg new file mode 100644 index 000000000..0609c79cc --- /dev/null +++ b/assets/icons/vports_named.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/icons/vports_restore.svg b/assets/icons/vports_restore.svg new file mode 100644 index 000000000..cbf2baabf --- /dev/null +++ b/assets/icons/vports_restore.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/build.rs b/build.rs index f6bd37116..fbe4cc33a 100644 --- a/build.rs +++ b/build.rs @@ -22,7 +22,7 @@ use std::fs; use std::path::Path; // Display order for known modules; unknown modules follow alphabetically. -const PRIORITY: &[&str] = &["home", "annotate", "insert", "view", "manage"]; +const PRIORITY: &[&str] = &["home", "insert", "annotate", "view", "manage"]; fn main() { let mods_dir = Path::new("src/modules"); diff --git a/src/modules/annotate/data_extract.rs b/src/modules/annotate/data_extract.rs new file mode 100644 index 000000000..c6fc5d183 --- /dev/null +++ b/src/modules/annotate/data_extract.rs @@ -0,0 +1,14 @@ +// DATAEXTRACTION command — launches the Data Extraction wizard. + +use crate::modules::{IconKind, ModuleEvent, ToolDef}; + +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/data_extract.svg")); + +pub fn tool() -> ToolDef { + ToolDef { + id: "DATAEXTRACTION", + label: "Extract\nData", + icon: ICON, + event: ModuleEvent::Command("DATAEXTRACTION".to_string()), + } +} diff --git a/src/modules/annotate/data_link.rs b/src/modules/annotate/data_link.rs new file mode 100644 index 000000000..a2e20e5b6 --- /dev/null +++ b/src/modules/annotate/data_link.rs @@ -0,0 +1,14 @@ +// DATALINK command — manages data links to external spreadsheets. + +use crate::modules::{IconKind, ModuleEvent, ToolDef}; + +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/data_link.svg")); + +pub fn tool() -> ToolDef { + ToolDef { + id: "DATALINK", + label: "Link\nData", + icon: ICON, + event: ModuleEvent::Command("DATALINK".to_string()), + } +} diff --git a/src/modules/annotate/mod.rs b/src/modules/annotate/mod.rs index 6f184b00e..82f413032 100644 --- a/src/modules/annotate/mod.rs +++ b/src/modules/annotate/mod.rs @@ -1,6 +1,8 @@ // Annotate module — dimension, text, leader, table, and markup tools. pub mod aligned_dim; +pub mod data_extract; +pub mod data_link; pub mod angular_dim; pub mod ddedit; pub mod diameter_dim; @@ -152,7 +154,12 @@ impl CadModule for AnnotateModule { style_key: StyleKey::TableStyle, combo_id: "TABLE_STYLE_COMBO", manager_cmd: Some("TABLESTYLE"), - rows: vec![], + rows: vec![ + vec![ + data_extract::tool(), + data_link::tool(), + ], + ], }, ], }, diff --git a/src/modules/registry.rs b/src/modules/registry.rs index f188f19ae..cd74d9a09 100644 --- a/src/modules/registry.rs +++ b/src/modules/registry.rs @@ -8,8 +8,8 @@ use crate::modules::CadModule; pub fn all_modules() -> Vec> { vec![ Box::new(super::home::HomeModule), - Box::new(super::annotate::AnnotateModule), Box::new(super::insert::InsertModule), + Box::new(super::annotate::AnnotateModule), Box::new(super::view::ViewModule), Box::new(super::manage::ManageModule), Box::new(super::layout::LayoutModule), diff --git a/src/modules/view/cascade.rs b/src/modules/view/cascade.rs new file mode 100644 index 000000000..edf5553c7 --- /dev/null +++ b/src/modules/view/cascade.rs @@ -0,0 +1,5 @@ +use crate::modules::{IconKind, ModuleEvent, ToolDef}; +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/cascade.svg")); +pub fn tool() -> ToolDef { + ToolDef { id: "CASCADE", label: "Cascade", icon: ICON, event: ModuleEvent::Command("CASCADE".to_string()) } +} diff --git a/src/modules/view/file_tabs.rs b/src/modules/view/file_tabs.rs new file mode 100644 index 000000000..b2d55d61f --- /dev/null +++ b/src/modules/view/file_tabs.rs @@ -0,0 +1,5 @@ +use crate::modules::{IconKind, ModuleEvent, ToolDef}; +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/file_tabs.svg")); +pub fn tool() -> ToolDef { + ToolDef { id: "FILETAB", label: "File\nTabs", icon: ICON, event: ModuleEvent::Command("FILETAB".to_string()) } +} diff --git a/src/modules/view/layout_tabs.rs b/src/modules/view/layout_tabs.rs new file mode 100644 index 000000000..0ce564ef5 --- /dev/null +++ b/src/modules/view/layout_tabs.rs @@ -0,0 +1,5 @@ +use crate::modules::{IconKind, ModuleEvent, ToolDef}; +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/layout_tabs.svg")); +pub fn tool() -> ToolDef { + ToolDef { id: "LAYOUTTAB", label: "Layout\nTabs", icon: ICON, event: ModuleEvent::Command("LAYOUTTAB".to_string()) } +} diff --git a/src/modules/view/mod.rs b/src/modules/view/mod.rs index 2b6b5c637..4bc7c762a 100644 --- a/src/modules/view/mod.rs +++ b/src/modules/view/mod.rs @@ -1,15 +1,30 @@ -// View module — navigation, visual styles, and viewport presets. +// View module — viewport tools, navigation, visual styles, palettes, interface. +mod cascade; +mod file_tabs; mod hidden; +mod layout_tabs; +mod navbar; mod orbit; mod ortho; mod pan; mod persp; +mod properties_palette; +mod sheetset; mod solid; +mod tile_horiz; +mod tile_vert; +mod tool_palettes; +mod ucs_icon; +mod viewcube; mod view_front; mod view_iso; mod view_right; mod view_top; +mod vports_config; +mod vports_join; +mod vports_named; +mod vports_restore; mod wireframe; mod xray; mod zoom_ext; @@ -18,7 +33,7 @@ mod zoom_out; pub mod plot_window; pub mod zoom_window; -use crate::modules::{CadModule, RibbonGroup}; +use crate::modules::{CadModule, RibbonGroup, RibbonItem}; pub struct ViewModule; @@ -32,40 +47,94 @@ impl CadModule for ViewModule { fn ribbon_groups(&self) -> Vec { vec![ + // ── Viewport Tools ─────────────────────────────────────────────── + RibbonGroup { + title: "Viewport Tools", + tools: vec![ + RibbonItem::LargeTool(ucs_icon::tool()), + RibbonItem::LargeTool(viewcube::tool()), + RibbonItem::LargeTool(navbar::tool()), + ], + }, + // ── Navigate ───────────────────────────────────────────────────── RibbonGroup { title: "Navigate", tools: vec![ - zoom_ext::tool().into(), - zoom_in::tool().into(), - zoom_out::tool().into(), - pan::tool().into(), - orbit::tool().into(), + RibbonItem::LargeTool(zoom_ext::tool()), + RibbonItem::Tool(zoom_in::tool()), + RibbonItem::Tool(zoom_out::tool()), + RibbonItem::Tool(pan::tool()), + RibbonItem::Tool(orbit::tool()), ], }, + // ── Model Viewports ─────────────────────────────────────────────── + RibbonGroup { + title: "Model Viewports", + tools: vec![ + RibbonItem::LargeTool(vports_config::tool()), + RibbonItem::Tool(vports_named::tool()), + RibbonItem::Tool(vports_join::tool()), + RibbonItem::Tool(vports_restore::tool()), + ], + }, + // ── Visual Style ────────────────────────────────────────────────── RibbonGroup { // WIREFRAME and SOLID ids are special-cased in ribbon.rs // for toggle-state highlighting based on Ribbon::wireframe. title: "Visual Style", tools: vec![ - wireframe::tool().into(), - solid::tool().into(), - hidden::tool().into(), - xray::tool().into(), + RibbonItem::LargeDropdown { + id: "VISUAL_STYLE", + label: "Visual\nStyle", + icon: wireframe::tool().icon, + items: vec![ + ("WIREFRAME", "Wireframe", wireframe::tool().icon), + ("SOLID", "Shaded", solid::tool().icon), + ("HIDDEN", "Hidden", hidden::tool().icon), + ("XRAY", "X-Ray", xray::tool().icon), + ], + default: "WIREFRAME", + }, ], }, + // ── Projection ──────────────────────────────────────────────────── RibbonGroup { // ORTHO and PERSP ids are special-cased in ribbon.rs // for toggle-state highlighting based on Camera::projection. title: "Projection", - tools: vec![ortho::tool().into(), persp::tool().into()], + tools: vec![ + RibbonItem::LargeTool(ortho::tool()), + RibbonItem::LargeTool(persp::tool()), + ], }, + // ── Preset Views ────────────────────────────────────────────────── RibbonGroup { title: "Preset", tools: vec![ - view_top::tool().into(), - view_front::tool().into(), - view_right::tool().into(), - view_iso::tool().into(), + RibbonItem::Tool(view_top::tool()), + RibbonItem::Tool(view_front::tool()), + RibbonItem::Tool(view_right::tool()), + RibbonItem::Tool(view_iso::tool()), + ], + }, + // ── Palettes ────────────────────────────────────────────────────── + RibbonGroup { + title: "Palettes", + tools: vec![ + RibbonItem::LargeTool(tool_palettes::tool()), + RibbonItem::LargeTool(properties_palette::tool()), + RibbonItem::LargeTool(sheetset::tool()), + ], + }, + // ── Interface ───────────────────────────────────────────────────── + RibbonGroup { + title: "Interface", + tools: vec![ + RibbonItem::LargeTool(file_tabs::tool()), + RibbonItem::LargeTool(layout_tabs::tool()), + RibbonItem::Tool(tile_horiz::tool()), + RibbonItem::Tool(tile_vert::tool()), + RibbonItem::Tool(cascade::tool()), ], }, ] diff --git a/src/modules/view/navbar.rs b/src/modules/view/navbar.rs new file mode 100644 index 000000000..81f6ab5e5 --- /dev/null +++ b/src/modules/view/navbar.rs @@ -0,0 +1,5 @@ +use crate::modules::{IconKind, ModuleEvent, ToolDef}; +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/navbar.svg")); +pub fn tool() -> ToolDef { + ToolDef { id: "NAVBAR", label: "Navigation\nBar", icon: ICON, event: ModuleEvent::Command("NAVBAR".to_string()) } +} diff --git a/src/modules/view/properties_palette.rs b/src/modules/view/properties_palette.rs new file mode 100644 index 000000000..5184dde0a --- /dev/null +++ b/src/modules/view/properties_palette.rs @@ -0,0 +1,5 @@ +use crate::modules::{IconKind, ModuleEvent, ToolDef}; +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/properties.svg")); +pub fn tool() -> ToolDef { + ToolDef { id: "PROPERTIES", label: "Properties", icon: ICON, event: ModuleEvent::Command("PROPERTIES".to_string()) } +} diff --git a/src/modules/view/sheetset.rs b/src/modules/view/sheetset.rs new file mode 100644 index 000000000..12ff86930 --- /dev/null +++ b/src/modules/view/sheetset.rs @@ -0,0 +1,5 @@ +use crate::modules::{IconKind, ModuleEvent, ToolDef}; +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/sheetset.svg")); +pub fn tool() -> ToolDef { + ToolDef { id: "SHEETSET", label: "Sheet Set\nManager", icon: ICON, event: ModuleEvent::Command("SHEETSET".to_string()) } +} diff --git a/src/modules/view/tile_horiz.rs b/src/modules/view/tile_horiz.rs new file mode 100644 index 000000000..6b5c0dc4f --- /dev/null +++ b/src/modules/view/tile_horiz.rs @@ -0,0 +1,5 @@ +use crate::modules::{IconKind, ModuleEvent, ToolDef}; +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/tile_horiz.svg")); +pub fn tool() -> ToolDef { + ToolDef { id: "HORIZONTAL", label: "Tile\nHoriz.", icon: ICON, event: ModuleEvent::Command("HORIZONTAL".to_string()) } +} diff --git a/src/modules/view/tile_vert.rs b/src/modules/view/tile_vert.rs new file mode 100644 index 000000000..b9ff4ee2a --- /dev/null +++ b/src/modules/view/tile_vert.rs @@ -0,0 +1,5 @@ +use crate::modules::{IconKind, ModuleEvent, ToolDef}; +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/tile_vert.svg")); +pub fn tool() -> ToolDef { + ToolDef { id: "VERTICAL", label: "Tile\nVert.", icon: ICON, event: ModuleEvent::Command("VERTICAL".to_string()) } +} diff --git a/src/modules/view/tool_palettes.rs b/src/modules/view/tool_palettes.rs new file mode 100644 index 000000000..ab55e7fd0 --- /dev/null +++ b/src/modules/view/tool_palettes.rs @@ -0,0 +1,5 @@ +use crate::modules::{IconKind, ModuleEvent, ToolDef}; +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/tool_palettes.svg")); +pub fn tool() -> ToolDef { + ToolDef { id: "TOOLPALETTES", label: "Tool\nPalettes", icon: ICON, event: ModuleEvent::Command("TOOLPALETTES".to_string()) } +} diff --git a/src/modules/view/ucs_icon.rs b/src/modules/view/ucs_icon.rs new file mode 100644 index 000000000..35e3273b4 --- /dev/null +++ b/src/modules/view/ucs_icon.rs @@ -0,0 +1,5 @@ +use crate::modules::{IconKind, ModuleEvent, ToolDef}; +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/ucs_icon.svg")); +pub fn tool() -> ToolDef { + ToolDef { id: "UCSICON", label: "UCS\nIcon", icon: ICON, event: ModuleEvent::Command("UCSICON".to_string()) } +} diff --git a/src/modules/view/viewcube.rs b/src/modules/view/viewcube.rs new file mode 100644 index 000000000..0d717c267 --- /dev/null +++ b/src/modules/view/viewcube.rs @@ -0,0 +1,5 @@ +use crate::modules::{IconKind, ModuleEvent, ToolDef}; +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/viewcube.svg")); +pub fn tool() -> ToolDef { + ToolDef { id: "NAVVCUBE", label: "View\nCube", icon: ICON, event: ModuleEvent::Command("NAVVCUBE".to_string()) } +} diff --git a/src/modules/view/vports_config.rs b/src/modules/view/vports_config.rs new file mode 100644 index 000000000..f97c68320 --- /dev/null +++ b/src/modules/view/vports_config.rs @@ -0,0 +1,5 @@ +use crate::modules::{IconKind, ModuleEvent, ToolDef}; +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/vports_config.svg")); +pub fn tool() -> ToolDef { + ToolDef { id: "VPORTS", label: "Viewport\nConfiguration", icon: ICON, event: ModuleEvent::Command("VPORTS".to_string()) } +} diff --git a/src/modules/view/vports_join.rs b/src/modules/view/vports_join.rs new file mode 100644 index 000000000..10ab31858 --- /dev/null +++ b/src/modules/view/vports_join.rs @@ -0,0 +1,5 @@ +use crate::modules::{IconKind, ModuleEvent, ToolDef}; +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/vports_join.svg")); +pub fn tool() -> ToolDef { + ToolDef { id: "VPJOIN", label: "Join", icon: ICON, event: ModuleEvent::Command("VPJOIN".to_string()) } +} diff --git a/src/modules/view/vports_named.rs b/src/modules/view/vports_named.rs new file mode 100644 index 000000000..96852154d --- /dev/null +++ b/src/modules/view/vports_named.rs @@ -0,0 +1,5 @@ +use crate::modules::{IconKind, ModuleEvent, ToolDef}; +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/vports_named.svg")); +pub fn tool() -> ToolDef { + ToolDef { id: "VPORTS_NAMED", label: "Named", icon: ICON, event: ModuleEvent::Command("VPORTS".to_string()) } +} diff --git a/src/modules/view/vports_restore.rs b/src/modules/view/vports_restore.rs new file mode 100644 index 000000000..d52d82cc7 --- /dev/null +++ b/src/modules/view/vports_restore.rs @@ -0,0 +1,5 @@ +use crate::modules::{IconKind, ModuleEvent, ToolDef}; +pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/vports_restore.svg")); +pub fn tool() -> ToolDef { + ToolDef { id: "VPORTS_RESTORE", label: "Restore", icon: ICON, event: ModuleEvent::Command("VPORTS".to_string()) } +}