generated from GarandPLG/rust-flake-template
Add max durability and enhance side panel UI
- Introduce `max_durability` fields to BaseBuilding, Stone, and Tunnel structures. - Extend `Structure` trait with `get_max_durability` and implement it in all structures. - Update `Structures` enum to forward `get_max_durability`. - Add color utilities and `get_span` method to `Players` enum for styled text. - Refactor `CellWidget` method names (`get_option_unit`, `set_structure`). - Revise side panel widget to accept references to `Structures` and `Option<Units>`, render colored blocks and detailed stats. - Simplify skirmish view to use `BoardState` directly and adapt side panel rendering.
This commit is contained in:
@@ -1,30 +1,31 @@
|
||||
use crate::app::{
|
||||
helpers::block_single_title_helper,
|
||||
states::skirmish_states::{
|
||||
structures::{Structure, Structures},
|
||||
units::{Unit, Units},
|
||||
},
|
||||
};
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
layout::{Alignment, Rect},
|
||||
style::Color,
|
||||
text::Line,
|
||||
widgets::{Block, BorderType, Borders, Paragraph, Widget},
|
||||
layout::{Alignment, Constraint, Layout, Margin, Rect},
|
||||
style::{Color, Stylize},
|
||||
text::{Line, Span},
|
||||
widgets::{Block, BorderType, Borders, Padding, Paragraph, Widget},
|
||||
};
|
||||
|
||||
use crate::app::helpers::block_title_helper;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct SidePanelWidget {
|
||||
pub struct SidePanelWidget<'a> {
|
||||
coords: (usize, usize),
|
||||
structure_name: &'static str,
|
||||
unit_name: &'static str,
|
||||
structure: &'a Structures,
|
||||
unit: &'a Option<Units>,
|
||||
}
|
||||
|
||||
impl SidePanelWidget {
|
||||
pub fn new(
|
||||
coords: (usize, usize),
|
||||
structure_name: &'static str,
|
||||
unit_name: &'static str,
|
||||
) -> Self {
|
||||
impl<'a> SidePanelWidget<'a> {
|
||||
pub fn new(coords: (usize, usize), structure: &'a Structures, unit: &'a Option<Units>) -> Self {
|
||||
Self {
|
||||
coords,
|
||||
structure_name,
|
||||
unit_name,
|
||||
structure,
|
||||
unit,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,35 +41,94 @@ impl SidePanelWidget {
|
||||
letters.iter().rev().collect()
|
||||
}
|
||||
|
||||
fn get_title(&self) -> Line<'_> {
|
||||
let cell_coords: String = format!("{}{}", self.col_to_letters(), self.coords.0);
|
||||
|
||||
let mut texts: Vec<(String, Color)> = Vec::with_capacity(3);
|
||||
|
||||
texts.push((cell_coords, Color::Yellow));
|
||||
texts.push((self.structure_name.to_string(), Color::Cyan));
|
||||
|
||||
if !self.unit_name.is_empty() {
|
||||
texts.push((self.unit_name.to_string(), Color::Green));
|
||||
}
|
||||
|
||||
block_title_helper(&texts, Some(" - "))
|
||||
}
|
||||
|
||||
fn get_block(&self) -> Block<'_> {
|
||||
fn get_outer_block(&self) -> Block<'_> {
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_type(BorderType::Double)
|
||||
.title(self.get_title())
|
||||
.title(block_single_title_helper(
|
||||
format!("{}{}", self.col_to_letters(), self.coords.0),
|
||||
Color::Yellow,
|
||||
))
|
||||
.title_alignment(Alignment::Center)
|
||||
}
|
||||
|
||||
fn get_inner_block<'b>(&self, title: String, color: Color) -> Block<'b> {
|
||||
Block::default()
|
||||
.borders(Borders::LEFT | Borders::TOP)
|
||||
.title(block_single_title_helper(title, color))
|
||||
.title_alignment(Alignment::Center)
|
||||
.padding(Padding::symmetric(1, 1))
|
||||
}
|
||||
|
||||
fn get_area_constraints(&self) -> [Constraint; 2] {
|
||||
if !self.unit.get_name().is_empty() {
|
||||
[Constraint::Percentage(50), Constraint::Percentage(50)]
|
||||
} else {
|
||||
[Constraint::Percentage(100), Constraint::Percentage(0)]
|
||||
}
|
||||
}
|
||||
|
||||
fn structure_text(&self) -> Vec<Line<'_>> {
|
||||
let s: &Structures = self.structure;
|
||||
let durability: u16 = s.get_durability();
|
||||
let max_durability: u16 = s.get_max_durability();
|
||||
let durability_percent: u16 = durability * 100 / max_durability;
|
||||
let stress: u8 = s.get_stress();
|
||||
let level: char = s.get_level();
|
||||
|
||||
let mut lines: Vec<Line<'_>> = vec![
|
||||
Line::from_iter([
|
||||
"Durability: ".gray(),
|
||||
durability.to_string().cyan(),
|
||||
"/".gray(),
|
||||
max_durability.to_string().cyan(),
|
||||
" ( ".gray(),
|
||||
durability_percent.to_string().cyan(),
|
||||
"% )".gray(),
|
||||
]),
|
||||
Line::from_iter(["Stress: ".gray(), stress.to_string().cyan(), "%".gray()]),
|
||||
];
|
||||
|
||||
if level != ' ' {
|
||||
lines.push(Line::from_iter([
|
||||
"Level: ".gray(),
|
||||
level.to_string().cyan(),
|
||||
]));
|
||||
}
|
||||
|
||||
lines
|
||||
}
|
||||
|
||||
fn unit_text(&self) -> Vec<Line<'_>> {
|
||||
let u: &Option<Units> = self.unit;
|
||||
let owner: Span<'_> = u.get_owner().get_span();
|
||||
|
||||
vec![Line::from_iter(vec!["Owner: ".gray(), owner])]
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for SidePanelWidget {
|
||||
impl Widget for SidePanelWidget<'_> {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
Paragraph::default()
|
||||
.alignment(Alignment::Center)
|
||||
.block(self.get_block())
|
||||
.render(area, buf);
|
||||
let block: Block<'_> = self.get_outer_block();
|
||||
let inner_area: Rect = block.inner(area).inner(Margin {
|
||||
horizontal: 2,
|
||||
vertical: 1,
|
||||
});
|
||||
block.render(area, buf);
|
||||
|
||||
let [structure_area, unit_area] =
|
||||
Layout::vertical(self.get_area_constraints()).areas(inner_area);
|
||||
|
||||
Paragraph::new(self.structure_text())
|
||||
.alignment(Alignment::Left)
|
||||
.block(self.get_inner_block(self.structure.get_name().to_string(), Color::Cyan))
|
||||
.render(structure_area, buf);
|
||||
|
||||
if !self.unit.get_name().is_empty() {
|
||||
Paragraph::new(self.unit_text())
|
||||
.alignment(Alignment::Left)
|
||||
.block(self.get_inner_block(self.unit.get_name().to_string(), Color::Green))
|
||||
.render(unit_area, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user