Show astronomical events in the UI #58

Merged
savanni merged 2 commits from astronomical-events into main 2023-08-10 17:15:55 +00:00
8 changed files with 136 additions and 29 deletions

View File

@ -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;
}

View File

@ -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,13 +43,8 @@ impl ApplicationWindow {
let date_label = Date::new();
layout.append(&date_label);
let next_event = gtk::Label::builder()
.margin_bottom(8)
.margin_top(8)
.margin_start(8)
.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 +57,7 @@ impl ApplicationWindow {
Self {
window,
date_label,
next_event,
events,
transit_card,
transit_clock,
}
@ -70,7 +65,7 @@ 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.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);

View File

@ -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<EventsPrivate>) @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")
}
}
}
}

View File

@ -1,6 +1,9 @@
mod date;
pub use date::Date;
mod events;
pub use events::Events;
mod label;
pub use label::Label;

View File

@ -81,18 +81,16 @@ pub fn main() {
let latitude = Latitude::from(41.78);
let longitude = Longitude::from(-71.41);
let runtime = Arc::new(
tokio::runtime::Builder::new_multi_thread()
let runtime = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap(),
);
.unwrap();
let core = Core {
tx: Arc::new(RwLock::new(None)),
};
let app_handle = runtime.spawn({
let _ = runtime.spawn({
let core = core.clone();
async move {
let soluna_client = SolunaClient::new();
@ -106,6 +104,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),
};
@ -141,6 +140,5 @@ pub fn main() {
let args: Vec<String> = env::args().collect();
ApplicationExtManual::run_with_args(&app, &args);
let _ = runtime.block_on(async { app_handle.await });
runtime.shutdown_background();
}

View File

@ -133,11 +133,9 @@ fn parse_events() -> Vec<Option<YearlyEvents>> {
pub struct Solstices(HashMap<i32, YearlyEvents>);
impl Solstices {
/*
pub fn acquire(&self, year: i32) -> Option<YearlyEvents> {
pub fn yearly_events(&self, year: i32) -> Option<YearlyEvents> {
self.0.get(&year).map(|c| c.clone())
}
*/
pub fn next_event(&self, date: chrono::DateTime<chrono::Utc>) -> Option<Event> {
let year_events = self.0.get(&date.year());

View File

@ -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<SunMoon>,
}

View File

@ -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<chrono::NaiveDate> for IFC {