ratatui_toolkit/primitives/statusline/methods/
mod.rs

1use ratatui::buffer::Buffer;
2use ratatui::layout::Rect;
3use ratatui::style::Style;
4use ratatui::text::Span;
5use ratatui::widgets::Widget;
6
7use crate::primitives::statusline::{
8    OperationalMode, StatusLineStacked, StyledStatusLine, SLANT_BL_TR, SLANT_TL_BR,
9};
10
11impl<'a> Widget for StatusLineStacked<'a> {
12    fn render(self, area: Rect, buf: &mut Buffer) {
13        let mut x_end = area.right();
14        for (status, gap) in self.right.iter() {
15            let width = status.width() as u16;
16            status.render(
17                Rect::new(x_end.saturating_sub(width), area.y, width, 1),
18                buf,
19            );
20            x_end = x_end.saturating_sub(width);
21
22            let width = gap.width() as u16;
23            gap.render(
24                Rect::new(x_end.saturating_sub(width), area.y, width, 1),
25                buf,
26            );
27            x_end = x_end.saturating_sub(width);
28        }
29
30        let mut x_start = area.x;
31        for (status, gap) in self.left.iter() {
32            let width = status.width() as u16;
33            status.render(Rect::new(x_start, area.y, width, 1), buf);
34            x_start += width;
35
36            let width = gap.width() as u16;
37            gap.render(Rect::new(x_start, area.y, width, 1), buf);
38            x_start += width;
39        }
40
41        buf.set_style(
42            Rect::new(x_start, area.y, x_end.saturating_sub(x_start), 1),
43            self.style,
44        );
45
46        let center_width = x_end
47            .saturating_sub(x_start)
48            .saturating_sub(self.center_margin * 2);
49
50        self.center.render(
51            Rect::new(x_start + self.center_margin, area.y, center_width, 1),
52            buf,
53        );
54    }
55}
56
57impl<'a> StyledStatusLine<'a> {
58    pub fn build(self) -> StatusLineStacked<'a> {
59        use ratatui::style::Color;
60
61        let color_title = Color::Rgb(70, 73, 77);
62        let color_mode = match self.mode {
63            OperationalMode::Operational => Color::Rgb(42, 193, 138),
64            OperationalMode::Dire => Color::Rgb(255, 210, 88),
65            OperationalMode::Evacuate => Color::Rgb(246, 90, 90),
66        };
67        let color_info = Color::Rgb(44, 163, 170);
68        let color_dark = Color::Rgb(80, 202, 210);
69        let text_black = Color::Rgb(16, 19, 23);
70
71        let mode_str = match self.mode {
72            OperationalMode::Operational => " OPERATIONAL ",
73            OperationalMode::Dire => " DIRE ",
74            OperationalMode::Evacuate => " EVACUATE ",
75        };
76
77        if self.use_slants {
78            StatusLineStacked::new()
79                .style(Style::new().fg(Color::White).bg(color_dark))
80                .start(
81                    Span::from(self.title).style(Style::new().fg(text_black).bg(color_title)),
82                    Span::from(SLANT_TL_BR).style(Style::new().fg(color_title).bg(color_mode)),
83                )
84                .start(
85                    Span::from(mode_str).style(Style::new().fg(text_black).bg(color_mode)),
86                    Span::from(SLANT_TL_BR).style(Style::new().fg(color_mode)),
87                )
88                .center_margin(1)
89                .center(self.center_text)
90                .end(
91                    Span::from(format!(
92                        "R[{}][{}µs] ",
93                        self.render_count, self.render_time_us
94                    ))
95                    .style(Style::new().fg(text_black).bg(color_info)),
96                    Span::from(SLANT_BL_TR).style(Style::new().fg(color_info).bg(color_dark)),
97                )
98                .end(
99                    "",
100                    Span::from(SLANT_BL_TR).style(Style::new().fg(color_dark).bg(color_info)),
101                )
102                .end(
103                    Span::from(format!(
104                        "E[{}][{}µs] ",
105                        self.event_count, self.event_time_us
106                    ))
107                    .style(Style::new().fg(text_black).bg(color_info)),
108                    Span::from(SLANT_BL_TR).style(Style::new().fg(color_info).bg(color_dark)),
109                )
110                .end(
111                    "",
112                    Span::from(SLANT_BL_TR).style(Style::new().fg(color_dark).bg(color_info)),
113                )
114                .end(
115                    Span::from(format!("MSG[{}] ", self.message_count))
116                        .style(Style::new().fg(text_black).bg(color_info)),
117                    Span::from(SLANT_BL_TR).style(Style::new().fg(color_info)),
118                )
119        } else {
120            StatusLineStacked::new()
121                .style(Style::new().fg(Color::White).bg(color_dark))
122                .start_bare(
123                    Span::from(self.title).style(Style::new().fg(Color::White).bg(color_title)),
124                )
125                .start_bare(Span::from(mode_str).style(Style::new().fg(text_black).bg(color_mode)))
126                .center_margin(1)
127                .center(self.center_text)
128                .end_bare(
129                    Span::from(format!(
130                        "R[{}][{}µs] ",
131                        self.render_count, self.render_time_us
132                    ))
133                    .style(Style::new().fg(text_black).bg(color_info)),
134                )
135                .end_bare(
136                    Span::from(format!(
137                        "E[{}][{}µs] ",
138                        self.event_count, self.event_time_us
139                    ))
140                    .style(Style::new().fg(text_black).bg(color_info)),
141                )
142                .end_bare(
143                    Span::from(format!(" MSG[{}] ", self.message_count))
144                        .style(Style::new().fg(text_black).bg(color_info)),
145                )
146        }
147    }
148}