ElyTable: a new chart goes in empty cells beside its data, off the view if need be, and scrolls into view (R2.10)

This commit is contained in:
ZacharyZhang-NY committed 2026-10-09 06:47:31 -04:00
1 parent 409805e863
commit f4dad1d269
6 files changed
+156 -19

No files matched your search

+52 -11
View File
@@ -334,20 +334,61 @@ fn undoing_a_new_kind_brings_the_whole_chart_back() {
);
}
/// A sheet of ones filling each `(columns, rows)` block.
fn blocks(filled: &[(std::ops::RangeInclusive<usize>, std::ops::RangeInclusive<usize>)]) -> String {
let rows: String = (1..=60)
.map(|r| {
let cells: String = (0..20)
.map(|c| match filled.iter().any(|(cols, rows)| cols.contains(&c) && rows.contains(&r)) {
true => r#"<table:table-cell office:value-type="float" office:value="1"><text:p>1</text:p></table:table-cell>"#,
false => "<table:table-cell/>",
})
.collect();
format!("<table:table-row>{cells}</table:table-row>")
})
.collect();
format!(
r#"<?xml version="1.0" encoding="UTF-8"?>
<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">
<office:body><office:spreadsheet><table:table table:name="S">{rows}</table:table></office:spreadsheet></office:body>
</office:document>"#
)
}
/// Charts `source` and checks it clears each data block.
fn charted(sheet: &str, visible: (i32, i32, i32, i32), source: &str, data: &[(&str, &str)]) {
let (_dir, mut worker, doc) = open_book(sheet);
doc.visible_area(&mut worker, visible, (256, 3840)).expect("the area");
let mut seen = poll_until(&mut worker, &doc, &Events::default(), SETTLE, |_| false);
let mut cell = |worker: &mut Worker, name: &str| {
worker.run(&doc, "cell.goto", &[name]).expect("the cell");
let before = seen.cell.cursor;
seen = poll_until(worker, &doc, &seen, SETTLE, |now| now.cell.cursor.is_some() && now.cell.cursor != before);
seen.cell.cursor.expect("the cell's rect")
};
let spans: Vec<_> = data.iter().map(|(from, to)| (cell(&mut worker, from), cell(&mut worker, to))).collect();
let all = written(&mut worker, &doc, source);
worker.run(&doc, "cell.goto", &["A1"]).expect("A1");
worker.run(&doc, "chart.insert", &[&all, "false", &Look { kind: "column".into(), ..Look::default() }.to_json()]).expect("inserts");
let framed = poll_until(&mut worker, &doc, &seen, SETTLE, |now| now.graphic.is_some());
let (x, y, w, h) = framed.graphic.expect("the chart is selected");
for ((a, b), (from, to)) in spans.iter().zip(data) {
let clear = x >= b.0 + b.2 || x + w <= a.0 || y >= b.1 + b.3 || y + h <= a.1;
assert!(clear, "the chart {:?} covers {from}:{to}", (x, y, w, h));
}
}
#[test]
fn a_new_chart_lands_beside_its_data() {
if skip() {
return;
}
let (_dir, mut worker, doc) = open_book(&data());
let all = written(&mut worker, &doc, "A1:C5");
let base = poll_until(&mut worker, &doc, &Events::default(), SETTLE, |_| false);
worker.run(&doc, "cell.goto", &["C5"]).expect("C5");
let corner = poll_until(&mut worker, &doc, &base, SETTLE, |seen| seen.cell.cursor.is_some() && seen.cell.cursor != base.cell.cursor);
let (x, y, w, h) = corner.cell.cursor.expect("the last data cell");
worker.run(&doc, "cell.goto", &["A1"]).expect("A1");
worker.run(&doc, "chart.insert", &[&all, "false", &Look { kind: "column".into(), ..Look::default() }.to_json()]).expect("inserts");
let framed = poll_until(&mut worker, &doc, &corner, SETTLE, |seen| seen.graphic.is_some());
let (left, top, _, _) = framed.graphic.expect("the chart is selected");
assert!(left >= x + w || top >= y + h, "the chart at {left},{top} covers data ending {},{}", x + w, y + h);
// Its own data, a neighbour past two empty columns.
charted(&blocks(&[(0..=2, 1..=5), (5..=15, 1..=20)]), (0, 0, 15000, 10000), "A1:C5", &[("A1", "C5"), ("F1", "P20")]);
// Data wider and taller than the view.
charted(&blocks(&[(0..=15, 1..=50)]), (0, 0, 15000, 10000), "A1:P50", &[("A1", "P50")]);
// A view narrower than the chart.
charted(&blocks(&[(0..=2, 1..=5)]), (0, 0, 6000, 3500), "A1:C5", &[("A1", "C5")]);
}