diff --git a/crates/gpui/src/elements/component.rs b/crates/gpui/src/elements/component.rs index c2158356e9ef9d8705dac599ccd93804f0f64c18..e2770c014859c902cc86fe1f04590f81595c94c5 100644 --- a/crates/gpui/src/elements/component.rs +++ b/crates/gpui/src/elements/component.rs @@ -105,22 +105,24 @@ impl Component for ElementAdapter { } // Component -> Element -pub struct ComponentAdapter { +pub struct ComponentAdapter { component: Option, + element: Option>, phantom: PhantomData, } -impl ComponentAdapter { +impl ComponentAdapter { pub fn new(e: E) -> Self { Self { component: Some(e), + element: None, phantom: PhantomData, } } } impl + 'static> Element for ComponentAdapter { - type LayoutState = AnyElement; + type LayoutState = (); type PaintState = (); @@ -130,10 +132,16 @@ impl + 'static> Element for ComponentAdapter { view: &mut V, cx: &mut LayoutContext, ) -> (Vector2F, Self::LayoutState) { - let component = self.component.take().unwrap(); - let mut element = component.render(view, cx.view_context()); - let constraint = element.layout(constraint, view, cx); - (constraint, element) + if self.element.is_none() { + let element = self + .component + .take() + .expect("Component can only be rendered once") + .render(view, cx.view_context()); + self.element = Some(element); + } + let constraint = self.element.as_mut().unwrap().layout(constraint, view, cx); + (constraint, ()) } fn paint( @@ -141,11 +149,14 @@ impl + 'static> Element for ComponentAdapter { scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, - layout: &mut Self::LayoutState, + _: &mut Self::LayoutState, view: &mut V, cx: &mut PaintContext, ) -> Self::PaintState { - layout.paint(scene, bounds.origin(), visible_bounds, view, cx) + self.element + .as_mut() + .expect("Layout should always be called before paint") + .paint(scene, bounds.origin(), visible_bounds, view, cx) } fn rect_for_text_range( @@ -153,25 +164,27 @@ impl + 'static> Element for ComponentAdapter { range_utf16: std::ops::Range, _: RectF, _: RectF, - element: &Self::LayoutState, + _: &Self::LayoutState, _: &Self::PaintState, view: &V, cx: &ViewContext, ) -> Option { - element.rect_for_text_range(range_utf16, view, cx) + self.element + .as_ref() + .and_then(|el| el.rect_for_text_range(range_utf16, view, cx)) } fn debug( &self, _: RectF, - element: &Self::LayoutState, + _: &Self::LayoutState, _: &Self::PaintState, view: &V, cx: &ViewContext, ) -> serde_json::Value { serde_json::json!({ "type": "ComponentAdapter", - "child": element.debug(view, cx), + "child": self.element.as_ref().map(|el| el.debug(view, cx)), }) } }