65 lines
3.0 KiB
Rust
65 lines
3.0 KiB
Rust
//! 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), Some(r1));
|
|
assert_eq!(d.hit_test(p, Point::new(100.0, 100.0), 0.0), 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<NodeId> = crate::geometry::layers_at(&d, p, Point::new(20.0, 20.0), 0.0).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");
|
|
}
|