2024-03-15 14:49:25 +00:00
|
|
|
/*
|
|
|
|
Copyright 2024, Savanni D'Gerinel <savanni@luminescent-dreams.com>
|
|
|
|
|
|
|
|
This file is part of Kifu.
|
|
|
|
|
|
|
|
Kifu is free software: you can redistribute it and/or modify it under the terms of the GNU
|
|
|
|
General Public License as published by the Free Software Foundation, either version 3 of the
|
|
|
|
License, or (at your option) any later version.
|
|
|
|
|
|
|
|
Kifu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
|
|
|
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
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/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
use adw::prelude::*;
|
2024-03-19 14:08:43 +00:00
|
|
|
/*
|
2024-03-15 14:49:25 +00:00
|
|
|
use gio::resources_lookup_data;
|
|
|
|
use glib::IsA;
|
|
|
|
use gtk::STYLE_PROVIDER_PRIORITY_USER;
|
2024-03-19 14:08:43 +00:00
|
|
|
*/
|
2024-03-15 14:49:25 +00:00
|
|
|
use kifu_core::{Config, Core};
|
2024-03-15 18:07:55 +00:00
|
|
|
use std::sync::{Arc, RwLock};
|
2024-03-15 14:49:25 +00:00
|
|
|
|
2024-03-21 12:43:08 +00:00
|
|
|
use crate::{view_models::HomeViewModel, view_models::SettingsViewModel};
|
2024-03-15 14:49:25 +00:00
|
|
|
|
2024-03-15 18:07:55 +00:00
|
|
|
#[derive(Clone)]
|
2024-03-15 14:49:25 +00:00
|
|
|
enum AppView {
|
|
|
|
Settings(SettingsViewModel),
|
2024-03-21 12:43:08 +00:00
|
|
|
Home(HomeViewModel),
|
2024-03-15 14:49:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// An application window should generally contain
|
|
|
|
// - 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
|
2024-03-15 18:07:55 +00:00
|
|
|
#[derive(Clone)]
|
2024-03-15 14:49:25 +00:00
|
|
|
pub struct AppWindow {
|
|
|
|
pub window: adw::ApplicationWindow,
|
|
|
|
header: adw::HeaderBar,
|
|
|
|
|
|
|
|
// content is a stack which contains the view models for the application. These are the main
|
|
|
|
// elements that users want to interact with: the home page, the game library, a review, a game
|
|
|
|
// itself, perhaps also chat rooms and player lists on other networks. stack contains the
|
|
|
|
// widgets that need to be rendered. The two of these work together in order to ensure that
|
|
|
|
// we can maintain the state of previous views. Since the two of these work together, they are
|
|
|
|
// a candidate for extraction into a new widget or a new struct.
|
|
|
|
stack: adw::NavigationView,
|
|
|
|
content: Vec<AppView>,
|
|
|
|
|
|
|
|
// Overlays are for transient content, such as about and settings, which can be accessed from
|
|
|
|
// anywhere but shouldn't be part of the main application flow.
|
|
|
|
panel_overlay: gtk::Overlay,
|
|
|
|
core: Core,
|
2024-03-15 18:07:55 +00:00
|
|
|
|
|
|
|
// 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>>>,
|
2024-03-15 14:49:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl AppWindow {
|
|
|
|
pub fn new(app: &adw::Application, core: Core) -> Self {
|
|
|
|
let window = Self::setup_window(app);
|
|
|
|
let header = Self::setup_header();
|
|
|
|
let panel_overlay = Self::setup_panel_overlay();
|
|
|
|
let (stack, content) = Self::setup_content(core.clone());
|
|
|
|
|
|
|
|
let layout = gtk::Box::builder()
|
|
|
|
.orientation(gtk::Orientation::Vertical)
|
|
|
|
.build();
|
|
|
|
layout.append(&header);
|
|
|
|
layout.append(&panel_overlay);
|
|
|
|
panel_overlay.set_child(Some(&stack));
|
|
|
|
|
|
|
|
window.set_content(Some(&layout));
|
|
|
|
|
|
|
|
Self {
|
|
|
|
window,
|
|
|
|
header,
|
|
|
|
stack,
|
|
|
|
content,
|
|
|
|
panel_overlay,
|
|
|
|
core,
|
2024-03-15 18:07:55 +00:00
|
|
|
settings_view_model: Default::default(),
|
2024-03-15 14:49:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-15 18:07:55 +00:00
|
|
|
pub fn open_settings(&self) {
|
2024-03-21 12:43:08 +00:00
|
|
|
let view_model = SettingsViewModel::new(&self.window, self.core.clone(), {
|
|
|
|
let s = self.clone();
|
|
|
|
move || {
|
|
|
|
s.close_overlay();
|
|
|
|
}
|
|
|
|
});
|
2024-03-15 18:07:55 +00:00
|
|
|
self.panel_overlay.add_overlay(&view_model.widget);
|
|
|
|
*self.settings_view_model.write().unwrap() = Some(view_model);
|
|
|
|
}
|
|
|
|
|
2024-03-21 12:43:08 +00:00
|
|
|
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 => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-15 14:49:25 +00:00
|
|
|
fn setup_window(app: &adw::Application) -> adw::ApplicationWindow {
|
|
|
|
let window = adw::ApplicationWindow::builder()
|
|
|
|
.application(app)
|
|
|
|
.width_request(800)
|
|
|
|
.height_request(500)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
window
|
|
|
|
}
|
|
|
|
|
|
|
|
fn setup_header() -> adw::HeaderBar {
|
|
|
|
let header = adw::HeaderBar::builder()
|
|
|
|
.title_widget(>k::Label::new(Some("Kifu")))
|
|
|
|
.build();
|
|
|
|
|
|
|
|
let app_menu = gio::Menu::new();
|
2024-03-15 18:07:55 +00:00
|
|
|
let menu_item = gio::MenuItem::new(Some("Configuration"), Some("app.show_settings"));
|
2024-03-15 14:49:25 +00:00
|
|
|
app_menu.append_item(&menu_item);
|
|
|
|
|
|
|
|
let hamburger = gtk::MenuButton::builder()
|
|
|
|
.icon_name("open-menu-symbolic")
|
|
|
|
.build();
|
|
|
|
hamburger.set_menu_model(Some(&app_menu));
|
|
|
|
|
|
|
|
header.pack_end(&hamburger);
|
|
|
|
header
|
|
|
|
}
|
|
|
|
|
|
|
|
fn setup_panel_overlay() -> gtk::Overlay {
|
|
|
|
gtk::Overlay::new()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn setup_content(core: Core) -> (adw::NavigationView, Vec<AppView>) {
|
|
|
|
let stack = adw::NavigationView::new();
|
|
|
|
let mut content = Vec::new();
|
|
|
|
|
|
|
|
let nothing_page = adw::StatusPage::builder().title("Nothing here").build();
|
|
|
|
let _ = stack.push(
|
|
|
|
&adw::NavigationPage::builder()
|
|
|
|
.can_pop(false)
|
|
|
|
.title("Kifu")
|
|
|
|
.child(¬hing_page)
|
|
|
|
.build(),
|
|
|
|
);
|
2024-03-21 12:43:08 +00:00
|
|
|
content.push(AppView::Home(HomeViewModel::new(core.clone())));
|
2024-03-15 14:49:25 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
match *core.library() {
|
|
|
|
Some(_) => {
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
let settings_vm = SettingsViewModel::new(core.clone());
|
|
|
|
let _ = stack.push(&adw::NavigationPage::new(&settings_vm.widget, "Settings"));
|
|
|
|
content.push(AppView::Settings(settings_vm));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
(stack, content)
|
|
|
|
}
|
|
|
|
|
|
|
|
// pub fn set_content(content: &impl IsA<gtk::Widget>) -> adw::ViewStack {
|
|
|
|
// self.content.set_child(Some(content));
|
|
|
|
// }
|
|
|
|
}
|