From 317acbf1d72ad94e835b105e4aea1ce96f5dd8e6 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 24 Oct 2023 14:55:23 +0200 Subject: [PATCH] WIP: Trampoline --- crates/gpui2/src/elements.rs | 2 + crates/gpui2/src/elements/trampoline.rs | 65 +++++++++++++++++++ .../src/derive_into_any_element.rs | 64 +++++++++++++++++- crates/ui2/src/components/assistant_panel.rs | 10 +-- 4 files changed, 132 insertions(+), 9 deletions(-) create mode 100644 crates/gpui2/src/elements/trampoline.rs diff --git a/crates/gpui2/src/elements.rs b/crates/gpui2/src/elements.rs index 83c27b8a3b..a1a54a2c87 100644 --- a/crates/gpui2/src/elements.rs +++ b/crates/gpui2/src/elements.rs @@ -2,8 +2,10 @@ mod div; mod img; mod svg; mod text; +mod trampoline; pub use div::*; pub use img::*; pub use svg::*; pub use text::*; +pub use trampoline::*; diff --git a/crates/gpui2/src/elements/trampoline.rs b/crates/gpui2/src/elements/trampoline.rs new file mode 100644 index 0000000000..5946e5eb7b --- /dev/null +++ b/crates/gpui2/src/elements/trampoline.rs @@ -0,0 +1,65 @@ +use crate::{Element, ViewContext, AnyElement, IntoAnyElement}; + +pub trait TemporaryRenderTraitDontWorryAboutIt { + fn render(self, cx: &mut ViewContext) -> AnyElement; +} + + +struct IntoAnyElementTrampolineName> { + contents: Option, + phantom: std::marker::PhantomData, +} + +impl> IntoAnyElementTrampolineName { + fn new(contents: E) -> Self { + IntoAnyElementTrampolineName { + contents: Some(contents), + phantom: std::marker::PhantomData, + + } + } +} + +impl> Element for IntoAnyElementTrampolineName { + type ViewState = S; + + type ElementState = AnyElement; + + fn id(&self) -> Option { + None + } + + fn initialize( + &mut self, + view_state: &mut Self::ViewState, + element_state: Option, + cx: &mut ViewContext, + ) -> Self::ElementState { + self.contents.take().unwrap().render(cx) + } + + fn layout( + &mut self, + view_state: &mut Self::ViewState, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ) -> crate::LayoutId { + element_state.layout(view_state, cx) + } + + fn paint( + &mut self, + bounds: crate::Bounds, + view_state: &mut Self::ViewState, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ) { + element_state.paint(view_state, cx); + } +} + +impl> IntoAnyElement for IntoAnyElementTrampolineName { + fn into_any(self) -> AnyElement { + AnyElement::new(self) + } +} diff --git a/crates/gpui2_macros/src/derive_into_any_element.rs b/crates/gpui2_macros/src/derive_into_any_element.rs index 4c6d9e3d7f..7f0c9ae2c0 100644 --- a/crates/gpui2_macros/src/derive_into_any_element.rs +++ b/crates/gpui2_macros/src/derive_into_any_element.rs @@ -11,7 +11,7 @@ // Defining a derive macro use proc_macro::TokenStream; -use quote::quote; +use quote::{quote, format_ident}; use syn::{parse_macro_input, DeriveInput}; pub fn derive_into_any_element(input: TokenStream) -> TokenStream { @@ -57,12 +57,72 @@ pub fn derive_into_any_element(input: TokenStream) -> TokenStream { let (_, ty_generics, _) = generics.split_for_impl(); let (impl_generics, _, where_clause) = trait_generics.split_for_impl(); + let trampoline_name = format_ident!("{}{}", name, "Trampoline"); + quote! { + struct #trampoline_name { + contents: Option, + phantom: std::marker::PhantomData, + } + + impl #trampoline_name { + fn new(contents: E) -> Self { + IntoAnyElementTrampolineName { + contents: Some(contents), + phantom: std::marker::PhantomData, + } + } + } + + impl Element for #trampoline_name { + type ViewState = S; + + type ElementState = AnyElement; + + fn id(&self) -> Option { + None + } + + fn initialize( + &mut self, + view_state: &mut Self::ViewState, + element_state: Option, + cx: &mut ViewContext, + ) -> Self::ElementState { + self.contents.take().unwrap().render(cx) + } + + fn layout( + &mut self, + view_state: &mut Self::ViewState, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ) -> crate::LayoutId { + element_state.layout(view_state, cx) + } + + fn paint( + &mut self, + bounds: crate::Bounds, + view_state: &mut Self::ViewState, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ) { + element_state.paint(view_state, cx); + } + } + + impl IntoAnyElement for IntoAnyElementTrampolineName { + fn into_any(self) -> AnyElement { + AnyElement::new(self) + } + } + impl #impl_generics gpui2::IntoAnyElement for #name #ty_generics #where_clause { fn into_any(self) -> gpui2::AnyElement { - Self::render(self).into_any() + #trampoline_name(self).into_any() } } } diff --git a/crates/ui2/src/components/assistant_panel.rs b/crates/ui2/src/components/assistant_panel.rs index 0f7aa8d75a..50046735d4 100644 --- a/crates/ui2/src/components/assistant_panel.rs +++ b/crates/ui2/src/components/assistant_panel.rs @@ -86,14 +86,10 @@ mod stories { use super::*; #[derive(IntoAnyElement)] - pub struct AssistantPanelStory<'a>(&'a AppContext); + pub struct AssistantPanelStory; - impl<'a> AssistantPanelStory<'a> { - pub fn new() -> Self { - Self - } - - fn render(self) -> impl IntoAnyElement { + impl AssistantPanelStory { + fn render(self, cx: &mut ViewContext) -> impl IntoAnyElement { Story::container(self.0) .child(Story::title_for::<_, AssistantPanel>(self.0)) .child(Story::label(self.cx, "Default"))