use crate::geometry::Rect;
use crate::painter::Painter;
use crate::theme::Theme;
use crate::widget::Widget;
pub struct ProgressBar {
rect: Rect,
fraction: f32,
show_percentage: bool,
}
impl ProgressBar {
pub fn new(rect: Rect) -> Self {
Self {
rect,
fraction: 0.0,
show_percentage: false,
}
}
pub fn with_fraction(mut self, fraction: f32) -> Self {
self.set_fraction(fraction);
self
}
pub fn with_percentage(mut self, show: bool) -> Self {
self.show_percentage = show;
self
}
pub fn fraction(&self) -> f32 {
self.fraction
}
pub fn set_fraction(&mut self, fraction: f32) {
self.fraction = fraction.clamp(0.0, 1.0);
}
pub fn rect(&self) -> Rect {
self.rect
}
pub fn set_rect(&mut self, rect: Rect) {
self.rect = rect;
}
}
impl Widget for ProgressBar {
fn bounds(&self) -> Rect {
self.rect
}
fn paint(&mut self, painter: &mut Painter, theme: &Theme) {
painter.fill_rect(self.rect, theme.background);
painter.sunken_bevel(self.rect, theme.highlight, theme.shadow);
painter.stroke_rect(self.rect, theme.border);
let inner = self.rect.inset(2);
if inner.w <= 0 || inner.h <= 0 {
return;
}
let fill_w = ((inner.w as f32) * self.fraction).round() as i32;
if fill_w > 0 {
painter.fill_rect(Rect::new(inner.x, inner.y, fill_w, inner.h), theme.shadow);
}
if self.show_percentage {
let pct = (self.fraction * 100.0).round() as i32;
let text = format!("{pct}%");
let size = theme.font_size;
let m = painter.measure_text(&text, size);
let tx = inner.x + ((inner.w - m.w) / 2).max(0);
let ty = inner.y + ((inner.h - m.h) / 2).max(0);
painter.text(tx, ty, &text, size, theme.text);
}
}
fn layout(&mut self, bounds: Rect) {
self.rect = bounds;
}
}