From 2ff346f3fd1db95b4aae65592bf44755441c44f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= Date: Sat, 18 Jan 2025 15:10:10 +0100 Subject: [PATCH] account-switcher: Refactor and fix visibility --- .../account_switcher_button.rs | 158 ++++++++---------- .../account_switcher_button.ui | 12 ++ .../account_switcher_popover.rs | 115 +++++++------ src/account_switcher/avatar_with_selection.rs | 20 +-- src/account_switcher/mod.rs | 2 +- src/account_switcher/session_item.rs | 54 +++--- 6 files changed, 174 insertions(+), 187 deletions(-) diff --git a/src/account_switcher/account_switcher_button.rs b/src/account_switcher/account_switcher_button.rs index 08bb8937..5017317f 100644 --- a/src/account_switcher/account_switcher_button.rs +++ b/src/account_switcher/account_switcher_button.rs @@ -1,9 +1,4 @@ -use gtk::{ - glib::{self, clone, closure}, - prelude::*, - subclass::prelude::*, - CompositeTemplate, -}; +use gtk::{glib, glib::clone, prelude::*, subclass::prelude::*, CompositeTemplate}; use super::AccountSwitcherPopover; use crate::{ @@ -14,17 +9,17 @@ use crate::{ }; mod imp { - use std::cell::RefCell; - use glib::subclass::InitializingObject; use super::*; - #[derive(Debug, Default, CompositeTemplate)] + #[derive(Debug, Default, CompositeTemplate, glib::Properties)] #[template(resource = "/org/gnome/Fractal/ui/account_switcher/account_switcher_button.ui")] + #[properties(wrapper_type = super::AccountSwitcherButton)] pub struct AccountSwitcherButton { - pub popover: BoundObjectWeakRef, - pub watch: RefCell>, + /// The popover of this button. + #[property(get, set = Self::set_popover, explicit_notify, nullable)] + popover: BoundObjectWeakRef, } #[glib::object_subclass] @@ -38,6 +33,7 @@ mod imp { SessionInfo::ensure_type(); Self::bind_template(klass); + Self::bind_template_callbacks(klass); TemplateCallbacks::bind_template_callbacks(klass); } @@ -46,102 +42,86 @@ mod imp { } } - impl ObjectImpl for AccountSwitcherButton { - fn constructed(&self) { - self.parent_constructed(); - let obj = self.obj(); - - obj.connect_toggled(|obj| { - obj.handle_toggled(); - }); - - let watch = obj - .property_expression("root") - .chain_property::("session-selection") - .chain_property::("n-items") - .chain_closure::(closure!(|_: Option, n_items: u32| { - n_items > 0 - })) - .bind(&*obj, "visible", glib::Object::NONE); - self.watch.replace(Some(watch)); - } - - fn dispose(&self) { - if let Some(watch) = self.watch.take() { - watch.unwatch(); - } - } - } + #[glib::derived_properties] + impl ObjectImpl for AccountSwitcherButton {} impl WidgetImpl for AccountSwitcherButton {} impl ButtonImpl for AccountSwitcherButton {} impl ToggleButtonImpl for AccountSwitcherButton {} -} -glib::wrapper! { - /// A button showing the currently selected account and opening the account switcher popover. - pub struct AccountSwitcherButton(ObjectSubclass) - @extends gtk::Widget, gtk::Button, gtk::ToggleButton, @implements gtk::Accessible; -} + #[gtk::template_callbacks] + impl AccountSwitcherButton { + /// Set the popover of this button. + fn set_popover(&self, popover: Option<&AccountSwitcherPopover>) { + let old_popover = self.popover.obj(); -#[gtk::template_callbacks] -impl AccountSwitcherButton { - pub fn new() -> Self { - glib::Object::new() - } - - pub fn popover(&self) -> Option { - self.imp().popover.obj() - } + if old_popover.as_ref() == popover { + return; + } + let obj = self.obj(); - pub fn set_popover(&self, popover: Option<&AccountSwitcherPopover>) { - let old_popover = self.popover(); + // Reset the state. + if let Some(popover) = old_popover { + popover.unparent(); + } + self.popover.disconnect_signals(); + obj.set_active(false); + + if let Some(popover) = popover { + // We need to remove the popover from the previous button, if any. + if let Some(parent) = popover + .parent() + .and_downcast::() + { + parent.set_popover(None::); + } - if old_popover.as_ref() == popover { - return; - } + let closed_handler = popover.connect_closed(clone!( + #[weak] + obj, + move |_| { + obj.set_active(false); + } + )); - let imp = self.imp(); + popover.set_parent(&*obj); + self.popover.set(popover, vec![closed_handler]); + } - // Reset the state. - if let Some(popover) = old_popover { - popover.unparent(); + obj.notify_popover(); } - imp.popover.disconnect_signals(); - self.set_active(false); - if let Some(popover) = popover { - // We need to remove the popover from the previous button, if any. - if let Some(parent) = popover.parent().and_downcast::() { - parent.set_popover(None); - } + /// Toggle the popover of this button. + #[template_callback] + fn toggle_popover(&self) { + let obj = self.obj(); - let closed_handler = popover.connect_closed(clone!( - #[weak(rename_to = obj)] - self, - move |_| { - obj.set_active(false); - } - )); + if obj.is_active() { + let Some(window) = obj.root().and_downcast::() else { + return; + }; + + let popover = window.account_switcher(); + self.set_popover(Some(popover)); - popover.set_parent(self); - imp.popover.set(popover, vec![closed_handler]); + popover.popup(); + } else if let Some(popover) = self.popover.obj() { + popover.popdown(); + } } } +} - fn handle_toggled(&self) { - if self.is_active() { - let Some(window) = self.root().and_downcast::() else { - return; - }; - - let popover = window.account_switcher(); - self.set_popover(Some(popover)); +glib::wrapper! { + /// A button showing the currently selected session and opening the account switcher popover. + pub struct AccountSwitcherButton(ObjectSubclass) + @extends gtk::Widget, gtk::Button, gtk::ToggleButton, @implements gtk::Accessible; +} - popover.popup(); - } else if let Some(popover) = self.popover() { - popover.popdown(); - } +#[gtk::template_callbacks] +impl AccountSwitcherButton { + pub fn new() -> Self { + glib::Object::new() } } diff --git a/src/account_switcher/account_switcher_button.ui b/src/account_switcher/account_switcher_button.ui index 073f17a8..a9921ad3 100644 --- a/src/account_switcher/account_switcher_button.ui +++ b/src/account_switcher/account_switcher_button.ui @@ -1,6 +1,18 @@