From 56a8133dd5896ea1109cdae68eb1199eba9240f2 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Mon, 18 Dec 2023 17:49:25 -0500 Subject: [PATCH] A lot of work, possibly meaningless, to try to handle state within the main window A note to self, when I return to this: the overlay modals don't make sense in this context. The main window should have views, and switching from one view to the next should involve just replacing the child. Modals can be put off until later. --- fitnesstrax/app/src/main.rs | 102 ++++++++++++++++++++++++++---------- 1 file changed, 73 insertions(+), 29 deletions(-) diff --git a/fitnesstrax/app/src/main.rs b/fitnesstrax/app/src/main.rs index a5a7683..64fb4e1 100644 --- a/fitnesstrax/app/src/main.rs +++ b/fitnesstrax/app/src/main.rs @@ -23,6 +23,7 @@ use gio::resources_lookup_data; use glib::Object; use gtk::{subclass::prelude::*, STYLE_PROVIDER_PRIORITY_USER}; use std::{ + cell::RefCell, env, sync::{Arc, RwLock}, }; @@ -136,7 +137,7 @@ enum MainView { Unconfigured(UnconfiguredView), /// The Historical view shows a history of records and whatnot. - HistoricalView(HistoricalView), + Historical(HistoricalView), } /// The application window, or the main window, is the main user interface for the app. @@ -144,7 +145,12 @@ struct AppWindow { app: App, window: adw::ApplicationWindow, overlay: gtk::Overlay, - current_view: MainView, + + current_view: RefCell, + + // We have to keep around a reference to the modal so that we know what to remove from the + // overlay. + modal: RefCell>, } impl AppWindow { @@ -155,6 +161,46 @@ impl AppWindow { /// /// app is a core [App] object which encapsulates all of the basic logic. fn new(adw_app: &adw::Application, app: App) -> AppWindow { + let window = adw::ApplicationWindow::builder() + .application(adw_app) + .width_request(800) + .height_request(600) + .build(); + + // GTK overlays aren't all that well documented. The Overlay object needs to be the + // content/child of the window. The main content should then be added to the overlay as + // `set_child`. The overlays/modals should be added as `add_overlay` and then removed with + // `remove_overlay`. + let overlay = gtk::Overlay::new(); + window.set_content(Some(&overlay)); + + let current_view = if app.database.read().unwrap().is_none() { + let view = UnconfiguredView::new(); + /* + overlay.set_child(Some(&view)); + + // I have to access the overlay directly here because I haven't fully constructed Self + // yet, and so I don't have access to `open_modal` yet. + */ + + MainView::Unconfigured(view) + } else { + let view = HistoricalView::new(); + /* + overlay.set_child(Some(&view)); + */ + + MainView::Historical(view) + }; + + let s = Self { + app, + window: window.clone(), + overlay, + current_view: RefCell::new(current_view), + modal: RefCell::new(None), + }; + let stylesheet = String::from_utf8( resources_lookup_data( &format!("{}style.css", RESOURCE_BASE_PATH), @@ -168,23 +214,16 @@ impl AppWindow { let provider = gtk::CssProvider::new(); provider.load_from_data(&stylesheet); - let window = adw::ApplicationWindow::builder() - .application(adw_app) - .width_request(800) - .height_request(600) - .build(); - let context = window.style_context(); context.add_provider(&provider, STYLE_PROVIDER_PRIORITY_USER); window.present(); - // GTK overlays aren't all that well documented. The Overlay object needs to be the - // content/child of the window. The main content should then be added to the overlay as - // `add_overlay`. The overlays/modals should be added as `set_child`. - let overlay = gtk::Overlay::new(); - window.set_content(Some(&overlay)); + s.redraw(); + s + + /* let current_view = if app.database.read().unwrap().is_none() { let view = UnconfiguredView::new(); overlay.set_child(Some(&view)); @@ -192,6 +231,9 @@ impl AppWindow { // I have to access the overlay directly here because I haven't fully constructed Self // yet, and so I don't have access to `open_modal` yet. overlay.add_overlay(&welcome_modal(|path| { + // When a path gets selected, I want to set the path in the configuration system, + // and I want to open the database. After that, this window should be redrawn with + // its new state. So the view state also needs to change. println!("path: {}", path.to_str().unwrap()) })); @@ -202,25 +244,27 @@ impl AppWindow { MainView::HistoricalView(view) }; + */ + } - Self { - app, - window, - overlay, - current_view, + fn redraw(&self) { + match *self.current_view.borrow() { + MainView::Unconfigured(ref view) => { + self.overlay.set_child(Some(view)); + + let modal = welcome_modal(|path| { + // When a path gets selected, I want to set the path in the configuration system, + // and I want to open the database. After that, this window should be redrawn with + // its new state. So the view state also needs to change. + println!("path: {}", path.to_str().unwrap()) + }); + + self.overlay.add_overlay(&modal); + *self.modal.borrow_mut() = Some(modal.upcast()); + } + MainView::Historical(ref view) => self.overlay.set_child(Some(view)), } } - - /// Use [modal] as a modal overlay of the application window. - fn open_modal(&self, modal: Modal) { - self.overlay.set_child(Some(&modal)); - } - - /// Close the modal by discarding the component. - fn close_modal(&self) { - let none: Option<>k::Widget> = None; - self.overlay.set_child(none); - } } fn main() {