Compare commits
No commits in common. "de54ec676f9eea35d520cb82cd0ef5fafeb68ded" and "c3c144e0359de7546c37385aa27853b4921bcb1f" have entirely different histories.
de54ec676f
...
c3c144e035
|
@ -4,14 +4,5 @@
|
||||||
|
|
||||||
.settings-view {
|
.settings-view {
|
||||||
margin: 8px;
|
margin: 8px;
|
||||||
padding: 4px;
|
|
||||||
background-color: @view_bg_color;
|
background-color: @view_bg_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-view {
|
|
||||||
padding: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-item > suffixes {
|
|
||||||
margin: 4px;
|
|
||||||
}
|
|
||||||
|
|
|
@ -23,12 +23,12 @@ use gtk::STYLE_PROVIDER_PRIORITY_USER;
|
||||||
use kifu_core::{Config, Core};
|
use kifu_core::{Config, Core};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use crate::{view_models::HomeViewModel, view_models::SettingsViewModel};
|
use crate::view_models::SettingsViewModel;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum AppView {
|
enum AppView {
|
||||||
Settings(SettingsViewModel),
|
Settings(SettingsViewModel),
|
||||||
Home(HomeViewModel),
|
Home,
|
||||||
}
|
}
|
||||||
|
|
||||||
// An application window should generally contain
|
// An application window should generally contain
|
||||||
|
@ -87,27 +87,11 @@ impl AppWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_settings(&self) {
|
pub fn open_settings(&self) {
|
||||||
let view_model = SettingsViewModel::new(&self.window, self.core.clone(), {
|
let view_model = SettingsViewModel::new(&self.window, self.core.clone());
|
||||||
let s = self.clone();
|
|
||||||
move || {
|
|
||||||
s.close_overlay();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
self.panel_overlay.add_overlay(&view_model.widget);
|
self.panel_overlay.add_overlay(&view_model.widget);
|
||||||
*self.settings_view_model.write().unwrap() = Some(view_model);
|
*self.settings_view_model.write().unwrap() = Some(view_model);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close_overlay(&self) {
|
|
||||||
let mut vm = self.settings_view_model.write().unwrap();
|
|
||||||
match *vm {
|
|
||||||
Some(ref mut view_model) => {
|
|
||||||
self.panel_overlay.remove_overlay(&view_model.widget);
|
|
||||||
*vm = None;
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setup_window(app: &adw::Application) -> adw::ApplicationWindow {
|
fn setup_window(app: &adw::Application) -> adw::ApplicationWindow {
|
||||||
let window = adw::ApplicationWindow::builder()
|
let window = adw::ApplicationWindow::builder()
|
||||||
.application(app)
|
.application(app)
|
||||||
|
@ -152,7 +136,7 @@ impl AppWindow {
|
||||||
.child(¬hing_page)
|
.child(¬hing_page)
|
||||||
.build(),
|
.build(),
|
||||||
);
|
);
|
||||||
content.push(AppView::Home(HomeViewModel::new(core.clone())));
|
content.push(AppView::Home);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
match *core.library() {
|
match *core.library() {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use async_std::channel::Receiver;
|
|
||||||
use async_std::task::spawn;
|
|
||||||
use gio::ActionEntry;
|
use gio::ActionEntry;
|
||||||
use kifu_core::{Config, ConfigOption, Core, CoreNotification, LibraryPath, Observable};
|
use kifu_core::{Config, ConfigOption, Core};
|
||||||
use kifu_gtk::{
|
use kifu_gtk::{
|
||||||
perftrace,
|
perftrace,
|
||||||
// ui::{ConfigurationPage, Home, PlayingField},
|
// ui::{ConfigurationPage, Home, PlayingField},
|
||||||
|
@ -16,29 +14,6 @@ const APP_ID_PROD: &str = "com.luminescent-dreams.kifu-gtk";
|
||||||
|
|
||||||
const RESOURCE_BASE_PATH: &str = "/com/luminescent-dreams/kifu-gtk/";
|
const RESOURCE_BASE_PATH: &str = "/com/luminescent-dreams/kifu-gtk/";
|
||||||
|
|
||||||
async fn handler(notifications: Receiver<CoreNotification>, app_id: String) {
|
|
||||||
loop {
|
|
||||||
let msg = notifications.recv().await;
|
|
||||||
match msg {
|
|
||||||
Ok(CoreNotification::ConfigurationUpdated(cfg)) => {
|
|
||||||
println!("commiting configuration");
|
|
||||||
let settings = gio::Settings::new(&app_id);
|
|
||||||
if let Some(LibraryPath(library_path)) = cfg.get() {
|
|
||||||
let _ = settings.set_string(
|
|
||||||
"library-path",
|
|
||||||
&library_path.into_os_string().into_string().unwrap(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(_) => println!("discarding message"),
|
|
||||||
Err(err) => {
|
|
||||||
println!("shutting down handler with error: {:?}", err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
fn handle_response(api: CoreApi, app_window: &AppWindow, message: CoreResponse) {
|
fn handle_response(api: CoreApi, app_window: &AppWindow, message: CoreResponse) {
|
||||||
let playing_field = Arc::new(RwLock::new(None));
|
let playing_field = Arc::new(RwLock::new(None));
|
||||||
|
@ -132,12 +107,6 @@ fn main() {
|
||||||
|
|
||||||
let core = Core::new(config);
|
let core = Core::new(config);
|
||||||
|
|
||||||
spawn({
|
|
||||||
let notifier = core.subscribe();
|
|
||||||
let app_id = app_id.to_owned();
|
|
||||||
handler(notifier, app_id)
|
|
||||||
});
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
let core_handle = runtime.spawn({
|
let core_handle = runtime.spawn({
|
||||||
let core = core.clone();
|
let core = core.clone();
|
||||||
|
@ -152,13 +121,14 @@ fn main() {
|
||||||
.resource_base_path("/com/luminescent-dreams/kifu-gtk")
|
.resource_base_path("/com/luminescent-dreams/kifu-gtk")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
||||||
app.connect_activate({
|
app.connect_activate({
|
||||||
let runtime = runtime.clone();
|
let runtime = runtime.clone();
|
||||||
move |app| {
|
move |app| {
|
||||||
let mut app_window = AppWindow::new(app, core.clone());
|
let mut app_window = AppWindow::new(app, core.clone());
|
||||||
|
|
||||||
match *core.library() {
|
match *core.library() {
|
||||||
Some(_) => {}
|
Some(_) => {},
|
||||||
None => app_window.open_settings(),
|
None => app_window.open_settings(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,25 +16,23 @@ You should have received a copy of the GNU General Public License along with Kif
|
||||||
|
|
||||||
use crate::LocalObserver;
|
use crate::LocalObserver;
|
||||||
use kifu_core::{Core, CoreNotification};
|
use kifu_core::{Core, CoreNotification};
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
/// Home controls the view that the user sees when starting the application if there are no games in progress. It provides a window into the database, showing a list of recently recorded games. It also provides the UI for starting a new game. This will render an empty database view if the user hasn't configured a database yet.
|
/// Home controls the view that the user sees when starting the application if there are no games in progress. It provides a window into the database, showing a list of recently recorded games. It also provides the UI for starting a new game. This will render an empty database view if the user hasn't configured a database yet.
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct HomeViewModel {
|
pub struct HomeViewModel {
|
||||||
core: Core,
|
core: Core,
|
||||||
notification_observer: Arc<LocalObserver<CoreNotification>>,
|
notification_observer: LocalObserver<CoreNotification>,
|
||||||
widget: gtk::Box,
|
widget: gtk::Box,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HomeViewModel {
|
impl HomeViewModel {
|
||||||
pub fn new(core: Core) -> Self {
|
fn new(core: Core) -> Self {
|
||||||
let notification_observer = LocalObserver::new(&core, |msg| {
|
let notification_observer = LocalObserver::new(&core, |msg| {
|
||||||
println!("HomeViewModel handler called with message: {:?}", msg)
|
println!("DatabaseViewModelHandler called with message: {:?}", msg)
|
||||||
});
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
core,
|
core,
|
||||||
notification_observer: Arc::new(notification_observer),
|
notification_observer,
|
||||||
widget: gtk::Box::new(gtk::Orientation::Horizontal, 0),
|
widget: gtk::Box::new(gtk::Orientation::Horizontal, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ use crate::{views, views::SettingsView, LocalObserver};
|
||||||
use async_std::task::spawn;
|
use async_std::task::spawn;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use kifu_core::{Config, Core, CoreNotification};
|
use kifu_core::{Config, Core, CoreNotification};
|
||||||
use std::{sync::Arc, rc::Rc};
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// SettingsViewModel
|
/// SettingsViewModel
|
||||||
///
|
///
|
||||||
|
@ -35,39 +35,24 @@ pub struct SettingsViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SettingsViewModel {
|
impl SettingsViewModel {
|
||||||
pub fn new(parent: &impl IsA<gtk::Window>, core: Core, on_close: impl Fn() + 'static) -> Self {
|
pub fn new(parent: &impl IsA<gtk::Window>, core: Core) -> Self {
|
||||||
let on_close = Arc::new(on_close);
|
|
||||||
|
|
||||||
let notification_observer = LocalObserver::new(&core, |msg| {
|
let notification_observer = LocalObserver::new(&core, |msg| {
|
||||||
println!("SettingsViewModel called with message: {:?}", msg)
|
println!("SettingsViewModel called with message: {:?}", msg)
|
||||||
});
|
});
|
||||||
|
|
||||||
let config = core.get_config();
|
let config = core.get_config();
|
||||||
|
|
||||||
let widget = SettingsView::new(
|
|
||||||
parent,
|
|
||||||
config,
|
|
||||||
{
|
|
||||||
let core = core.clone();
|
|
||||||
let on_close = on_close.clone();
|
|
||||||
move |new_config| {
|
|
||||||
spawn({
|
|
||||||
let core = core.clone();
|
|
||||||
on_close();
|
|
||||||
async move {
|
|
||||||
println!("running set_config in the background");
|
|
||||||
core.set_config(new_config).await;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
move || on_close(),
|
|
||||||
);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
core: core.clone(),
|
core: core.clone(),
|
||||||
notification_observer: Arc::new(notification_observer),
|
notification_observer: Arc::new(notification_observer),
|
||||||
widget,
|
widget: SettingsView::new(parent, config, {
|
||||||
|
&|new_config| {
|
||||||
|
spawn({
|
||||||
|
let core = core.clone();
|
||||||
|
async move { core.set_config(new_config).await }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License along with Kifu. If not, see <https://www.gnu.org/licenses/>.
|
You should have received a copy of the GNU General Public License along with Kifu. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::{cell::RefCell, path::Path, rc::Rc, borrow::Cow};
|
use std::{cell::RefCell, path::Path, rc::Rc};
|
||||||
|
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use glib::Object;
|
use glib::Object;
|
||||||
|
@ -23,48 +23,35 @@ use kifu_core::{Config, ConfigOption, LibraryPath};
|
||||||
|
|
||||||
fn library_chooser_row(
|
fn library_chooser_row(
|
||||||
parent: &impl IsA<gtk::Window>,
|
parent: &impl IsA<gtk::Window>,
|
||||||
library_path: Option<LibraryPath>,
|
|
||||||
on_library_chosen: Rc<impl Fn(ConfigOption) + 'static>,
|
on_library_chosen: Rc<impl Fn(ConfigOption) + 'static>,
|
||||||
) -> adw::ActionRow {
|
) -> adw::ActionRow {
|
||||||
let dialog = gtk::FileDialog::builder().build();
|
let dialog = gtk::FileDialog::builder().build();
|
||||||
|
|
||||||
let dialog_button = gtk::Button::builder()
|
let dialog_button = gtk::Button::builder()
|
||||||
.child(>k::Label::new(Some("Select Library")))
|
.child(>k::Label::new(Some("Select Library")))
|
||||||
.valign(gtk::Align::Center)
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let parent = parent.clone();
|
let parent = parent.clone();
|
||||||
|
dialog_button.connect_clicked(move |_| {
|
||||||
|
let no_parent: Option<>k::Window> = None;
|
||||||
|
let not_cancellable: Option<&gio::Cancellable> = None;
|
||||||
|
let on_library_chosen = on_library_chosen.clone();
|
||||||
|
dialog.select_folder(no_parent, not_cancellable, move |result| match result {
|
||||||
|
Ok(path) => {
|
||||||
|
on_library_chosen(ConfigOption::LibraryPath(LibraryPath(path.path().unwrap())))
|
||||||
|
}
|
||||||
|
Err(err) => println!("Error choosing a library: {:?}", err),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
let library_row = adw::ActionRow::builder()
|
let library_row = adw::ActionRow::builder()
|
||||||
.title("Library Path")
|
.title("Library Path")
|
||||||
.subtitle(library_path.map(|LibraryPath(path)| path.to_string_lossy().into_owned()).unwrap_or("No library set".to_owned()))
|
.subtitle("No library set")
|
||||||
.css_classes(["preference-item"])
|
// .child(&library_row)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
dialog_button.connect_clicked({
|
|
||||||
let library_row = library_row.clone();
|
|
||||||
move |_| {
|
|
||||||
let no_parent: Option<>k::Window> = None;
|
|
||||||
let not_cancellable: Option<&gio::Cancellable> = None;
|
|
||||||
let on_library_chosen = on_library_chosen.clone();
|
|
||||||
dialog.select_folder(no_parent, not_cancellable, {
|
|
||||||
let library_row = library_row.clone();
|
|
||||||
move |result| match result {
|
|
||||||
Ok(path) => {
|
|
||||||
let path_str: String =
|
|
||||||
path.path().unwrap().into_os_string().into_string().unwrap();
|
|
||||||
library_row.set_subtitle(&path_str);
|
|
||||||
on_library_chosen(ConfigOption::LibraryPath(LibraryPath(
|
|
||||||
path.path().unwrap(),
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
Err(err) => println!("Error choosing a library: {:?}", err),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
library_row.add_suffix(&dialog_button);
|
library_row.add_suffix(&dialog_button);
|
||||||
|
library_row.connect_activate(|_| println!("library row activated"));
|
||||||
|
|
||||||
library_row
|
library_row
|
||||||
}
|
}
|
||||||
|
@ -95,52 +82,39 @@ impl SettingsView {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
parent: &impl IsA<gtk::Window>,
|
parent: &impl IsA<gtk::Window>,
|
||||||
config: Config,
|
config: Config,
|
||||||
on_save: impl Fn(Config) + 'static,
|
on_save: &impl FnOnce(Config),
|
||||||
on_cancel: impl Fn() + 'static,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let s: Self = Object::builder().build();
|
let s: Self = Object::builder().build();
|
||||||
let config = Rc::new(RefCell::new(config));
|
let config = Rc::new(RefCell::new(config));
|
||||||
|
|
||||||
let group = adw::PreferencesGroup::builder().build();
|
let group = adw::PreferencesGroup::builder().vexpand(true).build();
|
||||||
|
|
||||||
let library_row = library_chooser_row(
|
let library_row = library_chooser_row(
|
||||||
parent,
|
parent,
|
||||||
config.borrow().get(),
|
|
||||||
Rc::new({
|
Rc::new({
|
||||||
let config = config.clone();
|
let config = config.clone();
|
||||||
move |library_path| {
|
move |library_path| {
|
||||||
config.borrow_mut().set(library_path);
|
config.borrow_mut().set(library_path);
|
||||||
|
println!("library path changed, need to update the UI");
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
group.add(&library_row);
|
group.add(&library_row);
|
||||||
|
|
||||||
let cancel_button = gtk::Button::builder().label("Cancel").build();
|
let cancel_button = gtk::Button::builder().label("Cancel").build();
|
||||||
cancel_button.connect_clicked(move |_| on_cancel());
|
|
||||||
let save_button = gtk::Button::builder().label("Save").build();
|
let save_button = gtk::Button::builder().label("Save").build();
|
||||||
save_button.connect_clicked({
|
|
||||||
let config = config.clone();
|
|
||||||
move |_| on_save(config.borrow().clone())
|
|
||||||
});
|
|
||||||
|
|
||||||
let action_row = gtk::Box::builder()
|
let action_row = gtk::Box::builder()
|
||||||
.orientation(gtk::Orientation::Horizontal)
|
.orientation(gtk::Orientation::Horizontal)
|
||||||
.halign(gtk::Align::End)
|
.halign(gtk::Align::End)
|
||||||
.valign(gtk::Align::End)
|
|
||||||
.build();
|
.build();
|
||||||
action_row.append(&cancel_button);
|
action_row.append(&cancel_button);
|
||||||
action_row.append(&save_button);
|
action_row.append(&save_button);
|
||||||
|
|
||||||
let preferences_box = gtk::Box::builder()
|
|
||||||
.orientation(gtk::Orientation::Vertical)
|
|
||||||
.build();
|
|
||||||
preferences_box.append(&group);
|
|
||||||
|
|
||||||
let layout = gtk::Box::builder()
|
let layout = gtk::Box::builder()
|
||||||
.orientation(gtk::Orientation::Vertical)
|
.orientation(gtk::Orientation::Vertical)
|
||||||
.spacing(8)
|
.vexpand(true)
|
||||||
.build();
|
.build();
|
||||||
layout.append(&preferences_box);
|
layout.append(&group);
|
||||||
layout.append(&action_row);
|
layout.append(&action_row);
|
||||||
|
|
||||||
s.set_child(Some(&layout));
|
s.set_child(Some(&layout));
|
||||||
|
|
Loading…
Reference in New Issue