142 lines
3.9 KiB
Rust
142 lines
3.9 KiB
Rust
use chrono::{Duration, NaiveTime};
|
|
use glib::Object;
|
|
use gtk::{prelude::*, subclass::prelude::*};
|
|
use std::{cell::RefCell, f64::consts::PI, rc::Rc};
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct Color {
|
|
pub r: f64,
|
|
pub g: f64,
|
|
pub b: f64,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct Wedge {
|
|
pub start_angle: f64,
|
|
pub end_angle: f64,
|
|
pub color: Color,
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct PieChartPrivate {
|
|
rotation: Rc<RefCell<f64>>,
|
|
wedges: Rc<RefCell<Vec<Wedge>>>,
|
|
}
|
|
|
|
#[glib::object_subclass]
|
|
impl ObjectSubclass for PieChartPrivate {
|
|
const NAME: &'static str = "PieChart";
|
|
type Type = PieChart;
|
|
type ParentType = gtk::DrawingArea;
|
|
}
|
|
|
|
impl ObjectImpl for PieChartPrivate {}
|
|
impl WidgetImpl for PieChartPrivate {}
|
|
impl DrawingAreaImpl for PieChartPrivate {}
|
|
|
|
glib::wrapper! {
|
|
pub struct PieChart(ObjectSubclass<PieChartPrivate>) @extends gtk::DrawingArea, gtk::Widget;
|
|
}
|
|
|
|
impl PieChart {
|
|
pub fn new(builder: PieChartBuilder) -> Self {
|
|
let s: Self = Object::builder().build();
|
|
s.set_content_width(500);
|
|
s.set_content_height(500);
|
|
|
|
*s.imp().rotation.borrow_mut() = builder.rotation;
|
|
*s.imp().wedges.borrow_mut() = builder.wedges;
|
|
|
|
s.set_draw_func({
|
|
let s = s.clone();
|
|
move |_, context, width, height| {
|
|
println!("redrawing: {} {}", width, height);
|
|
let radius = width.min(height) as f64 / 2. * 0.9;
|
|
let center_x = (width / 2) as f64;
|
|
let center_y = (height / 2) as f64;
|
|
|
|
let rotation = s.imp().rotation.borrow().clone();
|
|
let wedges = s.imp().wedges.borrow().clone();
|
|
|
|
context.set_source_rgba(0., 0., 0., 0.);
|
|
let _ = context.paint();
|
|
|
|
context.set_line_width(2.);
|
|
|
|
wedges.iter().for_each(
|
|
|Wedge {
|
|
start_angle,
|
|
end_angle,
|
|
color,
|
|
}| {
|
|
println!(
|
|
"wedge: {:.02?} {:.02?} {:.02?}",
|
|
start_angle, end_angle, color
|
|
);
|
|
println!(
|
|
"wedge: {:.02?} {:.02?} [{:.02?}]",
|
|
start_angle + rotation,
|
|
end_angle + rotation,
|
|
rotation
|
|
);
|
|
context.move_to(center_x, center_y);
|
|
context.set_source_rgb(color.r, color.g, color.b);
|
|
context.arc(
|
|
center_x,
|
|
center_y,
|
|
radius,
|
|
start_angle + rotation,
|
|
end_angle + rotation,
|
|
);
|
|
let _ = context.fill();
|
|
},
|
|
);
|
|
|
|
context.set_source_rgb(1., 1., 1.);
|
|
context.arc(center_x, center_y, radius, 0., 2. * PI);
|
|
let _ = context.stroke();
|
|
}
|
|
});
|
|
|
|
s
|
|
}
|
|
|
|
pub fn set_rotation(&mut self, rotation: f64) {
|
|
*self.imp().rotation.borrow_mut() = rotation;
|
|
self.queue_draw();
|
|
}
|
|
|
|
pub fn add_wedge(&mut self, wedge: Wedge) {
|
|
(*self.imp().wedges.borrow_mut()).push(wedge);
|
|
self.queue_draw();
|
|
}
|
|
|
|
pub fn builder() -> PieChartBuilder {
|
|
PieChartBuilder {
|
|
rotation: 0.,
|
|
wedges: vec![],
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct PieChartBuilder {
|
|
rotation: f64,
|
|
wedges: Vec<Wedge>,
|
|
}
|
|
|
|
impl PieChartBuilder {
|
|
pub fn rotation(mut self, rotation: f64) -> Self {
|
|
self.rotation = rotation;
|
|
self
|
|
}
|
|
|
|
pub fn wedges(mut self, wedges: Vec<Wedge>) -> Self {
|
|
self.wedges = wedges;
|
|
self
|
|
}
|
|
|
|
pub fn build(self) -> PieChart {
|
|
PieChart::new(self)
|
|
}
|
|
}
|