From 15ba043050bb872e857a266b675a20eaf7f058e9 Mon Sep 17 00:00:00 2001 From: Elias Projahn Date: Mon, 27 May 2024 12:39:29 +0200 Subject: [PATCH] Add MusicusActivatableRow --- src/editor/activatable_row.rs | 96 +++++++++++++++++++++++++++++++++++ src/editor/mod.rs | 1 + 2 files changed, 97 insertions(+) create mode 100644 src/editor/activatable_row.rs diff --git a/src/editor/activatable_row.rs b/src/editor/activatable_row.rs new file mode 100644 index 0000000..e8066ee --- /dev/null +++ b/src/editor/activatable_row.rs @@ -0,0 +1,96 @@ +use gtk::{ + glib::{self, clone, subclass::Signal}, + prelude::*, + subclass::prelude::*, +}; +use once_cell::sync::Lazy; + +use std::cell::RefCell; + +mod imp { + use super::*; + + #[derive(Default)] + pub struct MusicusActivatableRow { + pub previous_parent: RefCell>, + pub previous_signal_handler_id: RefCell>, + } + + #[glib::object_subclass] + impl ObjectSubclass for MusicusActivatableRow { + const NAME: &'static str = "MusicusActivatableRow"; + type Type = super::MusicusActivatableRow; + type ParentType = gtk::ListBoxRow; + } + + impl ObjectImpl for MusicusActivatableRow { + fn constructed(&self) { + self.parent_constructed(); + + let obj = self.obj(); + obj.connect_parent_notify(clone!(@weak obj => move |_: &super::MusicusActivatableRow| { + let previous_parent = obj.imp().previous_parent.borrow_mut().take(); + let previous_signal_handler_id = obj.imp().previous_signal_handler_id.borrow_mut().take(); + if let (Some(previous_parent), Some(previous_signal_handler_id)) = (previous_parent, previous_signal_handler_id) { + previous_parent.disconnect(previous_signal_handler_id); + } + + if let Some(parent) = obj.parent().and_downcast::() { + let signal_handler_id = parent.connect_row_activated(clone!(@weak obj => move |_: >k::ListBox, row: >k::ListBoxRow| { + if *row == obj { + obj.activate(); + } + })); + + obj.imp().previous_parent.replace(Some(parent)); + obj.imp().previous_signal_handler_id.replace(Some(signal_handler_id)); + } + })); + } + + fn signals() -> &'static [Signal] { + static SIGNALS: Lazy> = + Lazy::new(|| vec![Signal::builder("activated").build()]); + + SIGNALS.as_ref() + } + } + + impl WidgetImpl for MusicusActivatableRow {} + + impl ListBoxRowImpl for MusicusActivatableRow { + fn activate(&self) { + self.obj().emit_by_name::<()>("activated", &[]); + } + } +} + +glib::wrapper! { + /// A simple helper widget for connecting a signal handler to a single [`gtk::ListBoxRow`] for + /// handling activation. + pub struct MusicusActivatableRow(ObjectSubclass) + @extends gtk::Widget, gtk::ListBoxRow; +} + +impl MusicusActivatableRow { + pub fn new(child: &W) -> Self + where + W: IsA, + { + let obj: Self = glib::Object::builder() + .property("activatable", true) + .property("selectable", false) + .build(); + + obj.set_child(Some(child)); + obj + } + + pub fn connect_activated(&self, f: F) -> glib::SignalHandlerId { + self.connect_local("activated", true, move |values| { + let obj = values[0].get::().unwrap(); + f(&obj); + None + }) + } +} diff --git a/src/editor/mod.rs b/src/editor/mod.rs index 92cb362..0f41d6b 100644 --- a/src/editor/mod.rs +++ b/src/editor/mod.rs @@ -1,3 +1,4 @@ +pub mod activatable_row; pub mod person_editor; pub mod translation_entry; pub mod translation_section; \ No newline at end of file