Merge pull request #695 from marcoarnulfo:fix/formula-header-point

This commit is contained in:
Brandon Thomas 2026-10-12 23:48:52 -04:00
commit e548a2e705
2 changed files with 91 additions and 0 deletions

View File

@ -1793,6 +1793,9 @@ fn interact(app: &mut SheetApp, ui: &mut egui::Ui, resp: &egui::Response, geo: &
return;
}
let c = geo.col_at(sh, p.x);
if point_header(app, wb, sh, RangeRef::cols(c, c)) {
return;
}
if resp.drag_started()
&& !mods.any()
&& sel.ranges.len() == 1
@ -1813,6 +1816,9 @@ fn interact(app: &mut SheetApp, ui: &mut egui::Ui, resp: &egui::Response, geo: &
return;
}
let r = geo.row_at(sh, p.y);
if point_header(app, wb, sh, RangeRef::rows(r, r)) {
return;
}
let range = if mods.shift { RangeRef::rows(sel.anchor.row.min(r), sel.anchor.row.max(r)) } else { RangeRef::rows(r, r) };
select_ranges(app, range, mods.command, CellRef::new(r, geo.col_at(sh, geo.cells.left() + 1.0)));
app.grid.drag = Drag::Rows(if mods.shift { sel.anchor.row } else { r });
@ -2101,6 +2107,16 @@ fn interact(app: &mut SheetApp, ui: &mut egui::Ui, resp: &egui::Response, geo: &
keyboard(app, &ctx, resp, geo, sh);
}
/// Point mode on a header: inserts the whole-column or whole-row reference instead of selecting.
fn point_header(app: &mut SheetApp, wb: &Workbook, sh: &Sheet, range: RangeRef) -> bool {
let Some(ed) = app.editor.as_mut().filter(|ed| ed.can_point()) else { return false };
let r = range.a1();
let r = if ed.sheet != wb.active_sheet { format!("{}!{r}", gridcraft_engine::formula::quote_sheet(&sh.name)) } else { r };
ed.insert_ref(&r);
ed.request_focus = true;
true
}
fn select_to_pointer(app: &mut SheetApp, geo: &Geo, sh: &Sheet, wb: &Workbook, p: Pos2) {
let cell = CellRef::new(
geo.row_at(sh, p.y.clamp(geo.cells.top() + 1.0, geo.cells.bottom() - 1.0)),

View File

@ -0,0 +1,75 @@
//! Point mode on the headers: while a formula waits for a reference, a header click inserts a
//! whole-column or whole-row reference, driven through real egui pointer events.
use egui::{Event, Modifiers, PointerButton, Pos2, pos2, vec2};
use gridcraft_engine::Session;
use gridcraft_ui_egui::{SheetApp, grid::Geo};
use serde_json::json;
fn harness() -> egui_kittest::Harness<'static, SheetApp> {
let mut session = Session::new();
session.new_workbook();
session.execute("selection.set", json!({"range": "F8"})).unwrap();
let mut h = egui_kittest::Harness::builder().with_step_dt(1.0 / 60.0).with_size(vec2(1200.0, 800.0)).build_ui_state(
|ui, app: &mut SheetApp| {
app.logic(ui.ctx());
app.ui(ui);
},
SheetApp::new(session, Default::default()),
);
h.run_steps(4);
h.state_mut().begin_edit(Some("=SUM(".into()), false);
h.run_steps(2);
h
}
fn header_center(h: &egui_kittest::Harness<'_, SheetApp>, rows: bool, index: u32) -> Pos2 {
let app = h.state();
let sheet = app.session.active().unwrap().wb.active().unwrap();
let geo = Geo::new(sheet, app.grid.rect.unwrap(), app.view().scroll);
if rows {
pos2(geo.rect.left() + geo.header_w * 0.5, geo.y(sheet, index) + sheet.row_height(index) * geo.z * 0.5)
} else {
pos2(geo.x(sheet, index) + sheet.col_width(index) * geo.z * 0.5, geo.rect.top() + geo.header_h * 0.5)
}
}
fn click(h: &mut egui_kittest::Harness<'_, SheetApp>, pos: Pos2) {
for pressed in [true, false] {
h.input_mut()
.events
.extend([Event::PointerMoved(pos), Event::PointerButton { pos, button: PointerButton::Primary, pressed, modifiers: Modifiers::NONE }]);
h.step();
}
h.run_steps(2);
}
#[test]
fn column_header_click_inserts_a_column_reference() {
let mut h = harness();
let at = header_center(&h, false, 2);
click(&mut h, at);
let app = h.state();
assert_eq!(app.editor.as_ref().map(|e| e.text.as_str()), Some("=SUM(C:C"));
assert_eq!(app.session.active().unwrap().selection.current().a1(), "F8");
}
#[test]
fn row_header_click_inserts_a_row_reference() {
let mut h = harness();
let at = header_center(&h, true, 3);
click(&mut h, at);
let app = h.state();
assert_eq!(app.editor.as_ref().map(|e| e.text.as_str()), Some("=SUM(4:4"));
assert_eq!(app.session.active().unwrap().selection.current().a1(), "F8");
}
#[test]
fn a_second_header_click_replaces_the_pointed_reference() {
let mut h = harness();
let first = header_center(&h, false, 2);
click(&mut h, first);
let second = header_center(&h, false, 4);
click(&mut h, second);
assert_eq!(h.state().editor.as_ref().map(|e| e.text.as_str()), Some("=SUM(E:E"));
}