//! Clicking into boolean groups: a hit reaches the operand under the pointer, a plain click still //! picks the group, and a double click goes one level deeper than the selection. use crate::geometry::{enter_target, select_target}; use crate::{BoolOp, Document, NodeId, NodeKind}; use figcraft_geom::Point; fn page(d: &Document) -> NodeId { d.first_page().unwrap() } /// A frame holding a group holding a boolean group of two overlapping squares. fn setup() -> (Document, NodeId, NodeId, NodeId, NodeId, NodeId) { let mut d = Document::new("x"); let p = page(&d); let f = d.create(p, NodeKind::Frame, "F", 0.0, 0.0, 300.0, 300.0).unwrap(); let g = d.create(f, NodeKind::Group, "G", 0.0, 0.0, 0.0, 0.0).unwrap(); let b = d.create(g, NodeKind::BooleanOp { op: BoolOp::Subtract }, "Subtract", 0.0, 0.0, 0.0, 0.0).unwrap(); let r1 = d.create(b, NodeKind::Rectangle, "R1", 10.0, 10.0, 100.0, 100.0).unwrap(); let r2 = d.create(b, NodeKind::Rectangle, "R2", 60.0, 60.0, 100.0, 100.0).unwrap(); d.fit_to_children(b).unwrap(); d.fit_to_children(g).unwrap(); (d, f, g, b, r1, r2) } #[test] fn hits_reach_operands_but_clicks_pick_the_group() { let (d, f, g, b, r1, r2) = setup(); let p = page(&d); assert_eq!(d.hit_test(p, Point::new(20.0, 20.0), 0.0, None), Some(r1)); assert_eq!(d.hit_test(p, Point::new(100.0, 100.0), 0.0, None), Some(r2), "the top operand where they overlap"); // A plain click: the group in the frame; Cmd-click: the operand. assert_eq!(select_target(&d, r1, &[], false), g); assert_eq!(select_target(&d, r1, &[], true), r1); // With the boolean group selected, its siblings resolve as usual; with an operand selected, a // click on another operand picks that one. assert_eq!(select_target(&d, r2, &[r1], false), r2); // "Select layer" still lists the boolean group as one layer. let listed: Vec = crate::geometry::layers_at(&d, p, Point::new(20.0, 20.0), 0.0, None).into_iter().map(|(id, _)| id).collect(); assert_eq!(listed, vec![f, g, b]); } #[test] fn double_clicks_go_one_level_deeper() { let (d, f, g, b, r1, _) = setup(); assert_eq!(enter_target(&d, r1, &[]), g, "nothing selected: the plain click target"); assert_eq!(enter_target(&d, r1, &[g]), b, "into the group"); assert_eq!(enter_target(&d, r1, &[b]), r1, "into the boolean group"); assert_eq!(enter_target(&d, r1, &[r1]), r1, "the leaf itself: nothing deeper, it stays"); assert_eq!(enter_target(&d, r1, &[f]), g); // The deepest selected layer that holds it counts. assert_eq!(enter_target(&d, r1, &[f, b]), r1); } #[test] fn a_top_level_group_is_entered_too() { let mut d = Document::new("x"); let p = page(&d); let g = d.create(p, NodeKind::Group, "G", 0.0, 0.0, 0.0, 0.0).unwrap(); let r = d.create(g, NodeKind::Rectangle, "R", 10.0, 10.0, 20.0, 20.0).unwrap(); d.fit_to_children(g).unwrap(); assert_eq!(select_target(&d, r, &[g], false), g, "a click keeps the group"); assert_eq!(enter_target(&d, r, &[g]), r, "a double click enters it"); }