/* #[macro_use] extern crate serde_derive; #[macro_use] extern crate lazy_static; */ use chrono::{Datelike, Duration, NaiveTime}; use glib::Object; use gtk::{prelude::*, subclass::prelude::*, Orientation}; use ifc::IFC; use std::{cell::RefCell, env, f64::consts::PI, ops::Deref, rc::Rc}; mod drawing; use drawing::{Color, PieChart, Wedge}; /* use geo_types::{Latitude, Longitude}; */ mod soluna_client; use soluna_client::{LunarPhase, SunMoon}; /* mod solstices; use solstices::EVENTS; */ /* const EO_TEXT: &'static str = " day = {$day -> *[Sunday] Dimanĉo [Monday] Lundo [Tuesday] Mardo [Wednesday] Merkredo [Thursday] Ĵaŭdo [Friday] Vendredo [Saturday] Sabato [LeapDay] Leap Day [YearDay] Year Day } month = {$month -> *[January] Januaro [February] Februaro [March] Marto [April] Aprilo [May] Mayo [June] Junio [Sol] Solo [July] Julio [August] Aŭgusto [September] Septembro [October] Oktobro [November] Novembro [December] Decembro } spring_equinox = Printempa Ekvinokso summer_solstice = Somera Solstico autumn_equinox = Aŭtuna Ekvinokso winter_solstice = Vintra Solstico "; fn date(fluent: Arc, today: ifc::IFC) -> impl Render { let mut day_args = FluentArgs::new(); day_args.set( "day", FluentValue::String(Cow::Owned(String::from(today.weekday_ifc()))), ); let tago = fluent.tr("tago", Some(&day_args)).unwrap(); let mut month_args = FluentArgs::new(); month_args.set( "month", FluentValue::String(Cow::Owned(String::from(today.month_ifc()))), ); let monato = fluent.tr("month", Some(&month_args)).unwrap(); owned_html! {p : format!("{}, {} {}, {}", tago, monato, today.day(), today.year());} } */ /* fn soluna_desegno(sun_moon: SunMoon) -> impl Render { owned_html! { table { tr { th : "Sunleviĝo"; th : "Sunfalo"; th : "Lunleviĝo"; th : "Lunfalo"; } tr { td : format!("{}", sun_moon.sunrise.format("%H:%M")); td : format!("{}", sun_moon.sunset.format("%H:%M")); td : sun_moon.moonrise.map(|v| format!("{}", v.format("%H:%M"))).unwrap_or("".to_string()); td : sun_moon.moonset.map(|v| format!("{}", v.format("%H:%M"))).unwrap_or("".to_string()); td : format!("{:?}", sun_moon.moon_phase); } } } } */ /* fn astronomia_eventa_desegno( fluent: Arc, event: Option, ) -> impl Render { let s = match event { None => "".to_owned(), Some(event) => { let eventa_str = match event { Event::SpringEquinox(_) => fluent.tr("spring_equinox", None), Event::SummerSolstice(_) => fluent.tr("summer_solstice", None), Event::AutumnEquinox(_) => fluent.tr("autumn_equinox", None), Event::WinterSolstice(_) => fluent.tr("winter_solstice", None), } .unwrap(); format!("{} {}", eventa_str, event.date().format("%Y-%m-%d")) } }; owned_html! { div : s.clone(); } } */ /* fn page_template( fluent: Arc, today: ifc::IFC, sun_moon: SunMoon, event: Option, ) -> String { format!( "{}", html! { : doctype::HTML; html { head { title: "Superrigardo"; } body { h1(id="heading", class="title") : date(fluent.clone(), today); div : soluna_desegno(sun_moon.clone()); div : astronomia_eventa_desegno(fluent.clone(), event); // div : cirklo(); } } } ) } async fn page( fluent: Arc, solar_client: Arc, latitude: Latitude, longitude: Longitude, ) -> Result, Rejection> { let now = Utc::now(); let d = ifc::IFC::from(now.with_timezone(&New_York).date()); let sun_moon = solar_client .request(latitude, longitude, now.with_timezone(&New_York).date()) .await; let next_event = EVENTS.next_event(now); Ok(warp::reply::html(page_template( fluent, d, sun_moon, next_event, ))) } */ #[derive(Default)] pub struct DatePrivate {} #[glib::object_subclass] impl ObjectSubclass for DatePrivate { const NAME: &'static str = "Date"; type Type = Date; type ParentType = gtk::Box; } impl ObjectImpl for DatePrivate {} impl WidgetImpl for DatePrivate {} impl BoxImpl for DatePrivate {} glib::wrapper! { pub struct Date(ObjectSubclass) @extends gtk::Box, gtk::Widget; } impl Date { fn new() -> Self { let s: Self = Object::builder().build(); s.add_css_class("card"); s.add_css_class("activatable"); s.set_margin_bottom(8); s.set_margin_top(8); s.set_margin_start(8); s.set_margin_end(8); let dt = IFC::from(chrono::Local::now().date_naive().with_year(12023).unwrap()); s.append(>k::Label::new(Some( format!( "{:?}, {:?} {}, {}", dt.weekday(), dt.month(), dt.day(), dt.year() ) .as_ref(), ))); s } } pub struct TransitClockPrivate { info: Rc>>, } 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) @extends gtk::DrawingArea, gtk::Widget; } impl TransitClock { pub fn new(sun_moon_info: SunMoon) -> Self { let s: Self = Object::builder().build(); s.set_width_request(500); s.set_height_request(500); *s.imp().info.borrow_mut() = Some(sun_moon_info); s.set_draw_func({ let s = s.clone(); move |_, context, width, height| { 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(); PieChart::new() .width(width) .height(height) .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: 0.1, g: 0.1, b: 0.8, }, }] .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, 0.); context.line_to(radius - 10., 0.); let _ = context.stroke(); context.identity_matrix(); }); } } }); s } } pub fn main() { let app = gtk::Application::builder() .application_id("com.luminescent-dreams.dashboard") .resource_base_path("/com/luminescent-dreams/dashboard") .build(); app.connect_activate( // let runtime = runtime.clone(); |app| { let window = gtk::ApplicationWindow::new(app); window.present(); let layout = gtk::Box::builder() .orientation(Orientation::Vertical) .hexpand(true) .vexpand(true) .build(); let date = Date::new(); layout.append(&date); let button = gtk::Button::builder() .label("Text") .margin_bottom(8) .margin_top(8) .margin_start(8) .margin_end(8) .build(); layout.append(&button); let day = TransitClock::new(SunMoon { sunrise: NaiveTime::from_hms_opt(7, 0, 0).unwrap(), sunset: NaiveTime::from_hms_opt(22, 0, 0).unwrap(), moonrise: NaiveTime::from_hms_opt(15, 0, 0), moonset: NaiveTime::from_hms_opt(5, 0, 0), moon_phase: LunarPhase::WaningCrescent, }); layout.append(&day); window.set_child(Some(&layout)); }, ); let args: Vec = env::args().collect(); ApplicationExtManual::run_with_args(&app, &args); /* let now = Local::now(); let ifc = ifc::IFC::from(now.date_naive().with_year(12023).unwrap()); let next_event = EVENTS.next_event(now.with_timezone(&Utc)).unwrap(); println!( "{:?}, {:?} {}, {}", ifc.weekday(), ifc.month(), ifc.day(), ifc.year() ); println!("{:?}", next_event); let latitude = Latitude::from(41.78); let longitude = Longitude::from(-71.41); let soluna_client = SolunaClient::new(); let sun_moon = soluna_client .request(latitude, longitude, Local::now()) .await; println!( "Solar Transit: {} -> {}", sun_moon.sunrise.format("%H:%M").to_string(), sun_moon.sunset.format("%H:%M").to_string() ); println!( "Lunar Transit: {} -> {} [{:?}]", sun_moon .moonrise .map(|time| time.format("%H:%M").to_string()) .unwrap_or(" -- ".to_owned()), sun_moon .moonset .map(|time| time.format("%H:%M").to_string()) .unwrap_or(" -- ".to_owned()), sun_moon.moon_phase ); */ }