Totally rewrite dashboard as a GTK application #54
|
@ -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(>k::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());
|
||||
|
|
Loading…
Reference in New Issue