mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-25 11:16:49 -06:00
The corner drag now grabs the chart where the press began and the selected object's corner shows a resize cursor. The Format Chart Area Size fields, chart and axis title fields and the Table Name field reloaded their value from the workbook every frame, so typed or dragged edits were thrown away; they now keep a draft until the field loses focus (Escape cancels, like sheet tab rename).
120 lines
4.7 KiB
Rust
120 lines
4.7 KiB
Rust
//! Resizing a chart by dragging its bottom-right corner or with the Format Chart Area Size fields, through real input.
|
|
|
|
use egui::{Event, Key, Modifiers, PointerButton, accesskit::Role, pos2, vec2};
|
|
use egui_kittest::kittest::Queryable as _;
|
|
use gridcraft_engine::Session;
|
|
use gridcraft_engine::core::CellRef;
|
|
use gridcraft_ui_egui::{SheetApp, grid::Geo};
|
|
use serde_json::json;
|
|
|
|
type Harness = egui_kittest::Harness<'static, SheetApp>;
|
|
|
|
fn fixture() -> (Harness, u32) {
|
|
let mut session = Session::new();
|
|
session.new_workbook();
|
|
session.execute("cell.set", json!({"cell": "A1", "input": "1"})).unwrap();
|
|
session.execute("cell.set", json!({"cell": "A2", "input": "2"})).unwrap();
|
|
session.execute("selection.set", json!({"range": "A1:A2"})).unwrap();
|
|
let chart = session.execute("insert.chart", json!({"type": "column", "at": "D3", "width": 300, "height": 200})).unwrap();
|
|
let id = chart["chart"].as_u64().unwrap() as u32;
|
|
let mut h = egui_kittest::Harness::builder().with_size(vec2(1200.0, 800.0)).build_ui_state(
|
|
|ui, app: &mut SheetApp| {
|
|
let ctx = ui.ctx().clone();
|
|
app.logic(&ctx);
|
|
app.ui(ui);
|
|
},
|
|
SheetApp::new(session, Default::default()),
|
|
);
|
|
h.run_steps(4);
|
|
(h, id)
|
|
}
|
|
|
|
fn size(h: &Harness, id: u32) -> (f32, f32) {
|
|
let a = h.state().session.doc().unwrap().wb.active().unwrap().charts.iter().find(|c| c.id == id).unwrap().anchor;
|
|
(a.width, a.height)
|
|
}
|
|
|
|
fn corner(h: &Harness, id: u32) -> egui::Pos2 {
|
|
let app = h.state();
|
|
let sh = app.session.doc().unwrap().wb.active().unwrap();
|
|
let geo = Geo::new(sh, app.grid.rect.unwrap(), app.view().scroll);
|
|
let a = sh.charts.iter().find(|c| c.id == id).unwrap().anchor;
|
|
let min = geo.cell_rect(sh, CellRef::parse("D3").unwrap()).min + vec2(a.dx, a.dy) * geo.z;
|
|
min + vec2(a.width, a.height) * geo.z
|
|
}
|
|
|
|
fn button(h: &mut Harness, pos: egui::Pos2, pressed: bool) {
|
|
h.input_mut().events.push(Event::PointerButton { pos, button: PointerButton::Primary, pressed, modifiers: Modifiers::NONE });
|
|
h.run_steps(2);
|
|
}
|
|
|
|
#[test]
|
|
fn dragging_the_corner_handle_resizes_the_chart() {
|
|
let (mut h, id) = fixture();
|
|
let (w0, h0) = size(&h, id);
|
|
let start = corner(&h, id);
|
|
// Select the chart first, as the user does before grabbing a handle.
|
|
let inside = start - vec2(40.0, 40.0);
|
|
h.input_mut().events.push(Event::PointerMoved(inside));
|
|
h.run_steps(2);
|
|
button(&mut h, inside, true);
|
|
button(&mut h, inside, false);
|
|
assert_eq!(h.state().selected_chart, Some(id));
|
|
|
|
h.input_mut().events.push(Event::PointerMoved(start));
|
|
h.run_steps(2);
|
|
assert_eq!(h.output().platform_output.cursor_icon, egui::CursorIcon::ResizeNwSe, "the corner shows a resize cursor");
|
|
button(&mut h, start, true);
|
|
// The pointer moves well past the drag threshold in one step, like a quick drag.
|
|
let end = start + vec2(60.0, 30.0);
|
|
h.input_mut().events.push(Event::PointerMoved(pos2(end.x, end.y)));
|
|
h.run_steps(3);
|
|
button(&mut h, end, false);
|
|
let (w1, h1) = size(&h, id);
|
|
assert!(w1 > w0 + 40.0 && h1 > h0 + 20.0, "chart grew from {w0}x{h0} to {w1}x{h1}");
|
|
}
|
|
|
|
/// Opens Format Chart Area for the chart and expands its Size section; returns the Width field's rect.
|
|
fn open_size_fields(h: &mut Harness, id: u32) -> egui::Rect {
|
|
h.state_mut().selected_chart = Some(id);
|
|
h.state_mut().grid.pane = Some("formatChart".into());
|
|
h.run_steps(2);
|
|
h.get_by_role_and_label(Role::Button, "Size").click();
|
|
h.run_steps(2);
|
|
h.get_all_by_role(Role::SpinButton).next().unwrap().rect()
|
|
}
|
|
|
|
#[test]
|
|
fn typing_a_width_in_the_size_field_resizes_the_chart() {
|
|
let (mut h, id) = fixture();
|
|
let (_, h0) = size(&h, id);
|
|
let field = open_size_fields(&mut h, id);
|
|
h.input_mut().events.push(Event::PointerMoved(field.center()));
|
|
button(&mut h, field.center(), true);
|
|
button(&mut h, field.center(), false);
|
|
// Clicking the field selects its text; each keystroke must survive the next frame.
|
|
for digit in ["6", "4", "0"] {
|
|
h.input_mut().events.push(Event::Text(digit.into()));
|
|
h.run_steps(2);
|
|
}
|
|
h.key_press(Key::Enter);
|
|
h.run_steps(2);
|
|
assert_eq!(size(&h, id), (640.0, h0));
|
|
}
|
|
|
|
#[test]
|
|
fn dragging_the_size_field_resizes_the_chart() {
|
|
let (mut h, id) = fixture();
|
|
let (w0, _) = size(&h, id);
|
|
let field = open_size_fields(&mut h, id);
|
|
h.input_mut().events.push(Event::PointerMoved(field.center()));
|
|
button(&mut h, field.center(), true);
|
|
for step in 1..=6 {
|
|
h.input_mut().events.push(Event::PointerMoved(field.center() + vec2(10.0 * step as f32, 0.0)));
|
|
h.run_steps(1);
|
|
}
|
|
button(&mut h, field.center() + vec2(60.0, 0.0), false);
|
|
let (w1, _) = size(&h, id);
|
|
assert!(w1 > w0 + 20.0, "width went from {w0} to {w1}");
|
|
}
|