diff --git a/kifu/gtk/resources/style.css b/kifu/gtk/resources/style.css index 4282dcd..e3c8988 100644 --- a/kifu/gtk/resources/style.css +++ b/kifu/gtk/resources/style.css @@ -1,3 +1,8 @@ .content { padding: 8px; } + +.settings-view { + margin: 8px; + background-color: @view_bg_color; +} diff --git a/kifu/gtk/src/app_window.rs b/kifu/gtk/src/app_window.rs index 788e3ee..3fdf750 100644 --- a/kifu/gtk/src/app_window.rs +++ b/kifu/gtk/src/app_window.rs @@ -19,9 +19,11 @@ use gio::resources_lookup_data; use glib::IsA; use gtk::STYLE_PROVIDER_PRIORITY_USER; use kifu_core::{Config, Core}; +use std::sync::{Arc, RwLock}; use crate::view_models::SettingsViewModel; +#[derive(Clone)] enum AppView { Settings(SettingsViewModel), Home, @@ -31,6 +33,7 @@ enum AppView { // - an overlay widget // - the main content in a stack on the bottom panel of the overlay // - the settings and the about page in bins atop the overlay +#[derive(Clone)] pub struct AppWindow { pub window: adw::ApplicationWindow, header: adw::HeaderBar, @@ -48,42 +51,14 @@ pub struct AppWindow { // anywhere but shouldn't be part of the main application flow. panel_overlay: gtk::Overlay, core: Core, + + // Not liking this, but I have to keep track of the settings view model separately from + // anything else. I'll have to look into this later. + settings_view_model: Arc>>, } impl AppWindow { pub fn new(app: &adw::Application, core: Core) -> Self { - /* - - let stylesheet = String::from_utf8( - resources_lookup_data( - "/com/luminescent-dreams/kifu-gtk/style.css", - gio::ResourceLookupFlags::NONE, - ) - .expect("stylesheet should just be available") - .to_vec(), - ) - .expect("to parse stylesheet"); - - let provider = gtk::CssProvider::new(); - provider.load_from_data(&stylesheet); - let context = window.style_context(); - context.add_provider(&provider, STYLE_PROVIDER_PRIORITY_USER); - - let header = setup_header(); - - let current_view = match config.get::() { - Some(_) => AppView::Home, - None => AppView::Config(SettingsViewModel::new(core.clone())), - }; - - let content = adw::Bin::builder().css_classes(vec!["content"]).build(); - content.set_child(Some( - )); - - - window.set_content(Some(&layout)); - */ - let window = Self::setup_window(app); let header = Self::setup_header(); let panel_overlay = Self::setup_panel_overlay(); @@ -105,9 +80,16 @@ impl AppWindow { content, panel_overlay, core, + settings_view_model: Default::default(), } } + pub fn open_settings(&self) { + let view_model = SettingsViewModel::new(self.core.clone()); + self.panel_overlay.add_overlay(&view_model.widget); + *self.settings_view_model.write().unwrap() = Some(view_model); + } + fn setup_window(app: &adw::Application) -> adw::ApplicationWindow { let window = adw::ApplicationWindow::builder() .application(app) @@ -124,7 +106,7 @@ impl AppWindow { .build(); let app_menu = gio::Menu::new(); - let menu_item = gio::MenuItem::new(Some("Configuration"), Some("app.show_config")); + let menu_item = gio::MenuItem::new(Some("Configuration"), Some("app.show_settings")); app_menu.append_item(&menu_item); let hamburger = gtk::MenuButton::builder() diff --git a/kifu/gtk/src/main.rs b/kifu/gtk/src/main.rs index f8c2e5c..2b6da10 100644 --- a/kifu/gtk/src/main.rs +++ b/kifu/gtk/src/main.rs @@ -55,17 +55,17 @@ fn handle_response(api: CoreApi, app_window: &AppWindow, message: CoreResponse) fn load_config(app_id: &str) -> Config { let settings = gio::Settings::new(app_id); - let db_path: String = settings.string("database-path").into(); + let lib_path: String = settings.string("library-path").into(); let mut config = Config::new(); - config.set(ConfigOption::LibraryPath(db_path.into())); + config.set(ConfigOption::LibraryPath(lib_path.into())); config } -fn setup_app_configuration_action(app: &adw::Application) { +fn setup_app_configuration_action(app: &adw::Application, app_window: AppWindow) { println!("setup_app_configuration_action"); - let action = ActionEntry::builder("show_config") - .activate(|_app: &adw::Application, _, _| { - println!("show configuration window"); + let action = ActionEntry::builder("show_settings") + .activate(move |_app: &adw::Application, _, _| { + app_window.open_settings(); }) .build(); app.add_action_entries([action]); @@ -125,14 +125,21 @@ fn main() { app.connect_activate({ let runtime = runtime.clone(); move |app| { - let app_window = AppWindow::new(app, core.clone()); + let mut app_window = AppWindow::new(app, core.clone()); - setup_app_configuration_action(app); + match *core.library() { + Some(_) => {}, + None => app_window.open_settings(), + } + setup_app_configuration_action(app, app_window.clone()); + + /* let api = CoreApi { rt: runtime.clone(), core: core.clone(), }; + */ /* let action_config = gio::SimpleAction::new("show-config", None); diff --git a/kifu/gtk/src/view_models/settings_view_model.rs b/kifu/gtk/src/view_models/settings_view_model.rs index 1e2bfcb..57a66e9 100644 --- a/kifu/gtk/src/view_models/settings_view_model.rs +++ b/kifu/gtk/src/view_models/settings_view_model.rs @@ -16,17 +16,19 @@ You should have received a copy of the GNU General Public License along with Kif use crate::{views, LocalObserver, views::SettingsView}; use kifu_core::{Core, CoreNotification}; +use std::sync::Arc; /// SettingsViewModel /// /// Listens for messages from the core, and serves as intermediary between the Settings UI and the /// core. Because it needs to respond to events from the core, it owns the widget, which allows it /// to tell the widget to update after certain events. +#[derive(Clone)] pub struct SettingsViewModel { core: Core, // Technically, Settings doesn't care about any events from Core. We will keep this around for // now as reference, until something which does care shows up. - notification_observer: LocalObserver, + notification_observer: Arc>, pub widget: views::SettingsView, } @@ -38,7 +40,7 @@ impl SettingsViewModel { Self { core, - notification_observer, + notification_observer: Arc::new(notification_observer), widget: SettingsView::new(), } } diff --git a/kifu/gtk/src/views/settings.rs b/kifu/gtk/src/views/settings.rs index f80bccd..7ed6b56 100644 --- a/kifu/gtk/src/views/settings.rs +++ b/kifu/gtk/src/views/settings.rs @@ -16,6 +16,7 @@ You should have received a copy of the GNU General Public License along with Kif use glib::Object; use gtk::{prelude::*, subclass::prelude::*}; +use adw::prelude::*; pub struct SettingsPrivate {} @@ -23,7 +24,7 @@ pub struct SettingsPrivate {} impl ObjectSubclass for SettingsPrivate { const NAME: &'static str = "Settings"; type Type = SettingsView; - type ParentType = gtk::Box; + type ParentType = gtk::Frame; fn new() -> Self { Self {} @@ -32,15 +33,33 @@ impl ObjectSubclass for SettingsPrivate { impl ObjectImpl for SettingsPrivate {} impl WidgetImpl for SettingsPrivate {} -impl BoxImpl for SettingsPrivate {} +#[allow(deprecated)] +impl FrameImpl for SettingsPrivate {} glib::wrapper! { - pub struct SettingsView(ObjectSubclass) @extends gtk::Box, gtk::Widget, @implements gtk::Orientable; + pub struct SettingsView(ObjectSubclass) @extends gtk::Frame, gtk::Widget, @implements gtk::Accessible, gtk::Buildable, gtk::Orientable; } impl SettingsView { pub fn new() -> Self { let s: Self = Object::builder().build(); + + let group = adw::PreferencesGroup::builder().build(); + let library_row = adw::PreferencesRow::builder() + .title("Library Path") + .child(>k::Label::builder().label("Library Path").build()) + .build(); + group.add(&library_row); + + let layout = gtk::Box::builder() + .orientation(gtk::Orientation::Vertical) + .vexpand(true) + .build(); + layout.append(&group); + + s.set_child(Some(&layout)); + s.set_css_classes(&["settings-view"]); + s } }