2023-08-09 17:15:32 +00:00
|
|
|
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};
|
|
|
|
|
|
|
|
pub struct TransitClockPrivate {
|
|
|
|
info: Rc<RefCell<Option<SunMoon>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for TransitClockPrivate {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
info: Rc::new(RefCell::new(None)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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 TransitClock {
|
|
|
|
pub fn new() -> 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| {
|
2023-08-10 03:33:51 +00:00
|
|
|
let style_context = WidgetExt::style_context(&s);
|
2023-08-09 17:15:32 +00:00
|
|
|
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();
|
|
|
|
|
2023-08-10 03:33:51 +00:00
|
|
|
let night_color = style_context.lookup_color("dark_5").unwrap();
|
|
|
|
let day_color = style_context.lookup_color("blue_1").unwrap();
|
|
|
|
|
|
|
|
PieChart::new(&style_context)
|
2023-08-09 17:15:32 +00:00
|
|
|
.center(center_x, center_y)
|
|
|
|
.radius(radius)
|
|
|
|
.rotation(-PI / 2.)
|
|
|
|
.wedges(
|
2023-08-10 03:33:51 +00:00
|
|
|
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,
|
|
|
|
},
|
2023-08-09 17:15:32 +00:00
|
|
|
},
|
2023-08-10 03:33:51 +00:00
|
|
|
]
|
2023-08-09 17:15:32 +00:00
|
|
|
.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
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn update_transit(&self, transit_info: SunMoon) {
|
|
|
|
*self.imp().info.borrow_mut() = Some(transit_info);
|
|
|
|
self.queue_draw();
|
|
|
|
}
|
|
|
|
}
|