Merge pull request #5638 from RiceDee/fix/quick-bar-centred-in-margin

fix(ui): centre the quick-tools bar in the margin beside the page (#5635)
This commit is contained in:
FredApps authored and GitHub committed 2026-11-02 14:45:58 +01:00
commit 2d4e317a58
2 files changed
+62 -5

No files matched your search

+3 -1
View File
@@ -4055,7 +4055,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);
crate::hotbar::show(app, avail, ui.ctx());
}
if let Some((source, file, destination)) = remote_open {
+59 -4
View File
@@ -276,8 +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) {
/// The bar's narrowest form: one 32 pt button, 6 pt margins and a 1 pt border each side.
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 and the bar's own width: centred in the margin when it holds the bar,
/// else 14 pt in (a page filling the width). With no page on screen the caller passes a margin of 0,
/// which is 14 pt too.
fn quick_bar_offset(margin: f32, width: f32) -> f32 {
// shortcut: centred in at most 100 pt of margin, so a wide margin keeps the bar by the panel.
// `f32::min` returns the other operand for NaN, which would pass the fit check below.
let margin = if margin.is_nan() { 0.0 } else { margin.min(100.0) };
if margin >= width + 2.0 * 8.0 { (margin - 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<f32>, ui: &mut egui::Ui) {
let t = Tokens::get(ui.ctx());
let mut offset = vec2(0.0, 0.0);
if app.hotbar.full_side {
@@ -287,8 +302,13 @@ pub(super) fn quick_bar(app: &mut PdfCraftApp, area: Rect, ui: &mut egui::Ui) {
_ => {}
}
}
let pos = area.left_top() + vec2(14.0, 14.0) + offset;
egui::Area::new(egui::Id::unique("quick-bar")).order(egui::Order::Middle).fixed_pos(pos).show(ui.ctx(), |ui| {
let id = egui::Id::unique("quick-bar");
// Last frame's bar: Fill & Sign's Text and Date tools add a wider row of controls to it.
let width = ui.ctx().memory(|m| m.area_rect(id)).map_or(QUICK_BAR_WIDTH, |bar| bar.width().max(QUICK_BAR_WIDTH));
// The margin starts past a hotbar docked on the left.
let x = quick_bar_offset(page_left.map_or(0.0, |left| left - area.left() - offset.x), width);
let pos = area.left_top() + vec2(x, QUICK_BAR_EDGE) + offset;
egui::Area::new(id).order(egui::Order::Middle).fixed_pos(pos).show(ui.ctx(), |ui| {
egui::Frame::NONE
.fill(t.card)
.stroke(Stroke::new(1.0, t.border))
@@ -510,3 +530,38 @@ 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, 46.0), 13.0);
assert_eq!(quick_bar_offset(62.0, 46.0), 8.0);
// A wide margin centres in its first 100 pt, not all of it.
assert_eq!(quick_bar_offset(400.0, 46.0), 27.0);
}
#[test]
fn the_margin_that_just_holds_the_bar_centres_and_a_point_less_does_not() {
// 46 pt of bar and 8 pt to spare each side: 62 pt.
assert_eq!(quick_bar_offset(62.0, 46.0), 8.0);
assert_eq!(quick_bar_offset(61.0, 46.0), 14.0);
assert_eq!(quick_bar_offset(1000.0, 46.0), 27.0);
}
#[test]
fn a_wider_quick_bar_centres_by_its_own_width_and_needs_a_wider_margin() {
// Fill & Sign's Text tool widens the bar to 70 pt: it centres by that, and 72 pt no longer holds it.
assert_eq!(quick_bar_offset(120.0, 70.0), 15.0);
assert_eq!(quick_bar_offset(72.0, 70.0), 14.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, f32::NAN] {
assert_eq!(quick_bar_offset(margin, 46.0), 14.0, "{margin}");
}
}
}