Parameters: move user parameters up and down (#1323)

Fixes #1187. New parameters.move {name, before|after} reorders user parameters (the design's own params order, so it is saved with no format change, and undoable); the Parameters dialog's user rows get up/down buttons. Label in every catalog. I merged main in. Checked on main + this branch: cargo check --workspace, the engine parameters tests, the UI parameter_order test, and docs/features.md regenerates unchanged.
This commit is contained in:
DuBearte authored and GitHub committed 2026-10-15 06:34:16 -04:00
1 parent d7a4a29ce3
commit 4dc638109b
14 files changed
+152 -11

No files matched your search

+15
View File
@@ -24,6 +24,8 @@ pub static COMMANDS: &[CommandSpec] = &[
.params("name, new_name (expressions, feature inputs and dimensions that use it follow)"),
CommandSpec::new("parameters.delete", "Delete Parameter", delete).params("name (refused while something uses it; the error lists the users)"),
CommandSpec::new("parameters.favorite", "Favourite Parameter", favorite).params("name, favorite?: bool (default true)"),
CommandSpec::new("parameters.move", "Move Parameter", move_param)
.params("name, before | after: another user parameter; the user parameter is listed just before or after it"),
CommandSpec::new("parameters.comment", "Comment Parameter", comment).params("name, comment"),
CommandSpec::new("parameters.users", "Parameter Users", users)
.noundo()
@@ -179,6 +181,19 @@ fn favorite(s: &mut Session, p: &Value) -> Result<Value> {
Ok(json!({"name": name, "favorite": on}))
}
fn move_param(s: &mut Session, p: &Value) -> Result<Value> {
let cmd = "parameters.move";
let name = param_name(cmd, p)?.to_string();
let (target, after) = match (str_(p, "before"), str_(p, "after")) {
(Some(t), None) => (t.to_string(), false),
(None, Some(t)) => (t.to_string(), true),
_ => return Err(bad(cmd, "give one of `before` or `after`: another user parameter")),
};
s.doc_mut().move_user_param(&name, &target, after)?;
let order: Vec<&str> = s.doc.params.iter().filter(|q| !q.model).map(|q| q.name.as_str()).collect();
Ok(json!({"name": name, "order": order}))
}
fn comment(s: &mut Session, p: &Value) -> Result<Value> {
let cmd = "parameters.comment";
let name = param_name(cmd, p)?.to_string();
+49
View File
@@ -544,3 +544,52 @@ fn switching_configurations_back_reuses_the_later_features() {
assert!(rel(volume(&mut s), 40.0 * 30.0 * 10.0) < 1e-9);
assert!(hits(&s) > before, "{r}");
}
/// The user parameters' names in the order the Parameters dialog lists them.
fn user_order(s: &mut Session) -> Vec<String> {
let v = run(s, "parameters.list", json!({"filter": "user"}));
v["parameters"].as_array().unwrap().iter().map(|r| r["name"].as_str().unwrap().to_string()).collect()
}
#[test]
fn user_parameters_reorder_with_undo() {
// #1187: move a user parameter before or after another; nothing else changes.
let mut s = Session::default();
for (n, e) in [("a", "1 mm"), ("b", "2 mm"), ("c", "a + b")] {
run(&mut s, "parameters.add", json!({"name": n, "expression": e}));
}
assert_eq!(user_order(&mut s), ["a", "b", "c"]);
let r = run(&mut s, "parameters.move", json!({"name": "c", "before": "a"}));
assert_eq!(r["order"], json!(["c", "a", "b"]));
assert_eq!(user_order(&mut s), ["c", "a", "b"]);
run(&mut s, "parameters.move", json!({"name": "c", "after": "a"}));
assert_eq!(user_order(&mut s), ["a", "c", "b"]);
// Values and references are untouched; the order is kept in the design file.
let list = run(&mut s, "parameters.list", json!({"filter": "user"}));
let c = list["parameters"].as_array().unwrap().iter().find(|r| r["name"] == "c").unwrap().clone();
assert_eq!(c["expression"], "a + b");
assert!((c["value"].as_f64().unwrap() - 3.0).abs() < 1e-9, "{c}");
let back = Session::new(solidcraft_doc::Document::from_json(&s.doc.to_json()).unwrap());
let names: Vec<&str> = back.doc.params.iter().filter(|p| !p.model).map(|p| p.name.as_str()).collect();
assert_eq!(names, ["a", "c", "b"]);
run(&mut s, "edit.undo", json!({}));
assert_eq!(user_order(&mut s), ["c", "a", "b"]);
}
#[test]
fn moving_a_parameter_refuses_bad_targets() {
let mut s = Session::default();
run(&mut s, "parameters.add", json!({"name": "a", "expression": "1 mm"}));
run(&mut s, "parameters.add", json!({"name": "b", "expression": "2 mm"}));
let before = s.doc.to_json();
for p in [
json!({"name": "a", "before": "a"}),
json!({"name": "a", "before": "nope"}),
json!({"name": "nope", "before": "a"}),
json!({"name": "a"}),
json!({"name": "a", "before": "b", "after": "b"}),
] {
err(&mut s, "parameters.move", p);
}
assert_eq!(s.doc.to_json(), before);
}