From 5439e2ac045002a2255e4b1a5cdd36824c52cd43 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Thu, 24 Aug 2023 20:24:41 -0400 Subject: [PATCH] Set up a configuration UI --- kifu/core/src/api.rs | 7 ++++- kifu/core/src/ui/configuration.rs | 24 ++++++++++++++ kifu/core/src/ui/elements/action.rs | 10 ------ kifu/core/src/ui/elements/mod.rs | 30 +++++++++++++++++- kifu/core/src/ui/mod.rs | 5 ++- kifu/gtk/src/main.rs | 38 +++++++++++++++++----- kifu/gtk/src/ui/config.rs | 49 +++++++++++++++++++++++++++++ kifu/gtk/src/ui/layout.rs | 2 +- kifu/gtk/src/ui/mod.rs | 3 ++ 9 files changed, 147 insertions(+), 21 deletions(-) create mode 100644 kifu/core/src/ui/configuration.rs delete mode 100644 kifu/core/src/ui/elements/action.rs create mode 100644 kifu/gtk/src/ui/config.rs diff --git a/kifu/core/src/api.rs b/kifu/core/src/api.rs index fead3e7..9ac63a0 100644 --- a/kifu/core/src/api.rs +++ b/kifu/core/src/api.rs @@ -1,6 +1,6 @@ use crate::{ types::{AppState, Config, DatabasePath, GameState, Player, Rank}, - ui::{home, playing_field, HomeView, PlayingFieldView}, + ui::{configuration, home, playing_field, ConfigurationView, HomeView, PlayingFieldView}, }; use serde::{Deserialize, Serialize}; use std::sync::{Arc, RwLock}; @@ -12,6 +12,7 @@ use typeshare::typeshare; pub enum CoreRequest { CreateGame(CreateGameRequest), Home, + OpenConfiguration, PlayingField, PlayStone(PlayStoneRequest), StartGame, @@ -57,6 +58,7 @@ impl From for Player { #[typeshare] #[serde(tag = "type", content = "content")] pub enum CoreResponse { + ConfigurationView(ConfigurationView), HomeView(HomeView), PlayingFieldView(PlayingFieldView), } @@ -116,6 +118,9 @@ impl CoreApp { CoreRequest::Home => { CoreResponse::HomeView(home(self.state.read().unwrap().database.all_games())) } + CoreRequest::OpenConfiguration => { + CoreResponse::ConfigurationView(configuration(&self.config)) + } CoreRequest::PlayingField => { let app_state = self.state.read().unwrap(); let game = app_state.game.as_ref().unwrap(); diff --git a/kifu/core/src/ui/configuration.rs b/kifu/core/src/ui/configuration.rs new file mode 100644 index 0000000..c15f408 --- /dev/null +++ b/kifu/core/src/ui/configuration.rs @@ -0,0 +1,24 @@ +use crate::{ + types::{Config, DatabasePath}, + ui::Field, +}; +use serde::{Deserialize, Serialize}; +use typeshare::typeshare; + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[typeshare] +pub struct ConfigurationView { + pub library: Field<()>, +} + +pub fn configuration(config: &Config) -> ConfigurationView { + let path: Option = config.get(); + ConfigurationView { + library: Field { + id: "library-path-field".to_owned(), + label: "Library".to_owned(), + value: path.map(|path| path.to_string_lossy().into_owned()), + action: (), + }, + } +} diff --git a/kifu/core/src/ui/elements/action.rs b/kifu/core/src/ui/elements/action.rs deleted file mode 100644 index 69c5514..0000000 --- a/kifu/core/src/ui/elements/action.rs +++ /dev/null @@ -1,10 +0,0 @@ -use serde::{Deserialize, Serialize}; -use typeshare::typeshare; - -#[derive(Clone, Debug, Serialize, Deserialize)] -#[typeshare] -pub struct Action { - pub id: String, - pub label: String, - pub action: A, -} diff --git a/kifu/core/src/ui/elements/mod.rs b/kifu/core/src/ui/elements/mod.rs index 0a6140f..61d07b4 100644 --- a/kifu/core/src/ui/elements/mod.rs +++ b/kifu/core/src/ui/elements/mod.rs @@ -1,3 +1,31 @@ -pub mod action; +use serde::{Deserialize, Serialize}; +use typeshare::typeshare; + pub mod game_preview; pub mod menu; + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[typeshare] +pub struct Action { + pub id: String, + pub label: String, + pub action: A, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[typeshare] +pub struct Toggle { + pub id: String, + pub label: String, + pub value: bool, + pub action: A, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[typeshare] +pub struct Field { + pub id: String, + pub label: String, + pub value: Option, + pub action: A, +} diff --git a/kifu/core/src/ui/mod.rs b/kifu/core/src/ui/mod.rs index 7233ec5..9c63d14 100644 --- a/kifu/core/src/ui/mod.rs +++ b/kifu/core/src/ui/mod.rs @@ -1,5 +1,8 @@ +mod configuration; +pub use configuration::{configuration, ConfigurationView}; + mod elements; -pub use elements::{action::Action, game_preview::GamePreviewElement, menu::Menu}; +pub use elements::{game_preview::GamePreviewElement, menu::Menu, Action, Field, Toggle}; mod playing_field; pub use playing_field::{playing_field, PlayingFieldView}; diff --git a/kifu/gtk/src/main.rs b/kifu/gtk/src/main.rs index 0ff75e6..9cf9198 100644 --- a/kifu/gtk/src/main.rs +++ b/kifu/gtk/src/main.rs @@ -2,7 +2,7 @@ use adw::prelude::*; use kifu_core::{CoreApp, CoreRequest, CoreResponse}; use kifu_gtk::{ perftrace, - ui::{Home, Layout, PlayingField}, + ui::{ConfigurationPage, Home, Layout, PlayingField}, CoreApi, }; use std::sync::{Arc, RwLock}; @@ -10,6 +10,27 @@ use std::sync::{Arc, RwLock}; fn handle_response(api: CoreApi, layout: Layout, message: CoreResponse) { let playing_field = Arc::new(RwLock::new(None)); match message { + CoreResponse::ConfigurationView(view) => perftrace("ConfigurationView", || { + /* + let config_group = adw::PreferencesGroup::builder().build(); + config_group.add( + &adw::EntryRow::builder() + .name("library") + .title("Library path") + .build(), + ); + let config_page = adw::PreferencesPage::new(); + config_page.set_name(Some("preferences")); + config_page.add(&config_group); + */ + + let config_page = ConfigurationPage::new(view); + + let window = adw::PreferencesWindow::new(); + window.add(&config_page); + window.set_visible_page(&config_page); + window.present(); + }), CoreResponse::HomeView(view) => perftrace("HomeView", || { let api = api.clone(); @@ -70,12 +91,6 @@ fn main() { .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_activate({ let runtime = runtime.clone(); move |app| { @@ -88,6 +103,15 @@ fn main() { core: core.clone(), }; + let action_config = gio::SimpleAction::new("show-config", None); + action_config.connect_activate({ + let api = api.clone(); + move |_, _| { + api.dispatch(CoreRequest::OpenConfiguration); + } + }); + app.add_action(&action_config); + let window = adw::ApplicationWindow::builder() .application(app) .width_request(800) diff --git a/kifu/gtk/src/ui/config.rs b/kifu/gtk/src/ui/config.rs new file mode 100644 index 0000000..b854839 --- /dev/null +++ b/kifu/gtk/src/ui/config.rs @@ -0,0 +1,49 @@ +use adw::{prelude::*, subclass::prelude::*}; +use glib::Object; +use kifu_core::ui::ConfigurationView; + +#[derive(Default)] +pub struct ConfigurationPagePrivate {} + +#[glib::object_subclass] +impl ObjectSubclass for ConfigurationPagePrivate { + const NAME: &'static str = "Configuration"; + type Type = ConfigurationPage; + type ParentType = adw::PreferencesPage; +} + +impl ObjectImpl for ConfigurationPagePrivate {} +impl WidgetImpl for ConfigurationPagePrivate {} +impl PreferencesPageImpl for ConfigurationPagePrivate {} + +glib::wrapper! { + pub struct ConfigurationPage(ObjectSubclass) + @extends adw::PreferencesPage, gtk::Widget, + @implements gtk::Orientable; +} + +impl ConfigurationPage { + pub fn new(view: ConfigurationView) -> Self { + let s: Self = Object::builder().build(); + + let group = adw::PreferencesGroup::builder().build(); + + let library_entry = &adw::EntryRow::builder() + .name("library-path") + .title(view.library.label) + .show_apply_button(true) + .build(); + if let Some(path) = view.library.value { + library_entry.set_text(&path); + } + library_entry.connect_apply(|entry| { + println!("Set the library path to {}", entry.text()); + }); + + group.add(library_entry); + + s.add(&group); + + s + } +} diff --git a/kifu/gtk/src/ui/layout.rs b/kifu/gtk/src/ui/layout.rs index 868e9f0..5057bfc 100644 --- a/kifu/gtk/src/ui/layout.rs +++ b/kifu/gtk/src/ui/layout.rs @@ -12,7 +12,7 @@ pub struct LayoutPrivate { impl Default for LayoutPrivate { fn default() -> Self { let header = adw::HeaderBar::builder() - .title_widget(>k::Label::new(Some("Placeholder Title"))) + .title_widget(>k::Label::new(Some("Kifu"))) .build(); let app_menu = gio::Menu::new(); diff --git a/kifu/gtk/src/ui/mod.rs b/kifu/gtk/src/ui/mod.rs index 565384b..de1c5fe 100644 --- a/kifu/gtk/src/ui/mod.rs +++ b/kifu/gtk/src/ui/mod.rs @@ -1,6 +1,9 @@ mod chat; pub use chat::Chat; +mod config; +pub use config::ConfigurationPage; + mod game_preview; pub use game_preview::GamePreview;