From 3f8167719ac836536e4697a8a61604cf2b93db6a Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Sat, 17 Oct 2026 05:15:25 +0200 Subject: [PATCH] Keep chart source range in step with inserted and deleted lines Found while testing crates/engine/src/cmd/sheet.rs:216-238 (rewrite never updates Chart.source); used by crates/engine/src/cmd/insert.rs:849 (chart_switch) Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/engine/src/cmd/sheet.rs | 2 ++ crates/engine/src/tests.rs | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/crates/engine/src/cmd/sheet.rs b/crates/engine/src/cmd/sheet.rs index 7870dee4e..4f66bb1d6 100644 --- a/crates/engine/src/cmd/sheet.rs +++ b/crates/engine/src/cmd/sheet.rs @@ -226,6 +226,8 @@ fn rewrite(wb: &mut gridcraft_model::Workbook, target: &str, e: &Edit) { } }; for ch in sh.charts.iter_mut() { + // The source block moves with its cells; one that was deleted is dropped. + ch.source = ch.source.as_deref().map(fix).filter(|s| !s.contains("#REF!")); for se in ch.series.iter_mut() { se.values = fix(&se.values); se.categories = se.categories.as_deref().map(fix); diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index ae499a189..27caa0f4c 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -2370,6 +2370,28 @@ fn switch_row_column_with_whole_column_refs_is_bounded() { assert_eq!(s.doc().unwrap().wb.active().unwrap().charts[0].series.len(), 2); } +#[test] +fn switch_row_column_follows_inserted_and_deleted_lines() { + let mut s = s(); + s.execute("range.setValues", json!({"range": "A1", "values": [["", "Q1", "Q2"], ["North", 1, 2], ["South", 3, 4]]})).unwrap(); + s.execute("insert.chart", json!({"range": "A1:C3", "type": "column", "at": "F1"})).unwrap(); + s.execute("home.insertRows", json!({"rows": "1:1"})).unwrap(); + assert_eq!(s.doc().unwrap().wb.active().unwrap().charts[0].source.as_deref(), Some("Sheet1!A2:C4")); + s.execute("chart.switchRowColumn", json!({})).unwrap(); + let c = s.doc().unwrap().wb.active().unwrap().charts[0].clone(); + let values: Vec<&str> = c.series.iter().map(|x| x.values.as_str()).collect(); + assert_eq!(values, ["Sheet1!$B$3:$C$3", "Sheet1!$B$4:$C$4"]); + let names: Vec> = c.series.iter().map(|x| x.name.as_deref()).collect(); + assert_eq!(names, [Some("Sheet1!$A$3"), Some("Sheet1!$A$4")]); + assert_eq!(c.series[0].categories.as_deref(), Some("Sheet1!$B$2:$C$2")); + // Columns shift the source too. + s.execute("home.insertColumns", json!({"cols": "A:A"})).unwrap(); + assert_eq!(s.doc().unwrap().wb.active().unwrap().charts[0].source.as_deref(), Some("Sheet1!B2:D4")); + // Deleting the whole block leaves no stale source behind. + s.execute("home.deleteRows", json!({"rows": "2:4"})).unwrap(); + assert_eq!(s.doc().unwrap().wb.active().unwrap().charts[0].source, None); +} + #[test] fn ink_strokes_and_ink_to_shape() { let mut s = s();