From 48483da1a48578196f49d9b928c14558060d8efa Mon Sep 17 00:00:00 2001 From: GarandPLG Date: Tue, 7 Apr 2026 23:20:11 +0200 Subject: [PATCH] Refactor skirmish focus handling and CellWidget API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a MoveFocusedCell enum and a BoardState.change_focused_cell method to centralize focus movement logic. Update skirmish keybindings to use this new method and simplify board rendering by directly using stored CellWidget state. Make CellWidget setters chainable and expose the new enum in the module re‑exports. Remove duplicated max_offset logic and old move_* methods. --- src/app/keybindings/skirmish.rs | 63 +++++++++++-------- src/app/states/skirmish_states/board.rs | 23 +++++-- .../states/skirmish_states/focused_cell.rs | 36 +++++++---- src/app/states/skirmish_states/mod.rs | 2 +- src/app/widgets/board.rs | 12 +--- src/app/widgets/cell.rs | 9 +-- 6 files changed, 88 insertions(+), 57 deletions(-) diff --git a/src/app/keybindings/skirmish.rs b/src/app/keybindings/skirmish.rs index f99005f..900b07e 100644 --- a/src/app/keybindings/skirmish.rs +++ b/src/app/keybindings/skirmish.rs @@ -1,7 +1,10 @@ use crate::app::{ App, keybindings::{Action, common_keybindings, event_to_action}, - states::ZoomLevel, + states::{ + ZoomLevel, + skirmish_states::{BoardState, MoveFocusedCell}, + }, }; use ratatui::crossterm::event::KeyEvent; @@ -13,48 +16,58 @@ pub fn skirmish_keybindings(app: &mut App, key_event: &KeyEvent) { return; }; + let board: &mut BoardState = &mut states.skirmish.board; + match action { - Action::Up => states.skirmish.board.focused_cell.move_up(), - Action::Down => states.skirmish.board.focused_cell.move_down(), - Action::Left => states.skirmish.board.focused_cell.move_left(), - Action::Right => states.skirmish.board.focused_cell.move_right(), + Action::Up => { + board.change_focused_cell(MoveFocusedCell::Up); + } + Action::Down => { + board.change_focused_cell(MoveFocusedCell::Down); + } + Action::Left => { + board.change_focused_cell(MoveFocusedCell::Left); + } + Action::Right => { + board.change_focused_cell(MoveFocusedCell::Right); + } Action::ScrollUp => { - states.skirmish.board.vertical_offset.prev(); - states.skirmish.board.focused_cell.move_up(); + board.vertical_offset.prev(); + board.change_focused_cell(MoveFocusedCell::Up); } Action::ScrollDown => { - states.skirmish.board.vertical_offset.next(); - states.skirmish.board.focused_cell.move_down(); + board.vertical_offset.next(); + board.change_focused_cell(MoveFocusedCell::Down); } Action::ScrollLeft => { - states.skirmish.board.horizontal_offset.prev(); - states.skirmish.board.focused_cell.move_left(); + board.horizontal_offset.prev(); + board.change_focused_cell(MoveFocusedCell::Left); } Action::ScrollRight => { - states.skirmish.board.horizontal_offset.next(); - states.skirmish.board.focused_cell.move_right(); + board.horizontal_offset.next(); + board.change_focused_cell(MoveFocusedCell::Right); } - Action::ZoomIn => match states.skirmish.board.zoom_level { + Action::ZoomIn => match board.zoom_level { ZoomLevel::ZoomedIn => {} ZoomLevel::Default => { - states.skirmish.board.zoom_change(ZoomLevel::ZoomedIn); - states.skirmish.board.vertical_offset.next(); + board.zoom_change(ZoomLevel::ZoomedIn); + board.vertical_offset.next(); } ZoomLevel::ZoomedOut => { - states.skirmish.board.zoom_change(ZoomLevel::Default); - states.skirmish.board.vertical_offset.next(); - states.skirmish.board.vertical_offset.next(); + board.zoom_change(ZoomLevel::Default); + board.vertical_offset.next(); + board.vertical_offset.next(); } }, - Action::ZoomOut => match states.skirmish.board.zoom_level { + Action::ZoomOut => match board.zoom_level { ZoomLevel::ZoomedIn => { - states.skirmish.board.zoom_change(ZoomLevel::Default); - states.skirmish.board.vertical_offset.prev(); + board.zoom_change(ZoomLevel::Default); + board.vertical_offset.prev(); } ZoomLevel::Default => { - states.skirmish.board.zoom_change(ZoomLevel::ZoomedOut); - states.skirmish.board.vertical_offset.prev(); - states.skirmish.board.vertical_offset.prev(); + board.zoom_change(ZoomLevel::ZoomedOut); + board.vertical_offset.prev(); + board.vertical_offset.prev(); } ZoomLevel::ZoomedOut => {} }, diff --git a/src/app/states/skirmish_states/board.rs b/src/app/states/skirmish_states/board.rs index 4a842e7..0b36372 100644 --- a/src/app/states/skirmish_states/board.rs +++ b/src/app/states/skirmish_states/board.rs @@ -1,6 +1,6 @@ use crate::app::{ helpers::{CellSizes, cell_size_helper, cells_area_helper}, - states::{FocusedCell, Offset, ZoomLevel}, + states::{FocusedCell, Offset, ZoomLevel, skirmish_states::MoveFocusedCell}, widgets::CellWidget, }; use ratatui::layout::Rect; @@ -45,7 +45,13 @@ impl BoardState { for row in 0..map_height { for col in 0..map_width { - cells.push(CellWidget::new(row, col, zoom_level)); + cells.push(*CellWidget::new(row, col, zoom_level).set_selected( + if row == focused_cell.get_row() && col == focused_cell.get_col() { + true + } else { + false + }, + )); } } @@ -69,6 +75,10 @@ impl BoardState { &mut self.cells[row * self.map_width + col] } + fn max_offset(map_size: usize, size: usize) -> usize { + if map_size > size { map_size - size } else { 0 } + } + pub fn zoom_change(&mut self, new_zoom_level: ZoomLevel) { self.zoom_level = new_zoom_level; @@ -100,7 +110,12 @@ impl BoardState { } } - fn max_offset(map_size: usize, size: usize) -> usize { - if map_size > size { map_size - size } else { 0 } + pub fn change_focused_cell(&mut self, direction: MoveFocusedCell) { + let old_row: usize = self.focused_cell.get_row(); + let old_col: usize = self.focused_cell.get_col(); + let (new_row, new_col) = self.focused_cell.move_focused_cell(direction); + + self.get_mut_cell(old_row, old_col).set_selected(false); + self.get_mut_cell(new_row, new_col).set_selected(true); } } diff --git a/src/app/states/skirmish_states/focused_cell.rs b/src/app/states/skirmish_states/focused_cell.rs index f23de45..0779539 100644 --- a/src/app/states/skirmish_states/focused_cell.rs +++ b/src/app/states/skirmish_states/focused_cell.rs @@ -1,3 +1,10 @@ +pub enum MoveFocusedCell { + Up, + Down, + Left, + Right, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct FocusedCell { row: usize, @@ -24,19 +31,22 @@ impl FocusedCell { self.col } - pub fn move_up(&mut self) { - self.row = self.row.saturating_sub(1).max(0); - } + pub fn move_focused_cell(&mut self, direction: MoveFocusedCell) -> (usize, usize) { + match direction { + MoveFocusedCell::Up => { + self.row = self.row.saturating_sub(1).max(0); + } + MoveFocusedCell::Down => { + self.row = self.row.saturating_add(1).min(self.max_row - 1); + } + MoveFocusedCell::Left => { + self.col = self.col.saturating_sub(1).max(0); + } + MoveFocusedCell::Right => { + self.col = self.col.saturating_add(1).min(self.max_col - 1); + } + } - pub fn move_down(&mut self) { - self.row = self.row.saturating_add(1).min(self.max_row - 1); - } - - pub fn move_left(&mut self) { - self.col = self.col.saturating_sub(1).max(0); - } - - pub fn move_right(&mut self) { - self.col = self.col.saturating_add(1).min(self.max_col - 1); + (self.row, self.col) } } diff --git a/src/app/states/skirmish_states/mod.rs b/src/app/states/skirmish_states/mod.rs index 0534388..e8afc28 100644 --- a/src/app/states/skirmish_states/mod.rs +++ b/src/app/states/skirmish_states/mod.rs @@ -3,5 +3,5 @@ pub mod focused_cell; pub mod offset; pub use board::BoardState; -pub use focused_cell::FocusedCell; +pub use focused_cell::{FocusedCell, MoveFocusedCell}; pub use offset::Offset; diff --git a/src/app/widgets/board.rs b/src/app/widgets/board.rs index 17b1d69..bb23059 100644 --- a/src/app/widgets/board.rs +++ b/src/app/widgets/board.rs @@ -1,4 +1,4 @@ -use crate::app::{states::skirmish_states::BoardState, widgets::CellWidget}; +use crate::app::states::skirmish_states::BoardState; use ratatui::{ buffer::Buffer, layout::{Constraint, Layout, Rect}, @@ -37,19 +37,11 @@ impl Widget for BoardWidget<'_> { let map_row: usize = row_idx + self.state.vertical_offset.get_value(); let map_col: usize = col_idx + self.state.horizontal_offset.get_value(); - if let Some(template) = self + if let Some(cell) = self .state .cells .get(map_row * self.state.map_width + map_col) { - let mut cell: CellWidget = template.clone(); - - if map_row == self.state.focused_cell.get_row() - && map_col == self.state.focused_cell.get_col() - { - cell.set_selected(true); - } - cell.render(*cell_area, buf); } } diff --git a/src/app/widgets/cell.rs b/src/app/widgets/cell.rs index 4306fcc..8cbc3a1 100644 --- a/src/app/widgets/cell.rs +++ b/src/app/widgets/cell.rs @@ -15,13 +15,12 @@ use ratatui::{ // Base, // } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct CellWidget { row: usize, col: usize, selected: bool, zoom_level: ZoomLevel, - // text_area: Vec, // pub tags: Vec, } @@ -35,12 +34,14 @@ impl CellWidget { } } - pub fn set_selected(&mut self, selected: bool) { + pub fn set_selected(&mut self, selected: bool) -> &mut Self { self.selected = selected; + self } - pub fn set_zoom_level(&mut self, zoom_level: ZoomLevel) { + pub fn set_zoom_level(&mut self, zoom_level: ZoomLevel) -> &mut Self { self.zoom_level = zoom_level; + self } fn col_to_letters(&self) -> String {