Feat: add Dimension Style Manager dialog (DIMSTYLE/DDIM)
- Add DimStyleDialogOpen/Close/Apply/Select/Tab/New/SetCurrent/Delete messages and DsEdit/DsToggle with DsField enum for fine-grained edits - Store active dialog state (selected style, current tab, edit buffers) directly on H7CAD for all 28 most-used DimStyle properties - dimstyle_overlay: 5-tab modal panel (Lines, Arrows, Text, Scale/Units, Tolerances) with style list, Apply and Close buttons - DIMSTYLE / DDIM with no sub-command now opens the dialog; DIMSTYLE LIST / NEW / SET sub-commands remain available Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
20629d587a
commit
911e36ba04
4 changed files with 519 additions and 2 deletions
|
|
@ -2090,7 +2090,11 @@ impl H7CAD {
|
|||
let parts: Vec<&str> = raw_rest.split_whitespace().collect();
|
||||
let sub = parts.get(0).map(|s| s.to_uppercase()).unwrap_or_default();
|
||||
match sub.as_str() {
|
||||
"" | "LIST" | "?" => {
|
||||
// No sub-command or "DIALOG" → open the DimStyle Manager dialog
|
||||
"" | "DIALOG" | "UI" => {
|
||||
return Task::done(Message::DimStyleDialogOpen);
|
||||
}
|
||||
"LIST" | "?" => {
|
||||
let styles: Vec<String> = self.tabs[i].scene.document
|
||||
.dim_styles.iter()
|
||||
.map(|s| format!("{}(txt:{:.2} asz:{:.2})", s.name, s.dimtxt, s.dimasz))
|
||||
|
|
|
|||
|
|
@ -85,6 +85,37 @@ pub(super) struct H7CAD {
|
|||
page_setup_rotation: String,
|
||||
/// Plot scale: "Fit" | "1:1" | "1:2" | "1:4" | "1:5" | "1:10" | "1:20" | "1:50" | "1:100" | "2:1".
|
||||
page_setup_scale: String,
|
||||
|
||||
// ── DimStyle Dialog ───────────────────────────────────────────────────
|
||||
dimstyle_open: bool,
|
||||
/// Name of the style currently shown in the dialog.
|
||||
dimstyle_selected: String,
|
||||
/// Active tab: 0=Lines, 1=Arrows, 2=Text, 3=Scale/Units, 4=Tolerances.
|
||||
dimstyle_tab: u8,
|
||||
// Edit buffers (strings while typing):
|
||||
ds_dimdle: String, ds_dimdli: String, ds_dimgap: String,
|
||||
ds_dimexe: String, ds_dimexo: String,
|
||||
ds_dimsd1: bool, ds_dimsd2: bool,
|
||||
ds_dimse1: bool, ds_dimse2: bool,
|
||||
ds_dimasz: String, ds_dimcen: String, ds_dimtsz: String,
|
||||
ds_dimtxt: String, ds_dimtxsty: String, ds_dimtad: String,
|
||||
ds_dimtih: bool, ds_dimtoh: bool,
|
||||
ds_dimscale: String, ds_dimlfac: String,
|
||||
ds_dimlunit: String, ds_dimdec: String, ds_dimpost: String,
|
||||
ds_dimtol: bool, ds_dimlim: bool,
|
||||
ds_dimtp: String, ds_dimtm: String,
|
||||
ds_dimtdec: String, ds_dimtfac: String,
|
||||
}
|
||||
|
||||
/// Identifies a DimStyle field that can be edited in the dialog.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum DsField {
|
||||
Dimdle, Dimdli, Dimgap, Dimexe, Dimexo,
|
||||
Dimsd1, Dimsd2, Dimse1, Dimse2,
|
||||
Dimasz, Dimcen, Dimtsz,
|
||||
Dimtxt, Dimtxsty, Dimtad, Dimtih, Dimtoh,
|
||||
Dimscale, Dimlfac, Dimlunit, Dimdec, Dimpost,
|
||||
Dimtol, Dimlim, Dimtp, Dimtm, Dimtdec, Dimtfac,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
@ -293,6 +324,24 @@ pub enum Message {
|
|||
PlotExport,
|
||||
/// Callback after the user picks (or cancels) the export path.
|
||||
PlotExportPath(Option<std::path::PathBuf>),
|
||||
// ── DimStyle Dialog ───────────────────────────────────────────────────
|
||||
DimStyleDialogOpen,
|
||||
DimStyleDialogClose,
|
||||
/// Apply edits to the selected style.
|
||||
DimStyleDialogApply,
|
||||
/// Select a different style in the dialog list.
|
||||
DimStyleDialogSelect(String),
|
||||
/// Switch the active tab.
|
||||
DimStyleDialogTab(u8),
|
||||
/// Create a new empty style (prompts via command line).
|
||||
DimStyleDialogNew,
|
||||
/// Set the selected style as the document's current dim style.
|
||||
DimStyleDialogSetCurrent,
|
||||
/// Delete the selected style.
|
||||
DimStyleDialogDelete,
|
||||
// Field edit messages:
|
||||
DsEdit(DsField, String),
|
||||
DsToggle(DsField),
|
||||
}
|
||||
|
||||
impl H7CAD {
|
||||
|
|
@ -334,6 +383,26 @@ impl H7CAD {
|
|||
page_setup_offset_y: "0.0".to_string(),
|
||||
page_setup_rotation: "0".to_string(),
|
||||
page_setup_scale: "Fit".to_string(),
|
||||
// DimStyle dialog
|
||||
dimstyle_open: false,
|
||||
dimstyle_selected: "Standard".to_string(),
|
||||
dimstyle_tab: 0,
|
||||
ds_dimdle: "0".to_string(), ds_dimdli: "3.75".to_string(),
|
||||
ds_dimgap: "0.625".to_string(), ds_dimexe: "1.25".to_string(),
|
||||
ds_dimexo: "0.625".to_string(),
|
||||
ds_dimsd1: false, ds_dimsd2: false,
|
||||
ds_dimse1: false, ds_dimse2: false,
|
||||
ds_dimasz: "0.18".to_string(), ds_dimcen: "0.09".to_string(),
|
||||
ds_dimtsz: "0".to_string(),
|
||||
ds_dimtxt: "0.18".to_string(), ds_dimtxsty: "Standard".to_string(),
|
||||
ds_dimtad: "1".to_string(),
|
||||
ds_dimtih: false, ds_dimtoh: false,
|
||||
ds_dimscale: "1".to_string(), ds_dimlfac: "1".to_string(),
|
||||
ds_dimlunit: "2".to_string(), ds_dimdec: "2".to_string(),
|
||||
ds_dimpost: "<>".to_string(),
|
||||
ds_dimtol: false, ds_dimlim: false,
|
||||
ds_dimtp: "0".to_string(), ds_dimtm: "0".to_string(),
|
||||
ds_dimtdec: "2".to_string(), ds_dimtfac: "1".to_string(),
|
||||
};
|
||||
app.sync_ribbon_layers();
|
||||
app
|
||||
|
|
|
|||
|
|
@ -2101,6 +2101,185 @@ impl H7CAD {
|
|||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
// ── DimStyle Dialog ───────────────────────────────────────────────
|
||||
Message::DimStyleDialogOpen => {
|
||||
let i = self.active_tab;
|
||||
// Pick the document's current dim style or "Standard".
|
||||
let cur = self.tabs[i].scene.document.header.current_dimstyle_name.clone();
|
||||
let selected = if self.tabs[i].scene.document.dim_styles.get(&cur).is_some() {
|
||||
cur
|
||||
} else {
|
||||
self.tabs[i].scene.document.dim_styles
|
||||
.iter().next().map(|s| s.name.clone())
|
||||
.unwrap_or_else(|| "Standard".to_string())
|
||||
};
|
||||
self.dimstyle_selected = selected.clone();
|
||||
self.dimstyle_open = true;
|
||||
self.load_dimstyle_bufs(i);
|
||||
Task::none()
|
||||
}
|
||||
Message::DimStyleDialogClose => {
|
||||
self.dimstyle_open = false;
|
||||
Task::none()
|
||||
}
|
||||
Message::DimStyleDialogApply => {
|
||||
let i = self.active_tab;
|
||||
self.apply_dimstyle_bufs(i);
|
||||
Task::none()
|
||||
}
|
||||
Message::DimStyleDialogSelect(name) => {
|
||||
let i = self.active_tab;
|
||||
self.dimstyle_selected = name;
|
||||
self.load_dimstyle_bufs(i);
|
||||
Task::none()
|
||||
}
|
||||
Message::DimStyleDialogTab(tab) => {
|
||||
self.dimstyle_tab = tab;
|
||||
Task::none()
|
||||
}
|
||||
Message::DimStyleDialogNew => {
|
||||
// Delegate to the DIMSTYLE NEW command via command line prompt.
|
||||
self.command_line.push_info("Enter new DimStyle name:");
|
||||
self.dimstyle_open = false;
|
||||
Task::none()
|
||||
}
|
||||
Message::DimStyleDialogSetCurrent => {
|
||||
let i = self.active_tab;
|
||||
self.push_undo_snapshot(i, "DIMSTYLE SETCURRENT");
|
||||
self.tabs[i].scene.document.header.current_dimstyle_name =
|
||||
self.dimstyle_selected.clone();
|
||||
self.tabs[i].dirty = true;
|
||||
self.command_line.push_output(&format!(
|
||||
"Current dim style set to '{}'.", self.dimstyle_selected
|
||||
));
|
||||
Task::none()
|
||||
}
|
||||
Message::DimStyleDialogDelete => {
|
||||
let i = self.active_tab;
|
||||
let name = self.dimstyle_selected.clone();
|
||||
if name == "Standard" {
|
||||
self.command_line.push_error("Cannot delete the Standard dim style.");
|
||||
} else if self.tabs[i].scene.document.dim_styles.remove(&name).is_some() {
|
||||
self.tabs[i].dirty = true;
|
||||
// Select first remaining style.
|
||||
self.dimstyle_selected = self.tabs[i].scene.document.dim_styles
|
||||
.iter().next().map(|s| s.name.clone())
|
||||
.unwrap_or_else(|| "Standard".to_string());
|
||||
self.load_dimstyle_bufs(i);
|
||||
self.command_line.push_output(&format!("DimStyle '{}' deleted.", name));
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::DsEdit(field, val) => {
|
||||
self.apply_ds_edit(field, val);
|
||||
Task::none()
|
||||
}
|
||||
Message::DsToggle(field) => {
|
||||
self.apply_ds_toggle(field);
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── DimStyle dialog helpers ─────────────────────────────────────────────────
|
||||
|
||||
impl H7CAD {
|
||||
/// Populate all edit buffers from the currently selected dim style.
|
||||
fn load_dimstyle_bufs(&mut self, tab: usize) {
|
||||
let doc = &self.tabs[tab].scene.document;
|
||||
let Some(ds) = doc.dim_styles.get(&self.dimstyle_selected) else { return };
|
||||
self.ds_dimdle = format!("{}", ds.dimdle);
|
||||
self.ds_dimdli = format!("{}", ds.dimdli);
|
||||
self.ds_dimgap = format!("{}", ds.dimgap);
|
||||
self.ds_dimexe = format!("{}", ds.dimexe);
|
||||
self.ds_dimexo = format!("{}", ds.dimexo);
|
||||
self.ds_dimsd1 = ds.dimsd1; self.ds_dimsd2 = ds.dimsd2;
|
||||
self.ds_dimse1 = ds.dimse1; self.ds_dimse2 = ds.dimse2;
|
||||
self.ds_dimasz = format!("{}", ds.dimasz);
|
||||
self.ds_dimcen = format!("{}", ds.dimcen);
|
||||
self.ds_dimtsz = format!("{}", ds.dimtsz);
|
||||
self.ds_dimtxt = format!("{}", ds.dimtxt);
|
||||
self.ds_dimtxsty = ds.dimtxsty.clone();
|
||||
self.ds_dimtad = format!("{}", ds.dimtad);
|
||||
self.ds_dimtih = ds.dimtih; self.ds_dimtoh = ds.dimtoh;
|
||||
self.ds_dimscale = format!("{}", ds.dimscale);
|
||||
self.ds_dimlfac = format!("{}", ds.dimlfac);
|
||||
self.ds_dimlunit = format!("{}", ds.dimlunit);
|
||||
self.ds_dimdec = format!("{}", ds.dimdec);
|
||||
self.ds_dimpost = ds.dimpost.clone();
|
||||
self.ds_dimtol = ds.dimtol; self.ds_dimlim = ds.dimlim;
|
||||
self.ds_dimtp = format!("{}", ds.dimtp);
|
||||
self.ds_dimtm = format!("{}", ds.dimtm);
|
||||
self.ds_dimtdec = format!("{}", ds.dimtdec);
|
||||
self.ds_dimtfac = format!("{}", ds.dimtfac);
|
||||
}
|
||||
|
||||
/// Write edit buffers back into the selected dim style document entry.
|
||||
fn apply_dimstyle_bufs(&mut self, tab: usize) {
|
||||
self.push_undo_snapshot(tab, "DIMSTYLE EDIT");
|
||||
let doc = &mut self.tabs[tab].scene.document;
|
||||
let Some(ds) = doc.dim_styles.get_mut(&self.dimstyle_selected) else { return };
|
||||
macro_rules! set_f64 { ($field:ident, $buf:expr) => {
|
||||
if let Ok(v) = $buf.trim().parse::<f64>() { ds.$field = v; }
|
||||
}}
|
||||
macro_rules! set_i16 { ($field:ident, $buf:expr) => {
|
||||
if let Ok(v) = $buf.trim().parse::<i16>() { ds.$field = v; }
|
||||
}}
|
||||
set_f64!(dimdle, self.ds_dimdle); set_f64!(dimdli, self.ds_dimdli);
|
||||
set_f64!(dimgap, self.ds_dimgap); set_f64!(dimexe, self.ds_dimexe);
|
||||
set_f64!(dimexo, self.ds_dimexo); set_f64!(dimasz, self.ds_dimasz);
|
||||
set_f64!(dimcen, self.ds_dimcen); set_f64!(dimtsz, self.ds_dimtsz);
|
||||
set_f64!(dimtxt, self.ds_dimtxt); set_f64!(dimscale, self.ds_dimscale);
|
||||
set_f64!(dimlfac, self.ds_dimlfac); set_f64!(dimtp, self.ds_dimtp);
|
||||
set_f64!(dimtm, self.ds_dimtm); set_f64!(dimtfac, self.ds_dimtfac);
|
||||
set_i16!(dimtad, self.ds_dimtad); set_i16!(dimlunit, self.ds_dimlunit);
|
||||
set_i16!(dimdec, self.ds_dimdec); set_i16!(dimtdec, self.ds_dimtdec);
|
||||
ds.dimsd1 = self.ds_dimsd1; ds.dimsd2 = self.ds_dimsd2;
|
||||
ds.dimse1 = self.ds_dimse1; ds.dimse2 = self.ds_dimse2;
|
||||
ds.dimtih = self.ds_dimtih; ds.dimtoh = self.ds_dimtoh;
|
||||
ds.dimtol = self.ds_dimtol; ds.dimlim = self.ds_dimlim;
|
||||
ds.dimpost = self.ds_dimpost.clone();
|
||||
ds.dimtxsty = self.ds_dimtxsty.clone();
|
||||
self.tabs[tab].dirty = true;
|
||||
self.command_line.push_output(&format!(
|
||||
"DimStyle '{}' updated.", self.dimstyle_selected
|
||||
));
|
||||
}
|
||||
|
||||
/// Update a single string buffer field.
|
||||
fn apply_ds_edit(&mut self, field: super::DsField, val: String) {
|
||||
use super::DsField::*;
|
||||
match field {
|
||||
Dimdle => self.ds_dimdle = val, Dimdli => self.ds_dimdli = val,
|
||||
Dimgap => self.ds_dimgap = val, Dimexe => self.ds_dimexe = val,
|
||||
Dimexo => self.ds_dimexo = val, Dimasz => self.ds_dimasz = val,
|
||||
Dimcen => self.ds_dimcen = val, Dimtsz => self.ds_dimtsz = val,
|
||||
Dimtxt => self.ds_dimtxt = val, Dimtxsty => self.ds_dimtxsty = val,
|
||||
Dimtad => self.ds_dimtad = val, Dimscale => self.ds_dimscale = val,
|
||||
Dimlfac => self.ds_dimlfac = val, Dimlunit => self.ds_dimlunit = val,
|
||||
Dimdec => self.ds_dimdec = val, Dimpost => self.ds_dimpost = val,
|
||||
Dimtp => self.ds_dimtp = val, Dimtm => self.ds_dimtm = val,
|
||||
Dimtdec => self.ds_dimtdec = val, Dimtfac => self.ds_dimtfac = val,
|
||||
// Bool fields — no-op for string edit
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Toggle a boolean buffer field.
|
||||
fn apply_ds_toggle(&mut self, field: super::DsField) {
|
||||
use super::DsField::*;
|
||||
match field {
|
||||
Dimsd1 => self.ds_dimsd1 = !self.ds_dimsd1,
|
||||
Dimsd2 => self.ds_dimsd2 = !self.ds_dimsd2,
|
||||
Dimse1 => self.ds_dimse1 = !self.ds_dimse1,
|
||||
Dimse2 => self.ds_dimse2 = !self.ds_dimse2,
|
||||
Dimtih => self.ds_dimtih = !self.ds_dimtih,
|
||||
Dimtoh => self.ds_dimtoh = !self.ds_dimtoh,
|
||||
Dimtol => self.ds_dimtol = !self.ds_dimtol,
|
||||
Dimlim => self.ds_dimlim = !self.ds_dimlim,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
267
src/app/view.rs
267
src/app/view.rs
|
|
@ -227,7 +227,21 @@ impl H7CAD {
|
|||
iced::widget::Space::new().width(0).height(0).into()
|
||||
};
|
||||
|
||||
stack![main_ui, self.app_menu.view(), snap_layer, dropdown_layer, layout_ctx_layer, page_setup_layer].into()
|
||||
let dimstyle_layer: Element<'_, Message> = if self.dimstyle_open {
|
||||
let tab = &self.tabs[self.active_tab];
|
||||
let styles: Vec<String> = tab.scene.document.dim_styles
|
||||
.iter().map(|s| s.name.clone()).collect();
|
||||
dimstyle_overlay(
|
||||
styles,
|
||||
&self.dimstyle_selected,
|
||||
self.dimstyle_tab,
|
||||
self,
|
||||
)
|
||||
} else {
|
||||
iced::widget::Space::new().width(0).height(0).into()
|
||||
};
|
||||
|
||||
stack![main_ui, self.app_menu.view(), snap_layer, dropdown_layer, layout_ctx_layer, page_setup_layer, dimstyle_layer].into()
|
||||
}
|
||||
|
||||
pub fn subscription(&self) -> Subscription<Message> {
|
||||
|
|
@ -756,3 +770,254 @@ fn page_setup_overlay<'a>(
|
|||
|
||||
stack![catcher, positioned].into()
|
||||
}
|
||||
|
||||
// ── DimStyle Dialog overlay ─────────────────────────────────────────────────
|
||||
|
||||
fn dimstyle_overlay<'a>(
|
||||
styles: Vec<String>,
|
||||
selected: &'a str,
|
||||
tab: u8,
|
||||
app: &'a super::H7CAD,
|
||||
) -> Element<'a, Message> {
|
||||
use super::DsField;
|
||||
use iced::widget::checkbox;
|
||||
use iced::Length::Shrink;
|
||||
|
||||
const PANEL_BG: Color = Color { r: 0.15, g: 0.15, b: 0.15, a: 1.0 };
|
||||
const BORDER: Color = Color { r: 0.35, g: 0.35, b: 0.35, a: 1.0 };
|
||||
const TEXT_COL: Color = Color { r: 0.88, g: 0.88, b: 0.88, a: 1.0 };
|
||||
const DIM_COL: Color = Color { r: 0.55, g: 0.55, b: 0.55, a: 1.0 };
|
||||
const ACCENT: Color = Color { r: 0.25, g: 0.50, b: 0.85, a: 1.0 };
|
||||
const ACTIVE_BG: Color = Color { r: 0.20, g: 0.40, b: 0.70, a: 1.0 };
|
||||
|
||||
let lbl = |s: &'static str| text(s).size(11).color(DIM_COL).width(150);
|
||||
|
||||
let field_style = |_: &Theme, _: text_input::Status| text_input::Style {
|
||||
background: Background::Color(Color { r: 0.10, g: 0.10, b: 0.10, a: 1.0 }),
|
||||
border: Border { color: BORDER, width: 1.0, radius: 3.0.into() },
|
||||
icon: TEXT_COL, placeholder: DIM_COL, value: TEXT_COL, selection: ACCENT,
|
||||
};
|
||||
|
||||
let mk_field = |fld: DsField, val: &'a str| -> Element<'a, Message> {
|
||||
text_input("", val)
|
||||
.on_input(move |s| Message::DsEdit(fld.clone(), s))
|
||||
.style(field_style)
|
||||
.size(11)
|
||||
.width(90)
|
||||
.into()
|
||||
};
|
||||
|
||||
let btn_style = |accent: bool| move |_: &Theme, status: button::Status| button::Style {
|
||||
background: Some(Background::Color(match (accent, status) {
|
||||
(true, button::Status::Hovered | button::Status::Pressed) =>
|
||||
Color { r: 0.20, g: 0.42, b: 0.72, a: 1.0 },
|
||||
(false, button::Status::Hovered | button::Status::Pressed) =>
|
||||
Color { r: 0.28, g: 0.28, b: 0.28, a: 1.0 },
|
||||
(true, _) => ACCENT,
|
||||
_ => Color { r: 0.22, g: 0.22, b: 0.22, a: 1.0 },
|
||||
})),
|
||||
text_color: TEXT_COL,
|
||||
border: Border { color: BORDER, width: 1.0, radius: 4.0.into() },
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let tab_btn = |label: &'static str, idx: u8| {
|
||||
let active = tab == idx;
|
||||
button(text(label).size(11).color(TEXT_COL))
|
||||
.on_press(Message::DimStyleDialogTab(idx))
|
||||
.style(move |_: &Theme, st| button::Style {
|
||||
background: Some(Background::Color(match (active, st) {
|
||||
(true, _) => ACTIVE_BG,
|
||||
(false, button::Status::Hovered | button::Status::Pressed) =>
|
||||
Color { r: 0.28, g: 0.28, b: 0.28, a: 1.0 },
|
||||
_ => Color { r: 0.20, g: 0.20, b: 0.20, a: 1.0 },
|
||||
})),
|
||||
text_color: TEXT_COL,
|
||||
border: Border { color: BORDER, width: 1.0, radius: 3.0.into() },
|
||||
..Default::default()
|
||||
})
|
||||
.padding([4, 10])
|
||||
};
|
||||
|
||||
// ── Style list ────────────────────────────────────────────────────────
|
||||
let style_list: Element<'_, Message> = {
|
||||
let mut col = column![].spacing(2);
|
||||
for name in styles {
|
||||
let active = name == selected;
|
||||
col = col.push(
|
||||
button(text(name.clone()).size(11).color(TEXT_COL))
|
||||
.on_press(Message::DimStyleDialogSelect(name))
|
||||
.style(move |_: &Theme, st| button::Style {
|
||||
background: Some(Background::Color(match (active, st) {
|
||||
(true, _) => ACTIVE_BG,
|
||||
(false, button::Status::Hovered | button::Status::Pressed) =>
|
||||
Color { r: 0.28, g: 0.28, b: 0.28, a: 1.0 },
|
||||
_ => Color { r: 0.18, g: 0.18, b: 0.18, a: 1.0 },
|
||||
})),
|
||||
text_color: TEXT_COL,
|
||||
border: Border { color: BORDER, width: 0.0, radius: 3.0.into() },
|
||||
..Default::default()
|
||||
})
|
||||
.padding([3, 8])
|
||||
.width(Fill)
|
||||
);
|
||||
}
|
||||
iced::widget::scrollable(col).height(160).into()
|
||||
};
|
||||
|
||||
let style_panel = column![
|
||||
text("Styles").size(11).color(DIM_COL),
|
||||
container(style_list)
|
||||
.style(|_: &Theme| container::Style {
|
||||
background: Some(Background::Color(Color { r: 0.12, g: 0.12, b: 0.12, a: 1.0 })),
|
||||
border: Border { color: BORDER, width: 1.0, radius: 3.0.into() },
|
||||
..Default::default()
|
||||
})
|
||||
.width(150)
|
||||
.padding(2),
|
||||
row![
|
||||
button(text("New").size(10).color(TEXT_COL))
|
||||
.on_press(Message::DimStyleDialogNew)
|
||||
.style(btn_style(false)).padding([3, 8]),
|
||||
button(text("Delete").size(10).color(TEXT_COL))
|
||||
.on_press(Message::DimStyleDialogDelete)
|
||||
.style(btn_style(false)).padding([3, 8]),
|
||||
].spacing(4),
|
||||
button(text("Set Current").size(10).color(TEXT_COL))
|
||||
.on_press(Message::DimStyleDialogSetCurrent)
|
||||
.style(btn_style(false)).padding([3, 8]).width(Fill),
|
||||
].spacing(6).width(150);
|
||||
|
||||
// ── Tab bar ───────────────────────────────────────────────────────────
|
||||
let tabs = row![
|
||||
tab_btn("Lines", 0),
|
||||
tab_btn("Arrows", 1),
|
||||
tab_btn("Text", 2),
|
||||
tab_btn("Scale/Units", 3),
|
||||
tab_btn("Tolerances", 4),
|
||||
].spacing(2);
|
||||
|
||||
// ── Checkbox helper ───────────────────────────────────────────────────
|
||||
let chk = |label: &'static str, val: bool, fld: DsField| -> Element<'a, Message> {
|
||||
checkbox(val)
|
||||
.label(label)
|
||||
.on_toggle(move |_| Message::DsToggle(fld.clone()))
|
||||
.size(14)
|
||||
.text_size(11)
|
||||
.into()
|
||||
};
|
||||
|
||||
// ── Tab content ───────────────────────────────────────────────────────
|
||||
let tab_content: Element<'_, Message> = match tab {
|
||||
0 => column![
|
||||
text("Dimension Line").size(11).color(ACCENT),
|
||||
row![lbl("Extension (DIMDLE)"), mk_field(DsField::Dimdle, &app.ds_dimdle)].spacing(8).align_y(iced::Center),
|
||||
row![lbl("Spacing (DIMDLI)"), mk_field(DsField::Dimdli, &app.ds_dimdli)].spacing(8).align_y(iced::Center),
|
||||
row![lbl("Text gap (DIMGAP)"), mk_field(DsField::Dimgap, &app.ds_dimgap)].spacing(8).align_y(iced::Center),
|
||||
chk("Suppress 1st line (DIMSD1)", app.ds_dimsd1, DsField::Dimsd1),
|
||||
chk("Suppress 2nd line (DIMSD2)", app.ds_dimsd2, DsField::Dimsd2),
|
||||
text("Extension Line").size(11).color(ACCENT),
|
||||
row![lbl("Extension (DIMEXE)"), mk_field(DsField::Dimexe, &app.ds_dimexe)].spacing(8).align_y(iced::Center),
|
||||
row![lbl("Offset (DIMEXO)"), mk_field(DsField::Dimexo, &app.ds_dimexo)].spacing(8).align_y(iced::Center),
|
||||
chk("Suppress 1st line (DIMSE1)", app.ds_dimse1, DsField::Dimse1),
|
||||
chk("Suppress 2nd line (DIMSE2)", app.ds_dimse2, DsField::Dimse2),
|
||||
].spacing(6).into(),
|
||||
|
||||
1 => column![
|
||||
text("Arrows").size(11).color(ACCENT),
|
||||
row![lbl("Arrow size (DIMASZ)"), mk_field(DsField::Dimasz, &app.ds_dimasz)].spacing(8).align_y(iced::Center),
|
||||
row![lbl("Center mark (DIMCEN)"), mk_field(DsField::Dimcen, &app.ds_dimcen)].spacing(8).align_y(iced::Center),
|
||||
row![lbl("Tick size (DIMTSZ)"), mk_field(DsField::Dimtsz, &app.ds_dimtsz)].spacing(8).align_y(iced::Center),
|
||||
].spacing(6).into(),
|
||||
|
||||
2 => column![
|
||||
text("Text").size(11).color(ACCENT),
|
||||
row![lbl("Height (DIMTXT)"), mk_field(DsField::Dimtxt, &app.ds_dimtxt)].spacing(8).align_y(iced::Center),
|
||||
row![lbl("Style (DIMTXSTY)"), mk_field(DsField::Dimtxsty, &app.ds_dimtxsty)].spacing(8).align_y(iced::Center),
|
||||
row![lbl("Vertical pos (DIMTAD)"), mk_field(DsField::Dimtad, &app.ds_dimtad)].spacing(8).align_y(iced::Center),
|
||||
chk("Horizontal inside (DIMTIH)", app.ds_dimtih, DsField::Dimtih),
|
||||
chk("Horizontal outside (DIMTOH)", app.ds_dimtoh, DsField::Dimtoh),
|
||||
].spacing(6).into(),
|
||||
|
||||
3 => column![
|
||||
text("Scale").size(11).color(ACCENT),
|
||||
row![lbl("Overall scale (DIMSCALE)"), mk_field(DsField::Dimscale, &app.ds_dimscale)].spacing(8).align_y(iced::Center),
|
||||
row![lbl("Linear factor (DIMLFAC)"), mk_field(DsField::Dimlfac, &app.ds_dimlfac)].spacing(8).align_y(iced::Center),
|
||||
text("Units").size(11).color(ACCENT),
|
||||
row![lbl("Format (DIMLUNIT)"), mk_field(DsField::Dimlunit, &app.ds_dimlunit)].spacing(8).align_y(iced::Center),
|
||||
row![lbl("Decimals (DIMDEC)"), mk_field(DsField::Dimdec, &app.ds_dimdec)].spacing(8).align_y(iced::Center),
|
||||
row![lbl("Suffix (DIMPOST)"), mk_field(DsField::Dimpost, &app.ds_dimpost)].spacing(8).align_y(iced::Center),
|
||||
].spacing(6).into(),
|
||||
|
||||
_ => column![
|
||||
text("Tolerances").size(11).color(ACCENT),
|
||||
chk("Generate tolerances (DIMTOL)", app.ds_dimtol, DsField::Dimtol),
|
||||
chk("Limits generation (DIMLIM)", app.ds_dimlim, DsField::Dimlim),
|
||||
row![lbl("Plus tolerance (DIMTP)"), mk_field(DsField::Dimtp, &app.ds_dimtp)].spacing(8).align_y(iced::Center),
|
||||
row![lbl("Minus tolerance (DIMTM)"), mk_field(DsField::Dimtm, &app.ds_dimtm)].spacing(8).align_y(iced::Center),
|
||||
row![lbl("Tol. decimals (DIMTDEC)"), mk_field(DsField::Dimtdec, &app.ds_dimtdec)].spacing(8).align_y(iced::Center),
|
||||
row![lbl("Tol. scale (DIMTFAC)"), mk_field(DsField::Dimtfac, &app.ds_dimtfac)].spacing(8).align_y(iced::Center),
|
||||
].spacing(6).into(),
|
||||
};
|
||||
|
||||
// ── Right panel ───────────────────────────────────────────────────────
|
||||
let right_panel = column![
|
||||
text(format!("Editing: {selected}")).size(12).color(TEXT_COL),
|
||||
tabs,
|
||||
container(
|
||||
iced::widget::scrollable(
|
||||
container(tab_content).padding(8)
|
||||
).height(220)
|
||||
)
|
||||
.style(|_: &Theme| container::Style {
|
||||
background: Some(Background::Color(Color { r: 0.12, g: 0.12, b: 0.12, a: 1.0 })),
|
||||
border: Border { color: BORDER, width: 1.0, radius: 3.0.into() },
|
||||
..Default::default()
|
||||
})
|
||||
.width(Fill),
|
||||
row![
|
||||
button(text("Apply").size(11).color(TEXT_COL))
|
||||
.on_press(Message::DimStyleDialogApply)
|
||||
.style(btn_style(true)).padding([5, 16]),
|
||||
button(text("Close").size(11).color(TEXT_COL))
|
||||
.on_press(Message::DimStyleDialogClose)
|
||||
.style(btn_style(false)).padding([5, 12]),
|
||||
].spacing(8),
|
||||
].spacing(8).width(Fill);
|
||||
|
||||
// ── Main panel ────────────────────────────────────────────────────────
|
||||
let panel = container(
|
||||
column![
|
||||
row![
|
||||
text("Dimension Style Manager").size(14).color(TEXT_COL),
|
||||
Space::new().width(Fill),
|
||||
button(text("✕").size(12).color(DIM_COL))
|
||||
.on_press(Message::DimStyleDialogClose)
|
||||
.style(|_: &Theme, _| button::Style {
|
||||
background: Some(Background::Color(Color::TRANSPARENT)),
|
||||
text_color: DIM_COL,
|
||||
..Default::default()
|
||||
})
|
||||
.padding([2, 6]),
|
||||
].align_y(iced::Center),
|
||||
row![style_panel, right_panel].spacing(12).align_y(iced::Top),
|
||||
].spacing(10).padding(16)
|
||||
)
|
||||
.style(|_: &Theme| container::Style {
|
||||
background: Some(Background::Color(PANEL_BG)),
|
||||
border: Border { color: BORDER, width: 1.0, radius: 6.0.into() },
|
||||
..Default::default()
|
||||
})
|
||||
.width(Shrink);
|
||||
|
||||
let catcher = mouse_area(
|
||||
container(iced::widget::Space::new().width(Fill).height(Fill))
|
||||
).on_press(Message::DimStyleDialogClose);
|
||||
|
||||
let positioned = container(panel)
|
||||
.width(Fill).height(Fill)
|
||||
.align_x(iced::Alignment::Center)
|
||||
.align_y(iced::Alignment::Center);
|
||||
|
||||
stack![catcher, positioned].into()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue