feat: add 't' key to transpose row/column axes

Pressing 't' swaps all Row-axis categories to Column and all
Column-axis categories to Row, leaving Page categories unchanged.
Selection and scroll offsets are reset to (0,0).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ed L
2026-03-24 09:40:02 -07:00
parent c42553fa97
commit cb43a8130e
2 changed files with 46 additions and 1 deletions

View File

@ -112,6 +112,18 @@ impl View {
self.hidden_items.get(cat_name).map(|s| s.contains(item_name)).unwrap_or(false)
}
/// Swap all Row categories to Column and all Column categories to Row.
/// Page categories are unaffected.
pub fn transpose_axes(&mut self) {
let rows: Vec<String> = self.categories_on(Axis::Row).iter().map(|s| s.to_string()).collect();
let cols: Vec<String> = self.categories_on(Axis::Column).iter().map(|s| s.to_string()).collect();
for cat in &rows { self.set_axis(cat, Axis::Column); }
for cat in &cols { self.set_axis(cat, Axis::Row); }
self.selected = (0, 0);
self.row_offset = 0;
self.col_offset = 0;
}
/// Cycle axis for a category: Row → Column → Page → Row
pub fn cycle_axis(&mut self, cat_name: &str) {
let next = match self.axis_of(cat_name) {
@ -171,6 +183,34 @@ mod tests {
assert_eq!(v.categories_on(Axis::Page), vec!["Time"]);
}
#[test]
fn transpose_axes_swaps_row_and_column() {
let mut v = view_with_cats(&["Region", "Product"]);
// Default: Region=Row, Product=Column
assert_eq!(v.axis_of("Region"), Axis::Row);
assert_eq!(v.axis_of("Product"), Axis::Column);
v.transpose_axes();
assert_eq!(v.axis_of("Region"), Axis::Column);
assert_eq!(v.axis_of("Product"), Axis::Row);
}
#[test]
fn transpose_axes_leaves_page_categories_unchanged() {
let mut v = view_with_cats(&["Region", "Product", "Time"]);
// Default: Region=Row, Product=Column, Time=Page
v.transpose_axes();
assert_eq!(v.axis_of("Time"), Axis::Page);
}
#[test]
fn transpose_axes_is_its_own_inverse() {
let mut v = view_with_cats(&["Region", "Product"]);
v.transpose_axes();
v.transpose_axes();
assert_eq!(v.axis_of("Region"), Axis::Row);
assert_eq!(v.axis_of("Product"), Axis::Column);
}
#[test]
#[should_panic(expected = "axis_of called for category not registered")]
fn axis_of_unknown_category_panics() {