feat: add Axis::None for hidden dimensions with implicit aggregation
Categories on the None axis are excluded from the grid and cell keys. When evaluating cells, values across hidden dimensions are aggregated using a per-measure function (default SUM). Adds evaluate_aggregated to Model, none_cats to GridLayout, and 'n' shortcut in TileSelect. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -148,12 +148,13 @@ impl View {
|
||||
self.col_offset = 0;
|
||||
}
|
||||
|
||||
/// Cycle axis for a category: Row → Column → Page → Row
|
||||
/// Cycle axis for a category: Row → Column → Page → None → Row
|
||||
pub fn cycle_axis(&mut self, cat_name: &str) {
|
||||
let next = match self.axis_of(cat_name) {
|
||||
Axis::Row => Axis::Column,
|
||||
Axis::Column => Axis::Page,
|
||||
Axis::Page => Axis::Row,
|
||||
Axis::Page => Axis::None,
|
||||
Axis::None => Axis::Row,
|
||||
};
|
||||
self.set_axis(cat_name, next);
|
||||
self.selected = (0, 0);
|
||||
@ -302,9 +303,17 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cycle_axis_page_to_row() {
|
||||
fn cycle_axis_page_to_none() {
|
||||
let mut v = view_with_cats(&["Region", "Product", "Time"]);
|
||||
v.cycle_axis("Time");
|
||||
assert_eq!(v.axis_of("Time"), Axis::None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cycle_axis_none_to_row() {
|
||||
let mut v = view_with_cats(&["Region", "Product", "Time"]);
|
||||
v.set_axis("Time", Axis::None);
|
||||
v.cycle_axis("Time");
|
||||
assert_eq!(v.axis_of("Time"), Axis::Row);
|
||||
}
|
||||
|
||||
@ -351,7 +360,7 @@ mod prop_tests {
|
||||
fn each_category_on_exactly_one_axis(cats in unique_cat_names()) {
|
||||
let mut v = View::new("T");
|
||||
for c in &cats { v.on_category_added(c); }
|
||||
let all_axes = [Axis::Row, Axis::Column, Axis::Page];
|
||||
let all_axes = [Axis::Row, Axis::Column, Axis::Page, Axis::None];
|
||||
for c in &cats {
|
||||
let count = all_axes.iter()
|
||||
.filter(|&&ax| v.categories_on(ax).contains(&c.as_str()))
|
||||
@ -377,7 +386,7 @@ mod prop_tests {
|
||||
fn set_axis_updates_axis_of(
|
||||
cats in unique_cat_names(),
|
||||
target_idx in 0usize..8,
|
||||
axis in prop_oneof![Just(Axis::Row), Just(Axis::Column), Just(Axis::Page)],
|
||||
axis in prop_oneof![Just(Axis::Row), Just(Axis::Column), Just(Axis::Page), Just(Axis::None)],
|
||||
) {
|
||||
let mut v = View::new("T");
|
||||
for c in &cats { v.on_category_added(c); }
|
||||
@ -392,7 +401,7 @@ mod prop_tests {
|
||||
fn set_axis_exclusive(
|
||||
cats in unique_cat_names(),
|
||||
target_idx in 0usize..8,
|
||||
axis in prop_oneof![Just(Axis::Row), Just(Axis::Column), Just(Axis::Page)],
|
||||
axis in prop_oneof![Just(Axis::Row), Just(Axis::Column), Just(Axis::Page), Just(Axis::None)],
|
||||
) {
|
||||
let mut v = View::new("T");
|
||||
for c in &cats { v.on_category_added(c); }
|
||||
|
||||
Reference in New Issue
Block a user