Skip to main content

gtk3_macros/
lib.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3mod attribute_parser;
4mod composite_template_derive;
5mod util;
6
7use proc_macro::TokenStream;
8use syn::{DeriveInput, parse_macro_input};
9
10/// Derive macro for using a composite template in a widget.
11///
12/// The `template` attribute specifies where the template should be loaded
13/// from;  it can be a `file`, a `resource`, or a `string`.
14///
15/// The `template_child` attribute is used to mark all internal widgets
16/// we need to have programmatic access to.
17///
18/// # Example
19///
20/// Specify that `MyWidget` is using a composite template and load the
21/// template file the `composite_template.ui` file.
22///
23/// Then, in the [`ObjectSubclass`] implementation you will need to call
24/// [`bind_template`] in the [`class_init`] function, and [`init_template`] in
25/// [`instance_init`] function.
26///
27/// [`ObjectSubclass`]: ../glib/subclass/types/trait.ObjectSubclass.html
28/// [`bind_template`]: ../gtk/subclass/widget/trait.CompositeTemplate.html#tymethod.bind_template
29/// [`class_init`]: ../glib/subclass/types/trait.ObjectSubclass.html#method.class_init
30/// [`init_template`]: ../gtk/prelude/trait.InitializingWidgetExt.html#tymethod.init_template
31/// [`instance_init`]: ../glib/subclass/types/trait.ObjectSubclass.html#method.instance_init
32///
33/// ```no_run
34/// use gtk::prelude::*;
35/// use gtk::glib;
36/// use gtk::subclass::prelude::*;
37///
38/// mod imp {
39///     use super::*;
40///
41///     #[derive(Debug, Default, gtk::CompositeTemplate)]
42///     #[template(file = "composite_template.ui")]
43///     pub struct MyWidget {
44///         #[template_child]
45///         pub label: TemplateChild<gtk::Label>,
46///         #[template_child(id = "my_button_id")]
47///         pub button: TemplateChild<gtk::Button>,
48///     }
49///
50///     #[glib::object_subclass]
51///     impl ObjectSubclass for MyWidget {
52///         const NAME: &'static str = "MyWidget";
53///         type Type = super::MyWidget;
54///         type ParentType = gtk::Box;
55///
56///         fn class_init(klass: &mut Self::Class) {
57///             Self::bind_template(klass);
58///         }
59///
60///         fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
61///             obj.init_template();
62///         }
63///     }
64///
65///     impl ObjectImpl for MyWidget {}
66///     impl WidgetImpl for MyWidget {}
67///     impl ContainerImpl for MyWidget {}
68///     impl BoxImpl for MyWidget {}
69/// }
70///
71/// glib::wrapper! {
72///     pub struct MyWidget(ObjectSubclass<imp::MyWidget>) @extends gtk::Widget, gtk::Container, gtk::Box;
73/// }
74///
75/// impl MyWidget {
76///     pub fn new() -> Self {
77///         glib::Object::new()
78///     }
79/// }
80/// # fn main() {}
81/// ```
82#[proc_macro_derive(CompositeTemplate, attributes(template, template_child))]
83pub fn composite_template_derive(input: TokenStream) -> TokenStream {
84    let input = parse_macro_input!(input as DeriveInput);
85    let generated = composite_template_derive::impl_composite_template(&input);
86    generated.into()
87}