Totally rewrite dashboard as a GTK application #54

Merged
savanni merged 14 commits from dashboard-gtk into main 2023-08-09 18:14:01 +00:00
1 changed files with 139 additions and 53 deletions
Showing only changes of commit 4714a06daa - Show all commits

View File

@ -5,11 +5,19 @@ extern crate serde_derive;
extern crate lazy_static;
*/
use chrono::{Datelike, Duration, NaiveTime};
use glib::Object;
use chrono::{Datelike, Duration, Local, NaiveTime};
use geo_types::{Latitude, Longitude};
use glib::{Object, Sender};
use gtk::{prelude::*, subclass::prelude::*, Orientation};
use ifc::IFC;
use std::{cell::RefCell, env, f64::consts::PI, ops::Deref, rc::Rc};
use std::{
cell::RefCell,
env,
f64::consts::PI,
ops::Deref,
rc::Rc,
sync::{Arc, RwLock},
};
mod drawing;
use drawing::{Color, PieChart, Wedge};
@ -19,7 +27,7 @@ use geo_types::{Latitude, Longitude};
*/
mod soluna_client;
use soluna_client::{LunarPhase, SunMoon};
use soluna_client::{SolunaClient, SunMoon};
/*
mod solstices;
@ -169,8 +177,37 @@ async fn page(
}
*/
#[derive(Default)]
pub struct DatePrivate {}
#[derive(Clone, Debug)]
pub enum Message {
Refresh(State),
}
#[derive(Clone, Debug)]
pub struct State {
date: IFC,
transit: Option<SunMoon>,
}
#[derive(Clone)]
pub struct Core {
tx: Arc<RwLock<Option<Sender<Message>>>>,
}
pub struct DatePrivate {
date: Rc<RefCell<IFC>>,
label: Rc<RefCell<gtk::Label>>,
}
impl Default for DatePrivate {
fn default() -> Self {
Self {
date: Rc::new(RefCell::new(IFC::from(
chrono::Local::now().date_naive().with_year(12023).unwrap(),
))),
label: Rc::new(RefCell::new(gtk::Label::new(None))),
}
}
}
#[glib::object_subclass]
impl ObjectSubclass for DatePrivate {
@ -197,19 +234,27 @@ impl Date {
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(&gtk::Label::new(Some(
format!(
"{:?}, {:?} {}, {}",
dt.weekday(),
dt.month(),
dt.day(),
dt.year()
)
.as_ref(),
)));
s.append(&*s.imp().label.borrow());
s.redraw();
s
}
fn update_date(&self, date: IFC) {
*self.imp().date.borrow_mut() = date;
self.redraw();
}
fn redraw(&self) {
let date = self.imp().date.borrow().clone();
self.imp().label.borrow_mut().set_text(&format!(
"{:?}, {:?} {}, {}",
date.weekday(),
date.month(),
date.day(),
date.year()
));
}
}
pub struct TransitClockPrivate {
@ -240,13 +285,11 @@ glib::wrapper! {
}
impl TransitClock {
pub fn new(sun_moon_info: SunMoon) -> Self {
pub fn new() -> 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| {
@ -291,6 +334,11 @@ impl TransitClock {
s
}
pub fn update_transit(&self, transit_info: SunMoon) {
*self.imp().info.borrow_mut() = Some(transit_info);
self.queue_draw();
}
}
pub fn main() {
@ -299,45 +347,83 @@ pub fn main() {
.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 latitude = Latitude::from(41.78);
let longitude = Longitude::from(-71.41);
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 runtime = Arc::new(
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap(),
);
let core = Core {
tx: Arc::new(RwLock::new(None)),
};
let app_handle = runtime.spawn({
let core = core.clone();
async move {
let soluna_client = SolunaClient::new();
let transit = soluna_client
.request(latitude, longitude, Local::now())
.await;
let state = State {
date: IFC::from(Local::now().date_naive().with_year(12023).unwrap()),
transit: Some(transit),
};
loop {
if let Some(ref gtk_tx) = *core.tx.read().unwrap() {
let _ = gtk_tx.send(Message::Refresh(state.clone()));
}
std::thread::sleep(std::time::Duration::from_secs(300));
}
}
});
app.connect_activate(move |app| {
let (gtk_tx, gtk_rx) =
gtk::glib::MainContext::channel::<Message>(gtk::glib::PRIORITY_DEFAULT);
*core.tx.write().unwrap() = Some(gtk_tx);
let window = gtk::ApplicationWindow::new(app);
window.present();
let layout = gtk::Box::builder()
.orientation(Orientation::Vertical)
.hexpand(true)
.vexpand(true)
.build();
let date_label = Date::new();
layout.append(&date_label);
let transit_clock = TransitClock::new();
layout.append(&transit_clock);
window.set_child(Some(&layout));
gtk_rx.attach(None, move |msg| {
let Message::Refresh(state) = msg;
println!("new state: {:?}", state);
date_label.update_date(state.date);
if let Some(transit) = state.transit {
transit_clock.update_transit(transit);
}
Continue(true)
});
std::thread::spawn(move || {});
});
let args: Vec<String> = env::args().collect();
ApplicationExtManual::run_with_args(&app, &args);
let _ = runtime.block_on(async { app_handle.await });
/*
let now = Local::now();
let ifc = ifc::IFC::from(now.date_naive().with_year(12023).unwrap());