1use ratatui::prelude::{Widget, Rect, Buffer, Style, symbols, Color};
2
3#[derive(Debug, Clone, Copy, Default)]
6pub struct Meter {
7 meter_style: Style,
8 use_ascii: bool,
9 ratio: f64,
10}
11
12impl Meter {
13 pub fn ratio(self, ratio: f64) -> Self {
14 Self { ratio, ..self }
15 }
16
17 pub fn style(self, meter_style: Style) -> Self {
18 Self { meter_style, ..self }
19 }
20
21 pub fn use_ascii(self, use_ascii: bool) -> Self {
22 Self { use_ascii, ..self }
23 }
24}
25
26impl Widget for Meter {
27 fn render(self, area: Rect, buf: &mut Buffer) {
28 if area.is_empty() {
29 return;
30 }
31
32 buf.set_style(area, self.meter_style);
33
34 let filled_width = f64::from(area.width) * self.ratio;
36 let end = if self.use_ascii {
37 area.left() + filled_width.round() as u16
38 } else {
39 area.left() + filled_width.floor() as u16
40 };
41 for y in area.top()..area.bottom() {
42 for x in area.left()..end {
44 buf[(x, y)]
48 .set_symbol(symbols::block::FULL)
49 .set_fg(self.meter_style.fg.unwrap_or(Color::Reset))
50 .set_bg(self.meter_style.bg.unwrap_or(Color::Reset));
51 }
52 if !self.use_ascii && self.ratio < 1.0 {
53 let symbol = match ((filled_width % 1.0) * 8.0).round() as u16 {
54 1 => symbols::block::ONE_EIGHTH,
55 2 => symbols::block::ONE_QUARTER,
56 3 => symbols::block::THREE_EIGHTHS,
57 4 => symbols::block::HALF,
58 5 => symbols::block::FIVE_EIGHTHS,
59 6 => symbols::block::THREE_QUARTERS,
60 7 => symbols::block::SEVEN_EIGHTHS,
61 8 => symbols::block::FULL,
62 _ => " ",
63 };
64 buf[(end, y)].set_symbol(symbol);
65 }
66 }
67 }
68}