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}