diff --git a/crates/ui-egui/src/canvas.rs b/crates/ui-egui/src/canvas.rs index 5625587a69..62fc39ccae 100644 --- a/crates/ui-egui/src/canvas.rs +++ b/crates/ui-egui/src/canvas.rs @@ -3486,7 +3486,9 @@ fn apply_frame_requests(app: &mut PdfCraftApp, index: usize, ui: &mut egui::Ui, // Read mode hides the tools (#2646), and full screen is the page and nothing else (#1459); // the quick tools come back with the window. if app.mode != crate::Mode::Read && !app.full_screen { - quick_bar(app, avail, ui); + // The page nearest the left edge, whose margin the bar sits in. + let page_left = app.views[index].screen_rects.iter().map(|(_, r)| r.left()).reduce(f32::min); + quick_bar(app, avail, page_left, ui); } if let Some((source, file, destination)) = remote_open { app.open_remote_link(source, file, destination); diff --git a/crates/ui-egui/src/canvas/bars.rs b/crates/ui-egui/src/canvas/bars.rs index 2472366672..c5b4586946 100644 --- a/crates/ui-egui/src/canvas/bars.rs +++ b/crates/ui-egui/src/canvas/bars.rs @@ -276,10 +276,23 @@ fn notice_bar(ui: &mut egui::Ui, t: &Tokens, icon: &str, icon_color: Color32, te }); } -/// The floating quick-action bar at the left edge of the document area. -pub(super) fn quick_bar(app: &mut PdfCraftApp, area: Rect, ui: &mut egui::Ui) { +const QUICK_BAR_WIDTH: f32 = 46.0; +const QUICK_BAR_EDGE: f32 = 14.0; + +/// How far from the side panel the quick-action bar stands, given the width of the margin between +/// the panel and the page: centred in it when it holds the bar, else 14 pt in (a page filling the +/// width). +fn quick_bar_offset(margin: f32) -> f32 { + // shortcut: centred in at most 100 pt of margin, so a wide margin keeps the bar by the panel. + let margin = margin.min(100.0); + if margin >= QUICK_BAR_WIDTH + 2.0 * 8.0 { (margin - QUICK_BAR_WIDTH) / 2.0 } else { QUICK_BAR_EDGE } +} + +/// The floating quick-action bar in the margin between the side panel and the page. +pub(super) fn quick_bar(app: &mut PdfCraftApp, area: Rect, page_left: Option, ui: &mut egui::Ui) { let t = Tokens::get(ui.ctx()); - let pos = area.left_top() + vec2(14.0, 14.0); + let x = quick_bar_offset(page_left.map_or(0.0, |left| left - area.left())); + let pos = area.left_top() + vec2(x, QUICK_BAR_EDGE); egui::Area::new(egui::Id::unique("quick-bar")).order(egui::Order::Middle).fixed_pos(pos).show(ui.ctx(), |ui| { egui::Frame::NONE .fill(t.card) @@ -496,3 +509,23 @@ pub(super) fn quick_bar(app: &mut PdfCraftApp, area: Rect, ui: &mut egui::Ui) { }); }); } + +#[cfg(test)] +mod tests { + use super::quick_bar_offset; + + #[test] + fn the_quick_bar_centres_in_the_margin_that_holds_it() { + assert_eq!(quick_bar_offset(72.0), 13.0); + assert_eq!(quick_bar_offset(62.0), 8.0); + // A wide margin centres in its first 100 pt, not all of it. + assert_eq!(quick_bar_offset(400.0), 27.0); + } + + #[test] + fn the_quick_bar_keeps_14_pt_in_when_the_margin_cannot_hold_it() { + for margin in [61.9, 30.0, 0.0, -50.0, f32::NEG_INFINITY] { + assert_eq!(quick_bar_offset(margin), 14.0, "{margin}"); + } + } +}