@@ -1,9 +1,10 @@
use crate::{
- element::{AnyElement, Element, ElementMetadata},
+ element::{Element, ElementMetadata},
frame,
themes::rose_pine,
};
use gpui::ViewContext;
+use playground_macros::Element;
use std::{borrow::Cow, marker::PhantomData, rc::Rc};
struct ButtonHandlers<V, D> {
@@ -16,6 +17,8 @@ impl<V, D> Default for ButtonHandlers<V, D> {
}
}
+#[derive(Element)]
+#[element_crate = "crate"]
pub struct Button<V: 'static, D: 'static> {
metadata: ElementMetadata<V>,
handlers: ButtonHandlers<V, D>,
@@ -89,34 +92,34 @@ impl<V: 'static, D: 'static> Button<V, D> {
}
}
-impl<V: 'static, D> Element<V> for Button<V, D> {
- type Layout = AnyElement<V>;
-
- fn style_mut(&mut self) -> &mut crate::style::ElementStyle {
- &mut self.metadata.style
- }
-
- fn handlers_mut(&mut self) -> &mut crate::element::ElementHandlers<V> {
- &mut self.metadata.handlers
- }
-
- fn layout(
- &mut self,
- view: &mut V,
- cx: &mut crate::element::LayoutContext<V>,
- ) -> anyhow::Result<(taffy::tree::NodeId, Self::Layout)> {
- let mut element = self.render(view, cx).into_any();
- let node_id = element.layout(view, cx)?;
- Ok((node_id, element))
- }
-
- fn paint<'a>(
- &mut self,
- layout: crate::element::Layout<'a, Self::Layout>,
- view: &mut V,
- cx: &mut crate::element::PaintContext<V>,
- ) -> anyhow::Result<()> {
- layout.from_element.paint(view, cx)?;
- Ok(())
- }
-}
+// impl<V: 'static, D> Element<V> for Button<V, D> {
+// type Layout = AnyElement<V>;
+
+// fn style_mut(&mut self) -> &mut crate::style::ElementStyle {
+// &mut self.metadata.style
+// }
+
+// fn handlers_mut(&mut self) -> &mut crate::element::ElementHandlers<V> {
+// &mut self.metadata.handlers
+// }
+
+// fn layout(
+// &mut self,
+// view: &mut V,
+// cx: &mut crate::element::LayoutContext<V>,
+// ) -> anyhow::Result<(taffy::tree::NodeId, Self::Layout)> {
+// let mut element = self.render(view, cx).into_any();
+// let node_id = element.layout(view, cx)?;
+// Ok((node_id, element))
+// }
+
+// fn paint<'a>(
+// &mut self,
+// layout: crate::element::Layout<'a, Self::Layout>,
+// view: &mut V,
+// cx: &mut crate::element::PaintContext<V>,
+// ) -> anyhow::Result<()> {
+// layout.from_element.paint(view, cx)?;
+// Ok(())
+// }
+// }
@@ -1,48 +1,102 @@
-// type Result = ();
-// type LayoutContext<> = ();
-
-// trait Element<V: 'static>: 'static + Clone {
-// type Layout: 'static;
-
-// fn style_mut(&mut self) -> &mut Style;
-// fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>)
-// -> Result<(NodeId, Self::Layout)>;
-// fn paint<'a>(
-// &mut self,
-// layout: Layout<'a, Self::Layout>,
-// view: &mut V,
-// cx: &mut PaintContext<V>,
-// ) -> Result<()>;
-// }
-
-// struct Button {
-// style: Style,
-// }
-
-// type Style = ();
-
-// impl Button {
-// fn render<V>() -> impl Element<V> {
-// todo!()
-// }
-// }
-
-// impl<V: 'static> Element<V> for Foo {
-// type Layout = ();
-
-// fn style_mut(&mut self) -> &mut Style {
-// unimplemented!()
-// }
-
-// fn layout(
-// &mut self,
-// view: &mut V,
-// cx: &mut LayoutContext<V>,
-// ) -> Result<(NodeId, Self::Layout)> {
-// unimplemented!()
-// }
-
-// fn paint(&mut self, layout: Layout<()>, view: &mut V, cx: &mut PaintContext<V>) -> Result<()> {
-// unimplemented!()
-// }
-// }
+use proc_macro::TokenStream;
+use quote::{format_ident, quote};
+use syn::{
+ parse_macro_input, parse_quote, DeriveInput, GenericParam, Generics, Ident, Lit, Meta,
+ WhereClause,
+};
+
+pub fn derive_element(input: TokenStream) -> TokenStream {
+ let ast = parse_macro_input!(input as DeriveInput);
+ let type_name = ast.ident;
+
+ let crate_name: String = ast
+ .attrs
+ .iter()
+ .find_map(|attr| {
+ if attr.path.is_ident("element_crate") {
+ match attr.parse_meta() {
+ Ok(Meta::NameValue(nv)) => {
+ if let Lit::Str(s) = nv.lit {
+ Some(s.value())
+ } else {
+ None
+ }
+ }
+ _ => None,
+ }
+ } else {
+ None
+ }
+ })
+ .unwrap_or_else(|| String::from("playground"));
+
+ let crate_name = format_ident!("{}", crate_name);
+
+ let placeholder_view_generics: Generics = parse_quote! { <V: 'static> };
+ let placeholder_view_type_name: Ident = parse_quote! { V };
+ let view_type_name: Ident;
+ let impl_generics: syn::ImplGenerics<'_>;
+ let type_generics: Option<syn::TypeGenerics<'_>>;
+ let where_clause: Option<&'_ WhereClause>;
+
+ match ast.generics.params.iter().find_map(|param| {
+ if let GenericParam::Type(type_param) = param {
+ Some(type_param.ident.clone())
+ } else {
+ None
+ }
+ }) {
+ Some(type_name) => {
+ view_type_name = type_name;
+ let generics = ast.generics.split_for_impl();
+ impl_generics = generics.0;
+ type_generics = Some(generics.1);
+ where_clause = generics.2;
+ }
+ _ => {
+ view_type_name = placeholder_view_type_name;
+ let generics = placeholder_view_generics.split_for_impl();
+ impl_generics = generics.0;
+ type_generics = None;
+ where_clause = generics.2;
+ }
+ }
+
+ let gen = quote! {
+ impl #impl_generics #crate_name::element::Element<#view_type_name> for #type_name #type_generics
+ #where_clause
+ {
+ type Layout = #crate_name::element::AnyElement<V>;
+
+ fn style_mut(&mut self) -> &mut #crate_name::style::ElementStyle {
+ &mut self.metadata.style
+ }
+
+ fn handlers_mut(&mut self) -> &mut #crate_name::element::ElementHandlers<V> {
+ &mut self.metadata.handlers
+ }
+
+ fn layout(
+ &mut self,
+ view: &mut V,
+ cx: &mut #crate_name::element::LayoutContext<V>,
+ ) -> anyhow::Result<(taffy::tree::NodeId, Self::Layout)> {
+ let mut element = self.render(view, cx).into_any();
+ let node_id = element.layout(view, cx)?;
+ Ok((node_id, element))
+ }
+
+ fn paint<'a>(
+ &mut self,
+ layout: #crate_name::element::Layout<'a, Self::Layout>,
+ view: &mut V,
+ cx: &mut #crate_name::element::PaintContext<V>,
+ ) -> anyhow::Result<()> {
+ layout.from_element.paint(view, cx)?;
+ Ok(())
+ }
+ }
+ };
+
+ gen.into()
+}
@@ -7,3 +7,8 @@ mod tailwind_lengths;
pub fn tailwind_lengths(attr: TokenStream, item: TokenStream) -> TokenStream {
tailwind_lengths::tailwind_lengths(attr, item)
}
+
+#[proc_macro_derive(Element, attributes(element_crate))]
+pub fn derive_element(input: TokenStream) -> TokenStream {
+ derive_element::derive_element(input)
+}