forked from 1b-agent/opencadstudio-upstream
Add per-constraint delete; fix named-parameter reference bugs
Constraint delete: a Properties-panel row delete button, viewport
click-to-select on a constraint glyph pill with Delete-key support, and a
right-click "Delete Constraint" menu item — all routed through one
undoable Scene::selected_constraint-aware path.
Fixes two named-parameter bugs found while testing that feature:
- DIMCONSTRAINT: a parameter named like a mode-switch keyword ("r", "d",
"a", "x", "y") could never be referenced, since the keyword check ran
before the parameter-name check.
- PARAMETERS modal Apply rebuilt Scene::named_parameters but never
refreshed the Properties panel, leaving renamed/deleted rows stale
until an unrelated refresh (e.g. a selection change) happened to occur.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
1 parent
753df67ee4
commit
59ae38ae1a
14 files changed
+370
-77
No files matched your search
@@ -970,6 +970,41 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes one persistent sketch constraint by id (undoable), regardless
|
||||
/// of whether it's flagged as conflicting. Shared by the Properties
|
||||
/// panel's per-row delete button, the viewport's Delete key when a
|
||||
/// constraint glyph is selected, and its right-click "Delete Constraint"
|
||||
/// menu item — see `resolve_one_sketch_conflict` above for the same
|
||||
/// undo pattern applied to the solver's own auto-removal.
|
||||
pub(super) fn delete_sketch_constraint(
|
||||
&mut self,
|
||||
id: crate::scene::sketch_constraints::ConstraintId,
|
||||
) {
|
||||
let i = self.active_tab;
|
||||
let scope = self.tabs[i].current_sketch_scope();
|
||||
let Some(set) = self.tabs[i].scene.sketch_constraint_set(scope) else { return };
|
||||
let Some(constraint) = set.get(id) else { return };
|
||||
let touched: Vec<Handle> = constraint.refs.iter().map(|r| r.entity).collect();
|
||||
let label = "Delete constraint";
|
||||
|
||||
let constraints_before = set.clone();
|
||||
let pending = self.begin_undo(i, label, touched.len(), true);
|
||||
self.tabs[i]
|
||||
.scene
|
||||
.record_undo_sketch_constraints_before(scope, constraints_before);
|
||||
self.tabs[i].scene.sketch_constraint_set_mut(scope).remove(id);
|
||||
if self.tabs[i].scene.selected_constraint == Some(id) {
|
||||
self.tabs[i].scene.selected_constraint = None;
|
||||
}
|
||||
let changes: Vec<(Handle, crate::scene::ChangeKind)> =
|
||||
touched.into_iter().map(|h| (h, crate::scene::ChangeKind::Modified)).collect();
|
||||
self.tabs[i].scene.bump_entities(&changes);
|
||||
if let Some(pd) = pending {
|
||||
self.commit_undo_delta(i, pd);
|
||||
}
|
||||
self.refresh_properties();
|
||||
}
|
||||
|
||||
/// Rebuilds the active tab's `Scene::named_parameters` from the
|
||||
/// editor's working buffer and re-solves dependent constraints.
|
||||
pub(super) fn apply_named_parameter_editor_rows(&mut self) {
|
||||
@@ -7455,6 +7490,43 @@ mod sketch_constraint_undo_tests {
|
||||
assert_eq!(set.constraints.len(), 2, "undo should restore the removed constraint");
|
||||
}
|
||||
|
||||
/// `delete_sketch_constraint` is the non-conflict counterpart to
|
||||
/// `resolve_one_sketch_conflict` above: it removes an arbitrary
|
||||
/// constraint by id (undoable), and also clears
|
||||
/// `Scene::selected_constraint` when the deleted id was the one
|
||||
/// selected — otherwise a stale id would linger and the viewport's
|
||||
/// Delete key / right-click menu would target a constraint that no
|
||||
/// longer exists.
|
||||
#[test]
|
||||
fn delete_sketch_constraint_removes_an_arbitrary_constraint_and_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::AddSketchConstraint {
|
||||
kind: ConstraintKind::Horizontal,
|
||||
refs: vec![SketchRef::whole(line)],
|
||||
driving_param: None,
|
||||
label: "Horizontal constraint",
|
||||
});
|
||||
let set = app.tabs[app.active_tab].scene.sketch_constraint_set(SketchScope::ModelSpace).unwrap();
|
||||
assert_eq!(set.constraints.len(), 1);
|
||||
let id = set.constraints[0].id;
|
||||
app.tabs[app.active_tab].scene.selected_constraint = Some(id);
|
||||
|
||||
app.delete_sketch_constraint(id);
|
||||
let set = app.tabs[app.active_tab].scene.sketch_constraint_set(SketchScope::ModelSpace).unwrap();
|
||||
assert_eq!(set.constraints.len(), 0, "the constraint should have been removed");
|
||||
assert_eq!(
|
||||
app.tabs[app.active_tab].scene.selected_constraint, None,
|
||||
"deleting the selected constraint should clear the selection"
|
||||
);
|
||||
|
||||
app.undo_steps(1);
|
||||
let set = app.tabs[app.active_tab].scene.sketch_constraint_set(SketchScope::ModelSpace).unwrap();
|
||||
assert_eq!(set.constraints.len(), 1, "undo should restore the deleted constraint");
|
||||
}
|
||||
|
||||
/// `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
|
||||
|
||||
Reference in new issue
Block a user