mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-09 12:32:52 +00:00
fix(ui): a picture's grip and knob take their drag from the press
Found in review. On `main` the selected picture's grips and rotate knob were drag-only widgets of their own, so their drag began at the press. Their widgets went, and the page's response is click-and-drag, which calls it a drag only past egui's click distance: a move of a few pixels resized nothing. They take their drag from the press again. A click that doesn't move edits nothing, as before; a drag of the picture itself still waits, since a click selects. Tests: `a_short_drag_from_a_picture_grip_resizes_it` (seen failing with the fix reverted), `a_click_on_a_picture_grip_changes_nothing` (a pin, seen failing with the release planted to edit always). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2 files changed
+39
-3
No files matched your search
@@ -782,13 +782,16 @@ pub(crate) fn image_input(cx: &ImageCx<'_>, images: &[pdfcraft_engine::PageImage
|
||||
}
|
||||
|
||||
// A drag of the selected picture takes what its press was on ([`body_hit`], [`handle_hit`]):
|
||||
// the rotate knob turns it, a grip resizes it, the picture itself moves.
|
||||
// the rotate knob turns it, a grip resizes it, the picture itself moves. The knob and the
|
||||
// grips take it from the press, so a move too short to be a drag of the page counts; the
|
||||
// picture waits for that, as a click selects.
|
||||
let at_press = |part| matches!(part, PicturePart::Knob | PicturePart::Corner(_));
|
||||
if gate
|
||||
&& ptr.drag_started
|
||||
&& let Some(o) = ptr.origin
|
||||
&& let PagePress::Mine(Owner::Picture { index, part }) = press
|
||||
&& (index == i || part == PicturePart::OverSelected)
|
||||
&& let Some(s) = view.image_selection.as_mut()
|
||||
&& (ptr.drag_started || at_press(part) && ptr.pressed().is_some())
|
||||
&& let Some(s) = view.image_selection.as_mut().filter(|s| s.drag.is_none())
|
||||
{
|
||||
match part {
|
||||
PicturePart::Knob => {
|
||||
|
||||
@@ -7435,6 +7435,39 @@ fn a_drag_from_the_selected_picture_under_another_moves_the_selected_one() {
|
||||
assert_eq!(selected, Some(1), "a click selects the one on top");
|
||||
}
|
||||
|
||||
/// A move too short to be a drag of the page still resizes the selected picture from its grip, as
|
||||
/// the grip takes its drag from the press.
|
||||
#[test]
|
||||
fn a_short_drag_from_a_picture_grip_resizes_it() {
|
||||
let mut h = picture_pages(false);
|
||||
let id = h.state().views[0].id;
|
||||
let before = h.state().session.get(id).unwrap().page_images(0)[0].matrix;
|
||||
// The picture shows at x 30..160, y 170..250: its lower right grip, moved 3 px.
|
||||
let grip = page_at(&h, 0, 160.0, 170.0);
|
||||
h.hover_at(grip);
|
||||
h.run_steps(1);
|
||||
h.drag_at(grip);
|
||||
h.run_steps(1);
|
||||
h.hover_at(grip + egui::vec2(3.0, 0.0));
|
||||
h.run_steps(1);
|
||||
h.drop_at(grip + egui::vec2(3.0, 0.0));
|
||||
h.run_steps(3);
|
||||
assert_ne!(h.state().session.get(id).unwrap().page_images(0)[0].matrix, before, "the picture is resized");
|
||||
}
|
||||
|
||||
/// A click on a selected picture's grip that doesn't move resizes nothing: no edit, and the picture
|
||||
/// stays selected.
|
||||
#[test]
|
||||
fn a_click_on_a_picture_grip_changes_nothing() {
|
||||
let mut h = picture_pages(false);
|
||||
let id = h.state().views[0].id;
|
||||
let before = h.state().session.get(id).unwrap().edit_generation();
|
||||
let grip = page_at(&h, 0, 160.0, 170.0);
|
||||
slipping_click(&mut h, grip, grip);
|
||||
assert_eq!(h.state().session.get(id).unwrap().edit_generation(), before, "no edit");
|
||||
assert!(h.state().views[0].image_selection.is_some(), "the picture stays selected");
|
||||
}
|
||||
|
||||
/// In the page grid, Delete deletes the page chosen there. The picture selected before the grid
|
||||
/// opened is not on screen, and stays.
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user