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}