use crate::state::{AppState, Pane, UiMode};
use radiate_engines::Chromosome;
use ratatui::{
buffer::Buffer,
layout::Rect,
style::{Color, Style, Stylize},
text::{Line, Span},
widgets::{Borders, Paragraph, Widget},
};
pub struct SearchBarWidget<'a, C: Chromosome> {
pub state: &'a AppState<C>,
}
impl<'a, C: Chromosome> SearchBarWidget<'a, C> {
pub fn new(state: &'a AppState<C>) -> Self {
Self { state }
}
}
impl<'a, C: Chromosome> Widget for SearchBarWidget<'a, C> {
fn render(self, area: Rect, buf: &mut Buffer) {
let title = if self.state.nav.search.active {
Line::from(vec![
Span::from(" Search (").fg(Color::White).bold(),
Span::from("active").fg(Color::Green).bold(),
Span::from(") ").fg(Color::White).bold(),
])
} else {
Line::from(vec![
Span::from(" Search ").fg(Color::White).bold(),
Span::from("[/] ").fg(Color::Green).bold(),
])
};
let border_style = crate::styles::panel_block(self.state.nav.is_search_focused());
let total_renders = self.state.run.render_count;
let metric_summary = self.state.evo.metrics.summary();
let renders = vec![
" Metrics: ".fg(Color::Gray).bold(),
format!("{}", metric_summary.metrics).fg(Color::LightGreen),
", ".fg(Color::Gray).bold(),
format!("{} ", metric_summary.updates).fg(Color::LightGreen),
"| Renders: ".fg(Color::Gray).bold(),
format!("{} ", total_renders).fg(Color::LightGreen),
];
Paragraph::new(self.state.nav.search.query.as_str())
.block(
border_style
.title(title)
.title_bottom(help_text(self.state))
.title_bottom(Line::from(renders).right_aligned().fg(Color::LightBlue))
.style(Style::default())
.borders(Borders::ALL),
)
.style(Style::default())
.render(area, buf);
}
}
pub fn help_text<C: Chromosome>(state: &AppState<C>) -> Line<'static> {
let nav = &state.nav;
let pause = if state.run.paused { "resume" } else { "pause" };
let mut chips = match nav.mode {
UiMode::Dashboard => {
let mut v = match nav.focus {
Pane::List => vec![kv("j/k", "navigate")],
Pane::Chart => {
let view = state.current_chart_view().label().to_lowercase();
vec![kv("j/k", &format!("view: {view}"))]
}
};
v.push(kv("h/l", "tabs"));
if nav.dashboard_tab.supports_metric_modal() {
v.push(kv("↵", "expand"));
}
v.push(kv("/", "find"));
v.push(kv("p", pause));
v.push(kv("?", "help"));
v
}
UiMode::MetricModal => vec![
kv("h/l", "chart"),
kv("↵/esc", "close"),
kv("p", pause),
kv("?", "help"),
],
UiMode::Search => vec![kv("type", "filter"), kv("↵", "apply"), kv("esc", "cancel")],
UiMode::Help => vec![kv("?/esc", "close")],
}
.into_iter()
.flatten()
.collect::<Vec<_>>();
chips.insert(0, Span::raw(" "));
Line::from(chips).centered()
}
fn kv(key: &str, desc: &str) -> [Span<'static>; 2] {
[
Span::from(format!("[{key}]")).fg(Color::LightGreen).bold(),
Span::from(format!(" {desc} ")).fg(Color::Gray),
]
}