Lazy init game states and extract board module

App now stores CLI arguments and an optional GameStates, initializing
the
states lazily on the first window resize. Skirmish board logic is moved
to
a new BoardState module with dedicated helpers (cells_area_helper and
updated cell size handling). Views and keybindings are updated to use
the
optional state accessors.
This commit is contained in:
2026-04-02 00:45:57 +02:00
parent c4e28255b6
commit 923af91aeb
15 changed files with 228 additions and 178 deletions
+96
View File
@@ -0,0 +1,96 @@
use crate::app::{
helpers::{CellSizes, cell_size_helper, cells_area_helper},
states::{FocusedCell, Offset, ZoomLevel},
widgets::CellWidget,
};
use ratatui::layout::Rect;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BoardState {
pub cells_area: Rect,
pub cell_width: usize,
pub cell_height: usize,
pub map_width: usize,
pub map_height: usize,
pub cols: usize,
pub rows: usize,
pub vertical_offset: Offset,
pub horizontal_offset: Offset,
pub cells: Vec<CellWidget>,
pub zoom_level: ZoomLevel,
pub focused_cell: FocusedCell,
}
impl BoardState {
pub fn new(area: &Rect, map_width: usize, map_height: usize, zoom_level: ZoomLevel) -> Self {
let cells_area: Rect = cells_area_helper(area);
let cell_width: usize = cell_size_helper(CellSizes::Width, zoom_level);
let cell_height: usize = cell_size_helper(CellSizes::Height, zoom_level);
let cols: usize = (cells_area.width / cell_width as u16) as usize;
let rows: usize = (cells_area.height / cell_height as u16) as usize;
let v_max_offset: usize = Self::max_offset(map_height, rows);
let h_max_offset: usize = Self::max_offset(map_width, cols);
let vertical_offset: Offset =
Offset::new(Some((map_height - rows as usize) / 2), Some(v_max_offset));
let horizontal_offset: Offset = Offset::new(None, Some(h_max_offset));
let focused_cell: FocusedCell =
FocusedCell::new((map_height / 2) - 1, 2, map_height, map_width);
let mut cells: Vec<CellWidget> = Vec::new();
for row in 0..map_height {
for col in 0..map_width {
cells.push(CellWidget::new(row, col, false));
}
}
Self {
cells_area,
cell_width,
cell_height,
map_width,
map_height,
cols,
rows,
vertical_offset,
horizontal_offset,
cells,
zoom_level,
focused_cell,
}
}
pub fn zoom_change(&mut self, new_zoom_level: ZoomLevel) {
self.zoom_level = new_zoom_level;
self.cell_width = cell_size_helper(CellSizes::Width, self.zoom_level);
self.cell_height = cell_size_helper(CellSizes::Height, self.zoom_level);
self.cols = (self.cells_area.width / self.cell_width as u16) as usize;
self.rows = (self.cells_area.height / self.cell_height as u16) as usize;
let v_max_offset: usize = Self::max_offset(self.map_height, self.rows);
let h_max_offset: usize = Self::max_offset(self.map_width, self.cols);
self.vertical_offset =
Offset::new(Some(self.vertical_offset.get_value()), Some(v_max_offset));
self.horizontal_offset =
Offset::new(Some(self.horizontal_offset.get_value()), Some(h_max_offset));
self.focused_cell = FocusedCell::new(
self.focused_cell.row,
self.focused_cell.col,
self.map_height,
self.map_width,
);
}
fn max_offset(map_size: usize, size: usize) -> usize {
if map_size > size { map_size - size } else { 0 }
}
}
+2
View File
@@ -1,5 +1,7 @@
pub mod board;
pub mod focused_cell;
pub mod offset;
pub use board::BoardState;
pub use focused_cell::FocusedCell;
pub use offset::Offset;
+4 -18
View File
@@ -2,17 +2,13 @@
pub struct Offset {
value: usize,
max: usize,
value_initiated: bool,
max_initiated: bool,
}
impl Offset {
pub fn new() -> Self {
pub fn new(initial_value: Option<usize>, initial_max: Option<usize>) -> Self {
Self {
value: 0,
max: 0,
value_initiated: false,
max_initiated: false,
value: initial_value.unwrap_or(0),
max: initial_max.unwrap_or(0),
}
}
@@ -20,22 +16,12 @@ impl Offset {
self.value
}
pub fn set_initial_value(&mut self, value: usize) {
if self.value_initiated {
return;
}
pub fn set_value(&mut self, value: usize) {
self.value = value;
self.value_initiated = true;
}
pub fn set_max(&mut self, max: usize) {
if self.max_initiated {
return;
}
self.max = max;
self.max_initiated = true;
}
pub fn next(&mut self) {