From 7f0b451e2b4aaeb7bb31f9ec10670ac862a9d1f5 Mon Sep 17 00:00:00 2001 From: RiceDee <345114586+RiceDee@users.noreply.github.com> Date: Fri, 23 Oct 2026 15:48:26 +1100 Subject: [PATCH] fix(ui): a narrow added-text box keeps the edge its lines share The editor of a box narrower than its 60-point minimum was anchored by the box's own alignment. A box whose lines are all right-aligned (or centred) on their own while the box stays Left wasn't anchored, so its text was placed against the wider editor's edge, past the box. The lines are now compared with each other and the editor keeps the edge they share. --- crates/ui-egui/src/content_ui.rs | 10 ++++++---- crates/ui-egui/tests/it/content.rs | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/crates/ui-egui/src/content_ui.rs b/crates/ui-egui/src/content_ui.rs index 58f954a895..5e4f2975aa 100644 --- a/crates/ui-egui/src/content_ui.rs +++ b/crates/ui-egui/src/content_ui.rs @@ -565,10 +565,12 @@ pub(crate) fn editor(ctx: &egui::Context, view: &mut DocView, info: &DocInfo, ad // shortcut: lines aligned differently from each other in a box under 60 points keep the // editor's left edge; anchor each line on its own if such boxes turn out to matter. let width = r.width().max(60.0); - let uniform = (0..pdfcraft_engine::paragraph_align::count(&draft.text)).all(|i| draft.style.paragraph_align(i) == draft.style.align); - let anchor = match draft.style.align { - pdfcraft_engine::TextAlign::Center if uniform => 0.5, - pdfcraft_engine::TextAlign::Right if uniform => 1.0, + // The alignment every line shares, its own or the box's. + let first = draft.style.paragraph_align(0); + let shared = (1..pdfcraft_engine::paragraph_align::count(&draft.text)).all(|i| draft.style.paragraph_align(i) == first).then_some(first); + let anchor = match shared { + Some(pdfcraft_engine::TextAlign::Center) => 0.5, + Some(pdfcraft_engine::TextAlign::Right) => 1.0, _ => 0.0, }; let at = r.min - egui::vec2((width - r.width()) * anchor, 0.0); diff --git a/crates/ui-egui/tests/it/content.rs b/crates/ui-egui/tests/it/content.rs index a4024e513e..0798abdff5 100644 --- a/crates/ui-egui/tests/it/content.rs +++ b/crates/ui-egui/tests/it/content.rs @@ -760,6 +760,29 @@ fn the_text_editor_aligns_a_narrow_box_to_its_own_edge() { assert!(inside > 20 && past == 0, "the text is drawn in its box ({inside} dark pixels in it, {past} past its right edge)"); } +/// The same when the line is right-aligned on its own while the box keeps Left: all its lines +/// share one alignment, so the editor keeps the box's right edge for them. +#[test] +fn the_text_editor_aligns_a_narrow_box_whose_lines_share_an_alignment() { + let _gpu = gpu(); + let mut h = harness(); + let rect = [40.0, 195.0, 60.0, 210.0]; + let text = pdfcraft_engine::AddedText { rect, text: "Hi".into(), aligns: vec![Some(pdfcraft_engine::TextAlign::Right)], ..Default::default() }; + assert_eq!(text.align, pdfcraft_engine::TextAlign::Left); + assert!(h.state_mut().apply_edit(pdfcraft_engine::Edit::AddText { page: 0, text })); + assert!(h.state_mut().execute("edit.text")); + h.run_steps(3); + let point = at(&h, 50.0, 195.0); + click(&mut h, point); + assert_eq!(h.state().views[0].content.draft.as_ref().and_then(|d| d.index), Some(0), "the editor opened on the text"); + h.run_steps(3); + let r = item_on_screen(&h, rect); + let pixels = h.render().unwrap(); + let inside = ink(&pixels, r); + let past = ink(&pixels, egui::Rect::from_min_max(pos2(r.right() + 2.0, r.min.y), pos2(r.right() + 40.0, r.max.y))); + assert!(inside > 20 && past == 0, "the text is drawn in its box ({inside} dark pixels in it, {past} past its right edge)"); +} + fn mode_tab(h: &Harness<'static, PdfCraftApp>, label: &str) -> egui::Rect { h.get_all_by_role_and_label(egui::accesskit::Role::Button, label).map(|n| n.rect()).find(|r| r.bottom() < 120.0).expect("a mode tab") }