diff --git a/crates/ui-egui/src/canvas.rs b/crates/ui-egui/src/canvas.rs index cb8df52d..1897bf04 100644 --- a/crates/ui-egui/src/canvas.rs +++ b/crates/ui-egui/src/canvas.rs @@ -1484,7 +1484,9 @@ fn hatch(polys: &[Vec], gap: f32) -> Vec<[Pos2; 2]> { } /// The layers that get canvas labels and layout grids, in z-order: the page's visible top-level -/// layers and, inside sections whose contents show, their visible children (sections nest). +/// layers and, inside sections whose contents show, their visible children (sections nest). A +/// section comes after its children, so its title pill draws over (and takes clicks from) the +/// labels of frames near its top-left (#1150). fn boards(doc: &Document, page: NodeId) -> Vec { fn walk(doc: &Document, id: NodeId, depth: usize, out: &mut Vec) { let Some(n) = doc.node(id) else { return }; @@ -1493,10 +1495,10 @@ fn boards(doc: &Document, page: NodeId) -> Vec { if !cn.visible { continue; } - out.push(*c); if matches!(cn.kind, NodeKind::Section { contents_hidden: false }) && depth < 32 { walk(doc, *c, depth + 1, out); } + out.push(*c); } } let mut out = Vec::new(); diff --git a/crates/ui-egui/src/frame_label_tests.rs b/crates/ui-egui/src/frame_label_tests.rs index 687669e8..6c15fc00 100644 --- a/crates/ui-egui/src/frame_label_tests.rs +++ b/crates/ui-egui/src/frame_label_tests.rs @@ -156,3 +156,23 @@ fn a_sections_label_renames_it_and_a_click_elsewhere_commits() { assert!(u.app.ui.rename_label.is_none()); assert_eq!(u.app.session.ds().unwrap().history.undo.len(), undo + 1, "one undo step"); } + +#[test] +fn a_sections_pill_is_above_the_labels_of_frames_inside_it() { + // A frame near the section's top-left puts its label over the section's pill (#1150): the pill + // draws last, so pressing where they overlap selects the section. + let mut s = Session::new(); + let sec = id(s.execute("node.create", &json!({"type": "section", "x": 0, "y": 0, "width": 300, "height": 200, "name": "Marketing"})).unwrap()); + let f = id(s.execute("frame.create", &json!({"x": 10, "y": 22, "width": 100, "height": 80, "name": "Icon card", "parent": sec})).unwrap()); + s.execute("select.none", &json!({})).unwrap(); + let mut u = Ui::new(s); + u.frame(vec![]); + let at = mid(&label(&u, sec)); + let frame_label = egui::Rect::from_points(&label(&u, f)); + assert!(frame_label.contains(at), "the frame's label {frame_label:?} overlaps the pill at {at:?}"); + let order: Vec = u.app.session.tool.labels.iter().map(|(id, _)| *id).collect(); + assert_eq!(order, vec![f, sec], "the section's label comes after (above) its frames'"); + u.button(at, true); + u.button(at, false); + assert_eq!(u.app.session.selection(), vec![sec]); +}