mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-27 03:27:21 -06:00
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
bc5f6ca8ee
commit
76037a77ac
@@ -3361,6 +3361,7 @@ pub fn document_area(app: &mut PdfCraftApp, index: usize, ui: &mut egui::Ui) {
|
||||
});
|
||||
}
|
||||
find_bar(view, info.pages.len(), avail, ui, &t);
|
||||
page_size_hint(view, info, units, avail, unobstructed, ui, &t);
|
||||
if tool == QuickTool::EnhanceCamera {
|
||||
crate::camera_ui::bar(ui.ctx(), view, avail, &t, can_modify);
|
||||
}
|
||||
@@ -3709,6 +3710,37 @@ fn set_layers(app: &mut PdfCraftApp, index: usize, changes: &[(LayerOp, (u32, u1
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether `p` lies in the bottom-left quadrant of `area`, where the page size shows (#1855).
|
||||
fn in_size_hint_zone(area: Rect, p: Pos2) -> bool {
|
||||
p.x >= area.min.x && p.x < area.center().x && p.y > area.center().y && p.y <= area.max.y
|
||||
}
|
||||
|
||||
/// The current page's size, floating at the bottom-left of the document area while the pointer is
|
||||
/// in that quadrant, as Acrobat does. Same formatter and unit as Document Properties.
|
||||
fn page_size_hint(view: &DocView, info: &DocInfo, units: crate::units::Unit, area: Rect, unobstructed: bool, ui: &mut egui::Ui, t: &Tokens) {
|
||||
let Some(page) = info.pages.get(view.current) else { return };
|
||||
let inside = unobstructed && ui.input(|i| i.pointer.hover_pos()).is_some_and(|p| in_size_hint_zone(area, p));
|
||||
if !inside {
|
||||
return;
|
||||
}
|
||||
let text = units.size(f64::from(page.width), f64::from(page.height));
|
||||
egui::Area::new(egui::Id::new("page-size-hint"))
|
||||
.order(egui::Order::Foreground)
|
||||
.interactable(false)
|
||||
.pivot(egui::Align2::LEFT_BOTTOM)
|
||||
.fixed_pos(area.left_bottom() + vec2(14.0, -14.0))
|
||||
.show(ui.ctx(), |ui| {
|
||||
egui::Frame::NONE
|
||||
.fill(t.card)
|
||||
.stroke(Stroke::new(1.0, t.border))
|
||||
.corner_radius(CornerRadius::same(6))
|
||||
.inner_margin(egui::Margin::symmetric(8, 4))
|
||||
.show(ui, |ui| {
|
||||
ui.add(egui::Label::new(egui::RichText::new(text).color(t.text)).selectable(false));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Acrobat-style floating find bar at the top-right of the document area.
|
||||
fn find_bar(view: &mut DocView, pages: usize, area: Rect, ui: &mut egui::Ui, t: &Tokens) {
|
||||
let Some(find) = view.find.as_mut() else { return };
|
||||
@@ -4658,6 +4690,16 @@ pub(crate) fn texture_image(size: [usize; 2], pixels: pdfcraft_render::Pixels) -
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn page_size_hint_zone_is_the_bottom_left_quadrant() {
|
||||
let area = Rect::from_min_max(pos2(100.0, 50.0), pos2(500.0, 450.0));
|
||||
assert!(in_size_hint_zone(area, pos2(110.0, 440.0)));
|
||||
assert!(!in_size_hint_zone(area, pos2(110.0, 100.0)), "top-left");
|
||||
assert!(!in_size_hint_zone(area, pos2(400.0, 440.0)), "bottom-right");
|
||||
assert!(!in_size_hint_zone(area, pos2(50.0, 440.0)), "outside");
|
||||
assert!(!in_size_hint_zone(area, pos2(f32::NAN, 440.0)));
|
||||
}
|
||||
|
||||
use super::*;
|
||||
|
||||
fn annotation(fill_sign: bool) -> pdfcraft_render::Annotation {
|
||||
|
||||
@@ -1576,3 +1576,26 @@ fn click_and_drag_refuse_coordinates_that_overflow_like_move() {
|
||||
assert_eq!(ok(&mut h, &c, "ui.click", json!({ "x": x, "y": y }))["clicked"], json!([x, y]));
|
||||
ok(&mut h, &c, "ui.drag", json!({ "from": [x, y], "to": [x + 10.0, y], "steps": 2 }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn page_size_shows_while_the_pointer_is_in_the_bottom_left_quadrant() {
|
||||
let (mut h, _c) = harness();
|
||||
let area = h.state().views[0].viewport_rect();
|
||||
let shown = |h: &Harness<'static, PdfCraftApp>| {
|
||||
let layer = egui::LayerId::new(egui::Order::Foreground, egui::Id::new("page-size-hint"));
|
||||
h.ctx.memory(|m| m.areas().visible_last_frame(&layer))
|
||||
};
|
||||
let away = area.center() + egui::vec2(300.0, -200.0);
|
||||
h.event(egui::Event::PointerMoved(away));
|
||||
h.run_steps(3);
|
||||
assert!(!shown(&h), "top-right: hidden");
|
||||
h.event(egui::Event::PointerMoved(area.left_bottom() + egui::vec2(80.0, -80.0)));
|
||||
h.run_steps(3);
|
||||
assert!(shown(&h), "bottom-left: shown");
|
||||
if let Ok(dir) = std::env::var("PDFCRAFT_SHOT_DIR") {
|
||||
h.render().unwrap().save(format!("{dir}/page-size-hint.png")).unwrap();
|
||||
}
|
||||
h.event(egui::Event::PointerMoved(away));
|
||||
h.run_steps(3);
|
||||
assert!(!shown(&h), "pointer left: hidden again");
|
||||
}
|
||||
|
||||
@@ -1193,6 +1193,18 @@ tools = []
|
||||
evidence = ["crates/ui-egui/tests/comments.rs::hovering_a_comment_shows_its_author_and_text"]
|
||||
notes = "a popup with the author and the comment text, as Acrobat shows"
|
||||
|
||||
[[feature]]
|
||||
id = "view.page-size-hover"
|
||||
title = "Page size on hover (bottom-left of the page view)"
|
||||
area = "B"
|
||||
tier = "P2"
|
||||
milestone = "M3"
|
||||
status = "shipped"
|
||||
commands = []
|
||||
tools = []
|
||||
evidence = ["crates/ui-egui/tests/control.rs::page_size_shows_while_the_pointer_is_in_the_bottom_left_quadrant", "crates/ui-egui/src/canvas.rs::page_size_hint_zone_is_the_bottom_left_quadrant"]
|
||||
notes = "While the pointer is in the bottom-left quadrant of the page view, a small label shows the current page's size (after /Rotate and /UserUnit) in the Preferences unit, formatted as in Document Properties (#1855). It never takes clicks and hides when the pointer leaves. Acrobat's trigger is the corner itself and may differ in exact area and wording (not compared with real Acrobat); the size of the current page only, not of the page under the pointer; no headless tool (page sizes are in document info)."
|
||||
|
||||
[[feature]]
|
||||
id = "view.document-tabs"
|
||||
title = "Tabbed documents"
|
||||
|
||||
Reference in New Issue
Block a user