mirror of
https://github.com/storytold/gridcraft.git
synced 2026-11-05 01:50:01 -06:00
Objects: the Format Chart Size fields show a chart's real size and send only the edited dimension
The Width and Height fields ranged 40 to 4,000 and sent both values on every edit. egui clamps an existing value into a field's range, so a chart a file made 12,000 wide showed "Width 4000", and typing a new height sent that 4,000 as the width: the chart shrank although only its height changed, and the cap `chart.set` keeps for an existing size cannot help once the pane itself sends 4,000. Each field's range now reaches the larger of 4,000 and the chart's current size, so the field shows the real size, and a commit sends only the dimension that differs from the chart's (`chart.set` reads `width` and `height` independently). Test (real input): the_size_fields_keep_an_oversized_imported_chart_width_when_the_height_changes reopens a workbook with a 12,000-wide chart, opens Format Chart Area's Size section, checks the Width field shows 12000 and types 201 as the height: the width stays 12,000, the height is 201 and the journaled chart.set carries no width. Without the fix the field shows "Width 4000".
This commit is contained in:
@@ -308,13 +308,29 @@ fn format_chart(app: &mut SheetApp, ui: &mut Ui) {
|
||||
ui.collapsing("Size", |ui| {
|
||||
// Keep the value being typed or dragged between frames; reloading it from the chart every frame threw the edit away.
|
||||
let draft = egui::Id::unique(("gridcraft.chart_size_draft", id));
|
||||
let (mut w, mut h) = ui.data_mut(|d| d.get_temp::<(f32, f32)>(draft)).unwrap_or((chart.anchor.width, chart.anchor.height));
|
||||
let a = ui.add(egui::DragValue::new(&mut w).prefix("Width ").range(40.0..=4000.0));
|
||||
let b = ui.add(egui::DragValue::new(&mut h).prefix("Height ").range(40.0..=4000.0));
|
||||
let current = (chart.anchor.width, chart.anchor.height);
|
||||
let (mut w, mut h) = ui.data_mut(|d| d.get_temp::<(f32, f32)>(draft)).unwrap_or(current);
|
||||
// A file can make a chart larger than the 4,000 points a field otherwise reaches. The
|
||||
// range keeps such a size, so the field shows it instead of clamping it to 4,000.
|
||||
let range = |v: f32| 40.0..=v.max(4000.0);
|
||||
let a = ui.add(egui::DragValue::new(&mut w).prefix("Width ").range(range(current.0)));
|
||||
let b = ui.add(egui::DragValue::new(&mut h).prefix("Height ").range(range(current.1)));
|
||||
if a.drag_stopped() || a.lost_focus() || b.drag_stopped() || b.lost_focus() {
|
||||
ui.data_mut(|d| d.remove::<(f32, f32)>(draft));
|
||||
if !ui.input(|i| i.key_pressed(egui::Key::Escape)) {
|
||||
app.run_or_alert("chart.set", json!({"chart": id, "width": w, "height": h}));
|
||||
// Only an edited dimension is sent: the other keeps what the chart has, however
|
||||
// large a file made it.
|
||||
let mut params = serde_json::Map::new();
|
||||
params.insert("chart".into(), json!(id));
|
||||
if w != current.0 {
|
||||
params.insert("width".into(), json!(w));
|
||||
}
|
||||
if h != current.1 {
|
||||
params.insert("height".into(), json!(h));
|
||||
}
|
||||
if params.len() > 1 {
|
||||
app.run_or_alert("chart.set", Json::Object(params));
|
||||
}
|
||||
}
|
||||
} else if a.dragged() || a.has_focus() || b.dragged() || b.has_focus() {
|
||||
ui.data_mut(|d| d.insert_temp(draft, (w, h)));
|
||||
|
||||
@@ -118,6 +118,51 @@ fn dragging_the_size_field_resizes_the_chart() {
|
||||
assert!(w1 > w0 + 20.0, "width went from {w0} to {w1}");
|
||||
}
|
||||
|
||||
/// Makes the chart 12,000 wide and reopens the workbook from its XLSX bytes, the way a file can
|
||||
/// carry a chart larger than the 4,000 points the Size fields otherwise reach; returns its id.
|
||||
fn imported_oversized_chart(h: &mut Harness, id: u32) -> u32 {
|
||||
{
|
||||
let wb = std::sync::Arc::make_mut(&mut h.state_mut().session.doc_mut().unwrap().wb);
|
||||
wb.sheet_mut(0).unwrap().charts.iter_mut().find(|c| c.id == id).unwrap().anchor.width = 12_000.0;
|
||||
}
|
||||
let saved = h.state_mut().run("file.saveBytes", json!({"format": "xlsx"})).unwrap();
|
||||
h.state_mut().run("file.open", json!({"name": "wide.xlsx", "base64": saved["base64"]})).unwrap();
|
||||
h.run_steps(4);
|
||||
let id = h.state().session.doc().unwrap().wb.active().unwrap().charts[0].id;
|
||||
let (w, hh) = size(h, id);
|
||||
assert_eq!((w.round(), hh.round()), (12_000.0, 200.0), "the reader keeps the file's size");
|
||||
id
|
||||
}
|
||||
|
||||
/// A chart a file made 12,000 wide shows that width in the Size fields, and a new height sends
|
||||
/// the height alone, so nothing shrinks the width to the fields' 4,000 reach on the way.
|
||||
#[test]
|
||||
fn the_size_fields_keep_an_oversized_imported_chart_width_when_the_height_changes() {
|
||||
let (mut h, id) = fixture();
|
||||
let id = imported_oversized_chart(&mut h, id);
|
||||
open_size_fields(&mut h, id);
|
||||
let (width_value, height_field) = {
|
||||
let mut fields = h.get_all_by_role(Role::SpinButton);
|
||||
let width = fields.next().unwrap();
|
||||
let height = fields.next().unwrap();
|
||||
(width.value(), height.rect())
|
||||
};
|
||||
assert!(width_value.as_deref().is_some_and(|v| v.contains("12000")), "the field shows the file's width: {width_value:?}");
|
||||
h.input_mut().events.push(Event::PointerMoved(height_field.center()));
|
||||
button(&mut h, height_field.center(), true);
|
||||
button(&mut h, height_field.center(), false);
|
||||
for digit in ["2", "0", "1"] {
|
||||
h.input_mut().events.push(Event::Text(digit.into()));
|
||||
h.run_steps(2);
|
||||
}
|
||||
h.key_press(Key::Enter);
|
||||
h.run_steps(2);
|
||||
let (w, hh) = size(&h, id);
|
||||
assert_eq!((w.round(), hh), (12_000.0, 201.0), "the width stays and the height is the typed one");
|
||||
let (_, p) = h.state().session.journal.iter().rev().find(|(cmd, _)| cmd == "chart.set").unwrap();
|
||||
assert!(p.get("width").is_none(), "a height edit sends no width: {p}");
|
||||
}
|
||||
|
||||
fn right_click(h: &mut Harness, pos: egui::Pos2, wobble: egui::Vec2) {
|
||||
h.input_mut().events.push(Event::PointerMoved(pos));
|
||||
h.run_steps(2);
|
||||
|
||||
Reference in New Issue
Block a user