Show astronomical events in the UI #58
|
@ -1,5 +1,9 @@
|
||||||
@define-color background_color @purple_5;
|
|
||||||
|
|
||||||
label {
|
label {
|
||||||
font-size: 200%;
|
font-size: 200%;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
color: @accent_fg_color;
|
||||||
|
background-color: @accent_bg_color;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
components::{Date, TransitCard, TransitClock},
|
components::{Date, Events, TransitCard, TransitClock},
|
||||||
types::State,
|
types::State,
|
||||||
};
|
};
|
||||||
use adw::prelude::AdwApplicationWindowExt;
|
use adw::prelude::AdwApplicationWindowExt;
|
||||||
|
@ -10,7 +10,7 @@ use gtk::{prelude::*, STYLE_PROVIDER_PRIORITY_USER};
|
||||||
pub struct ApplicationWindow {
|
pub struct ApplicationWindow {
|
||||||
pub window: adw::ApplicationWindow,
|
pub window: adw::ApplicationWindow,
|
||||||
pub date_label: Date,
|
pub date_label: Date,
|
||||||
pub next_event: gtk::Label,
|
pub events: Events,
|
||||||
pub transit_card: TransitCard,
|
pub transit_card: TransitCard,
|
||||||
pub transit_clock: TransitClock,
|
pub transit_clock: TransitClock,
|
||||||
}
|
}
|
||||||
|
@ -43,13 +43,8 @@ impl ApplicationWindow {
|
||||||
let date_label = Date::new();
|
let date_label = Date::new();
|
||||||
layout.append(&date_label);
|
layout.append(&date_label);
|
||||||
|
|
||||||
let next_event = gtk::Label::builder()
|
let events = Events::new();
|
||||||
.margin_bottom(8)
|
layout.append(&events);
|
||||||
.margin_top(8)
|
|
||||||
.margin_start(8)
|
|
||||||
.margin_end(8)
|
|
||||||
.build();
|
|
||||||
layout.append(&next_event);
|
|
||||||
|
|
||||||
let transit_card = TransitCard::new();
|
let transit_card = TransitCard::new();
|
||||||
layout.append(&transit_card);
|
layout.append(&transit_card);
|
||||||
|
@ -62,7 +57,7 @@ impl ApplicationWindow {
|
||||||
Self {
|
Self {
|
||||||
window,
|
window,
|
||||||
date_label,
|
date_label,
|
||||||
next_event,
|
events,
|
||||||
transit_card,
|
transit_card,
|
||||||
transit_clock,
|
transit_clock,
|
||||||
}
|
}
|
||||||
|
@ -70,7 +65,7 @@ impl ApplicationWindow {
|
||||||
|
|
||||||
pub fn update_state(&self, state: State) {
|
pub fn update_state(&self, state: State) {
|
||||||
self.date_label.update_date(state.date);
|
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 {
|
if let Some(transit) = state.transit {
|
||||||
self.transit_card.update_transit(&transit);
|
self.transit_card.update_transit(&transit);
|
||||||
self.transit_clock.update_transit(transit);
|
self.transit_clock.update_transit(transit);
|
||||||
|
|
|
@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,9 @@
|
||||||
mod date;
|
mod date;
|
||||||
pub use date::Date;
|
pub use date::Date;
|
||||||
|
|
||||||
|
mod events;
|
||||||
|
pub use events::Events;
|
||||||
|
|
||||||
mod label;
|
mod label;
|
||||||
pub use label::Label;
|
pub use label::Label;
|
||||||
|
|
||||||
|
|
|
@ -81,18 +81,16 @@ pub fn main() {
|
||||||
let latitude = Latitude::from(41.78);
|
let latitude = Latitude::from(41.78);
|
||||||
let longitude = Longitude::from(-71.41);
|
let longitude = Longitude::from(-71.41);
|
||||||
|
|
||||||
let runtime = Arc::new(
|
let runtime = tokio::runtime::Builder::new_multi_thread()
|
||||||
tokio::runtime::Builder::new_multi_thread()
|
.enable_all()
|
||||||
.enable_all()
|
.build()
|
||||||
.build()
|
.unwrap();
|
||||||
.unwrap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let core = Core {
|
let core = Core {
|
||||||
tx: Arc::new(RwLock::new(None)),
|
tx: Arc::new(RwLock::new(None)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let app_handle = runtime.spawn({
|
let _ = runtime.spawn({
|
||||||
let core = core.clone();
|
let core = core.clone();
|
||||||
async move {
|
async move {
|
||||||
let soluna_client = SolunaClient::new();
|
let soluna_client = SolunaClient::new();
|
||||||
|
@ -106,6 +104,7 @@ pub fn main() {
|
||||||
let state = State {
|
let state = State {
|
||||||
date: IFC::from(now.date_naive().with_year(12023).unwrap()),
|
date: IFC::from(now.date_naive().with_year(12023).unwrap()),
|
||||||
next_event: EVENTS.next_event(now.with_timezone(&Utc)).unwrap(),
|
next_event: EVENTS.next_event(now.with_timezone(&Utc)).unwrap(),
|
||||||
|
events: EVENTS.yearly_events(now.year()).unwrap(),
|
||||||
transit: Some(transit),
|
transit: Some(transit),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -141,6 +140,5 @@ pub fn main() {
|
||||||
|
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
ApplicationExtManual::run_with_args(&app, &args);
|
ApplicationExtManual::run_with_args(&app, &args);
|
||||||
|
runtime.shutdown_background();
|
||||||
let _ = runtime.block_on(async { app_handle.await });
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,11 +133,9 @@ fn parse_events() -> Vec<Option<YearlyEvents>> {
|
||||||
pub struct Solstices(HashMap<i32, YearlyEvents>);
|
pub struct Solstices(HashMap<i32, YearlyEvents>);
|
||||||
|
|
||||||
impl Solstices {
|
impl Solstices {
|
||||||
/*
|
pub fn yearly_events(&self, year: i32) -> Option<YearlyEvents> {
|
||||||
pub fn acquire(&self, year: i32) -> Option<YearlyEvents> {
|
|
||||||
self.0.get(&year).map(|c| c.clone())
|
self.0.get(&year).map(|c| c.clone())
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
pub fn next_event(&self, date: chrono::DateTime<chrono::Utc>) -> Option<Event> {
|
pub fn next_event(&self, date: chrono::DateTime<chrono::Utc>) -> Option<Event> {
|
||||||
let year_events = self.0.get(&date.year());
|
let year_events = self.0.get(&date.year());
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
use crate::{solstices::Event, soluna_client::SunMoon};
|
use crate::{
|
||||||
|
solstices::{Event, YearlyEvents},
|
||||||
|
soluna_client::SunMoon,
|
||||||
|
};
|
||||||
use ifc::IFC;
|
use ifc::IFC;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
pub date: IFC,
|
pub date: IFC,
|
||||||
pub next_event: Event,
|
pub next_event: Event,
|
||||||
|
pub events: YearlyEvents,
|
||||||
pub transit: Option<SunMoon>,
|
pub transit: Option<SunMoon>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,9 +232,9 @@ impl IFC {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Day {
|
pub struct Day {
|
||||||
year: i32,
|
pub year: i32,
|
||||||
month: u8,
|
pub month: u8,
|
||||||
day: u8,
|
pub day: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<chrono::NaiveDate> for IFC {
|
impl From<chrono::NaiveDate> for IFC {
|
||||||
|
|
Loading…
Reference in New Issue