diff --git a/crates/ui-egui/src/dialogs/recolor.rs b/crates/ui-egui/src/dialogs/recolor.rs index 6050af15a..bdd509409 100644 --- a/crates/ui-egui/src/dialogs/recolor.rs +++ b/crates/ui-egui/src/dialogs/recolor.rs @@ -2,8 +2,9 @@ //! previewed live (engine: `recolor.reduce`, `recolor.randomize`, `recolor.apply`). //! //! Assign tab: Colors (Auto, or a count: similar colours merge into rows), Preserve White, Black and -//! Grays, the rows (click to select, Shift or Cmd/Ctrl-click to add; a row's arrow excludes or -//! includes it; the hex field edits its new colour, and a double-click on it opens the Color Picker, +//! Grays (they open as OK on art last left them), the rows (click to select, Shift or Cmd/Ctrl-click +//! to add; a row's arrow excludes or includes it; the hex field edits its new colour, and a +//! double-click on it opens the Color Picker, //! whose OK sets it in the model it was picked in), Merge and Separate, Randomize order or //! saturation and brightness, Reset, the Method and Limit to Library (its folder button imports a //! library file and limits to it; a library's colours apply as its swatches: a spot colour stays a @@ -100,9 +101,12 @@ pub fn open(app: &mut VectorcraftApp, p: &Value) -> Result { }; // Without art the rows are the group's colours, as they are. let start: Vec = if art { vec![] } else { assign.iter().map(|k| json!({"from": [k], "to": k})).collect() }; + // The Preserve checkboxes as they were last confirmed (#2960). + let kept = |k: &str, default: bool| app.ui.recolor_preserve.get(k).and_then(Value::as_bool).unwrap_or(default); let fields = json!({ "rows": start, "colors": count, "method": Method::ScaleTints.id(), - "preserveWhite": true, "preserveBlack": true, "preserveGrays": false, "limitTo": limit, + "preserveWhite": kept("preserveWhite", true), "preserveBlack": kept("preserveBlack", true), + "preserveGrays": kept("preserveGrays", false), "limitTo": limit, "group": group, "groupName": if new_group { Some(NEW_GROUP) } else { group }, "tab": "assign", "rule": Harmony::Complementary.id(), "linked": true, "preview": true, "__art": art, "__assign": assign, "__newGroup": new_group, }); @@ -277,7 +281,13 @@ fn confirm(app: &mut VectorcraftApp, d: &Dialog) -> Result { let colors: Vec = rows(&d).into_iter().filter(|r| !excluded(r)).map(|r| r["to"].clone()).collect(); return form::commit_preview(app, "swatch.newGroup", json!({"name": d.str("groupName"), "colors": colors, "keepModel": true})); } - form::commit_preview(app, CMD, apply_params(&d)) + let r = form::commit_preview(app, CMD, apply_params(&d))?; + // The Preserve checkboxes (shown with art) open as confirmed here next time (#2960). + if d.bool("__art") { + app.ui.recolor_preserve = + json!({"preserveWhite": d.bool("preserveWhite"), "preserveBlack": d.bool("preserveBlack"), "preserveGrays": d.bool("preserveGrays")}); + } + Ok(r) } /// The preset the fields match: an n-colour job (n rows, Scale Tints), a library, or Custom. diff --git a/crates/ui-egui/src/state.rs b/crates/ui-egui/src/state.rs index 2b5c9c379..63a4f0390 100644 --- a/crates/ui-egui/src/state.rs +++ b/crates/ui-egui/src/state.rs @@ -563,6 +563,10 @@ pub struct UiState { /// The Average & Join fields confirmed last (`to`; null: never used): its dialog opens on them. #[serde(default)] pub average_join: Value, + /// The Recolor Artwork Preserve checkboxes confirmed last (`preserveWhite`, `preserveBlack`, + /// `preserveGrays`; null: never used): its dialog opens with them (#2960). + #[serde(default)] + pub recolor_preserve: Value, /// The Simplify dialog's fields confirmed last with "Open this dialog with these settings next /// time" ticked (null: not ticked): Object › Path › Simplify opens the dialog on them instead /// of the Simplify slider. @@ -904,6 +908,7 @@ impl Default for UiState { eps_options: Value::Null, offset_path: Value::Null, average_join: Value::Null, + recolor_preserve: Value::Null, simplify: Value::Null, move_options: Value::Null, transform_each: Value::Null, diff --git a/crates/ui-egui/src/tests/recolor.rs b/crates/ui-egui/src/tests/recolor.rs index 8d38d8d2f..1abefd25c 100644 --- a/crates/ui-egui/src/tests/recolor.rs +++ b/crates/ui-egui/src/tests/recolor.rs @@ -238,6 +238,27 @@ fn each_recolor_hex_field_has_its_row_number() { assert!(h.query_by_role_and_label(egui::accesskit::Role::TextInput, "Color").is_none(), "no ambiguous Color field"); } +/// #2960: the Preserve checkboxes open as OK last left them; Cancel keeps what OK left. +#[test] +fn the_preserve_checkboxes_open_as_they_were_last_confirmed() { + let mut app = app(); + art(&mut app, &["#ff0000", "#ffffff", "#000000", "#808080"]); + let preserve = |app: &VectorcraftApp| ["preserveWhite", "preserveBlack", "preserveGrays"].map(|k| field(app, k)); + app.run("ui.recolorDialog", json!({})).unwrap(); + assert_eq!(preserve(&app), [json!(true), json!(true), json!(false)], "a first open"); + set(&mut app, "preserveWhite", json!(false)); + set(&mut app, "preserveBlack", json!(false)); + set(&mut app, "preserveGrays", json!(true)); + dialogs::confirm(&mut app).unwrap(); + app.run("select.all", json!({})).unwrap(); + app.run("ui.recolorDialog", json!({})).unwrap(); + assert_eq!(preserve(&app), [json!(false), json!(false), json!(true)], "as confirmed"); + set(&mut app, "preserveWhite", json!(true)); + dialogs::cancel(&mut app); + app.run("ui.recolorDialog", json!({})).unwrap(); + assert_eq!(preserve(&app), [json!(false), json!(false), json!(true)], "Cancel keeps what OK left"); +} + /// The rect of the widget drawn `size` big (the wheel is 220 across, its Brightness slider 220 by 22). fn widget_of_size(h: &egui_kittest::Harness<'_, VectorcraftApp>, size: egui::Vec2) -> Rect { h.ctx