Detailed changes
@@ -364,7 +364,7 @@ impl<V: 'static> Element<V> for AnyElement<V> {
fn paint(
self,
- bounds: Bounds<Pixels>,
+ _bounds: Bounds<Pixels>,
view_state: &mut V,
_: &mut Self::State,
cx: &mut ViewContext<V>,
@@ -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<gpui::AnyElement<#view_state_ty>>;
+
+ fn element_id(&self) -> Option<gpui::ElementId> {
+ None
+ }
+
+ fn layout(
+ &mut self,
+ view_state: &mut #view_state_ty,
+ _element_state: Option<Self::State>,
+ 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<gpui::Pixels>,
+ 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()
+}
@@ -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 {
@@ -1,8 +1,7 @@
-use gpui::img;
-
use crate::prelude::*;
+use gpui::img;
-#[derive(Component)]
+#[derive(Element)]
pub struct Avatar {
src: SharedString,
shape: Shape,
@@ -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<V: 'static> {
origin: ToastOrigin,
children: SmallVec<[AnyElement<V>; 2]>,
}
-impl<V: 'static> Element<V> for Toast<V> {
- type State = Option<AnyElement<V>>;
-
- fn element_id(&self) -> Option<ElementId> {
- None
- }
-
- fn layout(
- &mut self,
- view_state: &mut V,
- _element_state: Option<Self::State>,
- cx: &mut ViewContext<V>,
- ) -> (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<gpui::Pixels>,
- view_state: &mut V,
- element: &mut Self::State,
- cx: &mut ViewContext<V>,
- ) {
- let element = element.take().unwrap();
- element.paint(view_state, cx);
- }
-}
+// impl<V: 'static> Element<V> for Toast<V> {
+// type State = Option<AnyElement<V>>;
+
+// fn element_id(&self) -> Option<ElementId> {
+// None
+// }
+
+// fn layout(
+// &mut self,
+// view_state: &mut V,
+// _element_state: Option<Self::State>,
+// cx: &mut ViewContext<V>,
+// ) -> (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<gpui::Pixels>,
+// view_state: &mut V,
+// element: &mut Self::State,
+// cx: &mut ViewContext<V>,
+// ) {
+// let element = element.take().unwrap();
+// element.paint(view_state, cx);
+// }
+// }
impl<V: 'static> Toast<V> {
pub fn new(origin: ToastOrigin) -> Self {