Integrate standard parametric PR fixes

This commit is contained in:
Hakan Seven committed 2026-09-15 10:43:00 +03:00
1 parent d738ebfcc6
commit 06fcf09ae3
7 files changed
+179 -16

No files matched your search

+94 -9
View File
@@ -966,22 +966,20 @@ impl OpenCADStudio {
TableCellEditStart::Started
}
/// Removes and re-solves the first conflicting constraint in the active scope.
pub(super) fn resolve_one_parametric_conflict(&mut self) {
fn remove_parametric_constraint(
&mut self,
id: crate::scene::parametric_constraints::ConstraintId,
label: &'static str,
) -> bool {
let i = self.active_tab;
let scope = self.tabs[i].current_parametric_scope();
let Some(set) = self.tabs[i].scene.parametric_constraint_set(scope) else {
return;
};
let Some(&(id, _kind)) = set.conflicts.first() else {
return;
return false;
};
let Some(constraint) = set.get(id) else {
return;
return false;
};
let touched: Vec<Handle> = constraint.refs.iter().map(|r| r.entity).collect();
let label = "Remove conflicting constraint";
let constraints_before = set.clone();
let pending = self.begin_undo(i, label, touched.len(), true);
self.tabs[i]
@@ -999,6 +997,30 @@ impl OpenCADStudio {
if let Some(pd) = pending {
self.commit_undo_delta(i, pd);
}
self.refresh_properties();
true
}
/// Removes and re-solves the first conflicting constraint in the active scope.
pub(super) fn resolve_one_parametric_conflict(&mut self) {
let i = self.active_tab;
let scope = self.tabs[i].current_parametric_scope();
let Some(id) = self.tabs[i]
.scene
.parametric_constraint_set(scope)
.and_then(|set| set.conflicts.first().map(|(id, _)| *id))
else {
return;
};
self.remove_parametric_constraint(id, "Remove conflicting constraint");
}
/// Removes one user-selected constraint from the active standard graph scope.
pub(super) fn delete_parametric_constraint(
&mut self,
id: crate::scene::parametric_constraints::ConstraintId,
) {
self.remove_parametric_constraint(id, "Delete constraint");
}
/// Rebuilds the active tab's `Scene::named_parameters` from the
@@ -7867,6 +7889,44 @@ mod parametric_constraint_undo_tests {
);
}
#[test]
fn deleting_one_parametric_constraint_is_undoable() {
let mut app = OpenCADStudio::new_for_test();
let _ = app.automation_op(r#"{"op":"new"}"#);
let line = add_line(&mut app, 0.0, 0.0, 10.0, 3.0);
let _ = app.apply_cmd_result(CmdResult::AddParametricConstraint {
kind: ConstraintKind::Horizontal,
refs: vec![ParametricRef::whole(line)],
driving_param: None,
label: "Horizontal constraint",
});
let id = app.tabs[app.active_tab]
.scene
.parametric_constraint_set(ParametricScope::ModelSpace)
.unwrap()
.constraints[0]
.id;
app.delete_parametric_constraint(id);
assert!(app.tabs[app.active_tab]
.scene
.parametric_constraint_set(ParametricScope::ModelSpace)
.unwrap()
.constraints
.is_empty());
app.undo_steps(1);
assert_eq!(
app.tabs[app.active_tab]
.scene
.parametric_constraint_set(ParametricScope::ModelSpace)
.unwrap()
.constraints
.len(),
1
);
}
/// `named_parameters_design.md` stage 4: applying the PARAMETERS editor's
/// working buffer both defines the parameter and re-solves whatever
/// constraint already references it by name — the entire point of a
@@ -7950,6 +8010,31 @@ mod parametric_constraint_undo_tests {
);
}
/// The no-selection page must expose the active drawing's named parameters.
#[test]
fn no_selection_properties_exposes_named_parameters() {
let mut app = OpenCADStudio::new_for_test();
let _ = app.automation_op(r#"{"op":"new"}"#);
app.tabs[app.active_tab]
.scene
.named_parameters_mut()
.set("width", "12")
.unwrap();
app.refresh_properties();
assert!(app.tabs[app.active_tab]
.properties
.sections
.iter()
.flat_map(|section| &section.props)
.any(|property| matches!(
&property.value,
crate::scene::model::object::PropValue::ParamRow { name, .. }
if name == "width"
)));
}
/// End-to-end through the actual `Message` handlers a Properties-panel
/// click/keystroke would fire — not `apply_named_parameter_editor_rows`
/// directly — covering the whole Parameters-section lifecycle: add,
+2
View File
@@ -2902,6 +2902,8 @@ pub enum Message {
/// A Constraints-section row was clicked: select every entity in the
/// list (replacing the current selection) in the viewport.
PropConstraintLinkClick(Vec<acadrust::Handle>),
/// Remove one parametric constraint from the active standard graph scope.
PropConstraintDelete(crate::scene::parametric_constraints::ConstraintId),
// ── About window ────────────────────────────────────────────────────
AboutOpen,
// ── Graphics warning ────────────────────────────────────────────────
+36 -1
View File
@@ -484,6 +484,35 @@ impl OpenCADStudio {
},
],
},
PropSection {
title: t!("Parameters").into_owned(),
props: {
let mut props: Vec<Property> = scene
.named_parameters()
.iter()
.enumerate()
.map(|(index, parameter)| Property {
label: String::new(),
field: "named_parameter",
value: PropValue::ParamRow {
index,
name: parameter.name.clone(),
formula: parameter.source.clone(),
resolved: scene
.named_parameters()
.resolve(&parameter.name)
.map_err(|error| error.to_string()),
},
})
.collect();
props.push(Property {
label: String::new(),
field: "named_parameter_add",
value: PropValue::ParamAddRow,
});
props
},
},
];
ui::PropertiesPanel {
title: t!("No selection").into_owned(),
@@ -2202,6 +2231,11 @@ impl OpenCADStudio {
let scope = self.tabs[i].current_parametric_scope();
let scene = &self.tabs[i].scene;
if let Some(set) = scene.parametric_constraint_set(scope) {
let parameters = if set.local_parameters.is_empty() {
scene.named_parameters()
} else {
&set.local_parameters
};
let props: Vec<crate::scene::model::object::Property> = set
.constraints_touching(handle)
.map(|c| {
@@ -2219,7 +2253,7 @@ impl OpenCADStudio {
crate::scene::named_parameters::DrivingValue::Named(
name,
),
) => match scene.named_parameters().resolve(name) {
) => match parameters.resolve(name) {
Ok(v) => format!(" = {name} ({v:.2})"),
Err(_) => format!(" = {name} (?)"),
},
@@ -2239,6 +2273,7 @@ impl OpenCADStudio {
label,
field: "parametric_constraint",
value: crate::scene::model::object::PropValue::EntityLink {
id: c.id,
handles,
conflicting,
},
+4
View File
@@ -6250,6 +6250,10 @@ impl OpenCADStudio {
Message::PropParamCommit { index, field } => self.on_prop_param_commit(index, field),
Message::PropParamDelete(index) => self.on_prop_param_delete(index),
Message::PropParamAddNew => self.on_prop_param_add_new(),
Message::PropConstraintDelete(id) => {
self.delete_parametric_constraint(id);
Task::none()
}
Message::PropConstraintLinkClick(handles) => {
let i = self.active_tab;
self.tabs[i].scene.deselect_all();