From 315744ec20d8587219a7b052c2143d7495153e6b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 26 Oct 2023 12:20:46 +0200 Subject: [PATCH] Add derive macro for IntoAnyElement --- .../src/derive_into_any_element.rs | 54 +++++++++++++++++++ crates/gpui2_macros/src/gpui2_macros.rs | 6 +++ crates/ui2/src/components/panes.rs | 13 ++--- crates/ui2/src/components/status_bar.rs | 15 ++++-- 4 files changed, 79 insertions(+), 9 deletions(-) create mode 100644 crates/gpui2_macros/src/derive_into_any_element.rs diff --git a/crates/gpui2_macros/src/derive_into_any_element.rs b/crates/gpui2_macros/src/derive_into_any_element.rs new file mode 100644 index 0000000000..9f339f1b44 --- /dev/null +++ b/crates/gpui2_macros/src/derive_into_any_element.rs @@ -0,0 +1,54 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, DeriveInput}; + +pub fn derive_into_any_element(input: TokenStream) -> TokenStream { + let ast = parse_macro_input!(input as DeriveInput); + let name = &ast.ident; + let generics = &ast.generics; + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + let specified_view_type = ast + .attrs + .iter() + .find(|attr| attr.path.is_ident("element")) + .and_then(|attr| { + if let Ok(syn::Meta::List(meta_list)) = attr.parse_meta() { + meta_list.nested.iter().find_map(|nested| { + if let syn::NestedMeta::Meta(syn::Meta::NameValue(nv)) = nested { + if nv.path.is_ident("view_type") { + if let syn::Lit::Str(lit_str) = &nv.lit { + return Some( + lit_str + .parse::() + .expect("Failed to parse view_type"), + ); + } + } + } + None + }) + } else { + None + } + }); + + let view_type = specified_view_type.unwrap_or_else(|| { + if let Some(syn::GenericParam::Type(type_param)) = generics.params.first() { + type_param.ident.clone() + } else { + panic!("Expected first type parameter"); + } + }); + + let expanded = quote! { + impl #impl_generics gpui2::IntoAnyElement<#view_type> for #name #ty_generics #where_clause { + fn into_any(self) -> gpui2::AnyElement<#view_type> { + (move |view_state: &mut #view_type, cx: &mut gpui2::ViewContext<'_, '_, #view_type>| self.render(view_state, cx)) + .into_any() + } + } + }; + + TokenStream::from(expanded) +} diff --git a/crates/gpui2_macros/src/gpui2_macros.rs b/crates/gpui2_macros/src/gpui2_macros.rs index 59fd046c83..c4a3d5eeac 100644 --- a/crates/gpui2_macros/src/gpui2_macros.rs +++ b/crates/gpui2_macros/src/gpui2_macros.rs @@ -1,6 +1,7 @@ use proc_macro::TokenStream; mod derive_element; +mod derive_into_any_element; mod style_helpers; mod test; @@ -14,6 +15,11 @@ pub fn derive_element(input: TokenStream) -> TokenStream { derive_element::derive_element(input) } +#[proc_macro_derive(IntoAnyElement, attributes(element))] +pub fn derive_into_any_element(input: TokenStream) -> TokenStream { + derive_into_any_element::derive_into_any_element(input) +} + #[proc_macro_attribute] pub fn test(args: TokenStream, function: TokenStream) -> TokenStream { test::test(args, function) diff --git a/crates/ui2/src/components/panes.rs b/crates/ui2/src/components/panes.rs index f100723f91..bf135d85b6 100644 --- a/crates/ui2/src/components/panes.rs +++ b/crates/ui2/src/components/panes.rs @@ -12,6 +12,7 @@ pub enum SplitDirection { Vertical, } +#[derive(IntoAnyElement)] pub struct Pane { id: ElementId, size: Size, @@ -19,12 +20,12 @@ pub struct Pane { children: SmallVec<[AnyElement; 2]>, } -impl IntoAnyElement for Pane { - fn into_any(self) -> AnyElement { - (move |view_state: &mut V, cx: &mut ViewContext<'_, '_, V>| self.render(view_state, cx)) - .into_any() - } -} +// impl IntoAnyElement for Pane { +// fn into_any(self) -> AnyElement { +// (move |view_state: &mut V, cx: &mut ViewContext<'_, '_, V>| self.render(view_state, cx)) +// .into_any() +// } +// } impl Pane { pub fn new(id: impl Into, size: Size) -> Self { diff --git a/crates/ui2/src/components/status_bar.rs b/crates/ui2/src/components/status_bar.rs index 786b3670a0..2e4399539c 100644 --- a/crates/ui2/src/components/status_bar.rs +++ b/crates/ui2/src/components/status_bar.rs @@ -28,14 +28,23 @@ impl Default for ToolGroup { } } -#[derive(Element)] -#[element(view_state = "Workspace")] +#[derive(IntoAnyElement)] +#[element(view_type = "Workspace")] pub struct StatusBar { left_tools: Option, right_tools: Option, bottom_tools: Option, } +// impl IntoAnyElement for StatusBar { +// fn into_any(self) -> gpui2::AnyElement { +// (move |workspace: &mut Workspace, cx: &mut ViewContext<'_, '_, Workspace>| { +// self.render(workspace, cx) +// }) +// .into_any() +// } +// } + impl StatusBar { pub fn new() -> Self { Self { @@ -83,7 +92,7 @@ impl StatusBar { } fn render( - &mut self, + self, view: &mut Workspace, cx: &mut ViewContext, ) -> impl IntoAnyElement {