From 903bbb096d874a5bd0f27cb324129a2a92c8d42b Mon Sep 17 00:00:00 2001 From: lloyd <34131158+LloydNicholson@users.noreply.github.com> Date: Fri, 9 Oct 2026 17:23:15 +0200 Subject: [PATCH] Issue #51: General numbers fit by the cell's own font, not 11pt grid.rs measured the digit width once, for an 11pt cell font, and display_text judged how many General digits fit from that whatever the cell's size. 9pt marks such as 100 in columns with a stored width of 4 (common in mark sheets) came out as ##. The width is now measured per cell with its own font and size, as print.rs already does; the shared 11pt measurement and its paint_quadrant parameter go away. Test: a 9pt 100 in a 28px column draws in full, while 123456789 next to it still shows ####. Fails before the fix. Co-Authored-By: Claude Opus 5.5 --- crates/ui-egui/src/grid.rs | 18 ++++-------------- crates/ui-egui/tests/interaction.rs | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/crates/ui-egui/src/grid.rs b/crates/ui-egui/src/grid.rs index 4b326cc36..30e849333 100644 --- a/crates/ui-egui/src/grid.rs +++ b/crates/ui-egui/src/grid.rs @@ -373,7 +373,6 @@ pub fn show(app: &mut SheetApp, ui: &mut egui::Ui) { let painter = ui.painter_at(rect); painter.rect_filled(rect, 0.0, t.grid_bg); let mut cf = CfCache::new(); - let char_w = ui.fonts_mut(|f| f.glyph_width(&FontId::new(11.0 * 96.0 / 72.0 * geo.z, egui::FontFamily::Name(theme::CELL.into())), '0')).max(1.0); // Quadrants: (rows, cols, clip). let (sr0, sr1) = geo.scroll_rows(sh); let (sc0, sc1) = geo.scroll_cols(sh); @@ -395,7 +394,7 @@ pub fn show(app: &mut SheetApp, ui: &mut egui::Ui) { continue; } let p = painter.with_clip_rect(*clip); - paint_quadrant(&p, &geo, &wb, si, sh, *rows, *cols, char_w, &mut cf, &t); + paint_quadrant(&p, &geo, &wb, si, sh, *rows, *cols, &mut cf, &t); paint_selection(&p, &geo, sh, &sel, &t, app); } // Freeze lines. @@ -431,18 +430,7 @@ pub fn show(app: &mut SheetApp, ui: &mut egui::Ui) { } #[allow(clippy::too_many_arguments)] -fn paint_quadrant( - p: &Painter, - geo: &Geo, - wb: &Workbook, - si: usize, - sh: &Sheet, - rows: (u32, u32), - cols: (u32, u32), - char_w: f32, - cf: &mut CfCache, - t: &Tokens, -) { +fn paint_quadrant(p: &Painter, geo: &Geo, wb: &Workbook, si: usize, sh: &Sheet, rows: (u32, u32), cols: (u32, u32), cf: &mut CfCache, t: &Tokens) { let z = geo.z; let (r0, r1) = rows; let (c0, c1) = cols; @@ -560,6 +548,8 @@ fn paint_quadrant( let size = st.font.size * 96.0 / 72.0 * z; let fam = theme::cell_family(&st.font.name, st.font.bold, st.font.italic); let font = FontId::new(size, fam); + // Digits fit by the cell's own font and size, not the default 11pt (9pt marks in narrow columns). + let char_w = p.layout_no_wrap("0".to_string(), font.clone(), Color32::PLACEHOLDER).size().x.max(1.0); let avail_w = rect.right() - text_left; let (text, ncolor, numeric, fill_char) = display_text(wb, sh, c, &v, st, avail_w / z.max(0.1) * z, char_w); if text.is_empty() { diff --git a/crates/ui-egui/tests/interaction.rs b/crates/ui-egui/tests/interaction.rs index 74bbeb495..730cdae23 100644 --- a/crates/ui-egui/tests/interaction.rs +++ b/crates/ui-egui/tests/interaction.rs @@ -146,3 +146,26 @@ fn column_autocomplete_completes_on_enter() { key(&mut h, Key::Enter, Modifiers::NONE); assert_eq!(value(&h, "A5"), Value::from("Ea")); } + +#[test] +fn general_numbers_fit_by_the_cells_own_font() { + // 9pt marks in narrow columns (a stored width of 4, i.e. 28px; common in mark sheets): "100" fits. + let mut s = blank(); + s.execute("range.setValues", json!({"range": "A1", "values": [[100, 123456789]]})).unwrap(); + s.execute("home.fontSize", json!({"range": "A1:B1", "size": 9})).unwrap(); + s.execute("home.columnWidth", json!({"cols": "A:B", "width": 28})).unwrap(); + s.execute("selection.set", json!({"cell": "C3"})).unwrap(); + let h = harness(s); + let texts: Vec = h + .output() + .shapes + .iter() + .filter_map(|c| match &c.shape { + egui::Shape::Text(t) => Some(t.galley.job.text.clone()), + _ => None, + }) + .collect(); + assert!(texts.iter().any(|t| t == "100"), "100 drawn in full: {texts:?}"); + // A number that really doesn't fit still shows #### (once: only B1). + assert_eq!(texts.iter().filter(|t| t.starts_with('#')).count(), 1, "{texts:?}"); +}