derive_element.rs

 1use proc_macro::TokenStream;
 2use quote::quote;
 3use syn::{parse_macro_input, DeriveInput, GenericParam};
 4
 5pub fn derive_element(input: TokenStream) -> TokenStream {
 6    let ast = parse_macro_input!(input as DeriveInput);
 7    let type_name = ast.ident;
 8
 9    let mut state_type = quote! { () };
10
11    for param in &ast.generics.params {
12        if let GenericParam::Type(type_param) = param {
13            let type_ident = &type_param.ident;
14            state_type = quote! {#type_ident};
15        }
16    }
17
18    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
19
20    let gen = quote! {
21        impl #impl_generics gpui3::Element for #type_name #ty_generics
22        #where_clause
23        {
24            type ViewState = #state_type;
25            type ElementState = gpui3::AnyElement<#state_type>;
26
27            fn element_id(&self) -> Option<gpui3::ElementId> {
28                None
29            }
30
31            fn layout(
32                &mut self,
33                state: &mut #state_type,
34                element_state: Option<Self::ElementState>,
35                cx: &mut gpui3::ViewContext<Self::ViewState>,
36            ) -> (gpui3::LayoutId, Self::ElementState) {
37                use gpui3::IntoAnyElement;
38
39                let mut rendered_element = self.render(cx).into_any();
40                let layout_id = rendered_element.layout(state, cx);
41                (layout_id, rendered_element)
42            }
43
44            fn paint(
45                &mut self,
46                bounds: gpui3::Bounds<gpui3::Pixels>,
47                state: &mut Self::ViewState,
48                element_state: &mut Self::ElementState,
49                cx: &mut gpui3::ViewContext<Self::ViewState>,
50            ) {
51                // TODO: Where do we get the `offset` from?
52                element_state.paint(state, None, cx)
53            }
54        }
55    };
56
57    gen.into()
58}