From b3f1d57ecf93c3680a5bd4bec7afecb0aed2cb46 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Fri, 30 Oct 2026 07:51:50 -0700 Subject: [PATCH] Graphic Styles: addFromLibrary treats ids: null as left out graphicStyle.addFromLibrary with apply: true and ids: null tried to apply the style to no objects and failed with "no such objects" when nothing was selected. A null `ids` now behaves as leaving `ids` out: the style is applied to the selection when there is one, and only added otherwise. --- crates/engine/src/cmd/stylelib.rs | 5 +++-- crates/engine/src/tests/stylelib.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/crates/engine/src/cmd/stylelib.rs b/crates/engine/src/cmd/stylelib.rs index 1f4792c08..2864f574b 100644 --- a/crates/engine/src/cmd/stylelib.rs +++ b/crates/engine/src/cmd/stylelib.rs @@ -194,10 +194,11 @@ fn add(s: &mut Session, p: &Value) -> Result { "existing": existing.iter().map(|g| &g.name).collect::>(), }); let first = picked.first().map(|g| doc_name(&g.name)); - let targets = p.get("ids").is_some() || !super::appearance::appearance_targets(s, &json!({}))?.is_empty(); + let ids = p.get("ids").filter(|v| !v.is_null()); + let targets = ids.is_some() || !super::appearance::appearance_targets(s, &json!({}))?.is_empty(); if let Some(name) = first.filter(|_| apply && targets) { let mut params = json!({"name": name, "add": add}); - if let Some(ids) = p.get("ids") { + if let Some(ids) = ids { params["ids"] = ids.clone(); } s.execute("graphicStyle.apply", ¶ms)?; diff --git a/crates/engine/src/tests/stylelib.rs b/crates/engine/src/tests/stylelib.rs index 2c3a4c6fb..6a93b80a3 100644 --- a/crates/engine/src/tests/stylelib.rs +++ b/crates/engine/src/tests/stylelib.rs @@ -117,6 +117,35 @@ fn add_with_apply_styles_the_selection_in_the_same_undo_step() { assert_eq!(doc(&s).node(id).unwrap().opacity, 0.4); } +#[test] +fn add_with_null_ids_and_no_selection_only_adds_style() { + let mut omitted = session(); + let mut null_ids = session(); + let params = json!({"library": "shadows-glows", "name": "Halo", "apply": true}); + let expected = run(&mut omitted, "graphicStyle.addFromLibrary", params.clone()); + let mut with_null = params; + with_null["ids"] = Value::Null; + let actual = run(&mut null_ids, "graphicStyle.addFromLibrary", with_null); + assert_eq!(actual, expected); + assert_eq!(names(&actual["added"]), ["Halo"]); + assert!(actual.get("applied").is_none()); + assert!(doc(&null_ids).graphic_style("Halo").is_some()); + assert_eq!(undo_len(&null_ids), undo_len(&omitted)); +} + +#[test] +fn add_with_null_ids_applies_to_selection() { + let mut s = session(); + let id = rect(&mut s, 10.0, 20.0, 100.0, 50.0); + let before = undo_len(&s); + let result = run(&mut s, "graphicStyle.addFromLibrary", json!({"library": "shadows-glows", "name": "Halo", "apply": true, "ids": null})); + assert_eq!(result["applied"], "Halo"); + assert_eq!(undo_len(&s), before + 1); + let (style, linked) = s.selection_graphic_style().unwrap(); + assert_eq!((style.name.as_str(), linked), ("Halo", true)); + assert_eq!(doc(&s).node(id).unwrap().extras().graphic_style, Some(style.id)); +} + /// A document with pattern `name` (a dot) and its swatch. fn add_pattern(s: &mut Session, name: &str, radius: f64) { s.edit("Pattern", |d, _| {