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