/* Copyright 2024, Savanni D'Gerinel 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 . */ use adw::prelude::*; /* 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::HomeViewModel, view_models::SettingsViewModel}; #[derive(Clone)] enum AppView { Settings(SettingsViewModel), Home(HomeViewModel), } // 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 #[derive(Clone)] 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, // 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, // 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>>, } 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, settings_view_model: Default::default(), } } pub fn open_settings(&self) { 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.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 { 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(); let menu_item = gio::MenuItem::new(Some("Configuration"), Some("app.show_settings")); 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) { 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(), ); content.push(AppView::Home(HomeViewModel::new(core.clone()))); /* 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) -> adw::ViewStack { // self.content.set_child(Some(content)); // } }