use rosace_core::types::{Point, Size};
use rosace_render::Color;
use super::{Widget, LayoutCtx, PaintCtx};
pub struct CircularProgress {
value: Option<f32>, diameter: f32,
thickness: f32,
color: Option<Color>,
track: Option<Color>,
}
impl CircularProgress {
pub fn new(value: f32) -> Self {
Self { value: Some(value.clamp(0.0, 1.0)), diameter: 36.0, thickness: 4.0, color: None, track: None }
}
pub fn spinner() -> Self {
Self { value: None, diameter: 36.0, thickness: 4.0, color: None, track: None }
}
pub fn diameter(mut self, d: f32) -> Self { self.diameter = d; self }
pub fn thickness(mut self, t: f32) -> Self { self.thickness = t; self }
pub fn color(mut self, c: Color) -> Self { self.color = Some(c); self }
pub fn track(mut self, c: Color) -> Self { self.track = Some(c); self }
}
impl Widget for CircularProgress {
fn layout(&self, ctx: &LayoutCtx) -> Size {
ctx.constraints.constrain(Size { width: self.diameter, height: self.diameter })
}
fn paint(&self, ctx: &mut PaintCtx) {
let r = ctx.rect;
let color = self.color.unwrap_or_else(|| ctx.tc(ctx.theme.colors.primary));
let center = Point { x: r.origin.x + r.size.width / 2.0, y: r.origin.y + r.size.height / 2.0 };
let radius = (self.diameter - self.thickness) / 2.0;
match self.value {
Some(v) => {
let track = self.track.unwrap_or(Color::rgba(255, 255, 255, 28));
ctx.fill_arc(center, radius, self.thickness, 0.0, 360.0, track);
if v > 0.0 {
ctx.fill_arc(center, radius, self.thickness, -90.0, 360.0 * v, color);
}
}
None => {
let t = super::anim_clock();
let start = (t * 360.0) % 360.0;
ctx.fill_arc(center, radius, self.thickness, start, 270.0, color);
ctx.request_animation();
}
}
}
}