Files
war-in-tunnels/src/app/widgets/side_panel.rs
T
GarandPLG e4728aab5d Show unit task queue and mark in side panel
Add `get_tasks` to the `Unit` trait and implement it for `MinerUnit`,
`Units` enum and `Option<Units>`.  Use the new method in `base_text` to
display a “Tasks Queue” line.

Refactor task assignment in `BoardState` to a chained call.

Update the skirmish view and `SidePanelWidget` to pass a flag indicating
whether the displayed unit is the currently marked one, and highlight
the
unit name accordingly.
2026-05-17 11:00:06 +02:00

109 lines
3.1 KiB
Rust

use crate::app::{
helpers::block_single_title_helper,
states::skirmish_states::{
structures::{Structure, Structures},
units::{Unit, Units},
},
};
use ratatui::{
buffer::Buffer,
layout::{Alignment, Constraint, Layout, Margin, Rect},
style::Color,
widgets::{Block, BorderType, Borders, Padding, Paragraph, Widget},
};
#[derive(Debug, Clone, PartialEq)]
pub struct SidePanelWidget<'a> {
coords: (usize, usize),
structure: &'a Structures,
unit: &'a Option<Units>,
is_unit_marked: bool,
}
impl<'a> SidePanelWidget<'a> {
pub fn new(
coords: (usize, usize),
structure: &'a Structures,
unit: &'a Option<Units>,
is_unit_marked: bool,
) -> Self {
Self {
coords,
structure,
unit,
is_unit_marked,
}
}
fn col_to_letters(&self) -> String {
let mut col: usize = self.coords.1 + 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 get_outer_block(&self) -> Block<'_> {
Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Double)
.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::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.is_unit() {
[Constraint::Percentage(50), Constraint::Percentage(50)]
} else {
[Constraint::Percentage(100), Constraint::Percentage(0)]
}
}
}
impl Widget for SidePanelWidget<'_> {
fn render(self, area: Rect, buf: &mut Buffer) {
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.is_unit() {
let mut unit_name: String = self.unit.get_name().to_string();
if self.is_unit_marked {
unit_name = format!("> {} <", unit_name);
}
Paragraph::new(self.unit.text())
.alignment(Alignment::Left)
.block(self.get_inner_block(unit_name, Color::Green))
.render(unit_area, buf);
}
}
}