Skip to main content

basalt_tui/
statusbar.rs

1use std::marker::PhantomData;
2
3use ratatui::{
4    buffer::Buffer,
5    layout::{Constraint, Flex, Layout, Rect},
6    style::{Color, Stylize},
7    text::{Line, Span, Text},
8    widgets::{StatefulWidget, Widget},
9};
10
11#[derive(Default, Clone, PartialEq)]
12pub struct StatusBarState<'a> {
13    active_component_name: &'a str,
14    word_count: usize,
15    char_count: usize,
16}
17
18impl<'a> StatusBarState<'a> {
19    pub fn new(active_component_name: &'a str, word_count: usize, char_count: usize) -> Self {
20        Self {
21            active_component_name,
22            word_count,
23            char_count,
24        }
25    }
26}
27
28#[derive(Default)]
29pub struct StatusBar<'a> {
30    _lifetime: PhantomData<&'a ()>,
31}
32
33impl<'a> StatefulWidget for StatusBar<'a> {
34    type State = StatusBarState<'a>;
35
36    fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
37        let [left, right] = Layout::horizontal([Constraint::Fill(1), Constraint::Length(28)])
38            .flex(Flex::SpaceBetween)
39            .areas(area);
40
41        let active_component = [
42            Span::from("").dark_gray(),
43            Span::from(" ").bg(Color::DarkGray),
44            Span::from(state.active_component_name)
45                .dark_gray()
46                .reversed()
47                .bold(),
48            Span::from(" ").bg(Color::DarkGray),
49            Span::from("").dark_gray(),
50        ]
51        .to_vec();
52
53        Text::from(Line::from(active_component)).render(left, buf);
54
55        let [word_count, char_count] =
56            Layout::horizontal([Constraint::Fill(1), Constraint::Fill(1)])
57                .flex(Flex::End)
58                .areas(right);
59
60        Text::from(format!(
61            "{} word{}",
62            state.word_count,
63            if state.word_count == 1 { "" } else { "s" }
64        ))
65        .right_aligned()
66        .render(word_count, buf);
67
68        Text::from(format!(
69            "{} char{}",
70            state.char_count,
71            if state.char_count == 1 { "" } else { "s" }
72        ))
73        .right_aligned()
74        .render(char_count, buf);
75    }
76}