From 891e29ea92dc4a8bb01435a1aba1718bbb98a1c9 Mon Sep 17 00:00:00 2001 From: aiongg Date: Tue, 13 Oct 2026 19:07:03 +0000 Subject: [PATCH] Integration: #816's test (eyedropper ignores inactive states of a multi-state object) --- crates/tools/src/tests.rs | 55 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/crates/tools/src/tests.rs b/crates/tools/src/tests.rs index bd3b38ddb..710e39e81 100644 --- a/crates/tools/src/tests.rs +++ b/crates/tools/src/tests.rs @@ -1730,3 +1730,58 @@ fn a_selected_graphics_own_handles_resize_it_and_leave_the_frame() { let a = t.pointer(&ctx(&d, &content, &c, &l), &PointerEvent::new(PointerKind::Down, frame_corner.x, frame_corner.y)); assert!(!a.contains(&Action::Begin("Resize".into())), "{a:?}"); } + +#[test] +fn eyedropper_ignores_inactive_states_of_a_multi_state_object() { + use designcraft_doc::{Asset, AssetId, Content, Graphic}; + let mut d = Document::new(&NewDocument::default()); + let lid = d.default_layer(); + d.assets.insert( + AssetId(1), + std::sync::Arc::new(Asset { + id: AssetId(1), + name: "photo.png".into(), + mime: "image/png".into(), + link: None, + data: std::sync::Arc::new(vec![]), + pixels: Some((100, 100)), + page: 0, + pdf_crop: Default::default(), + pdf_box: None, + }), + ); + let area = Rect::new(100.0, 100.0, 200.0, 200.0); + let raster = { + let mut it = Item::new(ItemId(d.alloc()), lid, Shape::Rectangle, shapes::rectangle(area)); + it.content = Content::Graphic(Graphic { + asset: AssetId(1), + size: (100.0, 100.0), + xf: designcraft_geom::Affine::translate((0.0, 0.0)), + clip: None, + auto_fit: Default::default(), + fit_align: 4, + crop: [0.0; 4], + wrap: Default::default(), + }); + it + }; + let mut vector = Item::new(ItemId(d.alloc()), lid, Shape::Rectangle, shapes::rectangle(area)); + vector.fill.swatch = "[Black]".into(); + let target = add_rect(&mut d, Rect::new(400.0, 100.0, 450.0, 150.0)); + let s = Selection { items: vec![target], ..Default::default() }; + let sample = Action::Exec("color.sample".into(), serde_json::json!({"at": [120.0, 130.0], "spread": {"kind": "doc", "index": 0}})); + // Children [vector, raster] with the raster on top: it samples only while it is the active state. + for (active, samples) in [(1, true), (0, false)] { + let mut group = Item::new(ItemId(d.alloc()), lid, Shape::Rectangle, shapes::rectangle(area)); + group.content = Content::Group { items: vec![std::sync::Arc::new(vector.clone()), std::sync::Arc::new(raster.clone())] }; + group.states = vec!["a".into(), "b".into()]; + group.active_state = active; + let mut d2 = d.clone(); + d2.insert_item(SpreadRef::Doc(0), group, None).unwrap(); + let (c, l) = (Cache::new(), CanvasLayout::new(&d2, false)); + let off = l.xf(SpreadRef::Doc(0)).translation(); + let cx = ctx(&d2, &s, &c, &l); + let a = create("eyedropper").pointer(&cx, &PointerEvent::new(PointerKind::Down, 120.0 + off.x, 130.0 + off.y)); + assert_eq!(a.contains(&sample), samples, "active state {active}: {a:?}"); + } +}