From b2ca3d195dda3fcea5651db228ae6a74cc73b0c3 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Thu, 10 Aug 2023 12:35:48 -0400 Subject: [PATCH] Show the solstices and equinoxes --- dashboard/resources/style.css | 8 ++- dashboard/src/app_window.rs | 15 +++-- dashboard/src/components/events.rs | 105 +++++++++++++++++++++++++++++ dashboard/src/components/mod.rs | 3 + dashboard/src/main.rs | 1 + dashboard/src/solstices.rs | 4 +- dashboard/src/types.rs | 6 +- ifc/src/lib.rs | 6 +- 8 files changed, 135 insertions(+), 13 deletions(-) create mode 100644 dashboard/src/components/events.rs diff --git a/dashboard/resources/style.css b/dashboard/resources/style.css index 6f9bc0b..bf7d9e6 100644 --- a/dashboard/resources/style.css +++ b/dashboard/resources/style.css @@ -1,5 +1,9 @@ -@define-color background_color @purple_5; - label { font-size: 200%; + padding: 4px; +} + +.highlight { + color: @accent_fg_color; + background-color: @accent_bg_color; } diff --git a/dashboard/src/app_window.rs b/dashboard/src/app_window.rs index fd15ca2..10886bc 100644 --- a/dashboard/src/app_window.rs +++ b/dashboard/src/app_window.rs @@ -1,5 +1,5 @@ use crate::{ - components::{Date, TransitCard, TransitClock}, + components::{Date, Events, TransitCard, TransitClock}, types::State, }; use adw::prelude::AdwApplicationWindowExt; @@ -10,7 +10,7 @@ use gtk::{prelude::*, STYLE_PROVIDER_PRIORITY_USER}; pub struct ApplicationWindow { pub window: adw::ApplicationWindow, pub date_label: Date, - pub next_event: gtk::Label, + pub events: Events, pub transit_card: TransitCard, pub transit_clock: TransitClock, } @@ -43,6 +43,7 @@ impl ApplicationWindow { let date_label = Date::new(); layout.append(&date_label); + /* let next_event = gtk::Label::builder() .margin_bottom(8) .margin_top(8) @@ -50,6 +51,10 @@ impl ApplicationWindow { .margin_end(8) .build(); layout.append(&next_event); + */ + + let events = Events::new(); + layout.append(&events); let transit_card = TransitCard::new(); layout.append(&transit_card); @@ -62,7 +67,7 @@ impl ApplicationWindow { Self { window, date_label, - next_event, + events, transit_card, transit_clock, } @@ -70,7 +75,9 @@ impl ApplicationWindow { pub fn update_state(&self, state: State) { self.date_label.update_date(state.date); - self.next_event.set_text(&format!("{:?}", state.next_event)); + /* self.next_event.set_text(&format!("{:?}", state.next_event)); */ + + self.events.set_events(state.events, state.next_event); if let Some(transit) = state.transit { self.transit_card.update_transit(&transit); self.transit_clock.update_transit(transit); diff --git a/dashboard/src/components/events.rs b/dashboard/src/components/events.rs new file mode 100644 index 0000000..f1d072c --- /dev/null +++ b/dashboard/src/components/events.rs @@ -0,0 +1,105 @@ +use crate::{ + components::Date, + solstices::{self, YearlyEvents}, + soluna_client::SunMoon, +}; +use chrono::TimeZone; +use glib::Object; +use gtk::{prelude::*, subclass::prelude::*, IconLookupFlags}; +use ifc::IFC; + +#[derive(PartialEq)] +pub enum UpcomingEvent { + SpringEquinox, + SummerSolstice, + AutumnEquinox, + WinterSolstice, +} + +pub struct EventsPrivate { + spring_equinox: Date, + summer_solstice: Date, + autumn_equinox: Date, + winter_solstice: Date, + next: UpcomingEvent, +} + +impl Default for EventsPrivate { + fn default() -> Self { + Self { + spring_equinox: Date::new(), + summer_solstice: Date::new(), + autumn_equinox: Date::new(), + winter_solstice: Date::new(), + next: UpcomingEvent::SpringEquinox, + } + } +} + +#[glib::object_subclass] +impl ObjectSubclass for EventsPrivate { + const NAME: &'static str = "Events"; + type Type = Events; + type ParentType = gtk::Box; +} + +impl ObjectImpl for EventsPrivate {} +impl WidgetImpl for EventsPrivate {} +impl BoxImpl for EventsPrivate {} + +glib::wrapper! { + pub struct Events(ObjectSubclass) @extends gtk::Widget, gtk::Box, @implements gtk::Orientable; +} + +impl Events { + pub fn new() -> Self { + let s: Self = Object::builder().build(); + s.set_orientation(gtk::Orientation::Horizontal); + s.set_spacing(8); + + s.append(&s.imp().spring_equinox); + s.append(&s.imp().summer_solstice); + s.append(&s.imp().autumn_equinox); + s.append(&s.imp().winter_solstice); + + s + } + + pub fn set_events(&self, events: YearlyEvents, next_event: solstices::Event) { + self.imp() + .spring_equinox + .update_date(IFC::from(events.spring_equinox.date_naive())); + + self.imp() + .summer_solstice + .update_date(IFC::from(events.summer_solstice.date_naive())); + + self.imp() + .autumn_equinox + .update_date(IFC::from(events.autumn_equinox.date_naive())); + + self.imp() + .winter_solstice + .update_date(IFC::from(events.winter_solstice.date_naive())); + + self.imp().spring_equinox.remove_css_class("highlight"); + self.imp().summer_solstice.remove_css_class("highlight"); + self.imp().autumn_equinox.remove_css_class("highlight"); + self.imp().winter_solstice.remove_css_class("highlight"); + + match next_event { + solstices::Event::SpringEquinox(_) => { + self.imp().spring_equinox.add_css_class("highlight") + } + solstices::Event::SummerSolstice(_) => { + self.imp().summer_solstice.add_css_class("highlight") + } + solstices::Event::AutumnEquinox(_) => { + self.imp().autumn_equinox.add_css_class("highlight") + } + solstices::Event::WinterSolstice(_) => { + self.imp().winter_solstice.add_css_class("highlight") + } + } + } +} diff --git a/dashboard/src/components/mod.rs b/dashboard/src/components/mod.rs index 02a5aa4..4ec00a5 100644 --- a/dashboard/src/components/mod.rs +++ b/dashboard/src/components/mod.rs @@ -1,6 +1,9 @@ mod date; pub use date::Date; +mod events; +pub use events::Events; + mod label; pub use label::Label; diff --git a/dashboard/src/main.rs b/dashboard/src/main.rs index cd51809..7af3529 100644 --- a/dashboard/src/main.rs +++ b/dashboard/src/main.rs @@ -106,6 +106,7 @@ pub fn main() { let state = State { date: IFC::from(now.date_naive().with_year(12023).unwrap()), next_event: EVENTS.next_event(now.with_timezone(&Utc)).unwrap(), + events: EVENTS.yearly_events(now.year()).unwrap(), transit: Some(transit), }; diff --git a/dashboard/src/solstices.rs b/dashboard/src/solstices.rs index 6a0943b..4908292 100644 --- a/dashboard/src/solstices.rs +++ b/dashboard/src/solstices.rs @@ -133,11 +133,9 @@ fn parse_events() -> Vec> { pub struct Solstices(HashMap); impl Solstices { - /* - pub fn acquire(&self, year: i32) -> Option { + pub fn yearly_events(&self, year: i32) -> Option { self.0.get(&year).map(|c| c.clone()) } - */ pub fn next_event(&self, date: chrono::DateTime) -> Option { let year_events = self.0.get(&date.year()); diff --git a/dashboard/src/types.rs b/dashboard/src/types.rs index 045d448..1bcf577 100644 --- a/dashboard/src/types.rs +++ b/dashboard/src/types.rs @@ -1,9 +1,13 @@ -use crate::{solstices::Event, soluna_client::SunMoon}; +use crate::{ + solstices::{Event, YearlyEvents}, + soluna_client::SunMoon, +}; use ifc::IFC; #[derive(Clone, Debug)] pub struct State { pub date: IFC, pub next_event: Event, + pub events: YearlyEvents, pub transit: Option, } diff --git a/ifc/src/lib.rs b/ifc/src/lib.rs index 5d6d6a3..450b889 100644 --- a/ifc/src/lib.rs +++ b/ifc/src/lib.rs @@ -232,9 +232,9 @@ impl IFC { #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Day { - year: i32, - month: u8, - day: u8, + pub year: i32, + pub month: u8, + pub day: u8, } impl From for IFC {