Merge r2-fix-ui: tests the combined batch broke

This commit is contained in:
aiongg
2026-10-22 04:31:47 +00:00
8 changed files with 49 additions and 38 deletions
+2 -1
View File
@@ -569,7 +569,8 @@ pub(crate) fn delete_selected(view: &mut DocView) -> Option<Edit> {
/// as the object nudge does (`object_ui::nudge_keys`) and as dragging it does (#2608). The keys
/// are consumed before the view turns the page with them; one press is one undo step.
pub(crate) fn nudge_keys(ctx: &egui::Context, view: &mut DocView, doc: &Document) {
if ctx.egui_wants_keyboard_input() || view.prepare.grab.is_some() {
// `consume_key` lets an extra Alt through, and Alt+↑/↓ belongs to Calculation order's move.
if ctx.egui_wants_keyboard_input() || view.prepare.grab.is_some() || ctx.input(|i| i.modifiers.alt) {
return;
}
let Some((name, wi)) = view.prepare.selected.clone() else { return };
+3 -3
View File
@@ -713,7 +713,7 @@ fn mode_tab(h: &Harness<'static, PdfCraftApp>, label: &str) -> egui::Rect {
}
/// Scroll the page until `what` (on screen) lies across the mode bar, then the cursor over each
/// tab it lies under: with the All tools panel closed, Read, Edit, Convert and E-Sign.
/// tab it lies under: with the All tools panel closed, every tab: All tools, Edit, Convert and E-Sign.
fn mode_tab_cursors(
h: &mut Harness<'static, PdfCraftApp>,
what: impl Fn(&Harness<'static, PdfCraftApp>) -> egui::Rect,
@@ -727,7 +727,7 @@ fn mode_tab_cursors(
h.state_mut().views[0].goto = Some((0, (top - (tabs - y)) / page(h).height()));
h.run_steps(4);
let under = what(h);
["Read", "Edit", "Convert", "E-Sign"].map(|label| {
["All tools", "Edit", "Convert", "E-Sign"].map(|label| {
let at = mode_tab(h, label).center();
assert!(under.contains(at), "{under:?} lies under {label} at {at:?}");
h.hover_at(at);
@@ -737,7 +737,7 @@ fn mode_tab_cursors(
}
const HAND_ON_EVERY_TAB: [(&str, egui::CursorIcon); 4] = [
("Read", egui::CursorIcon::PointingHand),
("All tools", egui::CursorIcon::PointingHand),
("Edit", egui::CursorIcon::PointingHand),
("Convert", egui::CursorIcon::PointingHand),
("E-Sign", egui::CursorIcon::PointingHand),
+6 -9
View File
@@ -5879,12 +5879,13 @@ fn mode_tab(h: &Harness<'static, PdfCraftApp>, label: &str) -> egui::Rect {
}
/// The cursor over each mode bar tab that page 1's text lies under, once that text is scrolled
/// up under the bar. With the All tools panel closed it lies under Read, Edit, Convert and E-Sign.
fn mode_tab_cursors(h: &mut Harness<'static, PdfCraftApp>, text: egui::Rect) -> [(&'static str, egui::CursorIcon); 4] {
/// up under the bar. With the All tools panel closed it lies under Edit, Convert and E-Sign; it
/// starts right of All tools.
fn mode_tab_cursors(h: &mut Harness<'static, PdfCraftApp>, text: egui::Rect) -> [(&'static str, egui::CursorIcon); 3] {
h.state_mut().views[0].goto = Some((0, 0.5));
h.run_steps(4);
let offset = h.state().views[0].page_screen_rect(0).expect("on screen").top();
["Read", "Edit", "Convert", "E-Sign"].map(|label| {
["Edit", "Convert", "E-Sign"].map(|label| {
let at = mode_tab(h, label).center();
assert!(text.translate(egui::vec2(0.0, offset)).contains(at), "the text lies under {label}");
h.hover_at(at);
@@ -5893,12 +5894,8 @@ fn mode_tab_cursors(h: &mut Harness<'static, PdfCraftApp>, text: egui::Rect) ->
})
}
const HAND_ON_EVERY_TAB: [(&str, egui::CursorIcon); 4] = [
("Read", egui::CursorIcon::PointingHand),
("Edit", egui::CursorIcon::PointingHand),
("Convert", egui::CursorIcon::PointingHand),
("E-Sign", egui::CursorIcon::PointingHand),
];
const HAND_ON_EVERY_TAB: [(&str, egui::CursorIcon); 3] =
[("Edit", egui::CursorIcon::PointingHand), ("Convert", egui::CursorIcon::PointingHand), ("E-Sign", egui::CursorIcon::PointingHand)];
/// Page 1's text block on screen, relative to the page's top edge, in the window as it is now.
fn page_text(h: &Harness<'static, PdfCraftApp>) -> egui::Rect {
+23 -16
View File
@@ -1331,6 +1331,13 @@ fn lines_grow_and_shrink_with_their_handles_before_release() {
let _gpu = gpu();
for (document_rotation, view_rotation) in [(0, 0), (90, 0), (0, 90), (90, 270)] {
let rot = (document_rotation, view_rotation);
// A line runs across the page as /Rotate displays it (#3781): along user y on a quarter turn.
// `d` is the distance along the line from the click at (100, 250).
let along =
|h: &Harness<'static, PdfCraftApp>, d: f32| if document_rotation == 90 { at(h, 100.0, 250.0 + d) } else { at(h, 100.0 + d, 250.0) };
let line = |from: f32, to: f32| {
if document_rotation == 90 { [98.0, 250.0 + from, 102.0, 250.0 + to] } else { [100.0 + from, 248.0, 100.0 + to, 252.0] }
};
let mut h = harness();
if document_rotation != 0 {
h.state_mut().apply_edit(pdfcraft_engine::Edit::RotatePages { pages: vec![0], degrees: document_rotation });
@@ -1341,36 +1348,36 @@ fn lines_grow_and_shrink_with_their_handles_before_release() {
h.run_steps(3);
assert!(h.state_mut().execute("sign.fill.line"));
click(&mut h, 100.0, 250.0);
assert_rect(rects(&h)[0], [82.0, 248.0, 118.0, 252.0]);
assert_rect(rects(&h)[0], line(-18.0, 18.0));
// In line mode a click on the line picks it up, with its handles.
click(&mut h, 100.0, 250.0);
assert_eq!(h.state().views[0].comments.selected, Some((0, 0)), "{rot:?}");
let generation = h.state().session.get(h.state().views[0].id).unwrap().edit_generation();
// The handle at the line's end, dragged out to 160.
h.drag_at(at(&h, 118.0, 250.0));
// The handle at the line's end, dragged out to 60 from the middle.
h.drag_at(along(&h, 18.0));
h.run_steps(1);
h.hover_at(at(&h, 160.0, 250.0));
h.hover_at(along(&h, 60.0));
// Wait only for the one-time layers. Later pointer frames are immediate.
let mut grown = h.render().unwrap();
for _ in 0..50 {
if ink_near(&grown, at(&h, 150.0, 250.0)) {
if ink_near(&grown, along(&h, 50.0)) {
break;
}
h.run_steps(2);
std::thread::sleep(std::time::Duration::from_millis(10));
grown = h.render().unwrap();
}
assert!(ink_near(&grown, at(&h, 150.0, 250.0)), "{rot:?}: the line grows with the handle before release");
assert!(ink_near(&grown, at(&h, 90.0, 250.0)), "{rot:?}: from where it starts");
assert!(ink_near(&grown, along(&h, 50.0)), "{rot:?}: the line grows with the handle before release");
assert!(ink_near(&grown, along(&h, -10.0)), "{rot:?}: from where it starts");
// Back in, shorter than it was, still without letting go.
h.hover_at(at(&h, 100.0, 250.0));
h.hover_at(along(&h, 0.0));
h.run_steps(2);
let shrunk = h.render().unwrap();
assert!(ink_near(&shrunk, at(&h, 90.0, 250.0)), "{rot:?}: the line still starts where it did");
for x in [110.0, 150.0] {
assert!(!ink_near(&shrunk, at(&h, x, 250.0)), "{rot:?}: the line shrinks with the handle before release (ink at {x})");
assert!(ink_near(&shrunk, along(&h, -10.0)), "{rot:?}: the line still starts where it did");
for d in [10.0, 50.0] {
assert!(!ink_near(&shrunk, along(&h, d)), "{rot:?}: the line shrinks with the handle before release (ink at {d})");
}
let doc = h.state().session.get(h.state().views[0].id).unwrap();
assert_eq!((doc.edit_generation(), doc.can_undo()), (generation, Some("Add line")), "{rot:?}: pointer frames never edit the document");
@@ -1378,12 +1385,12 @@ fn lines_grow_and_shrink_with_their_handles_before_release() {
grown.save(format!("{dir}/line-live-grow-{document_rotation}-{view_rotation}.png")).unwrap();
shrunk.save(format!("{dir}/line-live-shrink-{document_rotation}-{view_rotation}.png")).unwrap();
}
h.drop_at(at(&h, 100.0, 250.0));
h.drop_at(along(&h, 0.0));
h.run_steps(3);
let doc = h.state().session.get(h.state().views[0].id).unwrap();
assert_eq!(doc.can_undo(), Some("Resize comment"), "{rot:?}");
let [now] = rects(&h)[..] else { panic!("{rot:?}: still one line: {:?}", rects(&h)) };
assert!(now.iter().zip([82.0, 248.0, 100.0, 252.0]).all(|(a, b)| (a - b).abs() < 0.01), "{rot:?}: {now:?}");
assert!(now.iter().zip(line(-18.0, 0.0)).all(|(a, b)| (a - b).abs() < 0.01), "{rot:?}: {now:?}");
}
}
@@ -1667,7 +1674,7 @@ fn mode_tab(h: &Harness<'static, PdfCraftApp>, label: &str) -> egui::Rect {
}
/// Scroll the page until `what` (on screen) lies across the mode bar, then the cursor over each
/// tab it lies under: with the All tools panel closed, Read, Edit, Convert and E-Sign.
/// tab it lies under: with the All tools panel closed, every tab: All tools, Edit, Convert and E-Sign.
fn mode_tab_cursors(
h: &mut Harness<'static, PdfCraftApp>,
what: impl Fn(&Harness<'static, PdfCraftApp>) -> egui::Rect,
@@ -1681,7 +1688,7 @@ fn mode_tab_cursors(
h.state_mut().views[0].goto = Some((0, (top - (tabs - y)) / page(h).height()));
h.run_steps(4);
let under = what(h);
["Read", "Edit", "Convert", "E-Sign"].map(|label| {
["All tools", "Edit", "Convert", "E-Sign"].map(|label| {
let at = mode_tab(h, label).center();
assert!(under.contains(at), "{under:?} lies under {label} at {at:?}");
h.hover_at(at);
@@ -1691,7 +1698,7 @@ fn mode_tab_cursors(
}
const HAND_ON_EVERY_TAB: [(&str, egui::CursorIcon); 4] = [
("Read", egui::CursorIcon::PointingHand),
("All tools", egui::CursorIcon::PointingHand),
("Edit", egui::CursorIcon::PointingHand),
("Convert", egui::CursorIcon::PointingHand),
("E-Sign", egui::CursorIcon::PointingHand),
+6 -9
View File
@@ -1282,11 +1282,12 @@ fn mode_tab(h: &Harness<'static, PdfCraftApp>, label: &str) -> egui::Rect {
}
/// Scroll the page until `what` (on screen) lies across the mode bar, then the cursor over each
/// tab it lies under: with the All tools panel closed, Read, Edit, Convert and E-Sign.
/// tab it lies under: with the All tools panel closed, Edit, Convert and E-Sign (the name field
/// starts right of All tools).
fn mode_tab_cursors(
h: &mut Harness<'static, PdfCraftApp>,
what: impl Fn(&Harness<'static, PdfCraftApp>) -> egui::Rect,
) -> [(&'static str, egui::CursorIcon); 4] {
) -> [(&'static str, egui::CursorIcon); 3] {
let page = |h: &Harness<'static, PdfCraftApp>| h.state().views[0].page_screen_rect(0).expect("on screen");
let y = what(h).center().y - page(h).top();
let tabs = mode_tab(h, "Convert").center().y;
@@ -1296,7 +1297,7 @@ fn mode_tab_cursors(
h.state_mut().views[0].goto = Some((0, (top - (tabs - y)) / page(h).height()));
h.run_steps(4);
let under = what(h);
["Read", "Edit", "Convert", "E-Sign"].map(|label| {
["Edit", "Convert", "E-Sign"].map(|label| {
let at = mode_tab(h, label).center();
assert!(under.contains(at), "{under:?} lies under {label} at {at:?}");
h.hover_at(at);
@@ -1305,12 +1306,8 @@ fn mode_tab_cursors(
})
}
const HAND_ON_EVERY_TAB: [(&str, egui::CursorIcon); 4] = [
("Read", egui::CursorIcon::PointingHand),
("Edit", egui::CursorIcon::PointingHand),
("Convert", egui::CursorIcon::PointingHand),
("E-Sign", egui::CursorIcon::PointingHand),
];
const HAND_ON_EVERY_TAB: [(&str, egui::CursorIcon); 3] =
[("Edit", egui::CursorIcon::PointingHand), ("Convert", egui::CursorIcon::PointingHand), ("E-Sign", egui::CursorIcon::PointingHand)];
/// A text field scrolled up under the mode bar leaves its tabs the hand (#2755). The field gave
/// them its I-beam, and its open editor floated over them and took their clicks.
@@ -5,6 +5,9 @@ Label = "2 Replaced"
Label = "0 Inserted"
Label = "0 Deleted"
Label = "1 Visual"
Label = "Show:"
CheckBox "Text" [on]
CheckBox "Visual" [on]
Button "Side by side"
Button "New file only"
Button "Mark as comments"
@@ -1,4 +1,5 @@
Label = "Layers"
Label = "1"
Button "Close" [off]
Button "Layer options" [off]
CheckBox "Draft notes" [on]
@@ -1,6 +1,11 @@
Label = "Pages"
Label = "2"
Button "Close" [off]
Label = "Thumbnail size"
Label = "100%"
Button "Smaller thumbnails" [off]
Slider "Thumbnail size"
Button "Larger thumbnails" [off]
Button "Page 1" [off]
Label = "1"
Button "Page 2" [off]