use ratatui::style::{Modifier, Style};
use crate::ui::theme::ThemePalette;
use super::TokenId;
use super::context::display_width;
pub trait TemplateRow {
fn resolve(&self, token: TokenId) -> String;
fn intrinsic_style(&self, token: TokenId) -> Style;
fn natural_width(&self, token: TokenId) -> usize {
display_width(&self.resolve(token))
}
fn status_icon_spans(&self) -> &[(String, Style)] {
&[]
}
fn is_stale(&self) -> bool {
false
}
fn git_segment_spans(&self, _token: TokenId, _width: usize) -> (Vec<(String, Style)>, usize) {
(Vec::new(), 0)
}
fn pr_check_spans(&self, _width: usize) -> (Vec<(String, Style)>, usize) {
(Vec::new(), 0)
}
fn group_status_spans(&self, _width: usize) -> (Vec<(String, Style)>, usize) {
(Vec::new(), 0)
}
}
pub struct GroupStatusCount {
pub icon: Vec<(String, Style)>,
pub count: usize,
pub pad: usize,
}
impl GroupStatusCount {
fn width(&self) -> usize {
let icon: usize = self.icon.iter().map(|(text, _)| display_width(text)).sum();
icon + self.pad + display_width(&self.count.to_string())
}
}
pub struct HeaderContext<'a> {
pub label: String,
pub count: usize,
pub statuses: Vec<GroupStatusCount>,
pub palette: &'a ThemePalette,
}
impl TemplateRow for HeaderContext<'_> {
fn resolve(&self, token: TokenId) -> String {
match token {
TokenId::Group => self.label.clone(),
TokenId::GroupCount => self.count.to_string(),
TokenId::GroupStatus => self
.statuses
.iter()
.map(|status| {
let icon: String = status.icon.iter().map(|(text, _)| text.as_str()).collect();
format!("{icon}{}{}", " ".repeat(status.pad), status.count)
})
.collect::<Vec<_>>()
.join(" "),
_ => String::new(),
}
}
fn intrinsic_style(&self, token: TokenId) -> Style {
match token {
TokenId::Group => Style::default()
.fg(self.palette.header)
.add_modifier(Modifier::BOLD),
_ => Style::default().fg(self.palette.dimmed),
}
}
fn group_status_spans(&self, width: usize) -> (Vec<(String, Style)>, usize) {
let mut spans: Vec<(String, Style)> = Vec::new();
let mut used = 0;
for status in &self.statuses {
let separator = usize::from(!spans.is_empty());
if used + separator + status.width() > width {
break;
}
if separator > 0 {
spans.push((" ".to_string(), Style::default()));
}
spans.extend(status.icon.iter().cloned());
if status.pad > 0 {
spans.push((" ".repeat(status.pad), Style::default()));
}
spans.push((
status.count.to_string(),
Style::default().fg(self.palette.dimmed),
));
used += separator + status.width();
}
(spans, used)
}
}