Merge PR #2703: Go to page brings the page into view horizontally too

crates/ui-egui/src/canvas.rs: goto branch keeps #2595's clamped vertical offset, then #2703's horizontal block
This commit is contained in:
aiongg
2026-10-16 14:02:30 +00:00
2 changed files with 36 additions and 0 deletions
+12
View File
@@ -2576,6 +2576,18 @@ pub fn document_area(app: &mut PdfCraftApp, index: usize, ui: &mut egui::Ui) {
// scroll bars float.)
let max_y = (content_h - avail.height()).max(0.0);
scroll = scroll.vertical_scroll_offset((r.top() - y_shift - GAP + frac * r.height()).max(0.0).min(max_y));
// Horizontally too, as Acrobat does (#2665): beside a much wider page the others sit off
// to one side. A page already shown whole, or one filling the window's width, keeps the
// scroll, so paging through a zoomed-in document stays on the same column. Otherwise a
// page that fits is centred, and a wider one scrolled just far enough to fill the window.
// The page counts with its side gutters, which keep its edge clear of the floating
// quick-action bar as the layout does.
let (x, w) = (view.last_scroll.x, avail.width());
let (left, right) = (r.left() - SIDE, r.right() + SIDE);
let target = if right - left <= w { if left >= x && right <= x + w { x } else { r.center().x - w / 2.0 } } else { x.clamp(left, right - w) };
if (target - x).abs() > 0.5 {
scroll = scroll.horizontal_scroll_offset(target.clamp(0.0, (content_w - w).max(0.0)));
}
}
let ppp = ui.ctx().pixels_per_point();
let scale = view.render_scale(ppp);
+24
View File
@@ -1860,3 +1860,27 @@ fn arrow_keys_follow_the_scroll_speed_preference() {
let (slow, normal, fast) = (lines_to_page_2("slow"), lines_to_page_2("normal"), lines_to_page_2("fast"));
assert!(fast * 3 < normal * 2 && normal * 3 < slow * 2, "presses to page 2: slow {slow}, normal {normal}, fast {fast}");
}
/// #2665: next to a very wide page the normal pages sit far to its right, outside the window.
/// Going to one changed the page counter but kept the horizontal scroll, so it stayed out of
/// sight; as in Acrobat, it is brought into view.
#[test]
fn go_to_page_brings_the_page_into_view_horizontally() {
use pdfcraft_ui_egui::canvas::Fit;
let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).build_eframe(|_cc| {
let mut app = PdfCraftApp::new();
app.set_option("language", "en").unwrap();
app.open_bytes("wide.pdf", None, sized_fixture(&[(595, 842), (595, 842), (595, 842), (6000, 2000)])).unwrap();
app.views[0].fit = Fit::None;
app.views[0].zoom = 1.0;
app
});
h.run_steps(4);
assert!(h.state().views[0].page_screen_rect(0).is_none(), "page 1 starts off-screen, right of the window");
h.state_mut().views[0].go_to_page(2);
h.run_steps(4);
let v = &h.state().views[0];
assert_eq!(v.current, 2);
let (r, vp) = (v.page_screen_rect(2).expect("page 3 on screen"), v.viewport_rect());
assert!(r.left() >= vp.left() && r.right() <= vp.right(), "page 3 at {r:?}, viewport {vp:?}");
}