@@ -41,13 +41,7 @@ use collections::HashMap;
use core::panic;
use json::ToJson;
use smallvec::SmallVec;
-use std::{
- any::Any,
- borrow::Cow,
- marker::PhantomData,
- mem,
- ops::{Deref, DerefMut, Range},
-};
+use std::{any::Any, borrow::Cow, mem, ops::Range};
pub trait Element<V: View>: 'static {
type LayoutState;
@@ -567,90 +561,6 @@ impl<V: View> RootElement<V> {
}
}
-pub trait Component<V: View>: 'static {
- fn render(&self, view: &mut V, cx: &mut ViewContext<V>) -> AnyElement<V>;
-}
-
-pub struct ComponentHost<V: View, C: Component<V>> {
- component: C,
- view_type: PhantomData<V>,
-}
-
-impl<V: View, C: Component<V>> ComponentHost<V, C> {
- pub fn new(c: C) -> Self {
- Self {
- component: c,
- view_type: PhantomData,
- }
- }
-}
-
-impl<V: View, C: Component<V>> Deref for ComponentHost<V, C> {
- type Target = C;
-
- fn deref(&self) -> &Self::Target {
- &self.component
- }
-}
-
-impl<V: View, C: Component<V>> DerefMut for ComponentHost<V, C> {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.component
- }
-}
-
-impl<V: View, C: Component<V>> Element<V> for ComponentHost<V, C> {
- type LayoutState = AnyElement<V>;
- type PaintState = ();
-
- fn layout(
- &mut self,
- constraint: SizeConstraint,
- view: &mut V,
- cx: &mut LayoutContext<V>,
- ) -> (Vector2F, AnyElement<V>) {
- let mut element = self.component.render(view, cx);
- let size = element.layout(constraint, view, cx);
- (size, element)
- }
-
- fn paint(
- &mut self,
- scene: &mut SceneBuilder,
- bounds: RectF,
- visible_bounds: RectF,
- element: &mut AnyElement<V>,
- view: &mut V,
- cx: &mut ViewContext<V>,
- ) {
- element.paint(scene, bounds.origin(), visible_bounds, view, cx);
- }
-
- fn rect_for_text_range(
- &self,
- range_utf16: Range<usize>,
- _: RectF,
- _: RectF,
- element: &AnyElement<V>,
- _: &(),
- view: &V,
- cx: &ViewContext<V>,
- ) -> Option<RectF> {
- element.rect_for_text_range(range_utf16, view, cx)
- }
-
- fn debug(
- &self,
- _: RectF,
- element: &AnyElement<V>,
- _: &(),
- view: &V,
- cx: &ViewContext<V>,
- ) -> serde_json::Value {
- element.debug(view, cx)
- }
-}
-
pub trait AnyRootElement {
fn layout(
&mut self,
@@ -3,8 +3,8 @@ use proc_macro2::Ident;
use quote::{format_ident, quote};
use std::mem;
use syn::{
- parse_macro_input, parse_quote, spanned::Spanned as _, AttributeArgs, FnArg, ItemFn, Lit, Meta,
- NestedMeta, Type,
+ parse_macro_input, parse_quote, spanned::Spanned as _, AttributeArgs, DeriveInput, FnArg,
+ ItemFn, Lit, Meta, NestedMeta, Type,
};
#[proc_macro_attribute]
@@ -275,3 +275,68 @@ fn parse_bool(literal: &Lit) -> Result<bool, TokenStream> {
result.map_err(|err| TokenStream::from(err.into_compile_error()))
}
+
+#[proc_macro_derive(Element)]
+pub fn element_derive(input: TokenStream) -> TokenStream {
+ // Parse the input tokens into a syntax tree
+ let input = parse_macro_input!(input as DeriveInput);
+
+ // The name of the struct/enum
+ let name = input.ident;
+
+ let expanded = quote! {
+ impl<V: gpui::View> gpui::elements::Element<V> for #name {
+ type LayoutState = gpui::elements::AnyElement<V>;
+ type PaintState = ();
+
+ fn layout(
+ &mut self,
+ constraint: gpui::SizeConstraint,
+ view: &mut V,
+ cx: &mut gpui::LayoutContext<V>,
+ ) -> (gpui::geometry::vector::Vector2F, gpui::elements::AnyElement<V>) {
+ let mut element = self.render(view, cx);
+ let size = element.layout(constraint, view, cx);
+ (size, element)
+ }
+
+ fn paint(
+ &mut self,
+ scene: &mut gpui::SceneBuilder,
+ bounds: gpui::geometry::rect::RectF,
+ visible_bounds: gpui::geometry::rect::RectF,
+ element: &mut gpui::elements::AnyElement<V>,
+ view: &mut V,
+ cx: &mut gpui::ViewContext<V>,
+ ) {
+ element.paint(scene, bounds.origin(), visible_bounds, view, cx);
+ }
+
+ fn rect_for_text_range(
+ &self,
+ range_utf16: std::ops::Range<usize>,
+ _: gpui::geometry::rect::RectF,
+ _: gpui::geometry::rect::RectF,
+ element: &gpui::elements::AnyElement<V>,
+ _: &(),
+ view: &V,
+ cx: &gpui::ViewContext<V>,
+ ) -> Option<gpui::geometry::rect::RectF> {
+ element.rect_for_text_range(range_utf16, view, cx)
+ }
+
+ fn debug(
+ &self,
+ _: gpui::geometry::rect::RectF,
+ element: &gpui::elements::AnyElement<V>,
+ _: &(),
+ view: &V,
+ cx: &gpui::ViewContext<V>,
+ ) -> serde_json::Value {
+ element.debug(view, cx)
+ }
+ }
+ };
+ // Return generated code
+ TokenStream::from(expanded)
+}