Set up the settings user interface #225
|
@ -1,3 +1,8 @@
|
|||
.content {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.settings-view {
|
||||
margin: 8px;
|
||||
background-color: @view_bg_color;
|
||||
}
|
||||
|
|
|
@ -19,9 +19,11 @@ use gio::resources_lookup_data;
|
|||
use glib::IsA;
|
||||
use gtk::STYLE_PROVIDER_PRIORITY_USER;
|
||||
use kifu_core::{Config, Core};
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use crate::view_models::SettingsViewModel;
|
||||
|
||||
#[derive(Clone)]
|
||||
enum AppView {
|
||||
Settings(SettingsViewModel),
|
||||
Home,
|
||||
|
@ -31,6 +33,7 @@ enum AppView {
|
|||
// - an overlay widget
|
||||
// - the main content in a stack on the bottom panel of the overlay
|
||||
// - the settings and the about page in bins atop the overlay
|
||||
#[derive(Clone)]
|
||||
pub struct AppWindow {
|
||||
pub window: adw::ApplicationWindow,
|
||||
header: adw::HeaderBar,
|
||||
|
@ -48,42 +51,14 @@ pub struct AppWindow {
|
|||
// anywhere but shouldn't be part of the main application flow.
|
||||
panel_overlay: gtk::Overlay,
|
||||
core: Core,
|
||||
|
||||
// Not liking this, but I have to keep track of the settings view model separately from
|
||||
// anything else. I'll have to look into this later.
|
||||
settings_view_model: Arc<RwLock<Option<SettingsViewModel>>>,
|
||||
}
|
||||
|
||||
impl AppWindow {
|
||||
pub fn new(app: &adw::Application, core: Core) -> Self {
|
||||
/*
|
||||
|
||||
let stylesheet = String::from_utf8(
|
||||
resources_lookup_data(
|
||||
"/com/luminescent-dreams/kifu-gtk/style.css",
|
||||
gio::ResourceLookupFlags::NONE,
|
||||
)
|
||||
.expect("stylesheet should just be available")
|
||||
.to_vec(),
|
||||
)
|
||||
.expect("to parse stylesheet");
|
||||
|
||||
let provider = gtk::CssProvider::new();
|
||||
provider.load_from_data(&stylesheet);
|
||||
let context = window.style_context();
|
||||
context.add_provider(&provider, STYLE_PROVIDER_PRIORITY_USER);
|
||||
|
||||
let header = setup_header();
|
||||
|
||||
let current_view = match config.get::<Database>() {
|
||||
Some(_) => AppView::Home,
|
||||
None => AppView::Config(SettingsViewModel::new(core.clone())),
|
||||
};
|
||||
|
||||
let content = adw::Bin::builder().css_classes(vec!["content"]).build();
|
||||
content.set_child(Some(
|
||||
));
|
||||
|
||||
|
||||
window.set_content(Some(&layout));
|
||||
*/
|
||||
|
||||
let window = Self::setup_window(app);
|
||||
let header = Self::setup_header();
|
||||
let panel_overlay = Self::setup_panel_overlay();
|
||||
|
@ -105,9 +80,16 @@ impl AppWindow {
|
|||
content,
|
||||
panel_overlay,
|
||||
core,
|
||||
settings_view_model: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open_settings(&self) {
|
||||
let view_model = SettingsViewModel::new(self.core.clone());
|
||||
self.panel_overlay.add_overlay(&view_model.widget);
|
||||
*self.settings_view_model.write().unwrap() = Some(view_model);
|
||||
}
|
||||
|
||||
fn setup_window(app: &adw::Application) -> adw::ApplicationWindow {
|
||||
let window = adw::ApplicationWindow::builder()
|
||||
.application(app)
|
||||
|
@ -124,7 +106,7 @@ impl AppWindow {
|
|||
.build();
|
||||
|
||||
let app_menu = gio::Menu::new();
|
||||
let menu_item = gio::MenuItem::new(Some("Configuration"), Some("app.show_config"));
|
||||
let menu_item = gio::MenuItem::new(Some("Configuration"), Some("app.show_settings"));
|
||||
app_menu.append_item(&menu_item);
|
||||
|
||||
let hamburger = gtk::MenuButton::builder()
|
||||
|
|
|
@ -55,17 +55,17 @@ fn handle_response(api: CoreApi, app_window: &AppWindow, message: CoreResponse)
|
|||
|
||||
fn load_config(app_id: &str) -> Config {
|
||||
let settings = gio::Settings::new(app_id);
|
||||
let db_path: String = settings.string("database-path").into();
|
||||
let lib_path: String = settings.string("library-path").into();
|
||||
let mut config = Config::new();
|
||||
config.set(ConfigOption::LibraryPath(db_path.into()));
|
||||
config.set(ConfigOption::LibraryPath(lib_path.into()));
|
||||
config
|
||||
}
|
||||
|
||||
fn setup_app_configuration_action(app: &adw::Application) {
|
||||
fn setup_app_configuration_action(app: &adw::Application, app_window: AppWindow) {
|
||||
println!("setup_app_configuration_action");
|
||||
let action = ActionEntry::builder("show_config")
|
||||
.activate(|_app: &adw::Application, _, _| {
|
||||
println!("show configuration window");
|
||||
let action = ActionEntry::builder("show_settings")
|
||||
.activate(move |_app: &adw::Application, _, _| {
|
||||
app_window.open_settings();
|
||||
})
|
||||
.build();
|
||||
app.add_action_entries([action]);
|
||||
|
@ -125,14 +125,21 @@ fn main() {
|
|||
app.connect_activate({
|
||||
let runtime = runtime.clone();
|
||||
move |app| {
|
||||
let app_window = AppWindow::new(app, core.clone());
|
||||
let mut app_window = AppWindow::new(app, core.clone());
|
||||
|
||||
setup_app_configuration_action(app);
|
||||
match *core.library() {
|
||||
Some(_) => {},
|
||||
None => app_window.open_settings(),
|
||||
}
|
||||
|
||||
setup_app_configuration_action(app, app_window.clone());
|
||||
|
||||
/*
|
||||
let api = CoreApi {
|
||||
rt: runtime.clone(),
|
||||
core: core.clone(),
|
||||
};
|
||||
*/
|
||||
|
||||
/*
|
||||
let action_config = gio::SimpleAction::new("show-config", None);
|
||||
|
|
|
@ -16,17 +16,19 @@ You should have received a copy of the GNU General Public License along with Kif
|
|||
|
||||
use crate::{views, LocalObserver, views::SettingsView};
|
||||
use kifu_core::{Core, CoreNotification};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// SettingsViewModel
|
||||
///
|
||||
/// Listens for messages from the core, and serves as intermediary between the Settings UI and the
|
||||
/// core. Because it needs to respond to events from the core, it owns the widget, which allows it
|
||||
/// to tell the widget to update after certain events.
|
||||
#[derive(Clone)]
|
||||
pub struct SettingsViewModel {
|
||||
core: Core,
|
||||
// Technically, Settings doesn't care about any events from Core. We will keep this around for
|
||||
// now as reference, until something which does care shows up.
|
||||
notification_observer: LocalObserver<CoreNotification>,
|
||||
notification_observer: Arc<LocalObserver<CoreNotification>>,
|
||||
pub widget: views::SettingsView,
|
||||
}
|
||||
|
||||
|
@ -38,7 +40,7 @@ impl SettingsViewModel {
|
|||
|
||||
Self {
|
||||
core,
|
||||
notification_observer,
|
||||
notification_observer: Arc::new(notification_observer),
|
||||
widget: SettingsView::new(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ You should have received a copy of the GNU General Public License along with Kif
|
|||
|
||||
use glib::Object;
|
||||
use gtk::{prelude::*, subclass::prelude::*};
|
||||
use adw::prelude::*;
|
||||
|
||||
pub struct SettingsPrivate {}
|
||||
|
||||
|
@ -23,7 +24,7 @@ pub struct SettingsPrivate {}
|
|||
impl ObjectSubclass for SettingsPrivate {
|
||||
const NAME: &'static str = "Settings";
|
||||
type Type = SettingsView;
|
||||
type ParentType = gtk::Box;
|
||||
type ParentType = gtk::Frame;
|
||||
|
||||
fn new() -> Self {
|
||||
Self {}
|
||||
|
@ -32,15 +33,33 @@ impl ObjectSubclass for SettingsPrivate {
|
|||
|
||||
impl ObjectImpl for SettingsPrivate {}
|
||||
impl WidgetImpl for SettingsPrivate {}
|
||||
impl BoxImpl for SettingsPrivate {}
|
||||
#[allow(deprecated)]
|
||||
impl FrameImpl for SettingsPrivate {}
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct SettingsView(ObjectSubclass<SettingsPrivate>) @extends gtk::Box, gtk::Widget, @implements gtk::Orientable;
|
||||
pub struct SettingsView(ObjectSubclass<SettingsPrivate>) @extends gtk::Frame, gtk::Widget, @implements gtk::Accessible, gtk::Buildable, gtk::Orientable;
|
||||
}
|
||||
|
||||
impl SettingsView {
|
||||
pub fn new() -> Self {
|
||||
let s: Self = Object::builder().build();
|
||||
|
||||
let group = adw::PreferencesGroup::builder().build();
|
||||
let library_row = adw::PreferencesRow::builder()
|
||||
.title("Library Path")
|
||||
.child(>k::Label::builder().label("Library Path").build())
|
||||
.build();
|
||||
group.add(&library_row);
|
||||
|
||||
let layout = gtk::Box::builder()
|
||||
.orientation(gtk::Orientation::Vertical)
|
||||
.vexpand(true)
|
||||
.build();
|
||||
layout.append(&group);
|
||||
|
||||
s.set_child(Some(&layout));
|
||||
s.set_css_classes(&["settings-view"]);
|
||||
|
||||
s
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue