use crate::core::buffer::Buffer;
use crate::core::color::Color;
use crate::core::rect::Rect;
use crate::style::Style;
use crate::widgets::Widget;
#[derive(Debug, Clone)]
pub struct Gauge<'a> {
pub ratio: f64,
pub label: &'a str,
pub style: Style,
pub gauge_style: Style,
pub use_unicode: bool,
}
impl<'a> Gauge<'a> {
pub fn new() -> Self {
Self {
ratio: 0.0,
label: "",
style: Style::new(),
gauge_style: Style::new().fg(Color::rgb(88, 166, 255)),
use_unicode: true,
}
}
pub fn with_ratio(mut self, ratio: f64) -> Self {
self.ratio = ratio.clamp(0.0, 1.0);
self
}
pub fn with_label(mut self, label: &'a str) -> Self {
self.label = label;
self
}
pub fn with_style(mut self, style: Style) -> Self {
self.style = style;
self
}
pub fn with_gauge_style(mut self, style: Style) -> Self {
self.gauge_style = style;
self
}
}
impl<'a> Widget for Gauge<'a> {
fn render(&self, buffer: &mut Buffer, area: Rect) {
if area.width < 2 || area.height < 1 {
return;
}
let w = area.width as usize;
let fill = (w as f64 * self.ratio) as usize;
let fg = self.gauge_style.fg_or_default();
let bg = self.style.bg;
let empty_bg = self.style.bg;
let (full, half, empty) = if self.use_unicode {
('━', '╌', '─')
} else {
('=', '-', ' ')
};
for i in 0..w {
let x = (area.x as usize) + i;
let y = area.y as usize;
if i < fill {
buffer.set(
x,
y,
crate::core::buffer::Cell {
ch: full,
fg,
bg,
bold: false,
italic: false,
underlined: false,
},
);
} else if i == fill && self.ratio > 0.0 {
buffer.set(
x,
y,
crate::core::buffer::Cell {
ch: half,
fg: fg.dim(0.5),
bg: empty_bg,
bold: false,
italic: false,
underlined: false,
},
);
} else {
buffer.set(
x,
y,
crate::core::buffer::Cell {
ch: empty,
fg: fg.dim(0.3),
bg: empty_bg,
bold: false,
italic: false,
underlined: false,
},
);
}
}
if !self.label.is_empty() {
let pct = (self.ratio * 100.0) as u32;
let label = format!(" {} {}%", self.label, pct);
let display: String = label.chars().take(w).collect();
let lx = area.x as usize + (w.saturating_sub(display.len())) / 2;
buffer.set_str(lx, area.y as usize, &display, Color::WHITE, bg);
}
}
}
impl<'a> Default for Gauge<'a> {
fn default() -> Self {
Self::new()
}
}