mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-06 02:21:45 +00:00
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:
2 files changed
+62
-5
No files matched your search
@@ -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 {
|
||||
|
||||
@@ -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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user