// Take a look at the license at the top of the repository in the LICENSE file. use gtk::{glib, prelude::*, subclass::prelude::*}; mod imp { use super::*; #[derive(Debug, Default, gtk::CompositeTemplate)] #[template(string = r#" "#)] pub struct MyWidget { #[template_child] pub label: TemplateChild, #[template_child(id = "my_label2")] pub label2: gtk::TemplateChild, } #[glib::object_subclass] impl ObjectSubclass for MyWidget { const NAME: &'static str = "MyWidget"; type Type = super::MyWidget; type ParentType = gtk::Widget; fn class_init(klass: &mut Self::Class) { klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { obj.init_template(); } } impl ObjectImpl for MyWidget { fn dispose(&self) { while let Some(child) = self.obj().first_child() { child.unparent(); } } } impl WidgetImpl for MyWidget {} } glib::wrapper! { pub struct MyWidget(ObjectSubclass) @extends gtk::Widget; } #[gtk::test] fn template_string() { let widget: MyWidget = glib::Object::new(); assert_eq!(widget.imp().label.label(), "foobar"); assert_eq!(widget.imp().label2.label(), "foobaz"); } mod imp2 { use std::cell::RefCell; use futures_channel::mpsc; use super::*; #[derive(Debug, gtk::CompositeTemplate)] #[template(string = r#" "#)] pub struct MyWidget2 { #[template_child] button: TemplateChild, tx: RefCell>, rx: RefCell>>, } impl Default for MyWidget2 { fn default() -> Self { let (tx, rx) = mpsc::channel(1); Self { button: Default::default(), tx: RefCell::new(tx), rx: RefCell::new(Some(rx)), } } } #[glib::object_subclass] impl ObjectSubclass for MyWidget2 { const NAME: &'static str = "MyWidget2"; type Type = super::MyWidget2; type ParentType = gtk::Widget; fn class_init(klass: &mut Self::Class) { klass.bind_template(); klass.bind_template_callbacks(); } fn instance_init(obj: &glib::subclass::InitializingObject) { obj.init_template(); } } #[gtk::template_callbacks] impl MyWidget2 { #[template_callback] async fn on_clicked(&self, button: >k::Button) { glib::timeout_future_seconds(0).await; button.set_label("Clicked"); self.tx.borrow_mut().try_send(42).unwrap(); } } impl super::MyWidget2 { pub async fn click_button(&self) -> Option { use futures_util::StreamExt; let mut rx = self.imp().rx.take()?; self.imp().button.emit_clicked(); let v = rx.next().await?; self.imp().rx.replace(Some(rx)); Some(v) } } impl ObjectImpl for MyWidget2 { fn dispose(&self) { while let Some(child) = self.obj().first_child() { child.unparent(); } } } impl WidgetImpl for MyWidget2 {} } glib::wrapper! { pub struct MyWidget2(ObjectSubclass) @extends gtk::Widget; } #[gtk::test] async fn async_callbacks() { let widget: MyWidget2 = glib::Object::new(); assert_eq!(widget.click_button().await, Some(42)); } mod imp3 { use super::*; #[derive(Debug, Default)] struct TemplateChild(T); #[derive(Debug, Default, gtk::CompositeTemplate)] #[template( string = r#"