Set up a configuration UI #66

Merged
savanni merged 7 commits from kifu/configuration into main 2023-08-25 01:08:33 +00:00
5 changed files with 43 additions and 39 deletions
Showing only changes of commit 784f3ff7f4 - Show all commits

View File

@ -1,15 +1,19 @@
use crate::{ use crate::{
types::{AppState, Config, DatabasePath, GameState, Player, Rank}, types::{AppState, Config, ConfigOption, DatabasePath, GameState, Player, Rank},
ui::{configuration, home, playing_field, ConfigurationView, HomeView, PlayingFieldView}, ui::{configuration, home, playing_field, ConfigurationView, HomeView, PlayingFieldView},
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::sync::{Arc, RwLock}; use std::{
path::PathBuf,
sync::{Arc, RwLock},
};
use typeshare::typeshare; use typeshare::typeshare;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[typeshare] #[typeshare]
#[serde(tag = "type", content = "content")] #[serde(tag = "type", content = "content")]
pub enum CoreRequest { pub enum CoreRequest {
ChangeSetting(ChangeSettingRequest),
CreateGame(CreateGameRequest), CreateGame(CreateGameRequest),
Home, Home,
OpenConfiguration, OpenConfiguration,
@ -18,6 +22,13 @@ pub enum CoreRequest {
StartGame, StartGame,
} }
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[typeshare]
#[serde(tag = "type", content = "content")]
pub enum ChangeSettingRequest {
LibraryPath(String),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[typeshare] #[typeshare]
pub struct PlayStoneRequest { pub struct PlayStoneRequest {
@ -61,11 +72,12 @@ pub enum CoreResponse {
ConfigurationView(ConfigurationView), ConfigurationView(ConfigurationView),
HomeView(HomeView), HomeView(HomeView),
PlayingFieldView(PlayingFieldView), PlayingFieldView(PlayingFieldView),
UpdatedConfigurationView(ConfigurationView),
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct CoreApp { pub struct CoreApp {
config: Config, config: Arc<RwLock<Config>>,
state: Arc<RwLock<AppState>>, state: Arc<RwLock<AppState>>,
} }
@ -76,25 +88,23 @@ impl CoreApp {
let db_path: DatabasePath = config.get().unwrap(); let db_path: DatabasePath = config.get().unwrap();
let state = Arc::new(RwLock::new(AppState::new(db_path))); let state = Arc::new(RwLock::new(AppState::new(db_path)));
Self { config, state } Self {
config: Arc::new(RwLock::new(config)),
state,
}
} }
pub async fn dispatch(&self, request: CoreRequest) -> CoreResponse { pub async fn dispatch(&self, request: CoreRequest) -> CoreResponse {
match request { match request {
/* CoreRequest::ChangeSetting(request) => match request {
CoreRequest::LaunchScreen => { ChangeSettingRequest::LibraryPath(path) => {
let app_state = self.state.read().unwrap(); let mut config = self.config.write().unwrap();
config.set(ConfigOption::DatabasePath(DatabasePath(PathBuf::from(
At launch, I want to either show a list of games in progress, the current game, or the game creation screen. path,
- if a live game is in progress, immmediately go to that game. Such a game will be classified at game creation, so it should be persisted to the state. ))));
- if no live games are in progress, but there are slow games in progress, show a list of the slow games and let the player choose which one to jump into. CoreResponse::UpdatedConfigurationView(configuration(&config))
- if no games are in progress, show only the game creation screen
- game creation menu should be present both when there are only slow games and when there are no games
- the UI returned here will always be available in other places, such as when the user is viewing a game and wants to return to this page
For the initial version, I want only to show the game creation screen. Then I will backtrack record application state so that the only decisions can be made.
} }
*/ },
CoreRequest::CreateGame(create_request) => { CoreRequest::CreateGame(create_request) => {
let mut app_state = self.state.write().unwrap(); let mut app_state = self.state.write().unwrap();
let white_player = { let white_player = {
@ -119,7 +129,7 @@ impl CoreApp {
CoreResponse::HomeView(home(self.state.read().unwrap().database.all_games())) CoreResponse::HomeView(home(self.state.read().unwrap().database.all_games()))
} }
CoreRequest::OpenConfiguration => { CoreRequest::OpenConfiguration => {
CoreResponse::ConfigurationView(configuration(&self.config)) CoreResponse::ConfigurationView(configuration(&self.config.read().unwrap()))
} }
CoreRequest::PlayingField => { CoreRequest::PlayingField => {
let app_state = self.state.read().unwrap(); let app_state = self.state.read().unwrap();

View File

@ -3,7 +3,8 @@ extern crate config_derive;
mod api; mod api;
pub use api::{ pub use api::{
CoreApp, CoreRequest, CoreResponse, CreateGameRequest, HotseatPlayerRequest, PlayerInfoRequest, ChangeSettingRequest, CoreApp, CoreRequest, CoreResponse, CreateGameRequest,
HotseatPlayerRequest, PlayerInfoRequest,
}; };
mod board; mod board;

View File

@ -16,7 +16,7 @@ define_config! {
} }
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, ConfigOption)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize, ConfigOption)]
pub struct DatabasePath(PathBuf); pub struct DatabasePath(pub PathBuf);
impl std::ops::Deref for DatabasePath { impl std::ops::Deref for DatabasePath {
type Target = PathBuf; type Target = PathBuf;

View File

@ -11,20 +11,7 @@ fn handle_response(api: CoreApi, layout: Layout, message: CoreResponse) {
let playing_field = Arc::new(RwLock::new(None)); let playing_field = Arc::new(RwLock::new(None));
match message { match message {
CoreResponse::ConfigurationView(view) => perftrace("ConfigurationView", || { CoreResponse::ConfigurationView(view) => perftrace("ConfigurationView", || {
/* let config_page = ConfigurationPage::new(api, view);
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(); let window = adw::PreferencesWindow::new();
window.add(&config_page); window.add(&config_page);
@ -51,6 +38,9 @@ fn handle_response(api: CoreApi, layout: Layout, message: CoreResponse) {
playing_field.as_ref().map(|field| field.update_view(view)); playing_field.as_ref().map(|field| field.update_view(view));
} }
}), }),
CoreResponse::UpdatedConfigurationView(view) => perftrace("UpdatedConfiguration", || {
println!("updated configuration: {:?}", view);
}),
} }
} }

View File

@ -1,6 +1,7 @@
use crate::CoreApi;
use adw::{prelude::*, subclass::prelude::*}; use adw::{prelude::*, subclass::prelude::*};
use glib::Object; use glib::Object;
use kifu_core::ui::ConfigurationView; use kifu_core::{ui::ConfigurationView, ChangeSettingRequest, CoreRequest};
#[derive(Default)] #[derive(Default)]
pub struct ConfigurationPagePrivate {} pub struct ConfigurationPagePrivate {}
@ -23,7 +24,7 @@ glib::wrapper! {
} }
impl ConfigurationPage { impl ConfigurationPage {
pub fn new(view: ConfigurationView) -> Self { pub fn new(api: CoreApi, view: ConfigurationView) -> Self {
let s: Self = Object::builder().build(); let s: Self = Object::builder().build();
let group = adw::PreferencesGroup::builder().build(); let group = adw::PreferencesGroup::builder().build();
@ -36,8 +37,10 @@ impl ConfigurationPage {
if let Some(path) = view.library.value { if let Some(path) = view.library.value {
library_entry.set_text(&path); library_entry.set_text(&path);
} }
library_entry.connect_apply(|entry| { library_entry.connect_apply(move |entry| {
println!("Set the library path to {}", entry.text()); api.dispatch(CoreRequest::ChangeSetting(
ChangeSettingRequest::LibraryPath(entry.text().into()),
));
}); });
group.add(library_entry); group.add(library_entry);