use ratatui::Frame;
use ratatui::layout::Rect;
use ratatui::style::{Color, Modifier, Style};
use ratatui::text::{Line, Span};
use ratatui::widgets::Paragraph;
use super::super::app::{App, Tab, ToastKind};
use super::super::theme;
const SEP: &str = " ";
const SEP_WIDTH: usize = 3;
const PREV_MARK: &str = "‹ ";
const NEXT_MARK: &str = " ›";
pub(super) fn draw(frame: &mut Frame<'_>, area: Rect, app: &App) {
let avail = area.width as usize;
let spans = if fits_normal(avail) {
build_normal(app, avail)
} else {
build_overflow(app)
};
let para = Paragraph::new(Line::from(spans)).style(theme::base());
frame.render_widget(para, area);
}
fn full_strip_width() -> usize {
Tab::ALL
.iter()
.enumerate()
.map(|(i, t)| {
let sep = if i > 0 { SEP_WIDTH } else { 0 };
sep + t.title().len()
})
.sum()
}
fn fits_normal(avail: usize) -> bool {
full_strip_width() <= avail
}
fn build_normal(app: &App, _avail: usize) -> Vec<Span<'static>> {
let mut spans: Vec<Span<'static>> = Vec::new();
for (i, tab) in Tab::ALL.iter().enumerate() {
if i > 0 {
spans.push(Span::styled(SEP, theme::dim()));
}
let label = tab.title().to_lowercase();
if *tab == app.tab {
spans.push(Span::styled(
label,
Style::default()
.fg(theme::accent_color())
.add_modifier(Modifier::BOLD | Modifier::UNDERLINED),
));
} else {
let color = activity_color(app.tab_activity[tab.index()]);
spans.push(Span::styled(label, Style::default().fg(color)));
}
}
spans
}
fn build_overflow(app: &App) -> Vec<Span<'static>> {
let active_idx = app.tab.index();
let last_idx = Tab::ALL.len().saturating_sub(1);
let mut spans: Vec<Span<'static>> = Vec::new();
if active_idx > 0 {
spans.push(Span::styled(PREV_MARK, theme::faint()));
}
let label = app.tab.title().to_lowercase();
spans.push(Span::styled(
label,
Style::default()
.fg(theme::accent_color())
.add_modifier(Modifier::BOLD | Modifier::UNDERLINED),
));
if active_idx < last_idx {
spans.push(Span::styled(NEXT_MARK, theme::faint()));
}
spans
}
fn activity_color(activity: Option<ToastKind>) -> Color {
match activity {
None => theme::text_dim_color(),
Some(ToastKind::Success) => theme::success_color(),
Some(ToastKind::Danger) => theme::danger_color(),
Some(ToastKind::Warning) => theme::warning_color(),
Some(ToastKind::Info) => theme::text_color(),
}
}
#[cfg(test)]
#[path = "../../../tests/inline/tui_render_tabs.rs"]
mod tab_overflow_tests;