Skip to main content

CompositeTemplate

Derive Macro CompositeTemplate 

Source
#[derive(CompositeTemplate)]
{
    // Attributes available to this derive:
    #[template]
    #[template_child]
}
Expand description

Derive macro for using a composite template in a widget.

The template attribute specifies where the template should be loaded from; it can be a file, a resource, or a string.

The template_child attribute is used to mark all internal widgets we need to have programmatic access to. It can take two parameters:

  • id which defaults to the item name if not defined
  • internal whether the child should be accessible as an “internal-child”, defaults to false

§Example

Specify that MyWidget is using a composite template and load the template file the composite_template.ui file.

Then, in the ObjectSubclass implementation you will need to call bind_template in the class_init function, and init_template in instance_init function.

use gtk::{glib, prelude::*, subclass::prelude::*};

mod imp {
    use super::*;

    #[derive(Debug, Default, gtk::CompositeTemplate)]
    #[template(file = "test/template.ui")]
    pub struct MyWidget {
        #[template_child]
        pub label: TemplateChild<gtk::Label>,
        #[template_child(id = "my_button_id")]
        pub button: TemplateChild<gtk::Button>,
    }

    #[glib::object_subclass]
    impl ObjectSubclass for MyWidget {
        const NAME: &'static str = "MyWidget";
        type Type = super::MyWidget;
        type ParentType = gtk::Box;

        fn class_init(klass: &mut Self::Class) {
            klass.bind_template();
        }

        fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
            obj.init_template();
        }
    }

    impl ObjectImpl for MyWidget {}
    impl WidgetImpl for MyWidget {}
    impl BoxImpl for MyWidget {}
}

glib::wrapper! {
    pub struct MyWidget(ObjectSubclass<imp::MyWidget>)
    @extends gtk::Widget, gtk::Box,
    @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget;
}

impl MyWidget {
    pub fn new() -> Self {
        glib::Object::new()
    }
}

The CompositeTemplate macro can also be used with Blueprint if the feature blueprint is enabled. you can use string or file relative to the project directory but not resource

ⓘ
use gtk::{glib, prelude::*, subclass::prelude::*};

mod imp {
    use super::*;

    #[derive(Debug, Default, gtk::CompositeTemplate)]
    #[template(string = "
    using Gtk 4.0;
    template $MyWidget : Widget {
        Label label {
            label: 'foobar';
        }

        Label my_label2 {
            label: 'foobaz';
        }
    }
    ")]
    pub struct MyWidget {
        #[template_child]
        pub label: TemplateChild<gtk::Label>,
        #[template_child(id = "my_label2")]
        pub label2: gtk::TemplateChild<gtk::Label>,
    }

    #[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<Self>) {
            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<imp::MyWidget>)
    @extends gtk::Widget,
    @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget;
}