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]