From be33f000e2cfda239637db52d645bffa93aef804 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 18 Nov 2023 00:27:40 -0700 Subject: [PATCH] WIP: Lots of errors, starting on resurrecting derive Element --- crates/gpui2/src/element.rs | 2 +- crates/gpui2_macros/src/derive_element.rs | 75 +++++++++++++++++++++++ crates/gpui2_macros/src/gpui2_macros.rs | 18 +++--- crates/ui2/src/components/avatar.rs | 5 +- crates/ui2/src/components/toast.rs | 60 +++++++++--------- 5 files changed, 118 insertions(+), 42 deletions(-) create mode 100644 crates/gpui2_macros/src/derive_element.rs diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index 5220892885b780274a56b6102ee547841a4b9b41..f296e9214cde59179c62dde5b3669291cfded3be 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -364,7 +364,7 @@ impl Element for AnyElement { fn paint( self, - bounds: Bounds, + _bounds: Bounds, view_state: &mut V, _: &mut Self::State, cx: &mut ViewContext, diff --git a/crates/gpui2_macros/src/derive_element.rs b/crates/gpui2_macros/src/derive_element.rs new file mode 100644 index 0000000000000000000000000000000000000000..e8c698c1fe00e74f3d399b7d819065e04f781fe4 --- /dev/null +++ b/crates/gpui2_macros/src/derive_element.rs @@ -0,0 +1,75 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, DeriveInput, GenericParam}; + +pub fn derive_element(input: TokenStream) -> TokenStream { + let ast = parse_macro_input!(input as DeriveInput); + let type_name = ast.ident; + + let mut view_state_ty = quote! { V }; + + for param in &ast.generics.params { + if let GenericParam::Type(type_param) = param { + let type_ident = &type_param.ident; + view_state_ty = quote! {#type_ident}; + break; + } + } + + let attrs = &ast.attrs; + for attr in attrs { + if attr.path.is_ident("element") { + match attr.parse_meta() { + Ok(syn::Meta::List(i)) => { + for nested_meta in i.nested { + if let syn::NestedMeta::Meta(syn::Meta::NameValue(nv)) = nested_meta { + if nv.path.is_ident("view_state") { + if let syn::Lit::Str(lit_str) = nv.lit { + view_state_ty = lit_str.value().parse().unwrap(); + } + } + } + } + } + _ => (), + } + } + } + + let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); + + let gen = quote! { + impl #impl_generics gpui::Element<#view_state_ty> for #type_name #ty_generics + #where_clause + { + type State = Option>; + + fn element_id(&self) -> Option { + None + } + + fn layout( + &mut self, + view_state: &mut #view_state_ty, + _element_state: Option, + cx: &mut gpui::ViewContext<#view_state_ty>, + ) -> (gpui::LayoutId, Self::State) { + let mut element = self.render(view_state, cx).into_any(); + let layout_id = element.layout(view_state, cx); + (layout_id, Some(element)) + } + + fn paint( + self, + _bounds: gpui::Bounds, + view_state: &mut #view_state_ty, + rendered_element: &mut Self::State, + cx: &mut gpui::ViewContext<#view_state_ty>, + ) { + rendered_element.take().unwrap().paint(view_state, cx) + } + } + }; + + gen.into() +} diff --git a/crates/gpui2_macros/src/gpui2_macros.rs b/crates/gpui2_macros/src/gpui2_macros.rs index 02c9629d01ea60f500639f98ccfe5d7c2dd8b223..a611727066aaa5ff1b5d4223ebef717e0edb6923 100644 --- a/crates/gpui2_macros/src/gpui2_macros.rs +++ b/crates/gpui2_macros/src/gpui2_macros.rs @@ -7,11 +7,6 @@ mod test; use proc_macro::TokenStream; -#[proc_macro] -pub fn style_helpers(args: TokenStream) -> TokenStream { - style_helpers::style_helpers(args) -} - #[proc_macro_derive(Action)] pub fn action(input: TokenStream) -> TokenStream { action::action(input) @@ -27,10 +22,15 @@ pub fn derive_component(input: TokenStream) -> TokenStream { derive_component::derive_component(input) } -// #[proc_macro_derive(Element)] -// pub fn derive_element(input: TokenStream) -> TokenStream { -// derive_element::derive_element(input) -// } +#[proc_macro_derive(Element, attributes(element))] +pub fn derive_element(input: TokenStream) -> TokenStream { + derive_element::derive_element(input) +} + +#[proc_macro] +pub fn style_helpers(input: TokenStream) -> TokenStream { + style_helpers::style_helpers(input) +} #[proc_macro_attribute] pub fn test(args: TokenStream, function: TokenStream) -> TokenStream { diff --git a/crates/ui2/src/components/avatar.rs b/crates/ui2/src/components/avatar.rs index 5ab00b33edf36e3d3b6513bbf2c32b07fc89459c..95e0653d36d409c82b6c06834704709bf1d6b12b 100644 --- a/crates/ui2/src/components/avatar.rs +++ b/crates/ui2/src/components/avatar.rs @@ -1,8 +1,7 @@ -use gpui::img; - use crate::prelude::*; +use gpui::img; -#[derive(Component)] +#[derive(Element)] pub struct Avatar { src: SharedString, shape: Shape, diff --git a/crates/ui2/src/components/toast.rs b/crates/ui2/src/components/toast.rs index 08e850d2a2b56a24e41400d3bc81d0041e7f8bc1..a40f3cace47d5151d261e475586702fa0199c407 100644 --- a/crates/ui2/src/components/toast.rs +++ b/crates/ui2/src/components/toast.rs @@ -1,4 +1,5 @@ use crate::prelude::*; +use gpui::Element; use gpui::{prelude::*, AnyElement}; use smallvec::SmallVec; @@ -21,40 +22,41 @@ pub enum ToastOrigin { /// they are actively showing the a process in progress. /// /// Only one toast may be visible at a time. +#[derive(Element)] pub struct Toast { origin: ToastOrigin, children: SmallVec<[AnyElement; 2]>, } -impl Element for Toast { - type State = Option>; - - fn element_id(&self) -> Option { - None - } - - fn layout( - &mut self, - view_state: &mut V, - _element_state: Option, - cx: &mut ViewContext, - ) -> (gpui::LayoutId, Self::State) { - let mut element = self.render(view_state, cx).into_any(); - let layout_id = element.layout(view_state, cx); - (layout_id, Some(element)) - } - - fn paint( - self, - bounds: gpui::Bounds, - view_state: &mut V, - element: &mut Self::State, - cx: &mut ViewContext, - ) { - let element = element.take().unwrap(); - element.paint(view_state, cx); - } -} +// impl Element for Toast { +// type State = Option>; + +// fn element_id(&self) -> Option { +// None +// } + +// fn layout( +// &mut self, +// view_state: &mut V, +// _element_state: Option, +// cx: &mut ViewContext, +// ) -> (gpui::LayoutId, Self::State) { +// let mut element = self.render(view_state, cx).into_any(); +// let layout_id = element.layout(view_state, cx); +// (layout_id, Some(element)) +// } + +// fn paint( +// self, +// bounds: gpui::Bounds, +// view_state: &mut V, +// element: &mut Self::State, +// cx: &mut ViewContext, +// ) { +// let element = element.take().unwrap(); +// element.paint(view_state, cx); +// } +// } impl Toast { pub fn new(origin: ToastOrigin) -> Self {