diff --git a/crates/ui-egui/src/addons/cutting/tests.rs b/crates/ui-egui/src/addons/cutting/tests.rs index 39adb0539f..2e69eab904 100644 --- a/crates/ui-egui/src/addons/cutting/tests.rs +++ b/crates/ui-egui/src/addons/cutting/tests.rs @@ -118,4 +118,28 @@ fn weed_box_and_lines_previews_cancels_and_runs_on_ok() { crate::dialogs::set_field(d, "spacing".into(), json!(20)); crate::dialogs::confirm(&mut app).unwrap(); assert_eq!(count(&app), nodes + 8, "a group, the box and six pieces of line"); + + // A Spacing below 0 is refused, not swapped for the Count. + app.run("edit.undo", json!({})).unwrap(); + app.run("select.set", json!({"ids": [id]})).unwrap(); + open(&mut app); + let n = steps(&app); + crate::dialogs::set_field(app.ui.dialog.as_mut().unwrap(), "spacing".into(), json!(-5)); + let e = crate::dialogs::confirm(&mut app).unwrap_err().to_string(); + assert!(e.contains("`spacing` must be more than 0"), "{e}"); + assert_eq!(steps(&app), n, "no undo step"); + + // A Spacing with no value, or of 0 written with its unit, leaves the Count in use: a Count of 0 + // draws the box alone. + crate::dialogs::cancel(&mut app); + for spacing in [serde_json::Value::Null, json!("0 pt")] { + app.run("select.set", json!({"ids": [id]})).unwrap(); + open(&mut app); + let d = app.ui.dialog.as_mut().unwrap(); + crate::dialogs::set_field(d, "spacing".into(), spacing.clone()); + crate::dialogs::set_field(d, "count".into(), json!(0)); + crate::dialogs::confirm(&mut app).unwrap(); + assert_eq!(count(&app), nodes + 2, "{spacing}: a group and the box"); + app.run("edit.undo", json!({})).unwrap(); + } } diff --git a/crates/ui-egui/src/dialogs/command.rs b/crates/ui-egui/src/dialogs/command.rs index 374868e27f..2e277caea8 100644 --- a/crates/ui-egui/src/dialogs/command.rs +++ b/crates/ui-egui/src/dialogs/command.rs @@ -87,13 +87,18 @@ fn call(d: &Dialog) -> (String, Value) { { o.remove("rowGutter"); } - // Weed Box and Lines: a Spacing above 0 divides the box instead of the Count, and only the one - // in use is sent. + // Weed Box and Lines: a Spacing of 0, or none, leaves the Count in use; any other Spacing is + // sent instead of the Count, so the command refuses one below 0. if d.str("__command") == crate::addons::cutting::WEED && let Some(o) = params.as_object_mut() { - let by_spacing = o.get("spacing").and_then(Value::as_f64).is_some_and(|s| s > 0.0); - o.remove(if by_spacing { "count" } else { "spacing" }); + let zero = |s: &Value| match s { + Value::Null => true, + Value::String(t) => vectorcraft_doc::Unit::Points.parse(t).or_else(|| t.trim().parse().ok()) == Some(0.0), + v => v.as_f64() == Some(0.0), + }; + let by_count = o.get("spacing").is_none_or(zero); + o.remove(if by_count { "spacing" } else { "count" }); } (d.str("__command"), params) }