diff --git a/src/app/command_driver.rs b/src/app/command_driver.rs index 4bf5ba085..5546cddf8 100644 --- a/src/app/command_driver.rs +++ b/src/app/command_driver.rs @@ -8038,6 +8038,15 @@ mod parametric_constraint_undo_tests { crate::scene::model::object::PropValue::ParamRow { name, .. } if name == "width" ))); + assert!(app.tabs[app.active_tab] + .properties + .sections + .iter() + .flat_map(|section| §ion.props) + .any(|property| matches!( + property.value, + crate::scene::model::object::PropValue::ParamsVisibilityToggle(_) + ))); } /// End-to-end through the actual `Message` handlers a Properties-panel diff --git a/src/app/commands/inquiry.rs b/src/app/commands/inquiry.rs index df9671461..161a6c28c 100644 --- a/src/app/commands/inquiry.rs +++ b/src/app/commands/inquiry.rs @@ -25,7 +25,7 @@ impl OpenCADStudio { .collect(); if handles.len() < 2 { self.command_line - .push_info(crate::t!("Select at least two unlocked objects to align.").as_ref()); + .push_info(crate::t!("Select objects").as_ref()); return; } @@ -54,8 +54,6 @@ impl OpenCADStudio { }) .collect(); if bounds.len() < 2 { - self.command_line - .push_info(crate::t!("The selected objects do not provide usable bounds.").as_ref()); return; } diff --git a/src/app/properties.rs b/src/app/properties.rs index abbcebf7c..f31741f8b 100644 --- a/src/app/properties.rs +++ b/src/app/properties.rs @@ -487,7 +487,14 @@ impl OpenCADStudio { PropSection { title: t!("Parameters").into_owned(), props: { - let mut props: Vec = scene + let mut props = vec![Property { + label: String::new(), + field: "show_constraint_values", + value: PropValue::ParamsVisibilityToggle( + self.show_constraint_values, + ), + }]; + props.extend(scene .named_parameters() .iter() .enumerate() @@ -503,8 +510,7 @@ impl OpenCADStudio { .resolve(¶meter.name) .map_err(|error| error.to_string()), }, - }) - .collect(); + })); props.push(Property { label: String::new(), field: "named_parameter_add", @@ -3267,6 +3273,9 @@ fn make_sections_read_only(sections: &mut [crate::scene::model::object::PropSect PropValue::EntityLink { handles, .. } => format!("{} entity link(s)", handles.len()), PropValue::ParamRow { name, formula, .. } => format!("{name} = {formula}"), PropValue::ParamAddRow => String::new(), + PropValue::ParamsVisibilityToggle(value) => { + if *value { t!("On") } else { t!("Off") }.into_owned() + } }; property.field = "locked_read_only"; property.value = PropValue::ReadOnly(text); diff --git a/src/app/view/overlay.rs b/src/app/view/overlay.rs index 6c53708ab..77c57b46c 100644 --- a/src/app/view/overlay.rs +++ b/src/app/view/overlay.rs @@ -1256,7 +1256,7 @@ pub(super) fn viewport_context_menu_overlay( // none of the entity-selection actions above (Move/Copy/Isolate/ // Select Similar) apply to it. items.push(item( - t!("Delete Constraint").into_owned(), + t!("Delete").into_owned(), Message::PropConstraintDelete(id), )); items.push(sep()); diff --git a/src/scene/model/object.rs b/src/scene/model/object.rs index e2b228d3d..6c3f2eb39 100644 --- a/src/scene/model/object.rs +++ b/src/scene/model/object.rs @@ -85,6 +85,11 @@ pub enum PropValue { }, /// The trailing "+ Add parameter" row in the Parameters section. ParamAddRow, + /// The Parameters section's leading header row (no-selection page only): + /// a global on/off toggle for whether any constraint pill in the + /// viewport shows its driven value/parameter-name text. Mirrors + /// `App::show_constraint_values`. + ParamsVisibilityToggle(bool), } /// A single property row in the Properties panel. diff --git a/src/scene/selection.rs b/src/scene/selection.rs index d30b0de2e..ef48c55d8 100644 --- a/src/scene/selection.rs +++ b/src/scene/selection.rs @@ -754,7 +754,8 @@ impl Scene { | PropValue::FieldLwVaries { .. } | PropValue::EntityLink { .. } | PropValue::ParamRow { .. } - | PropValue::ParamAddRow => continue, + | PropValue::ParamAddRow + | PropValue::ParamsVisibilityToggle(_) => continue, } }; out.push(choice(prop.field, prop.label, editor)); @@ -891,7 +892,8 @@ impl Scene { | PropValue::FieldLwVaries { .. } | PropValue::EntityLink { .. } | PropValue::ParamRow { .. } - | PropValue::ParamAddRow => return None, + | PropValue::ParamAddRow + | PropValue::ParamsVisibilityToggle(_) => return None, }) } } diff --git a/src/ui/properties.rs b/src/ui/properties.rs index 59a11dedb..d5b233e06 100644 --- a/src/ui/properties.rs +++ b/src/ui/properties.rs @@ -872,6 +872,7 @@ impl PropertiesPanel { self.render_param_row(*index, name, formula, resolved) } PropValue::ParamAddRow => render_param_add_row(), + PropValue::ParamsVisibilityToggle(value) => render_params_visibility_toggle_row(*value), } } @@ -1984,6 +1985,43 @@ fn render_param_add_row<'a>() -> Element<'a, Message> { container(btn).width(Length::Fill).into() } +// ── Parameters section: leading global visibility toggle ─────────────────── + +/// The Parameters section's leading header row (no-selection page): a +/// global on/off toggle for whether any constraint pill in the viewport +/// shows its driven value/parameter-name text — lives next to the +/// named-parameter table it governs. +fn render_params_visibility_toggle_row<'a>(value: bool) -> Element<'a, Message> { + let btn_label = if value { t!("On") } else { t!("Off") }.into_owned(); + let btn = button( + row![ + crate::ui::icons::semantic(crate::ui::icons::layer_visible(value), 13.0), + text(btn_label).size(FONT_SZ), + ] + .spacing(6) + .align_y(iced::Center), + ) + .on_press(Message::ShowConstraintValuesChanged(!value)) + .style(move |theme: &Theme, status| { + let palette = theme.palette(); + let pair = match status { + button::Status::Hovered | button::Status::Pressed => palette.background.weak, + _ => palette.background.base, + }; + button::Style { + background: Some(Background::Color(pair.color)), + border: Border { color: palette.background.neutral.color, width: 1.0, radius: 2.0.into() }, + text_color: pair.text, + ..Default::default() + } + }) + .padding([4, 8]) + .width(Length::Fill); + container(row![text(t!("Values").into_owned()).size(FONT_SZ).width(Length::Fill), btn].align_y(iced::Center)) + .width(Length::Fill) + .into() +} + /// Build a label | widget property row. fn prop_row_widget<'a>(label: &'a str, widget: Element<'a, Message>) -> Element<'a, Message> { prop_row_with_active(label, widget, false)