use retroglyph_core::{Backend, Rect, Style, Terminal};
use super::Widget;
#[derive(Clone, Copy, Debug)]
pub struct ProgressBar {
value: u32,
max: u32,
filled_style: Style,
empty_style: Style,
}
impl ProgressBar {
#[must_use]
pub fn new(value: u32, max: u32) -> Self {
Self {
value,
max,
filled_style: Style::new(),
empty_style: Style::new(),
}
}
#[must_use]
pub const fn filled_style(mut self, style: Style) -> Self {
self.filled_style = style;
self
}
#[must_use]
pub const fn empty_style(mut self, style: Style) -> Self {
self.empty_style = style;
self
}
}
impl<B: Backend> Widget<B> for ProgressBar {
fn render(self, area: Rect, term: &mut Terminal<B>) {
if area.width() == 0 || self.max == 0 {
return;
}
let filled_cells = ((u64::from(self.value.min(self.max)) * u64::from(area.width()))
/ u64::from(self.max)) as u16;
let y = area.top();
for x in area.left()..area.right() {
let is_filled = x < area.left() + filled_cells;
let style = if is_filled {
self.filled_style
} else {
self.empty_style
};
term.reset_style()
.fg(style.foreground())
.bg(style.background());
term.put(x, y, if is_filled { '█' } else { '░' });
}
term.reset_style();
}
}
#[cfg(test)]
mod tests {
use retroglyph_core::Headless;
use super::*;
#[test]
fn fills_proportionally() {
let area = Rect::new(0, 0, 10, 1);
let mut term = Terminal::new(Headless::new(10, 1));
ProgressBar::new(5, 10).render(area, &mut term);
for x in 0..5 {
assert_eq!(term.grid().get(x, 0).glyph(), '█');
}
for x in 5..10 {
assert_eq!(term.grid().get(x, 0).glyph(), '░');
}
}
#[test]
fn zero_max_is_a_no_op() {
let area = Rect::new(0, 0, 10, 1);
let mut term = Terminal::new(Headless::new(10, 1));
ProgressBar::new(0, 0).render(area, &mut term);
assert_eq!(term.grid().get(0, 0).glyph(), ' ');
}
#[test]
fn filled_and_empty_styles_are_configurable() {
use retroglyph_core::Color;
let area = Rect::new(0, 0, 4, 1);
let mut term = Terminal::new(Headless::new(4, 1));
ProgressBar::new(2, 4)
.filled_style(Style::new().fg(Color::WHITE))
.empty_style(Style::new().fg(Color::BLACK))
.render(area, &mut term);
assert_eq!(term.grid().get(0, 0).style().foreground(), Color::WHITE);
assert_eq!(term.grid().get(3, 0).style().foreground(), Color::BLACK);
}
}