refactor: make active_view and axis_of infallible

Both functions previously returned Option despite their invariants
guaranteeing a value: active_view always names an existing view
(maintained by new/switch_view/delete_view), and axis_of only returns
None for categories never registered with the view (a programming error).

Callers no longer need to handle the impossible None case, eliminating
~15 match/if-let Option guards across app.rs, dispatch.rs, grid.rs,
tile_bar.rs, and category_panel.rs.

Also adds Model::evaluate_f64 (returns 0.0 for empty cells) and collapses
the double match-on-axis pattern in tile_bar/category_panel into a single
axis_display(Axis) helper.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ed L
2026-03-24 09:00:25 -07:00
parent a2e519efcc
commit 6038cb2d81
9 changed files with 168 additions and 208 deletions

View File

@ -114,7 +114,7 @@ mod tests {
#[test]
fn row_and_col_counts_match_item_counts() {
let m = two_cat_model();
let layout = GridLayout::new(&m, m.active_view().unwrap());
let layout = GridLayout::new(&m, m.active_view());
assert_eq!(layout.row_count(), 2); // Food, Clothing
assert_eq!(layout.col_count(), 2); // Jan, Feb
}
@ -122,7 +122,7 @@ mod tests {
#[test]
fn cell_key_encodes_correct_coordinates() {
let m = two_cat_model();
let layout = GridLayout::new(&m, m.active_view().unwrap());
let layout = GridLayout::new(&m, m.active_view());
// row 0 = Food, col 1 = Feb
let key = layout.cell_key(0, 1).unwrap();
assert_eq!(key, coord(&[("Month", "Feb"), ("Type", "Food")]));
@ -131,7 +131,7 @@ mod tests {
#[test]
fn cell_key_out_of_bounds_returns_none() {
let m = two_cat_model();
let layout = GridLayout::new(&m, m.active_view().unwrap());
let layout = GridLayout::new(&m, m.active_view());
assert!(layout.cell_key(99, 0).is_none());
assert!(layout.cell_key(0, 99).is_none());
}
@ -146,8 +146,8 @@ mod tests {
m.category_mut("Month").unwrap().add_item("Jan");
m.category_mut("Region").unwrap().add_item("East");
m.category_mut("Region").unwrap().add_item("West");
m.active_view_mut().unwrap().set_page_selection("Region", "West");
let layout = GridLayout::new(&m, m.active_view().unwrap());
m.active_view_mut().set_page_selection("Region", "West");
let layout = GridLayout::new(&m, m.active_view());
let key = layout.cell_key(0, 0).unwrap();
assert_eq!(key.get("Region"), Some("West"));
}
@ -159,7 +159,7 @@ mod tests {
coord(&[("Month", "Feb"), ("Type", "Clothing")]),
CellValue::Number(42.0),
);
let layout = GridLayout::new(&m, m.active_view().unwrap());
let layout = GridLayout::new(&m, m.active_view());
// Clothing = row 1, Feb = col 1
let key = layout.cell_key(1, 1).unwrap();
assert_eq!(m.evaluate(&key), Some(CellValue::Number(42.0)));
@ -174,8 +174,8 @@ mod tests {
m.category_mut("Type").unwrap().add_item("Food");
m.category_mut("Month").unwrap().add_item("Jan");
m.category_mut("Year").unwrap().add_item("2025");
m.active_view_mut().unwrap().set_axis("Year", crate::view::Axis::Column);
let layout = GridLayout::new(&m, m.active_view().unwrap());
m.active_view_mut().set_axis("Year", crate::view::Axis::Column);
let layout = GridLayout::new(&m, m.active_view());
assert_eq!(layout.col_label(0), "Jan/2025");
}
}