monorepo/dashboard/src/components/transit_clock.rs

104 lines
4.0 KiB
Rust

use crate::{
drawing::{Color, PieChart, Wedge},
soluna_client::SunMoon,
};
use chrono::{Duration, NaiveTime};
use glib::Object;
use gtk::{prelude::*, subclass::prelude::*};
use std::{cell::RefCell, f64::consts::PI, rc::Rc};
#[derive(Default)]
pub struct TransitClockPrivate {
info: Rc<RefCell<Option<SunMoon>>>,
}
#[glib::object_subclass]
impl ObjectSubclass for TransitClockPrivate {
const NAME: &'static str = "TransitClock";
type Type = TransitClock;
type ParentType = gtk::DrawingArea;
}
impl ObjectImpl for TransitClockPrivate {}
impl WidgetImpl for TransitClockPrivate {}
impl DrawingAreaImpl for TransitClockPrivate {}
glib::wrapper! {
pub struct TransitClock(ObjectSubclass<TransitClockPrivate>) @extends gtk::DrawingArea, gtk::Widget;
}
impl Default for TransitClock {
fn default() -> Self {
let s: Self = Object::builder().build();
s.set_width_request(500);
s.set_height_request(500);
s.set_draw_func({
let s = s.clone();
move |_, context, width, height| {
let style_context = WidgetExt::style_context(&s);
let center_x = width as f64 / 2.;
let center_y = height as f64 / 2.;
let radius = width.min(height) as f64 / 2. * 0.9;
if let Some(ref info) = *s.imp().info.borrow() {
let full_day = Duration::days(1).num_seconds() as f64;
let sunrise = info.sunrise - NaiveTime::from_hms_opt(0, 0, 0).unwrap();
let sunset = info.sunset - NaiveTime::from_hms_opt(0, 0, 0).unwrap();
let night_color = style_context.lookup_color("dark_5").unwrap();
let day_color = style_context.lookup_color("blue_1").unwrap();
PieChart::new(&style_context)
.center(center_x, center_y)
.radius(radius)
.rotation(-PI / 2.)
.wedges(
vec![
Wedge {
start_angle: (PI * 2.) * sunset.num_seconds() as f64 / full_day,
end_angle: (PI * 2.) * sunrise.num_seconds() as f64 / full_day,
color: Color {
r: night_color.red() as f64,
g: night_color.green() as f64,
b: night_color.blue() as f64,
},
},
Wedge {
start_angle: (PI * 2.) * sunrise.num_seconds() as f64
/ full_day,
end_angle: (PI * 2.) * sunset.num_seconds() as f64 / full_day,
color: Color {
r: day_color.red() as f64,
g: day_color.green() as f64,
b: day_color.blue() as f64,
},
},
]
.into_iter(),
)
.draw(context);
(0..24).for_each(|tick| {
context.set_source_rgb(0., 0., 0.);
context.translate(center_x, center_y);
context.rotate(tick as f64 * (PI / 12.));
context.move_to(radius - 5., 0.);
context.line_to(radius - 10., 0.);
let _ = context.stroke();
context.identity_matrix();
});
}
}
});
s
}
}
impl TransitClock {
pub fn update_transit(&self, transit_info: SunMoon) {
*self.imp().info.borrow_mut() = Some(transit_info);
self.queue_draw();
}
}