mirror of
https://github.com/storytold/wordcraft.git
synced 2026-11-14 14:32:31 +00:00
Text boxes in a group: the topmost member takes the click
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
37e891544d
commit
7095a4eaf1
2 files changed
+36
-2
No files matched your search
@@ -467,7 +467,7 @@ impl DocLayout {
|
||||
pub fn story_at(&self, page: usize, x: f32, y: f32) -> Option<StoryRef> {
|
||||
let p = self.pages.get(page)?;
|
||||
// A group's text boxes count as text boxes too (#6027).
|
||||
// Topmost first, a text box on its own or one in a group alike.
|
||||
// Topmost first, a text box on its own or one in a group alike (a group's last member is painted on top).
|
||||
let text_box = |behind: bool| {
|
||||
p.items.iter().rev().find_map(|it| {
|
||||
let Placed::Object { rect, spin, text_box, wrap, group_boxes, .. } = it else { return None };
|
||||
@@ -477,7 +477,11 @@ impl DocLayout {
|
||||
let centre = Point::new(rect.x + rect.w / 2.0, rect.y + rect.h / 2.0);
|
||||
let (ux, uy) = spin.unapply(centre.x, centre.y, x, y);
|
||||
text_box.filter(|_| rect.contains(Point::new(ux, uy))).or_else(|| {
|
||||
group_boxes.iter().find(|(r, _)| Rect::new(rect.x + r.x, rect.y + r.y, r.w, r.h).contains(Point::new(x, y))).map(|(_, id)| *id)
|
||||
group_boxes
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|(r, _)| Rect::new(rect.x + r.x, rect.y + r.y, r.w, r.h).contains(Point::new(x, y)))
|
||||
.map(|(_, id)| *id)
|
||||
})
|
||||
})
|
||||
};
|
||||
|
||||
@@ -3992,6 +3992,36 @@ fn grouped_text_box_areas_turn_with_the_group_and_work_in_headers() {
|
||||
assert_eq!(l.header_footer_text_box_at(0, 150.0, 40.0), None, "the group's bar is not text");
|
||||
}
|
||||
|
||||
/// #6027: where two text boxes of one group overlap, a click enters the one painted on top (the
|
||||
/// last member), in the body and in a header alike.
|
||||
#[test]
|
||||
fn click_in_overlapping_grouped_text_boxes_enters_the_top_one() {
|
||||
let (low, top) = (3, 4);
|
||||
let group = |rect| Placed::Object {
|
||||
rect,
|
||||
spin: Default::default(),
|
||||
story: StoryRef::Part(1),
|
||||
path: Path::top(0),
|
||||
off: 0,
|
||||
text_box: None,
|
||||
wrap: Default::default(),
|
||||
origin: Default::default(),
|
||||
group_boxes: vec![(wordcraft_geom::Rect::new(0.0, 0.0, 100.0, 100.0), low), (wordcraft_geom::Rect::new(50.0, 50.0, 100.0, 100.0), top)],
|
||||
};
|
||||
let page = Page {
|
||||
items: vec![group(wordcraft_geom::Rect::new(100.0, 100.0, 150.0, 150.0))],
|
||||
header: vec![group(wordcraft_geom::Rect::new(100.0, 100.0, 150.0, 150.0))],
|
||||
..Default::default()
|
||||
};
|
||||
let l = DocLayout { pages: vec![page], ..Default::default() };
|
||||
// Overlap (page 175, 175 is inside both boxes): the top box takes the click, and typing.
|
||||
assert_eq!(l.story_at(0, 175.0, 175.0), Some(StoryRef::Part(top)));
|
||||
assert_eq!(l.header_footer_text_box_at(0, 175.0, 175.0), Some(top));
|
||||
// Outside the overlap each box still answers for itself.
|
||||
assert_eq!(l.story_at(0, 110.0, 110.0), Some(StoryRef::Part(low)));
|
||||
assert_eq!(l.story_at(0, 240.0, 240.0), Some(StoryRef::Part(top)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deleted_float_leaves_no_wrap_area_without_markup() {
|
||||
crate::test_fonts();
|
||||
|
||||
Reference in new issue
Block a user