Set up a configuration UI #66
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue