generated from GarandPLG/rust-flake-template
869ba0bb7f
Introduce a marking mode that lets users toggle cells with Space and clear them with Backspace. BoardState now stores `marking_cells` and a list of `marked_cells` and provides methods to start, clear, and update marks. CellWidget tracks a `marked` flag and renders marked cells in LightMagenta. Keybindings are updated: Space now reads “Marking cells”, Backspace reads “Cancel marking”, and the original Enter binding is commented out. The former `resize_change` and `zoom_change` functions are renamed to `change_resize` and `change_zoom`; all call sites are updated accordingly.
149 lines
3.9 KiB
Rust
149 lines
3.9 KiB
Rust
use crate::app::states::ZoomLevel;
|
|
use ratatui::{
|
|
buffer::Buffer,
|
|
layout::{Alignment, Rect},
|
|
style::{Color, Style, Stylize},
|
|
text::{Line, Span, ToSpan},
|
|
widgets::{Block, Borders, Paragraph, Widget},
|
|
};
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum CellTag {
|
|
Base(Players),
|
|
Tunel,
|
|
Stone,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum Players {
|
|
Player,
|
|
Enemy,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub struct CellWidget {
|
|
row: usize,
|
|
col: usize,
|
|
selected: bool,
|
|
zoom_level: ZoomLevel,
|
|
tag: CellTag,
|
|
marked: bool,
|
|
}
|
|
|
|
impl CellWidget {
|
|
pub fn new(
|
|
row: usize,
|
|
col: usize,
|
|
zoom_level: ZoomLevel,
|
|
selected: bool,
|
|
tag: CellTag,
|
|
) -> Self {
|
|
Self {
|
|
row,
|
|
col,
|
|
selected,
|
|
zoom_level,
|
|
tag,
|
|
marked: false,
|
|
}
|
|
}
|
|
|
|
pub fn set_selected(&mut self, selected: bool) {
|
|
self.selected = selected;
|
|
}
|
|
|
|
pub fn set_zoom_level(&mut self, zoom_level: ZoomLevel) {
|
|
self.zoom_level = zoom_level;
|
|
}
|
|
|
|
pub fn set_tag(&mut self, tag: CellTag) {
|
|
self.tag = tag;
|
|
}
|
|
|
|
pub fn get_marked(&self) -> bool {
|
|
self.marked
|
|
}
|
|
|
|
pub fn set_marked(&mut self, marked: bool) {
|
|
self.marked = marked
|
|
}
|
|
|
|
fn col_to_letters(&self) -> String {
|
|
let mut col: usize = self.col + 1;
|
|
let mut letters: Vec<char> = Vec::new();
|
|
|
|
while col > 0 {
|
|
letters.push((b'A' + ((col - 1) % 26) as u8) as char);
|
|
col = (col - 1) / 26;
|
|
}
|
|
|
|
letters.iter().rev().collect()
|
|
}
|
|
|
|
fn display_coords(&self) -> Span<'_> {
|
|
if self.selected || self.tag != CellTag::Stone {
|
|
format!("{}{}", self.col_to_letters(), self.row).green()
|
|
} else {
|
|
"".to_span()
|
|
}
|
|
}
|
|
|
|
fn fg_color(&self) -> Color {
|
|
match self.tag {
|
|
_ if self.marked => Color::LightMagenta,
|
|
_ if self.selected => Color::LightYellow,
|
|
CellTag::Base(Players::Player) if !self.selected => Color::LightBlue,
|
|
CellTag::Base(Players::Enemy) if !self.selected => Color::LightRed,
|
|
CellTag::Tunel if !self.selected => Color::Gray,
|
|
_ => Color::White,
|
|
}
|
|
}
|
|
|
|
fn get_text_area(&self) -> Vec<Line<'_>> {
|
|
let tag: &str = match self.tag {
|
|
CellTag::Base(_) => "B",
|
|
CellTag::Tunel => "T",
|
|
CellTag::Stone => " ",
|
|
};
|
|
let units: &str = " "; // TODO: units count on that cell
|
|
|
|
let mut text_area: Vec<Line<'_>> = Vec::new();
|
|
|
|
match self.zoom_level {
|
|
ZoomLevel::ZoomedIn => {
|
|
text_area.push(Line::from(format!(" {}", units)));
|
|
text_area.push(Line::from(format!(" ")));
|
|
text_area.push(Line::from(format!(" {} ", tag)));
|
|
text_area.push(Line::from(format!(" ")));
|
|
text_area.push(Line::from(format!(" ")));
|
|
}
|
|
ZoomLevel::Default => {
|
|
text_area.push(Line::from(format!(" {}", units)));
|
|
text_area.push(Line::from(format!(" {} ", tag)));
|
|
text_area.push(Line::from(format!(" ")));
|
|
}
|
|
ZoomLevel::ZoomedOut => {
|
|
text_area.push(Line::from(format!(" {} ", tag)));
|
|
}
|
|
}
|
|
|
|
text_area
|
|
}
|
|
|
|
fn get_block(&self) -> Block<'_> {
|
|
Block::default()
|
|
.borders(Borders::ALL)
|
|
.style(Style::default().fg(self.fg_color()))
|
|
.title(self.display_coords())
|
|
}
|
|
}
|
|
|
|
impl Widget for CellWidget {
|
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
|
Paragraph::new(self.get_text_area())
|
|
.alignment(Alignment::Center)
|
|
.block(self.get_block())
|
|
.render(area, buf);
|
|
}
|
|
}
|