From 0b6d243946db1352a1be7de9570b8e2d47c0ee01 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sun, 25 Oct 2026 16:47:19 -0700 Subject: [PATCH] Format Chart Area: Chart Type offers the stacked and 100% stacked types and marks the current one The Chart Type section of the Format Chart Area pane listed nine types, with stacked column as the only stacked one, so a chart could not be switched there to stacked bar, 100% stacked column or bar, stacked line, or stacked or 100% stacked area. It now lists them after their family's entries, and "Stacked" is renamed "Stacked Column". Each entry is drawn selected when it is the chart's current type, as the Legend entries are, using the same type and subtype mapping that chart.set applies. --- crates/ui-egui/src/panes.rs | 11 ++- crates/ui-egui/tests/it/format_chart_type.rs | 91 ++++++++++++++++++++ crates/ui-egui/tests/it/main.rs | 1 + 3 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 crates/ui-egui/tests/it/format_chart_type.rs diff --git a/crates/ui-egui/src/panes.rs b/crates/ui-egui/src/panes.rs index 65d169c87..4cf5bbbc1 100644 --- a/crates/ui-egui/src/panes.rs +++ b/crates/ui-egui/src/panes.rs @@ -185,16 +185,23 @@ fn format_chart(app: &mut SheetApp, ui: &mut Ui) { ui.horizontal_wrapped(|ui| { for (l, k, s) in [ ("Column", "column", ""), - ("Stacked", "column", "stacked"), + ("Stacked Column", "column", "stacked"), + ("100% Stacked Column", "column", "stacked100"), ("Bar", "bar", ""), + ("Stacked Bar", "bar", "stacked"), + ("100% Stacked Bar", "bar", "stacked100"), ("Line", "line", "markers"), + ("Stacked Line", "line", "stacked"), ("Area", "area", ""), + ("Stacked Area", "area", "stacked"), + ("100% Stacked Area", "area", "stacked100"), ("Pie", "pie", ""), ("Doughnut", "doughnut", ""), ("Scatter", "scatter", ""), ("Radar", "radar", ""), ] { - if ui.button(l).clicked() { + let cur = chart.kind == gridcraft_engine::cmd::insert::chart_kind(k, s); + if ui.selectable_label(cur, l).clicked() { app.run_or_alert("chart.set", json!({"chart": id, "type": k, "subtype": s})); } } diff --git a/crates/ui-egui/tests/it/format_chart_type.rs b/crates/ui-egui/tests/it/format_chart_type.rs new file mode 100644 index 000000000..ae19e1091 --- /dev/null +++ b/crates/ui-egui/tests/it/format_chart_type.rs @@ -0,0 +1,91 @@ +//! The Format Chart Area pane's Chart Type section changes the chart's type and marks the current one. + +use egui::accesskit::{Role, Toggled}; +use egui_kittest::kittest::{NodeT, Queryable}; +use gridcraft_engine::Session; +use gridcraft_engine::model::ChartKind; +use gridcraft_ui_egui::SheetApp; +use serde_json::json; + +type Harness = egui_kittest::Harness<'static, SheetApp>; + +/// A two-series chart made with `insert.chart`'s `type` `t` and `subtype` `sub`, with Format Chart Area open on its Chart Type section. +fn open_chart_type(t: &str, sub: &str) -> (Harness, u32) { + let mut session = Session::new(); + session.new_workbook(); + session.execute("range.setValues", json!({"range": "A1", "values": [["Quarter", "North", "South"], ["Q1", 10, 30], ["Q2", 30, 10]]})).unwrap(); + session.execute("selection.set", json!({"range": "A1:C3"})).unwrap(); + let chart = session.execute("insert.chart", json!({"type": t, "subtype": sub, "at": "E3"})).unwrap(); + let id = chart["chart"].as_u64().unwrap() as u32; + let mut h = crate::support::harness(session, 4); + 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::DisclosureTriangle, "Chart Type").click(); + h.run_steps(2); + (h, id) +} + +fn kind(h: &Harness, id: u32) -> ChartKind { + h.state().session.active().unwrap().wb.active().unwrap().charts.iter().find(|c| c.id == id).unwrap().kind +} + +/// Whether the pane's `label` button is drawn as the chart's current type. The pane sits on the +/// right, past the Chart Type header's left edge; the ribbon's buttons are elsewhere. +fn marked(h: &Harness, label: &str) -> bool { + let left = h.get_by_role_and_label(Role::DisclosureTriangle, "Chart Type").rect().left(); + let button = h.get_all_by_role_and_label(Role::Button, label).find(|n| n.rect().left() >= left - 1.0).unwrap(); + button.accesskit_node().toggled() == Some(Toggled::True) +} + +fn click(h: &mut Harness, label: &str) { + let left = h.get_by_role_and_label(Role::DisclosureTriangle, "Chart Type").rect().left(); + h.get_all_by_role_and_label(Role::Button, label).find(|n| n.rect().left() >= left - 1.0).unwrap().click(); + h.run_steps(2); +} + +#[test] +fn chart_type_offers_the_stacked_and_hundred_percent_stacked_types() { + let (mut h, id) = open_chart_type("column", ""); + for (label, want) in [ + ("Stacked Column", ChartKind::ColumnStacked), + ("100% Stacked Column", ChartKind::ColumnStacked100), + ("Stacked Bar", ChartKind::BarStacked), + ("100% Stacked Bar", ChartKind::BarStacked100), + ("Stacked Line", ChartKind::LineStacked), + ("Stacked Area", ChartKind::AreaStacked), + ("100% Stacked Area", ChartKind::AreaStacked100), + ("Column", ChartKind::ColumnClustered), + ] { + click(&mut h, label); + assert_eq!(kind(&h, id), want, "{label} changes the chart's type"); + } +} + +#[test] +fn chart_type_marks_the_chart_s_current_type() { + for (t, sub, label) in + [("bar", "stacked100", "100% Stacked Bar"), ("area", "stacked", "Stacked Area"), ("column", "", "Column"), ("line", "markers", "Line")] + { + let (h, _) = open_chart_type(t, sub); + for other in [ + "Column", + "Stacked Column", + "100% Stacked Column", + "Bar", + "Stacked Bar", + "100% Stacked Bar", + "Line", + "Stacked Line", + "Area", + "Stacked Area", + "100% Stacked Area", + "Pie", + "Doughnut", + "Scatter", + "Radar", + ] { + assert_eq!(marked(&h, other), other == label, "{other} on a {t} {sub} chart"); + } + } +} diff --git a/crates/ui-egui/tests/it/main.rs b/crates/ui-egui/tests/it/main.rs index 53625015e..5eeb4c411 100644 --- a/crates/ui-egui/tests/it/main.rs +++ b/crates/ui-egui/tests/it/main.rs @@ -37,6 +37,7 @@ mod filter_menu_enter; mod find_dialog_focus; mod floating_pictures; mod font_size_box; +mod format_chart_type; mod format_painter; mod formula_bar; mod formula_bar_expand;