Merge pull request #4982 from dotCooCoo/fix/issue-2960

Fix #2960: Recolor Artwork keeps its Preserve checkboxes between uses
This commit is contained in:
BFlat
2026-11-01 05:29:25 +07:00
committed by GitHub
3 changed files with 40 additions and 4 deletions
+14 -4
View File
@@ -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<Value, String> {
};
// Without art the rows are the group's colours, as they are.
let start: Vec<Value> = 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<Value, String> {
let colors: Vec<Value> = 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.
+5
View File
@@ -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,
+21
View File
@@ -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