use adw::prelude::AdwApplicationWindowExt; use gtk::prelude::*; use kifu_core::{CoreApp, CoreRequest, CoreResponse}; use kifu_gtk::{ perftrace, ui::{Home, PlayingField}, CoreApi, }; use std::sync::{Arc, RwLock}; fn handle_response(api: CoreApi, window: adw::ApplicationWindow, message: CoreResponse) { let playing_field = Arc::new(RwLock::new(None)); match message { CoreResponse::HomeView(view) => perftrace("HomeView", || { let api = api.clone(); let home = Home::new(api, view); window.set_content(Some(&home)); }), CoreResponse::PlayingFieldView(view) => perftrace("PlayingFieldView", || { let api = api.clone(); let mut playing_field = playing_field.write().unwrap(); if playing_field.is_none() { perftrace("creating a new playing field", || { let field = PlayingField::new(api, view); window.set_content(Some(&field)); *playing_field = Some(field); }) } else { playing_field.as_ref().map(|field| field.update_view(view)); } }), } } fn main() { gio::resources_register_include!("com.luminescent-dreams.kifu-gtk.gresource") .expect("Failed to register resources"); let runtime = Arc::new( tokio::runtime::Builder::new_multi_thread() .enable_all() .build() .unwrap(), ); let config_path = std::env::var("CONFIG") .and_then(|config| Ok(std::path::PathBuf::from(config))) .or({ std::env::var("HOME").and_then(|base| { let mut config_path = std::path::PathBuf::from(base); config_path.push(".config"); config_path.push("kifu"); Ok(config_path) }) }) .expect("no config path could be found"); let core = CoreApp::new(config_path); let core_handle = runtime.spawn({ let core = core.clone(); async move { core.run().await; } }); let app = adw::Application::builder() .application_id("com.luminescent-dreams.kifu-gtk") .resource_base_path("/com/luminescent-dreams/kifu-gtk") .build(); let action_config = gio::SimpleAction::new("show-config", None); action_config.connect_activate(|_, _| { println!("trigger the configuration menu"); }); app.add_action(&action_config); app.connect_startup(|app| { println!("connect_startup"); let menu_model = gio::Menu::new(); menu_model.append(Some("Quit"), None); menu_model.append(Some("Configuration"), Some("show-config")); app.set_menubar(Some(&menu_model)); }); app.connect_activate({ let runtime = runtime.clone(); move |app| { let (gtk_tx, gtk_rx) = gtk::glib::MainContext::channel::(gtk::glib::PRIORITY_DEFAULT); let api = CoreApi { gtk_tx, rt: runtime.clone(), core: core.clone(), }; let window = adw::ApplicationWindow::new(app); window.present(); window.set_show_menubar(true); gtk_rx.attach(None, { let api = api.clone(); move |message| { perftrace("handle_response", || { handle_response(api.clone(), window.clone(), message) }); Continue(true) } }); api.dispatch(CoreRequest::Home); } }); println!("running the gtk loop"); app.run(); let _ = runtime.block_on(async { core_handle.await }); }