Change the layout/app_window to an ordinary object with necessary objects

This commit is contained in:
Savanni D'Gerinel 2023-08-24 21:56:03 -04:00
parent 784f3ff7f4
commit cc828c417a
3 changed files with 66 additions and 86 deletions

View File

@ -2,12 +2,12 @@ use adw::prelude::*;
use kifu_core::{CoreApp, CoreRequest, CoreResponse}; use kifu_core::{CoreApp, CoreRequest, CoreResponse};
use kifu_gtk::{ use kifu_gtk::{
perftrace, perftrace,
ui::{ConfigurationPage, Home, Layout, PlayingField}, ui::{AppWindow, ConfigurationPage, Home, PlayingField},
CoreApi, CoreApi,
}; };
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
fn handle_response(api: CoreApi, layout: Layout, 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));
match message { match message {
CoreResponse::ConfigurationView(view) => perftrace("ConfigurationView", || { CoreResponse::ConfigurationView(view) => perftrace("ConfigurationView", || {
@ -22,7 +22,7 @@ fn handle_response(api: CoreApi, layout: Layout, message: CoreResponse) {
let api = api.clone(); let api = api.clone();
let home = Home::new(api, view); let home = Home::new(api, view);
layout.set_content(&home); app_window.set_content(&home);
}), }),
CoreResponse::PlayingFieldView(view) => perftrace("PlayingFieldView", || { CoreResponse::PlayingFieldView(view) => perftrace("PlayingFieldView", || {
let api = api.clone(); let api = api.clone();
@ -31,7 +31,7 @@ fn handle_response(api: CoreApi, layout: Layout, message: CoreResponse) {
if playing_field.is_none() { if playing_field.is_none() {
perftrace("creating a new playing field", || { perftrace("creating a new playing field", || {
let field = PlayingField::new(api, view); let field = PlayingField::new(api, view);
layout.set_content(&field); app_window.set_content(&field);
*playing_field = Some(field); *playing_field = Some(field);
}) })
} else { } else {
@ -87,6 +87,8 @@ fn main() {
let (gtk_tx, gtk_rx) = let (gtk_tx, gtk_rx) =
gtk::glib::MainContext::channel::<CoreResponse>(gtk::glib::PRIORITY_DEFAULT); gtk::glib::MainContext::channel::<CoreResponse>(gtk::glib::PRIORITY_DEFAULT);
let app_window = AppWindow::new(&app);
let api = CoreApi { let api = CoreApi {
gtk_tx, gtk_tx,
rt: runtime.clone(), rt: runtime.clone(),
@ -102,22 +104,13 @@ fn main() {
}); });
app.add_action(&action_config); app.add_action(&action_config);
let window = adw::ApplicationWindow::builder() app_window.window.present();
.application(app)
.width_request(800)
.height_request(500)
.build();
let layout = Layout::new();
window.set_content(Some(&layout));
window.present();
gtk_rx.attach(None, { gtk_rx.attach(None, {
let api = api.clone(); let api = api.clone();
move |message| { move |message| {
perftrace("handle_response", || { perftrace("handle_response", || {
handle_response(api.clone(), layout.clone(), message) handle_response(api.clone(), &app_window, message)
}); });
Continue(true) Continue(true)
} }

View File

@ -1,71 +0,0 @@
use glib::Object;
use gtk::{prelude::*, subclass::prelude::*};
use std::{cell::RefCell, rc::Rc};
// Deprecated even from day 1. We want to use ToolbarView as soon as it's available in the versions
// of Libadwaita available in NixOS.
pub struct LayoutPrivate {
pub header: adw::HeaderBar,
pub content: Rc<RefCell<gtk::Widget>>,
}
impl Default for LayoutPrivate {
fn default() -> Self {
let header = adw::HeaderBar::builder()
.title_widget(&gtk::Label::new(Some("Kifu")))
.build();
let app_menu = gio::Menu::new();
let menu_item = gio::MenuItem::new(Some("Configuration"), Some("app.show-config"));
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);
let content = adw::StatusPage::builder().title("Nothing here").build();
Self {
header,
content: Rc::new(RefCell::new(content.into())),
}
}
}
#[glib::object_subclass]
impl ObjectSubclass for LayoutPrivate {
const NAME: &'static str = "Layout";
type Type = Layout;
type ParentType = gtk::Box;
}
impl ObjectImpl for LayoutPrivate {}
impl WidgetImpl for LayoutPrivate {}
impl BoxImpl for LayoutPrivate {}
glib::wrapper! {
pub struct Layout(ObjectSubclass<LayoutPrivate>) @extends gtk::Box, gtk::Widget, @implements gtk::Orientable;
}
impl Layout {
pub fn new() -> Self {
let s: Self = Object::builder().build();
s.set_orientation(gtk::Orientation::Vertical);
s.set_homogeneous(false);
s.append(&s.imp().header);
s.append(&*s.imp().content.borrow());
s
}
pub fn set_content(&self, content: &impl IsA<gtk::Widget>) {
let mut widget = self.imp().content.borrow_mut();
self.remove(&*widget);
*widget = content.clone().upcast::<gtk::Widget>();
self.append(&*widget);
}
}

View File

@ -1,3 +1,7 @@
use adw::prelude::*;
use glib::IsA;
use gtk::prelude::*;
mod chat; mod chat;
pub use chat::Chat; pub use chat::Chat;
@ -27,3 +31,57 @@ pub use board::Board;
#[cfg(feature = "screenplay")] #[cfg(feature = "screenplay")]
pub use playing_field::playing_field_view; pub use playing_field::playing_field_view;
pub struct AppWindow {
pub window: adw::ApplicationWindow,
pub header: adw::HeaderBar,
pub content: adw::Bin,
}
impl AppWindow {
pub fn new(app: &adw::Application) -> Self {
let header = adw::HeaderBar::builder()
.title_widget(&gtk::Label::new(Some("Kifu")))
.build();
let app_menu = gio::Menu::new();
let menu_item = gio::MenuItem::new(Some("Configuration"), Some("app.show-config"));
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);
let content = adw::Bin::new();
content.set_child(Some(
&adw::StatusPage::builder().title("Nothing here").build(),
));
let layout = gtk::Box::builder()
.orientation(gtk::Orientation::Vertical)
.build();
layout.append(&header);
layout.append(&content);
let window = adw::ApplicationWindow::builder()
.application(app)
.width_request(800)
.height_request(500)
.build();
window.set_content(Some(&layout));
Self {
window,
header,
content,
}
}
pub fn set_content(&self, content: &impl IsA<gtk::Widget>) {
self.content.set_child(Some(content));
}
}