diff --git a/dashboard/src/app_window.rs b/dashboard/src/app_window.rs index 7051687..fd15ca2 100644 --- a/dashboard/src/app_window.rs +++ b/dashboard/src/app_window.rs @@ -1,5 +1,5 @@ use crate::{ - components::{Date, TransitClock}, + components::{Date, TransitCard, TransitClock}, types::State, }; use adw::prelude::AdwApplicationWindowExt; @@ -11,6 +11,7 @@ pub struct ApplicationWindow { pub window: adw::ApplicationWindow, pub date_label: Date, pub next_event: gtk::Label, + pub transit_card: TransitCard, pub transit_clock: TransitClock, } @@ -48,10 +49,11 @@ impl ApplicationWindow { .margin_start(8) .margin_end(8) .build(); - next_event.add_css_class("card"); - next_event.add_css_class("activatable"); layout.append(&next_event); + let transit_card = TransitCard::new(); + layout.append(&transit_card); + let transit_clock = TransitClock::new(); layout.append(&transit_clock); @@ -61,6 +63,7 @@ impl ApplicationWindow { window, date_label, next_event, + transit_card, transit_clock, } } @@ -69,6 +72,7 @@ impl ApplicationWindow { self.date_label.update_date(state.date); self.next_event.set_text(&format!("{:?}", 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/date.rs b/dashboard/src/components/date.rs index 3df0e39..f8698e4 100644 --- a/dashboard/src/components/date.rs +++ b/dashboard/src/components/date.rs @@ -38,8 +38,6 @@ glib::wrapper! { impl Date { pub 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); diff --git a/dashboard/src/components/label.rs b/dashboard/src/components/label.rs new file mode 100644 index 0000000..b793ccc --- /dev/null +++ b/dashboard/src/components/label.rs @@ -0,0 +1,58 @@ +use crate::soluna_client::SunMoon; +use glib::Object; +use gtk::{prelude::*, subclass::prelude::*, IconLookupFlags}; + +#[derive(Default)] +pub struct LabelPrivate { + label: gtk::Label, + icon: gtk::Image, +} + +#[glib::object_subclass] +impl ObjectSubclass for LabelPrivate { + const NAME: &'static str = "Label"; + type Type = Label; + type ParentType = gtk::Box; +} + +impl ObjectImpl for LabelPrivate {} +impl WidgetImpl for LabelPrivate {} +impl BoxImpl for LabelPrivate {} + +glib::wrapper! { + pub struct Label(ObjectSubclass) @extends gtk::Box, gtk::Widget, + @implements gtk::Orientable; +} + +impl Label { + pub fn new(text: Option<&str>, icon: Option) -> Self { + let s: Self = Object::builder().build(); + s.set_orientation(gtk::Orientation::Horizontal); + s.set_spacing(8); + s.set_margin_bottom(8); + s.set_margin_top(8); + s.set_margin_start(8); + s.set_margin_end(8); + + s.append(&s.imp().icon); + s.append(&s.imp().label); + + if let Some(text) = text { + s.set_text(text); + } + + if let Some(icon) = icon { + s.set_icon(icon); + } + + s + } + + pub fn set_text(&self, text: &str) { + self.imp().label.set_text(text); + } + + pub fn set_icon(&self, icon: gio::ThemedIcon) { + self.imp().icon.set_from_gicon(&icon); + } +} diff --git a/dashboard/src/components/mod.rs b/dashboard/src/components/mod.rs index a011020..02a5aa4 100644 --- a/dashboard/src/components/mod.rs +++ b/dashboard/src/components/mod.rs @@ -1,5 +1,11 @@ mod date; pub use date::Date; +mod label; +pub use label::Label; + +mod transit_card; +pub use transit_card::TransitCard; + mod transit_clock; pub use transit_clock::TransitClock; diff --git a/dashboard/src/components/transit_card.rs b/dashboard/src/components/transit_card.rs new file mode 100644 index 0000000..27334e7 --- /dev/null +++ b/dashboard/src/components/transit_card.rs @@ -0,0 +1,72 @@ +use crate::{components::Label, soluna_client::SunMoon}; +use glib::Object; +use gtk::{prelude::*, subclass::prelude::*, IconLookupFlags}; + +pub struct TransitCardPrivate { + sunrise: Label, + sunset: Label, + moonrise: Label, + moonset: Label, +} + +impl Default for TransitCardPrivate { + fn default() -> Self { + Self { + sunrise: Label::new(None, Some(gio::ThemedIcon::new("daytime-sunrise-symbolic"))), + sunset: Label::new(None, Some(gio::ThemedIcon::new("daytime-sunset-symbolic"))), + moonrise: Label::new(None, Some(gio::ThemedIcon::new("moon-outline-symbolic"))), + moonset: Label::new(None, Some(gio::ThemedIcon::new("moon-outline-symbolic"))), + } + } +} + +#[glib::object_subclass] +impl ObjectSubclass for TransitCardPrivate { + const NAME: &'static str = "TransitCard"; + type Type = TransitCard; + type ParentType = gtk::Grid; +} + +impl ObjectImpl for TransitCardPrivate {} +impl WidgetImpl for TransitCardPrivate {} +impl GridImpl for TransitCardPrivate {} + +glib::wrapper! { + pub struct TransitCard(ObjectSubclass) @extends gtk::Grid, gtk::Widget; +} + +impl TransitCard { + pub fn new() -> Self { + let s: Self = Object::builder().build(); + s.add_css_class("card"); + s.set_column_homogeneous(true); + + s.attach(&s.imp().sunrise, 0, 0, 1, 1); + s.attach(&s.imp().sunset, 0, 1, 1, 1); + s.attach(&s.imp().moonrise, 1, 0, 1, 1); + s.attach(&s.imp().moonset, 1, 1, 1, 1); + + s + } + + pub fn update_transit(&self, transit_info: &SunMoon) { + self.imp() + .sunrise + .set_text(format!("{}", transit_info.sunrise.format("%H:%M")).as_ref()); + self.imp() + .sunset + .set_text(format!("{}", transit_info.sunset.format("%H:%M")).as_ref()); + self.imp().moonrise.set_text( + &transit_info + .moonrise + .map(|time| format!("{}", time.format("%H:%M"))) + .unwrap_or("".to_owned()), + ); + self.imp().moonset.set_text( + &transit_info + .moonset + .map(|time| format!("{}", time.format("%H:%M"))) + .unwrap_or("".to_owned()), + ); + } +}