diff --git a/src/app/mod.rs b/src/app/mod.rs index 6e9dbae47..164c54d4a 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1071,6 +1071,9 @@ pub enum Message { // Field edit messages: DsEdit(DsField, String), DsToggle(DsField), + /// Cycle a block/linetype Handle field on the selected dim style to the + /// next available block-record / linetype. + DsCycleHandle(&'static str), // ── Raster Image ────────────────────────────────────────────────────── /// Open file-picker dialog for IMAGE command (async). ImagePick, diff --git a/src/app/update.rs b/src/app/update.rs index 4adbccb26..e2e15bb0d 100644 --- a/src/app/update.rs +++ b/src/app/update.rs @@ -6534,6 +6534,53 @@ impl OpenCADStudio { self.apply_ds_toggle(field); Task::none() } + Message::DsCycleHandle(field) => { + let i = self.active_tab; + let name = self.dimstyle_selected.clone(); + let is_lt = matches!( + field, + "dimltex_handle" | "dimltex1_handle" | "dimltex2_handle" + ); + let doc = &self.tabs[i].scene.document; + let mut candidates: Vec = + vec![acadrust::types::Handle::NULL]; + if is_lt { + candidates.extend(doc.line_types.iter().map(|lt| lt.handle)); + } else { + candidates.extend(doc.block_records.iter().map(|b| b.handle)); + } + let Some(ds) = doc.dim_styles.get(&name) else { + return Task::none(); + }; + let cur = match field { + "dimblk" => ds.dimblk, + "dimblk1" => ds.dimblk1, + "dimblk2" => ds.dimblk2, + "dimldrblk" => ds.dimldrblk, + "dimltex_handle" => ds.dimltex_handle, + "dimltex1_handle" => ds.dimltex1_handle, + "dimltex2_handle" => ds.dimltex2_handle, + _ => return Task::none(), + }; + let idx = candidates.iter().position(|h| *h == cur).unwrap_or(0); + let next = candidates[(idx + 1) % candidates.len()]; + self.push_undo_snapshot(i, "DIMSTYLE EDIT"); + if let Some(ds) = self.tabs[i].scene.document.dim_styles.get_mut(&name) { + match field { + "dimblk" => ds.dimblk = next, + "dimblk1" => ds.dimblk1 = next, + "dimblk2" => ds.dimblk2 = next, + "dimldrblk" => ds.dimldrblk = next, + "dimltex_handle" => ds.dimltex_handle = next, + "dimltex1_handle" => ds.dimltex1_handle = next, + "dimltex2_handle" => ds.dimltex2_handle = next, + _ => {} + } + } + self.tabs[i].dirty = true; + self.tabs[i].scene.bump_geometry(); + Task::none() + } } } } diff --git a/src/app/view.rs b/src/app/view.rs index 087181e24..eb358898c 100644 --- a/src/app/view.rs +++ b/src/app/view.rs @@ -234,6 +234,50 @@ impl OpenCADStudio { .iter() .map(|s| s.name.clone()) .collect(); + let doc = &tab.scene.document; + let blk_name = |h: acadrust::types::Handle| -> String { + if h.is_null() { + "Default".to_string() + } else { + doc.block_records + .iter() + .find(|b| b.handle == h) + .map(|b| b.name.trim_start_matches('_').to_string()) + .unwrap_or_else(|| "?".to_string()) + } + }; + let lt_name = |h: acadrust::types::Handle| -> String { + if h.is_null() { + "ByBlock".to_string() + } else { + doc.line_types + .iter() + .find(|lt| lt.handle == h) + .map(|lt| lt.name.clone()) + .unwrap_or_else(|| "?".to_string()) + } + }; + let ds_sel = doc.dim_styles.get(&self.dimstyle_selected); + let ( + dimblk_name, + dimblk1_name, + dimblk2_name, + dimldrblk_name, + dimltex_name, + dimltex1_name, + dimltex2_name, + ) = match ds_sel { + Some(d) => ( + blk_name(d.dimblk), + blk_name(d.dimblk1), + blk_name(d.dimblk2), + blk_name(d.dimldrblk), + lt_name(d.dimltex_handle), + lt_name(d.dimltex1_handle), + lt_name(d.dimltex2_handle), + ), + None => Default::default(), + }; return crate::ui::dimstyle::view_window( styles, &self.dimstyle_selected, @@ -308,6 +352,13 @@ impl OpenCADStudio { dimalttz: &self.ds_dimalttz, dimtolj: &self.ds_dimtolj, dimtzin: &self.ds_dimtzin, + dimblk_name, + dimblk1_name, + dimblk2_name, + dimldrblk_name, + dimltex_name, + dimltex1_name, + dimltex2_name, }, ); } diff --git a/src/ui/dimstyle.rs b/src/ui/dimstyle.rs index e915de9da..2a8c4218f 100644 --- a/src/ui/dimstyle.rs +++ b/src/ui/dimstyle.rs @@ -130,6 +130,14 @@ pub struct DimStyleValues<'a> { pub dimalttz: &'a str, pub dimtolj: &'a str, pub dimtzin: &'a str, + // Resolved display names for the block/linetype Handle fields. + pub dimblk_name: String, + pub dimblk1_name: String, + pub dimblk2_name: String, + pub dimldrblk_name: String, + pub dimltex_name: String, + pub dimltex1_name: String, + pub dimltex2_name: String, } fn btn_s(accent: bool) -> impl Fn(&Theme, button::Status) -> button::Style { @@ -376,6 +384,22 @@ pub fn view_window<'a>( .into() }; + // Block / linetype Handle cycler: shows the resolved name and a button that + // advances to the next available block-record (arrowheads) or linetype. + let hrow = move |label: &'static str, name: String, field: &'static str| -> Element<'a, Message> { + row![ + lbl(label), + text(name).size(11).width(110), + button(text("Cycle").size(10)) + .on_press(Message::DsCycleHandle(field)) + .style(btn_s(false)) + .padding([2, 8]), + ] + .spacing(8) + .align_y(iced::Center) + .into() + }; + let tab_content: Element<'_, Message> = match tab { 0 => column![ text("Dimension Line").size(11).color(ACCENT), @@ -420,11 +444,18 @@ pub fn view_window<'a>( row![lbl("Ext line weight (DIMLWE)"), mk_field(DsField::Dimlwe, vals.dimlwe)].spacing(8).align_y(iced::Center), chk("Fixed-length ext lines (DIMFXLON)", vals.dimfxlon, DsField::Dimfxlon), row![lbl("Fixed length (DIMFXL)"), mk_field(DsField::Dimfxl, vals.dimfxl)].spacing(8).align_y(iced::Center), + hrow("Dim line linetype (DIMLTYPE)", vals.dimltex_name.clone(), "dimltex_handle"), + hrow("Ext line 1 linetype (DIMLTEX1)", vals.dimltex1_name.clone(), "dimltex1_handle"), + hrow("Ext line 2 linetype (DIMLTEX2)", vals.dimltex2_name.clone(), "dimltex2_handle"), ] .spacing(7) .into(), 1 => column![ text("Arrows").size(11).color(ACCENT), + hrow("Arrowhead (DIMBLK)", vals.dimblk_name.clone(), "dimblk"), + hrow("1st arrowhead (DIMBLK1)", vals.dimblk1_name.clone(), "dimblk1"), + hrow("2nd arrowhead (DIMBLK2)", vals.dimblk2_name.clone(), "dimblk2"), + hrow("Leader arrowhead (DIMLDRBLK)", vals.dimldrblk_name.clone(), "dimldrblk"), row![ lbl("Arrow size (DIMASZ)"), mk_field(DsField::Dimasz, vals.dimasz)