generated from GarandPLG/rust-flake-template
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:
+15
-5
@@ -22,22 +22,29 @@ pub struct App {
|
||||
pub exit: bool,
|
||||
pub view: View,
|
||||
pub window_area: Rect,
|
||||
pub states: GameStates,
|
||||
pub args: Cli,
|
||||
pub states: Option<GameStates>,
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn new(args: Cli) -> Self {
|
||||
let mut states: GameStates = GameStates::new(&args);
|
||||
states.skirmish.init_board();
|
||||
|
||||
Self {
|
||||
exit: false,
|
||||
view: args.view,
|
||||
window_area: Rect::default(),
|
||||
states,
|
||||
args: args,
|
||||
states: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn states(&self) -> Option<&GameStates> {
|
||||
self.states.as_ref()
|
||||
}
|
||||
|
||||
pub fn states_mut(&mut self) -> Option<&mut GameStates> {
|
||||
self.states.as_mut()
|
||||
}
|
||||
|
||||
pub fn run(&mut self, terminal: &mut DefaultTerminal, rx: Receiver<Event>) -> Result<()> {
|
||||
while !self.exit {
|
||||
terminal.draw(|frame: &mut Frame<'_>| self.draw(frame))?;
|
||||
@@ -65,6 +72,9 @@ impl App {
|
||||
|| window_area.height != self.window_area.height
|
||||
{
|
||||
self.window_area = window_area;
|
||||
if self.states.is_none() {
|
||||
self.states = Some(GameStates::new(&self.args, &self.window_area))
|
||||
}
|
||||
}
|
||||
|
||||
frame.render_widget(self, window_area);
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
use crate::app::views::skirmish_layout;
|
||||
use ratatui::{
|
||||
layout::{Margin, Rect},
|
||||
widgets::{Block, Borders},
|
||||
};
|
||||
|
||||
pub fn cells_area_helper(area: &Rect) -> Rect {
|
||||
Block::new()
|
||||
.borders(Borders::LEFT | Borders::TOP | Borders::RIGHT)
|
||||
.inner(skirmish_layout(*area)[1])
|
||||
.inner(Margin {
|
||||
horizontal: 3,
|
||||
vertical: 1,
|
||||
})
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
pub mod block_title;
|
||||
pub mod cells_area;
|
||||
pub mod main_menu_option;
|
||||
pub mod zoom_level;
|
||||
|
||||
pub use block_title::{block_single_title_helper, block_title_helper};
|
||||
pub use cells_area::cells_area_helper;
|
||||
pub use main_menu_option::main_menu_option_helper;
|
||||
pub use zoom_level::{CellSizes, cell_size_helper};
|
||||
|
||||
@@ -5,7 +5,7 @@ pub enum CellSizes {
|
||||
Height,
|
||||
}
|
||||
|
||||
pub fn cell_size_helper(cell_size: CellSizes, zoom_level: ZoomLevel) -> u16 {
|
||||
pub fn cell_size_helper(cell_size: CellSizes, zoom_level: ZoomLevel) -> usize {
|
||||
match (cell_size, zoom_level) {
|
||||
(CellSizes::Width, ZoomLevel::ZoomedIn) => 13,
|
||||
(CellSizes::Width, ZoomLevel::Default) => 9,
|
||||
|
||||
@@ -7,17 +7,22 @@ use ratatui::crossterm::event::KeyEvent;
|
||||
pub fn main_menu_keybindings(app: &mut App, event: &KeyEvent) {
|
||||
if let Some(action) = event_to_action(&event) {
|
||||
common_keybindings(app, action);
|
||||
|
||||
let Some(states) = app.states_mut() else {
|
||||
return;
|
||||
};
|
||||
|
||||
match action {
|
||||
Action::Up => {
|
||||
app.states.main_menu.selected_view =
|
||||
app.states.main_menu.selected_view.saturating_sub(1).max(1);
|
||||
states.main_menu.selected_view =
|
||||
states.main_menu.selected_view.saturating_sub(1).max(1);
|
||||
}
|
||||
Action::Down => {
|
||||
app.states.main_menu.selected_view =
|
||||
app.states.main_menu.selected_view.saturating_add(1).min(3);
|
||||
states.main_menu.selected_view =
|
||||
states.main_menu.selected_view.saturating_add(1).min(3);
|
||||
}
|
||||
Action::Space => {
|
||||
let selected_view: usize = app.states.main_menu.selected_view;
|
||||
let selected_view: usize = states.main_menu.selected_view;
|
||||
|
||||
if selected_view == 1 {
|
||||
app.view = View::Skirmish;
|
||||
|
||||
@@ -8,48 +8,53 @@ use ratatui::crossterm::event::KeyEvent;
|
||||
pub fn skirmish_keybindings(app: &mut App, key_event: &KeyEvent) {
|
||||
if let Some(action) = event_to_action(&key_event) {
|
||||
common_keybindings(app, action);
|
||||
|
||||
let Some(states) = app.states_mut() else {
|
||||
return;
|
||||
};
|
||||
|
||||
match action {
|
||||
Action::Up => app.states.skirmish.focused_cell.move_up(),
|
||||
Action::Down => app.states.skirmish.focused_cell.move_down(),
|
||||
Action::Left => app.states.skirmish.focused_cell.move_left(),
|
||||
Action::Right => app.states.skirmish.focused_cell.move_right(),
|
||||
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::ScrollUp => {
|
||||
app.states.skirmish.vertical_offset.prev();
|
||||
app.states.skirmish.focused_cell.move_up();
|
||||
states.skirmish.board.vertical_offset.prev();
|
||||
states.skirmish.board.focused_cell.move_up();
|
||||
}
|
||||
Action::ScrollDown => {
|
||||
app.states.skirmish.vertical_offset.next();
|
||||
app.states.skirmish.focused_cell.move_down();
|
||||
states.skirmish.board.vertical_offset.next();
|
||||
states.skirmish.board.focused_cell.move_down();
|
||||
}
|
||||
Action::ScrollLeft => {
|
||||
app.states.skirmish.horizontal_offset.prev();
|
||||
app.states.skirmish.focused_cell.move_left();
|
||||
states.skirmish.board.horizontal_offset.prev();
|
||||
states.skirmish.board.focused_cell.move_left();
|
||||
}
|
||||
Action::ScrollRight => {
|
||||
app.states.skirmish.horizontal_offset.next();
|
||||
app.states.skirmish.focused_cell.move_right();
|
||||
states.skirmish.board.horizontal_offset.next();
|
||||
states.skirmish.board.focused_cell.move_right();
|
||||
}
|
||||
Action::ZoomIn => match app.states.skirmish.zoom_level {
|
||||
Action::ZoomIn => match states.skirmish.board.zoom_level {
|
||||
ZoomLevel::ZoomedIn => {}
|
||||
ZoomLevel::Default => {
|
||||
app.states.skirmish.zoom_level = ZoomLevel::ZoomedIn;
|
||||
app.states.skirmish.vertical_offset.next();
|
||||
states.skirmish.board.zoom_change(ZoomLevel::ZoomedIn);
|
||||
states.skirmish.board.vertical_offset.next();
|
||||
}
|
||||
ZoomLevel::ZoomedOut => {
|
||||
app.states.skirmish.zoom_level = ZoomLevel::Default;
|
||||
app.states.skirmish.vertical_offset.next();
|
||||
app.states.skirmish.vertical_offset.next();
|
||||
states.skirmish.board.zoom_change(ZoomLevel::Default);
|
||||
states.skirmish.board.vertical_offset.next();
|
||||
states.skirmish.board.vertical_offset.next();
|
||||
}
|
||||
},
|
||||
Action::ZoomOut => match app.states.skirmish.zoom_level {
|
||||
Action::ZoomOut => match states.skirmish.board.zoom_level {
|
||||
ZoomLevel::ZoomedIn => {
|
||||
app.states.skirmish.zoom_level = ZoomLevel::Default;
|
||||
app.states.skirmish.vertical_offset.prev();
|
||||
states.skirmish.board.zoom_change(ZoomLevel::Default);
|
||||
states.skirmish.board.vertical_offset.prev();
|
||||
}
|
||||
ZoomLevel::Default => {
|
||||
app.states.skirmish.zoom_level = ZoomLevel::ZoomedOut;
|
||||
app.states.skirmish.vertical_offset.prev();
|
||||
app.states.skirmish.vertical_offset.prev();
|
||||
states.skirmish.board.zoom_change(ZoomLevel::ZoomedOut);
|
||||
states.skirmish.board.vertical_offset.prev();
|
||||
states.skirmish.board.vertical_offset.prev();
|
||||
}
|
||||
ZoomLevel::ZoomedOut => {}
|
||||
},
|
||||
|
||||
+8
-13
@@ -1,10 +1,11 @@
|
||||
use crate::{
|
||||
app::states::{
|
||||
FocusedCell, MainMenuState, Offset, PerkDecksState, SettingsState, SkillsConfigState,
|
||||
SkirmishState,
|
||||
MainMenuState, PerkDecksState, SettingsState, SkillsConfigState, SkirmishState,
|
||||
skirmish_states::BoardState,
|
||||
},
|
||||
cli::Cli,
|
||||
};
|
||||
use ratatui::layout::Rect;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct GameStates {
|
||||
@@ -16,7 +17,7 @@ pub struct GameStates {
|
||||
}
|
||||
|
||||
impl GameStates {
|
||||
pub fn new(args: &Cli) -> Self {
|
||||
pub fn new(args: &Cli, area: &Rect) -> Self {
|
||||
Self {
|
||||
main_menu: MainMenuState {
|
||||
id: 0,
|
||||
@@ -26,17 +27,11 @@ impl GameStates {
|
||||
skirmish: SkirmishState {
|
||||
id: 1,
|
||||
name: "Skirmish",
|
||||
vertical_offset: Offset::new(),
|
||||
horizontal_offset: Offset::new(),
|
||||
map_width: args.map_width as usize,
|
||||
map_height: args.map_height as usize,
|
||||
board_cells: Vec::new(),
|
||||
zoom_level: args.zoom_level,
|
||||
focused_cell: FocusedCell::new(
|
||||
(args.map_height / 2) as usize - 1,
|
||||
2,
|
||||
args.map_height as usize,
|
||||
board: BoardState::new(
|
||||
area,
|
||||
args.map_width as usize,
|
||||
args.map_height as usize,
|
||||
args.zoom_level,
|
||||
),
|
||||
},
|
||||
perk_decks: PerkDecksState {
|
||||
|
||||
@@ -1,34 +1,11 @@
|
||||
use crate::app::{
|
||||
states::{FocusedCell, Offset},
|
||||
widgets::CellWidget,
|
||||
};
|
||||
use crate::app::states::skirmish_states::BoardState;
|
||||
use clap::ValueEnum;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct SkirmishState {
|
||||
pub id: usize,
|
||||
pub name: &'static str,
|
||||
pub map_width: usize,
|
||||
pub map_height: usize,
|
||||
pub vertical_offset: Offset,
|
||||
pub horizontal_offset: Offset,
|
||||
pub board_cells: Vec<CellWidget>,
|
||||
pub zoom_level: ZoomLevel,
|
||||
pub focused_cell: FocusedCell,
|
||||
}
|
||||
|
||||
impl SkirmishState {
|
||||
pub fn init_board(&mut self) {
|
||||
if !self.board_cells.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
for row in 0..self.map_height {
|
||||
for col in 0..self.map_width {
|
||||
self.board_cells.push(CellWidget::new(row, col, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
pub board: BoardState,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ValueEnum)]
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -30,6 +30,8 @@ fn main_menu_layout(area: Rect) -> [Rect; 2] {
|
||||
}
|
||||
|
||||
pub fn main_menu_view(app: &App, area: Rect, buf: &mut Buffer) {
|
||||
let Some(states) = app.states() else { return };
|
||||
|
||||
let [main_menu_area, keybindings_area] = main_menu_layout(area);
|
||||
|
||||
Block::new()
|
||||
@@ -70,7 +72,7 @@ pub fn main_menu_view(app: &App, area: Rect, buf: &mut Buffer) {
|
||||
.map(|(i, view)| {
|
||||
let view_string: String = main_menu_option_helper(format!("{:?}", view));
|
||||
|
||||
let styled: Line<'_> = if app.states.main_menu.selected_view == i {
|
||||
let styled: Line<'_> = if states.main_menu.selected_view == i {
|
||||
Line::from_iter(["> ".cyan(), view_string.yellow()]).yellow()
|
||||
} else {
|
||||
Line::from(format!(" {view_string}")).white()
|
||||
|
||||
@@ -4,4 +4,4 @@ pub mod skirmish;
|
||||
|
||||
pub use default::default_view;
|
||||
pub use main_menu::main_menu_view;
|
||||
pub use skirmish::skirmish_view;
|
||||
pub use skirmish::{skirmish_layout, skirmish_view};
|
||||
|
||||
@@ -28,7 +28,7 @@ const ACTIONS: &[Action] = &[
|
||||
Action::Esc,
|
||||
];
|
||||
|
||||
fn skirmish_layout(area: Rect) -> [Rect; 3] {
|
||||
pub fn skirmish_layout(area: Rect) -> [Rect; 3] {
|
||||
Layout::vertical([
|
||||
Constraint::Length(4),
|
||||
Constraint::Fill(1),
|
||||
@@ -37,22 +37,21 @@ fn skirmish_layout(area: Rect) -> [Rect; 3] {
|
||||
.areas(area)
|
||||
}
|
||||
|
||||
pub fn skirmish_view(app: &mut App, area: Rect, buf: &mut Buffer) {
|
||||
pub fn skirmish_view(app: &App, area: Rect, buf: &mut Buffer) {
|
||||
let Some(states) = app.states() else { return };
|
||||
|
||||
let [title_area, main_area, keybindings_area] = skirmish_layout(area);
|
||||
|
||||
{
|
||||
let lines: Vec<Line<'_>> = Vec::from_iter([
|
||||
Line::raw("War in Tunnels").yellow(),
|
||||
Line::from_iter([
|
||||
format!("Wood: {} (+{}) | ", app.states.settings.starting_wood, 5),
|
||||
format!("Iron: {} (+{}) | ", app.states.settings.starting_iron, 1),
|
||||
format!(
|
||||
"Supply Limit: {}/{} | ",
|
||||
10, app.states.settings.supply_limit
|
||||
),
|
||||
format!("Wood: {} (+{}) | ", states.settings.starting_wood, 5),
|
||||
format!("Iron: {} (+{}) | ", states.settings.starting_iron, 1),
|
||||
format!("Supply Limit: {}/{} | ", 10, states.settings.supply_limit),
|
||||
format!(
|
||||
"Skills points: {} ({}/{}) | ",
|
||||
1, 20, app.states.settings.skill_points_limit
|
||||
1, 20, states.settings.skill_points_limit
|
||||
),
|
||||
format!("Perk Deck: {}/9", 5),
|
||||
]),
|
||||
@@ -91,7 +90,7 @@ pub fn skirmish_view(app: &mut App, area: Rect, buf: &mut Buffer) {
|
||||
vertical: 1,
|
||||
});
|
||||
|
||||
BoardWidget::new(app, cells_area.width, cells_area.height).render(cells_area, buf);
|
||||
BoardWidget::new(&states.skirmish.board).render(cells_area, buf);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
+31
-75
@@ -1,9 +1,4 @@
|
||||
use crate::app::{
|
||||
App,
|
||||
helpers::{CellSizes, cell_size_helper},
|
||||
states::FocusedCell,
|
||||
widgets::CellWidget,
|
||||
};
|
||||
use crate::app::states::skirmish_states::BoardState;
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
layout::{Constraint, Layout, Rect},
|
||||
@@ -12,87 +7,48 @@ use ratatui::{
|
||||
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,
|
||||
state: &'a BoardState,
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
pub fn new(state: &'a BoardState) -> Self {
|
||||
Self { state }
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
let horizontal: Rc<[Rect]> =
|
||||
Layout::horizontal(vec![
|
||||
Constraint::Length(self.state.cell_width as u16);
|
||||
self.state.cols
|
||||
])
|
||||
.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);
|
||||
let vertical: Rc<[Rect]> =
|
||||
Layout::vertical(vec![
|
||||
Constraint::Length(self.state.cell_height as u16);
|
||||
self.state.rows
|
||||
])
|
||||
.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;
|
||||
}
|
||||
if let Some(cell) = self.state.cells.get(
|
||||
(row_idx + self.state.vertical_offset.get_value()) * self.state.map_width
|
||||
+ (col_idx + self.state.horizontal_offset.get_value()),
|
||||
) {
|
||||
// FIXME: Fix showing selected cell
|
||||
|
||||
// if row_idx + self.state.vertical_offset.get_value()
|
||||
// == self.state.focused_cell.row
|
||||
// && col_idx + self.state.horizontal_offset.get_value()
|
||||
// == self.state.focused_cell.col
|
||||
// {
|
||||
// cell.selected = true;
|
||||
// } else {
|
||||
// cell.selected = false;
|
||||
// }
|
||||
|
||||
cell.render(*cell_area, buf);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user