Set up a configuration UI #66
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
types::{AppState, Config, DatabasePath, GameState, Player, Rank},
|
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 serde::{Deserialize, Serialize};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
@ -12,6 +12,7 @@ use typeshare::typeshare;
|
||||||
pub enum CoreRequest {
|
pub enum CoreRequest {
|
||||||
CreateGame(CreateGameRequest),
|
CreateGame(CreateGameRequest),
|
||||||
Home,
|
Home,
|
||||||
|
OpenConfiguration,
|
||||||
PlayingField,
|
PlayingField,
|
||||||
PlayStone(PlayStoneRequest),
|
PlayStone(PlayStoneRequest),
|
||||||
StartGame,
|
StartGame,
|
||||||
|
@ -57,6 +58,7 @@ impl From<HotseatPlayerRequest> for Player {
|
||||||
#[typeshare]
|
#[typeshare]
|
||||||
#[serde(tag = "type", content = "content")]
|
#[serde(tag = "type", content = "content")]
|
||||||
pub enum CoreResponse {
|
pub enum CoreResponse {
|
||||||
|
ConfigurationView(ConfigurationView),
|
||||||
HomeView(HomeView),
|
HomeView(HomeView),
|
||||||
PlayingFieldView(PlayingFieldView),
|
PlayingFieldView(PlayingFieldView),
|
||||||
}
|
}
|
||||||
|
@ -116,6 +118,9 @@ impl CoreApp {
|
||||||
CoreRequest::Home => {
|
CoreRequest::Home => {
|
||||||
CoreResponse::HomeView(home(self.state.read().unwrap().database.all_games()))
|
CoreResponse::HomeView(home(self.state.read().unwrap().database.all_games()))
|
||||||
}
|
}
|
||||||
|
CoreRequest::OpenConfiguration => {
|
||||||
|
CoreResponse::ConfigurationView(configuration(&self.config))
|
||||||
|
}
|
||||||
CoreRequest::PlayingField => {
|
CoreRequest::PlayingField => {
|
||||||
let app_state = self.state.read().unwrap();
|
let app_state = self.state.read().unwrap();
|
||||||
let game = app_state.game.as_ref().unwrap();
|
let game = app_state.game.as_ref().unwrap();
|
||||||
|
|
|
@ -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<DatabasePath> = 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: (),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +0,0 @@
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use typeshare::typeshare;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
#[typeshare]
|
|
||||||
pub struct Action<A> {
|
|
||||||
pub id: String,
|
|
||||||
pub label: String,
|
|
||||||
pub action: A,
|
|
||||||
}
|
|
|
@ -1,3 +1,31 @@
|
||||||
pub mod action;
|
use serde::{Deserialize, Serialize};
|
||||||
|
use typeshare::typeshare;
|
||||||
|
|
||||||
pub mod game_preview;
|
pub mod game_preview;
|
||||||
pub mod menu;
|
pub mod menu;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[typeshare]
|
||||||
|
pub struct Action<A> {
|
||||||
|
pub id: String,
|
||||||
|
pub label: String,
|
||||||
|
pub action: A,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[typeshare]
|
||||||
|
pub struct Toggle<A> {
|
||||||
|
pub id: String,
|
||||||
|
pub label: String,
|
||||||
|
pub value: bool,
|
||||||
|
pub action: A,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[typeshare]
|
||||||
|
pub struct Field<A> {
|
||||||
|
pub id: String,
|
||||||
|
pub label: String,
|
||||||
|
pub value: Option<String>,
|
||||||
|
pub action: A,
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
mod configuration;
|
||||||
|
pub use configuration::{configuration, ConfigurationView};
|
||||||
|
|
||||||
mod elements;
|
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;
|
mod playing_field;
|
||||||
pub use playing_field::{playing_field, PlayingFieldView};
|
pub use playing_field::{playing_field, PlayingFieldView};
|
||||||
|
|
|
@ -2,7 +2,7 @@ use adw::prelude::*;
|
||||||
use kifu_core::{CoreApp, CoreRequest, CoreResponse};
|
use kifu_core::{CoreApp, CoreRequest, CoreResponse};
|
||||||
use kifu_gtk::{
|
use kifu_gtk::{
|
||||||
perftrace,
|
perftrace,
|
||||||
ui::{Home, Layout, PlayingField},
|
ui::{ConfigurationPage, Home, Layout, PlayingField},
|
||||||
CoreApi,
|
CoreApi,
|
||||||
};
|
};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
@ -10,6 +10,27 @@ use std::sync::{Arc, RwLock};
|
||||||
fn handle_response(api: CoreApi, layout: Layout, message: CoreResponse) {
|
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", || {
|
||||||
|
/*
|
||||||
|
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", || {
|
CoreResponse::HomeView(view) => perftrace("HomeView", || {
|
||||||
let api = api.clone();
|
let api = api.clone();
|
||||||
|
|
||||||
|
@ -70,12 +91,6 @@ fn main() {
|
||||||
.resource_base_path("/com/luminescent-dreams/kifu-gtk")
|
.resource_base_path("/com/luminescent-dreams/kifu-gtk")
|
||||||
.build();
|
.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({
|
app.connect_activate({
|
||||||
let runtime = runtime.clone();
|
let runtime = runtime.clone();
|
||||||
move |app| {
|
move |app| {
|
||||||
|
@ -88,6 +103,15 @@ fn main() {
|
||||||
core: core.clone(),
|
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()
|
let window = adw::ApplicationWindow::builder()
|
||||||
.application(app)
|
.application(app)
|
||||||
.width_request(800)
|
.width_request(800)
|
||||||
|
|
|
@ -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<ConfigurationPagePrivate>)
|
||||||
|
@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
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ pub struct LayoutPrivate {
|
||||||
impl Default for LayoutPrivate {
|
impl Default for LayoutPrivate {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let header = adw::HeaderBar::builder()
|
let header = adw::HeaderBar::builder()
|
||||||
.title_widget(>k::Label::new(Some("Placeholder Title")))
|
.title_widget(>k::Label::new(Some("Kifu")))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let app_menu = gio::Menu::new();
|
let app_menu = gio::Menu::new();
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
mod chat;
|
mod chat;
|
||||||
pub use chat::Chat;
|
pub use chat::Chat;
|
||||||
|
|
||||||
|
mod config;
|
||||||
|
pub use config::ConfigurationPage;
|
||||||
|
|
||||||
mod game_preview;
|
mod game_preview;
|
||||||
pub use game_preview::GamePreview;
|
pub use game_preview::GamePreview;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue