Files
war-in-tunnels/src/app/widgets/cell.rs
T
GarandPLG 6dc5f8605c Replace CellTag with CellStructure and embed BaseBuilding
The refactor removes the `Buildings` enum and the `building` module,
replacing
`CellTag` with a new `CellStructure` enum that directly holds a
`BaseBuilding`.
A `get_owner` method is added to `BaseBuilding` to support the new
structure.
All related imports, constructors, and rendering logic are updated to
use
`CellStructure` instead of the old tag and building fields.
2026-04-16 21:56:06 +02:00

160 lines
4.5 KiB
Rust

use crate::app::{
states::{CellStructure, Players, ZoomLevel},
units::Units,
};
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 struct CellWidget {
row: usize,
col: usize,
selected: bool,
zoom_level: ZoomLevel,
structure: CellStructure,
marked: bool,
unit: Option<Units>,
}
impl CellWidget {
pub fn new(
row: usize,
col: usize,
zoom_level: ZoomLevel,
selected: bool,
structure: CellStructure,
unit: Option<Units>,
) -> Self {
Self {
row,
col,
selected,
zoom_level,
marked: false,
structure,
unit,
}
}
pub fn set_selected(&mut self, selected: bool) -> &mut Self {
self.selected = selected;
self
}
pub fn set_zoom_level(&mut self, zoom_level: ZoomLevel) {
self.zoom_level = zoom_level;
}
pub fn set_structure(&mut self, sctructure: CellStructure) {
self.structure = sctructure;
}
pub fn get_marked(&self) -> bool {
self.marked
}
pub fn set_marked(&mut self, marked: bool) -> &mut Self {
self.marked = marked;
self
}
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.structure != CellStructure::Stone || self.marked {
format!("{}{}", self.col_to_letters(), self.row).green()
} else {
"".to_span()
}
}
fn fg_color(&self) -> Color {
match self.structure {
_ if self.marked && self.selected => Color::Magenta,
_ if self.marked && !self.selected => Color::LightMagenta,
_ if self.selected && !self.marked => Color::LightYellow,
CellStructure::Base(base) if !self.selected => match base.get_owner() {
Players::Player => Color::LightBlue,
Players::Enemy => Color::LightRed,
},
CellStructure::Tunel if !self.selected => Color::Gray,
_ => Color::White,
}
}
fn get_text_area(&self) -> Vec<Line<'_>> {
let tag: &str = match self.structure {
CellStructure::Base(base) => base.get_tag(),
CellStructure::Tunel => "T",
CellStructure::Stone => " ",
// _ => " ",
};
let b_level: &str = match self.structure {
CellStructure::Base(base) => base.get_level(),
_ => " ",
};
let unit: &str = match self.unit {
Some(unit) => match unit {
Units::Miner(miner) => miner.get_tag(),
// _ => " ",
},
None => " ",
};
let mut text_area: Vec<Line<'_>> = Vec::new();
match self.zoom_level {
ZoomLevel::ZoomedIn => {
text_area.push(Line::from(format!(" {} {} ", b_level, unit)));
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!(" {} {} ", b_level, unit)));
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);
}
}