use crate::drawing::{Drawable, Plan};
use crate::layouts::{HasPlanner, Layout};
use skia_safe::{Canvas, Color, Color4f, Font, Paint, PaintCap, PaintStyle, Point, Rect};
use std::cell::RefCell;
use std::rc::Rc;
pub struct RingProgressChart {
pub pct: RefCell<f32>,
label: String,
color: Color,
font: Font,
planner: RefCell<Option<Rc<dyn Layout>>>,
}
impl HasPlanner for RingProgressChart {
fn planner(&self) -> &RefCell<Option<Rc<dyn Layout>>> {
&self.planner
}
fn set_planner(&self, p: Option<Rc<dyn Layout>>) {
*self.planner.borrow_mut() = p;
}
}
impl Drawable for RingProgressChart {
fn draw(&self, canvas: &Canvas) -> anyhow::Result<()> {
let area = self.get_planned_drawing_area(canvas);
let size = area.width().min(area.height());
let radius = size / 2.0;
let cx = area.left + area.width() / 2.0;
let cy = area.top + area.height() / 2.0;
let arc_rect = Rect::from_xywh(cx - radius, cy - radius, size, size);
let mut p = Paint::default();
p.set_anti_alias(true)
.set_style(PaintStyle::Stroke)
.set_stroke_width(4.0);
p.set_color4f(Color4f::new(1.0, 1.0, 1.0, 0.1), None);
canvas.draw_arc(arc_rect, 0.0, 360.0, false, &p);
p.set_color(self.color).set_stroke_cap(PaintCap::Round);
let sweep = (self.pct.borrow().clamp(0.0, 100.0) / 100.0) * 360.0;
if sweep > 0.0 {
canvas.draw_arc(arc_rect, -90.0, sweep, false, &p);
}
let mut lbl_paint = Paint::default();
lbl_paint.set_anti_alias(true).set_color(Color::WHITE);
let text_w = self.font.measure_str(&self.label, Some(&lbl_paint)).0;
canvas.draw_str(
&self.label,
Point::new(cx - text_w / 2.0, cy + 3.5),
&self.font,
&lbl_paint,
);
Ok(())
}
fn get_horizontal_plan(&self) -> Plan {
Plan::Fill
}
fn get_vertical_plan(&self) -> Plan {
Plan::Fill
}
}
impl RingProgressChart {
pub fn new(pct: f32, label: &str, color: Color, font: Font) -> Rc<Self> {
let mut small_font = font;
small_font.set_size(10.0);
Rc::new(Self {
pct: RefCell::new(pct),
label: label.to_string(),
color,
font: small_font,
planner: RefCell::new(None),
})
}
}