#[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:
idwhich defaults to the item name if not definedinternalwhether the child should be accessible as an “internal-child”, defaults tofalse
§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 but not resource. The path given by file
is relative to the file by default but you can set it relative to the
project directory by writing it as an absolute path.
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;
}Alternatives to the definition above using file, depending on whether you
prefer to put the blueprint file next to the widget code, or put them all
together:
#[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "mywidget.blp")]
pub struct MyWidget {
#[template_child]
pub label: TemplateChild<gtk::Label>,
#[template_child(id = "my_label2")]
pub label2: gtk::TemplateChild<gtk::Label>,
}
#[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "/data/ui/mywidget.blp")]
pub struct MyWidget {
#[template_child]
pub label: TemplateChild<gtk::Label>,
#[template_child(id = "my_label2")]
pub label2: gtk::TemplateChild<gtk::Label>,
}