Files
war-in-tunnels/src/app/widgets/board.rs
T
GarandPLG bf8883934d Add zoom level helper and use it for cell sizing
Introduce a new `zoom_level` module containing the `CellSizes` enum and
`cell_size_helper` function to map `ZoomLevel` values to width and
height
dimensions. Export the helper from `mod.rs` and refactor `BoardWidget`
to
import and use `cell_size_helper`, eliminating duplicated match
statements.
2026-04-01 19:57:44 +02:00

103 lines
3.2 KiB
Rust

use crate::app::{
App,
helpers::{CellSizes, cell_size_helper},
states::FocusedCell,
widgets::CellWidget,
};
use ratatui::{
buffer::Buffer,
layout::{Constraint, Layout, Rect},
widgets::Widget,
};
use std::rc::Rc;
pub struct BoardWidget<'a> {
map_width: usize,
cell_width: u16,
cell_height: u16,
cols: u16,
rows: u16,
h_offset: usize,
v_offset: usize,
cells: &'a mut Vec<CellWidget>,
focused_cell: &'a FocusedCell,
}
impl<'a> BoardWidget<'a> {
fn max_offset(map_size: u16, size: u16) -> usize {
if map_size > size {
(map_size - size) as usize
} else {
0
}
}
pub fn new(app: &'a mut App, area_width: u16, area_height: u16) -> Self {
let cell_height: u16 = cell_size_helper(CellSizes::Height, app.states.skirmish.zoom_level);
let cell_width: u16 = cell_size_helper(CellSizes::Width, app.states.skirmish.zoom_level);
let rows: u16 = area_height / cell_height;
let cols: u16 = area_width / cell_width;
let v_max_offset: usize = Self::max_offset(app.states.skirmish.map_height as u16, rows);
let h_max_offset: usize = Self::max_offset(app.states.skirmish.map_width as u16, cols);
app.states.skirmish.horizontal_offset.set_max(h_max_offset);
app.states.skirmish.vertical_offset.set_max(v_max_offset);
if v_max_offset > 0 {
app.states
.skirmish
.vertical_offset
.set_initial_value((app.states.skirmish.map_height - rows as usize) / 2);
}
Self {
map_width: app.states.skirmish.map_width as usize,
cell_width,
cell_height,
cols,
rows,
h_offset: app.states.skirmish.horizontal_offset.get_value(),
v_offset: app.states.skirmish.vertical_offset.get_value(),
cells: &mut app.states.skirmish.board_cells,
focused_cell: &app.states.skirmish.focused_cell,
}
}
}
impl Widget for BoardWidget<'_> {
fn render(self, area: Rect, buf: &mut Buffer) {
let horizontal: Rc<[Rect]> = Layout::horizontal(vec![
Constraint::Length(self.cell_width);
self.cols as usize
])
.split(area);
for (col_idx, col_area) in horizontal.iter().enumerate() {
let vertical: Rc<[Rect]> = Layout::vertical(vec![
Constraint::Length(self.cell_height);
self.rows as usize
])
.split(*col_area);
for (row_idx, cell_area) in vertical.iter().enumerate() {
if let Some(cell) = self
.cells
.get_mut((row_idx + self.v_offset) * self.map_width + (col_idx + self.h_offset))
{
if row_idx + self.v_offset == self.focused_cell.row
&& col_idx + self.h_offset == self.focused_cell.col
{
cell.selected = true;
} else {
cell.selected = false;
}
cell.render(*cell_area, buf);
}
}
}
}
}