diff --git a/src/ui/app.rs b/src/ui/app.rs index 0536410..ef523fc 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -899,11 +899,31 @@ impl App { // ── Motion helpers ─────────────────────────────────────────────────────── fn move_selection(&mut self, dr: i32, dc: i32) { + // Compute max row/col from actual item counts so we never go out of bounds. + let row_max = { + let row_cats: Vec = self.model.active_view() + .map(|v| v.categories_on(crate::view::Axis::Row).into_iter().map(String::from).collect()) + .unwrap_or_default(); + row_cats.first() + .and_then(|c| self.model.category(c)) + .map(|c| c.items.len().saturating_sub(1)) + .unwrap_or(0) + }; + let col_max = { + let col_cats: Vec = self.model.active_view() + .map(|v| v.categories_on(crate::view::Axis::Column).into_iter().map(String::from).collect()) + .unwrap_or_default(); + col_cats.first() + .and_then(|c| self.model.category(c)) + .map(|c| c.items.len().saturating_sub(1)) + .unwrap_or(0) + }; + if let Some(view) = self.model.active_view_mut() { let (r, c) = view.selected; view.selected = ( - (r as i32 + dr).max(0) as usize, - (c as i32 + dc).max(0) as usize, + (r as i32 + dr).clamp(0, row_max as i32) as usize, + (c as i32 + dc).clamp(0, col_max as i32) as usize, ); } } diff --git a/whatever.improv b/whatever.improv index 4250f06..ef62240 100644 --- a/whatever.improv +++ b/whatever.improv @@ -128,29 +128,6 @@ "Number": 3.0 } ], - [ - [ - [ - "Month", - "Janury" - ], - [ - "Payer", - "Bernadette" - ], - [ - "Recipient", - "Bob" - ], - [ - "Type", - "Food" - ] - ], - { - "Number": 12.0 - } - ], [ [ [ @@ -196,6 +173,121 @@ { "Number": 5.0 } + ], + [ + [ + [ + "Month", + "February" + ], + [ + "Payer", + "Bernadette" + ], + [ + "Recipient", + "Bob" + ], + [ + "Type", + "Medical" + ] + ], + { + "Number": 33.0 + } + ], + [ + [ + [ + "Month", + "February" + ], + [ + "Payer", + "Bernadette" + ], + [ + "Recipient", + "Bob" + ], + [ + "Type", + "Gas" + ] + ], + { + "Number": 55.0 + } + ], + [ + [ + [ + "Month", + "February" + ], + [ + "Payer", + "Bernadette" + ], + [ + "Recipient", + "Bob" + ], + [ + "Type", + "Food" + ] + ], + { + "Number": 4.0 + } + ], + [ + [ + [ + "Month", + "February" + ], + [ + "Payer", + "Bernadette" + ], + [ + "Recipient", + "Bob" + ], + [ + "Type", + "Clothing" + ] + ], + { + "Text": "i5" + } + ], + [ + [ + [ + "Month", + "Janury" + ], + [ + "Payer", + "Bernadette" + ], + [ + "Recipient", + "Bob" + ], + [ + "Type", + "Food" + ] + ], + { + "Number": 12.0 + } ] ], "formulas": [], @@ -217,11 +309,11 @@ "row_offset": 0, "col_offset": 0, "selected": [ - 1, - 1 + 6, + 2 ] } }, "active_view": "Default", "next_category_id": 4 -} +} \ No newline at end of file