From a36dcbb3bc82fd23c09e116e5e95ba60ad18c8b0 Mon Sep 17 00:00:00 2001 From: mtlcl410 <2368091+mtlcl410@users.noreply.github.com> Date: Fri, 30 Oct 2026 23:50:06 +0800 Subject: [PATCH] M5: a callout's leader line follows its text box while the box is resized (#1152) Review on #4094: resizing a callout's text box moved its frame, but changing_points had no Resize branch, so no leader line was drawn to the box until the page was redrawn. A Resize gesture, and the ResizeAnnotation edit just released, now count as changing the callout: its points stay and its line is drawn to where the box is going. A box moved alone and released keeps its knee beside it, as while it was dragged. Test: a_callout_being_resized_draws_its_leader_line, which fails with the fix reverted. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Pq7HyCfwzyRXj4VfQAVVdv --- crates/ui-egui/src/tools/comments/paint.rs | 17 +++++++++++++++++ crates/ui-egui/src/tools/comments/tests.rs | 14 ++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/crates/ui-egui/src/tools/comments/paint.rs b/crates/ui-egui/src/tools/comments/paint.rs index 787da6f3f8..0a0ef1ebd9 100644 --- a/crates/ui-egui/src/tools/comments/paint.rs +++ b/crates/ui-egui/src/tools/comments/paint.rs @@ -100,6 +100,10 @@ pub(super) fn changing_points( }), (_, Some(Edit::ReshapeAnnotation { page: p, index: i, points: to })) if (*p, *i) == (page, index) => Some(to.clone()), (_, Some(Edit::MoveAnnotation { page: p, index: i, dx, dy })) if (*p, *i) == (page, index) => Some(shifted(*dx, *dy)), + // A callout's text box resized (or moved alone): its points stay, and its line is drawn to + // the box where it is going (see `paint_points`). + (Some(Gesture::Resize { page: p, index: i, .. }), _) if (*p, *i) == (page, index) => pointer.map(|_| points.to_vec()), + (_, Some(Edit::ResizeAnnotation { page: p, index: i, .. })) if (*p, *i) == (page, index) => Some(points.to_vec()), _ => None, } } @@ -119,6 +123,19 @@ fn paint_points(painter: &egui::Painter, cx: &PageCx<'_>, view: &DocView, a: &An { *p = [f64::from(first[0]), f64::from(first[1])]; } + // A callout's box moved alone and released: its knee came along, as while it was dragged. + if let (Some(Edit::ResizeAnnotation { page, index, rect }), Some(tb)) = (view.pending_edit.as_ref(), a.text_box.filter(|_| is_callout(a))) + && (*page, *index) == (cx.page, a.index) + { + let tb = tb.map(f64::from); + let same = |a: f64, b: f64| (a - b).abs() < 0.01; + if same(rect[2] - rect[0], tb[2] - tb[0]) && same(rect[3] - rect[1], tb[3] - tb[1]) { + let (dx, dy) = (rect[0] - tb[0], rect[1] - tb[1]); + for q in points.iter_mut().skip(1) { + *q = [q[0] + dx, q[1] + dy]; + } + } + } let screen: Vec = points.iter().map(|q| cx.to_screen(*q)).collect(); if changed { let stroke = Stroke::new(1.5, SELECT_BLUE); diff --git a/crates/ui-egui/src/tools/comments/tests.rs b/crates/ui-egui/src/tools/comments/tests.rs index 0989ee1642..5150cf6d4b 100644 --- a/crates/ui-egui/src/tools/comments/tests.rs +++ b/crates/ui-egui/src/tools/comments/tests.rs @@ -24,6 +24,20 @@ fn a_moved_or_reshaped_line_is_drawn_at_its_new_points() { assert_eq!(changing_points(None, None, (0, 3), &line, to_user, to, straight), None, "not changing"); } +/// Review on #4094: a callout's text box being resized, and the resize just released, draw its +/// leader line too (to the box where it is going): its points are changing, though they stay. +#[test] +fn a_callout_being_resized_draws_its_leader_line() { + let lead = [[10.0, 10.0], [40.0, 30.0]]; + let to_user = |p: Pos2| [f64::from(p.x), f64::from(p.y)]; + let resizing = Gesture::Resize { page: 0, index: 3, handle: (1, 1), from: pos2(80.0, 60.0), aspect_ratio: None }; + let at = Some(pos2(95.0, 70.0)); + assert_eq!(changing_points(Some(&resizing), None, (0, 3), &lead, to_user, at, straight), Some(lead.to_vec())); + assert_eq!(changing_points(Some(&resizing), None, (0, 4), &lead, to_user, at, straight), None, "another comment's resize"); + let released = Edit::ResizeAnnotation { page: 0, index: 3, rect: [50.0, 20.0, 110.0, 70.0] }; + assert_eq!(changing_points(None, Some(&released), (0, 3), &lead, to_user, None, straight), Some(lead.to_vec())); +} + /// A sticky note on a page turned a quarter is drawn upright beside its `/Rect`: an edit /// composer stays open while the drawn note is partly in view, even with `/Rect` out of it. #[test]