Checkpoint

Antonio Scandurra created

Change summary

crates/gpui3/src/element.rs       | 165 ++++++++++++++++++--------------
crates/gpui3/src/elements/div.rs  |  23 +++-
crates/gpui3/src/elements/img.rs  |  22 ++-
crates/gpui3/src/elements/svg.rs  |  26 +++--
crates/gpui3/src/elements/text.rs |  38 ++++---
crates/gpui3/src/view.rs          | 165 ++++++++++++++++++++------------
crates/gpui3/src/window.rs        |   3 
7 files changed, 263 insertions(+), 179 deletions(-)

Detailed changes

crates/gpui3/src/element.rs 🔗

@@ -1,6 +1,7 @@
 use crate::{BorrowWindow, Bounds, ElementId, FocusHandle, LayoutId, Pixels, Point, ViewContext};
 use derive_more::{Deref, DerefMut};
 pub(crate) use smallvec::SmallVec;
+use std::mem;
 
 pub trait Element: 'static + Send + Sync + IntoAnyElement<Self::ViewState> {
     type ViewState: 'static + Send + Sync;
@@ -8,17 +9,24 @@ pub trait Element: 'static + Send + Sync + IntoAnyElement<Self::ViewState> {
 
     fn id(&self) -> Option<ElementId>;
 
-    fn layout(
+    fn initialize(
         &mut self,
-        state: &mut Self::ViewState,
+        view_state: &mut Self::ViewState,
         element_state: Option<Self::ElementState>,
         cx: &mut ViewContext<Self::ViewState>,
-    ) -> (LayoutId, Self::ElementState);
+    ) -> Self::ElementState;
+
+    fn layout(
+        &mut self,
+        view_state: &mut Self::ViewState,
+        element_state: &mut Self::ElementState,
+        cx: &mut ViewContext<Self::ViewState>,
+    ) -> LayoutId;
 
     fn paint(
         &mut self,
         bounds: Bounds<Pixels>,
-        state: &mut Self::ViewState,
+        view_state: &mut Self::ViewState,
         element_state: &mut Self::ElementState,
         cx: &mut ViewContext<Self::ViewState>,
     );
@@ -97,9 +105,10 @@ pub trait ParentElement: Element {
     }
 }
 
-trait ElementObject<S>: 'static + Send + Sync {
-    fn layout(&mut self, state: &mut S, cx: &mut ViewContext<S>) -> LayoutId;
-    fn paint(&mut self, state: &mut S, offset: Option<Point<Pixels>>, cx: &mut ViewContext<S>);
+trait ElementObject<V>: 'static + Send + Sync {
+    fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
+    fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId;
+    fn paint(&mut self, view_state: &mut V, offset: Option<Point<Pixels>>, cx: &mut ViewContext<V>);
 }
 
 struct RenderedElement<E: Element> {
@@ -108,17 +117,17 @@ struct RenderedElement<E: Element> {
 }
 
 #[derive(Default)]
-enum ElementRenderPhase<S> {
+enum ElementRenderPhase<V> {
     #[default]
-    Rendered,
+    Start,
+    Initialized {
+        frame_state: Option<V>,
+    },
     LayoutRequested {
         layout_id: LayoutId,
-        frame_state: Option<S>,
-    },
-    Painted {
-        bounds: Bounds<Pixels>,
-        frame_state: Option<S>,
+        frame_state: Option<V>,
     },
+    Painted,
 }
 
 /// Internal struct that wraps an element to store Layout and ElementState after the element is rendered.
@@ -128,52 +137,57 @@ impl<E: Element> RenderedElement<E> {
     fn new(element: E) -> Self {
         RenderedElement {
             element,
-            phase: ElementRenderPhase::Rendered,
+            phase: ElementRenderPhase::Start,
         }
     }
+}
 
-    fn paint_with_element_state(
-        &mut self,
-        bounds: Bounds<Pixels>,
-        view_state: &mut E::ViewState,
-        frame_state: &mut Option<E::ElementState>,
-        cx: &mut ViewContext<E::ViewState>,
-    ) {
-        if let Some(id) = self.element.id() {
+impl<E> ElementObject<E::ViewState> for RenderedElement<E>
+where
+    E: Element,
+{
+    fn initialize(&mut self, view_state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) {
+        let frame_state = if let Some(id) = self.element.id() {
             cx.with_element_state(id, |element_state, cx| {
-                let mut element_state = element_state.unwrap();
-                self.element
-                    .paint(bounds, view_state, &mut element_state, cx);
+                let element_state = self.element.initialize(view_state, element_state, cx);
                 ((), element_state)
             });
+            None
         } else {
-            self.element
-                .paint(bounds, view_state, frame_state.as_mut().unwrap(), cx);
-        }
+            let frame_state = self.element.initialize(view_state, None, cx);
+            Some(frame_state)
+        };
+
+        self.phase = ElementRenderPhase::Initialized { frame_state };
     }
-}
 
-impl<E, S> ElementObject<E::ViewState> for RenderedElement<E>
-where
-    E: Element<ElementState = S>,
-    S: 'static + Send + Sync,
-{
     fn layout(&mut self, state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) -> LayoutId {
-        let (layout_id, frame_state) = if let Some(id) = self.element.id() {
-            let layout_id = cx.with_element_state(id, |element_state, cx| {
-                self.element.layout(state, element_state, cx)
-            });
-            (layout_id, None)
-        } else {
-            let (layout_id, frame_state) = self.element.layout(state, None, cx);
-            (layout_id, Some(frame_state))
+        let layout_id;
+        let mut frame_state;
+        match mem::take(&mut self.phase) {
+            ElementRenderPhase::Initialized {
+                frame_state: initial_frame_state,
+            } => {
+                frame_state = initial_frame_state;
+                if let Some(id) = self.element.id() {
+                    layout_id = cx.with_element_state(id, |element_state, cx| {
+                        let mut element_state = element_state.unwrap();
+                        let layout_id = self.element.layout(state, &mut element_state, cx);
+                        (layout_id, element_state)
+                    });
+                } else {
+                    layout_id = self
+                        .element
+                        .layout(state, frame_state.as_mut().unwrap(), cx);
+                }
+            }
+            _ => panic!("must call initialize before layout"),
         };
 
         self.phase = ElementRenderPhase::LayoutRequested {
             layout_id,
             frame_state,
         };
-
         layout_id
     }
 
@@ -183,60 +197,63 @@ where
         offset: Option<Point<Pixels>>,
         cx: &mut ViewContext<E::ViewState>,
     ) {
-        self.phase = match std::mem::take(&mut self.phase) {
-            ElementRenderPhase::Rendered => panic!("must call layout before paint"),
-
+        self.phase = match mem::take(&mut self.phase) {
             ElementRenderPhase::LayoutRequested {
                 layout_id,
                 mut frame_state,
             } => {
                 let mut bounds = cx.layout_bounds(layout_id);
                 offset.map(|offset| bounds.origin += offset);
-                self.paint_with_element_state(bounds, view_state, &mut frame_state, cx);
-                ElementRenderPhase::Painted {
-                    bounds,
-                    frame_state,
+                if let Some(id) = self.element.id() {
+                    cx.with_element_state(id, |element_state, cx| {
+                        let mut element_state = element_state.unwrap();
+                        self.element
+                            .paint(bounds, view_state, &mut element_state, cx);
+                        ((), element_state)
+                    });
+                } else {
+                    self.element
+                        .paint(bounds, view_state, frame_state.as_mut().unwrap(), cx);
                 }
+                ElementRenderPhase::Painted
             }
 
-            ElementRenderPhase::Painted {
-                bounds,
-                mut frame_state,
-            } => {
-                self.paint_with_element_state(bounds, view_state, &mut frame_state, cx);
-                ElementRenderPhase::Painted {
-                    bounds,
-                    frame_state,
-                }
-            }
+            _ => panic!("must call layout before paint"),
         };
     }
 }
 
-pub struct AnyElement<S>(Box<dyn ElementObject<S>>);
+pub struct AnyElement<V>(Box<dyn ElementObject<V>>);
 
-impl<S: 'static + Send + Sync> AnyElement<S> {
-    pub fn new<E: Element<ViewState = S>>(element: E) -> Self {
+impl<V: 'static + Send + Sync> AnyElement<V> {
+    pub fn new<E: Element<ViewState = V>>(element: E) -> Self {
         AnyElement(Box::new(RenderedElement::new(element)))
     }
-}
 
-impl<S: 'static + Send + Sync> AnyElement<S> {
-    pub fn layout(&mut self, state: &mut S, cx: &mut ViewContext<S>) -> LayoutId {
-        self.0.layout(state, cx)
+    pub fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
+        self.0.initialize(view_state, cx);
     }
 
-    pub fn paint(&mut self, state: &mut S, offset: Option<Point<Pixels>>, cx: &mut ViewContext<S>) {
-        self.0.paint(state, offset, cx)
+    pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
+        self.0.layout(view_state, cx)
+    }
+
+    pub fn paint(
+        &mut self,
+        view_state: &mut V,
+        offset: Option<Point<Pixels>>,
+        cx: &mut ViewContext<V>,
+    ) {
+        self.0.paint(view_state, offset, cx)
     }
 }
 
-pub trait IntoAnyElement<S> {
-    fn into_any(self) -> AnyElement<S>;
+pub trait IntoAnyElement<V> {
+    fn into_any(self) -> AnyElement<V>;
 }
 
-impl<S> IntoAnyElement<S> for AnyElement<S> {
-    fn into_any(self) -> AnyElement<S> {
+impl<V> IntoAnyElement<V> for AnyElement<V> {
+    fn into_any(self) -> AnyElement<V> {
         self
     }
 }

crates/gpui3/src/elements/div.rs 🔗

@@ -369,14 +369,25 @@ where
         self.identity.id()
     }
 
-    fn layout(
+    fn initialize(
         &mut self,
         view_state: &mut Self::ViewState,
         element_state: Option<Self::ElementState>,
         cx: &mut ViewContext<Self::ViewState>,
-    ) -> (LayoutId, Self::ElementState) {
-        let element_state = element_state.unwrap_or_default();
-        let style = self.compute_style(Bounds::default(), &element_state, cx);
+    ) -> Self::ElementState {
+        for child in &mut self.children {
+            child.initialize(view_state, cx);
+        }
+        element_state.unwrap_or_default()
+    }
+
+    fn layout(
+        &mut self,
+        view_state: &mut Self::ViewState,
+        element_state: &mut Self::ElementState,
+        cx: &mut ViewContext<Self::ViewState>,
+    ) -> LayoutId {
+        let style = self.compute_style(Bounds::default(), element_state, cx);
         style.apply_text_style(cx, |cx| {
             self.with_element_id(cx, |this, cx| {
                 let layout_ids = this
@@ -384,9 +395,7 @@ where
                     .iter_mut()
                     .map(|child| child.layout(view_state, cx))
                     .collect::<Vec<_>>();
-
-                let layout_id = cx.request_layout(&style, layout_ids);
-                (layout_id, element_state)
+                cx.request_layout(&style, layout_ids)
             })
         })
     }

crates/gpui3/src/elements/img.rs 🔗

@@ -71,24 +71,30 @@ where
         self.base.id()
     }
 
-    fn layout(
+    fn initialize(
         &mut self,
-        view_state: &mut Self::ViewState,
+        view_state: &mut V,
         element_state: Option<Self::ElementState>,
+        cx: &mut ViewContext<V>,
+    ) -> Self::ElementState {
+        self.base.initialize(view_state, element_state, cx)
+    }
+
+    fn layout(
+        &mut self,
+        view_state: &mut V,
+        element_state: &mut Self::ElementState,
         cx: &mut ViewContext<Self::ViewState>,
-    ) -> (LayoutId, Self::ElementState)
-    where
-        Self: Sized,
-    {
+    ) -> LayoutId {
         self.base.layout(view_state, element_state, cx)
     }
 
     fn paint(
         &mut self,
         bounds: Bounds<Pixels>,
-        view: &mut Self::ViewState,
+        view: &mut V,
         element_state: &mut Self::ElementState,
-        cx: &mut ViewContext<Self::ViewState>,
+        cx: &mut ViewContext<V>,
     ) {
         cx.stack(0, |cx| {
             self.base.paint(bounds, view, element_state, cx);

crates/gpui3/src/elements/svg.rs 🔗

@@ -1,7 +1,7 @@
 use crate::{
     div, Active, Anonymous, AnyElement, Bounds, Click, Div, DivState, Element, ElementId,
     ElementIdentity, EventListeners, Hover, Identified, Interactive, IntoAnyElement, LayoutId,
-    NonFocusable, Pixels, SharedString, StyleRefinement, Styled,
+    NonFocusable, Pixels, SharedString, StyleRefinement, Styled, ViewContext,
 };
 use util::ResultExt;
 
@@ -62,16 +62,22 @@ where
         self.base.id()
     }
 
-    fn layout(
+    fn initialize(
         &mut self,
-        view: &mut V,
+        view_state: &mut V,
         element_state: Option<Self::ElementState>,
-        cx: &mut crate::ViewContext<V>,
-    ) -> (LayoutId, Self::ElementState)
-    where
-        Self: Sized,
-    {
-        self.base.layout(view, element_state, cx)
+        cx: &mut ViewContext<V>,
+    ) -> Self::ElementState {
+        self.base.initialize(view_state, element_state, cx)
+    }
+
+    fn layout(
+        &mut self,
+        view_state: &mut V,
+        element_state: &mut Self::ElementState,
+        cx: &mut ViewContext<Self::ViewState>,
+    ) -> LayoutId {
+        self.base.layout(view_state, element_state, cx)
     }
 
     fn paint(
@@ -79,7 +85,7 @@ where
         bounds: Bounds<Pixels>,
         view: &mut Self::ViewState,
         element_state: &mut Self::ElementState,
-        cx: &mut crate::ViewContext<V>,
+        cx: &mut ViewContext<V>,
     ) where
         Self: Sized,
     {

crates/gpui3/src/elements/text.rs 🔗

@@ -39,31 +39,40 @@ impl<S: 'static + Send + Sync> IntoAnyElement<S> for String {
     }
 }
 
-pub struct Text<S> {
+pub struct Text<V> {
     text: SharedString,
-    state_type: PhantomData<S>,
+    state_type: PhantomData<V>,
 }
 
-impl<S: 'static + Send + Sync> IntoAnyElement<S> for Text<S> {
-    fn into_any(self) -> AnyElement<S> {
+impl<V: 'static + Send + Sync> IntoAnyElement<V> for Text<V> {
+    fn into_any(self) -> AnyElement<V> {
         AnyElement::new(self)
     }
 }
 
-impl<S: 'static + Send + Sync> Element for Text<S> {
-    type ViewState = S;
+impl<V: 'static + Send + Sync> Element for Text<V> {
+    type ViewState = V;
     type ElementState = Arc<Mutex<Option<TextElementState>>>;
 
     fn id(&self) -> Option<crate::ElementId> {
         None
     }
 
+    fn initialize(
+        &mut self,
+        _view_state: &mut V,
+        element_state: Option<Self::ElementState>,
+        _cx: &mut ViewContext<V>,
+    ) -> Self::ElementState {
+        element_state.unwrap_or_default()
+    }
+
     fn layout(
         &mut self,
-        _view: &mut S,
-        _element_state: Option<Self::ElementState>,
-        cx: &mut ViewContext<S>,
-    ) -> (LayoutId, Self::ElementState) {
+        _view: &mut V,
+        element_state: &mut Self::ElementState,
+        cx: &mut ViewContext<V>,
+    ) -> LayoutId {
         let text_system = cx.text_system().clone();
         let text_style = cx.text_style();
         let font_size = text_style.font_size * cx.rem_size();
@@ -71,7 +80,6 @@ impl<S: 'static + Send + Sync> Element for Text<S> {
             .line_height
             .to_pixels(font_size.into(), cx.rem_size());
         let text = self.text.clone();
-        let element_state = Arc::new(Mutex::new(None));
 
         let rem_size = cx.rem_size();
         let layout_id = cx.request_measured_layout(Default::default(), rem_size, {
@@ -102,15 +110,15 @@ impl<S: 'static + Send + Sync> Element for Text<S> {
             }
         });
 
-        (layout_id, element_state)
+        layout_id
     }
 
-    fn paint<'a>(
+    fn paint(
         &mut self,
         bounds: Bounds<Pixels>,
-        _: &mut Self::ViewState,
+        _: &mut V,
         element_state: &mut Self::ElementState,
-        cx: &mut ViewContext<S>,
+        cx: &mut ViewContext<V>,
     ) {
         let element_state = element_state.lock();
         let element_state = element_state

crates/gpui3/src/view.rs 🔗

@@ -6,12 +6,12 @@ use crate::{
 };
 use std::{marker::PhantomData, sync::Arc};
 
-pub struct View<S: Send + Sync> {
-    state: Handle<S>,
-    render: Arc<dyn Fn(&mut S, &mut ViewContext<S>) -> AnyElement<S> + Send + Sync + 'static>,
+pub struct View<V: Send + Sync> {
+    state: Handle<V>,
+    render: Arc<dyn Fn(&mut V, &mut ViewContext<V>) -> AnyElement<V> + Send + Sync + 'static>,
 }
 
-impl<S: 'static + Send + Sync> View<S> {
+impl<V: 'static + Send + Sync> View<V> {
     pub fn into_any(self) -> AnyView {
         AnyView {
             view: Arc::new(Mutex::new(self)),
@@ -19,7 +19,7 @@ impl<S: 'static + Send + Sync> View<S> {
     }
 }
 
-impl<S: Send + Sync> Clone for View<S> {
+impl<V: Send + Sync> Clone for View<V> {
     fn clone(&self) -> Self {
         Self {
             state: self.state.clone(),
@@ -28,13 +28,13 @@ impl<S: Send + Sync> Clone for View<S> {
     }
 }
 
-pub fn view<S, E>(
-    state: Handle<S>,
-    render: impl Fn(&mut S, &mut ViewContext<S>) -> E + Send + Sync + 'static,
-) -> View<S>
+pub fn view<V, E>(
+    state: Handle<V>,
+    render: impl Fn(&mut V, &mut ViewContext<V>) -> E + Send + Sync + 'static,
+) -> View<V>
 where
-    E: IntoAnyElement<S>,
-    S: 'static + Send + Sync,
+    E: IntoAnyElement<V>,
+    V: 'static + Send + Sync,
 {
     View {
         state,
@@ -42,8 +42,8 @@ where
     }
 }
 
-impl<S: 'static + Send + Sync, ParentViewState: 'static + Send + Sync>
-    IntoAnyElement<ParentViewState> for View<S>
+impl<V: 'static + Send + Sync, ParentViewState: 'static + Send + Sync>
+    IntoAnyElement<ParentViewState> for View<V>
 {
     fn into_any(self) -> AnyElement<ParentViewState> {
         AnyElement::new(EraseViewState {
@@ -53,74 +53,87 @@ impl<S: 'static + Send + Sync, ParentViewState: 'static + Send + Sync>
     }
 }
 
-impl<S: 'static + Send + Sync> Element for View<S> {
+impl<V: 'static + Send + Sync> Element for View<V> {
     type ViewState = ();
-    type ElementState = AnyElement<S>;
+    type ElementState = AnyElement<V>;
 
     fn id(&self) -> Option<crate::ElementId> {
         Some(ElementId::View(self.state.id))
     }
 
-    fn layout(
+    fn initialize(
         &mut self,
-        _: &mut Self::ViewState,
+        _: &mut (),
         _: Option<Self::ElementState>,
-        cx: &mut ViewContext<Self::ViewState>,
-    ) -> (LayoutId, Self::ElementState) {
-        self.state.update(cx, |state, cx| {
-            let mut element = (self.render)(state, cx);
-            let layout_id = element.layout(state, cx);
-            (layout_id, element)
-        })
+        cx: &mut ViewContext<()>,
+    ) -> Self::ElementState {
+        self.state.update(cx, |state, cx| (self.render)(state, cx))
+    }
+
+    fn layout(
+        &mut self,
+        _: &mut (),
+        element: &mut Self::ElementState,
+        cx: &mut ViewContext<()>,
+    ) -> LayoutId {
+        self.state.update(cx, |state, cx| element.layout(state, cx))
     }
 
     fn paint(
         &mut self,
         _: Bounds<Pixels>,
-        _: &mut Self::ViewState,
+        _: &mut (),
         element: &mut Self::ElementState,
-        cx: &mut ViewContext<Self::ViewState>,
+        cx: &mut ViewContext<()>,
     ) {
         self.state
             .update(cx, |state, cx| element.paint(state, None, cx))
     }
 }
 
-struct EraseViewState<ViewState: 'static + Send + Sync, ParentViewState> {
-    view: View<ViewState>,
-    parent_view_state_type: PhantomData<ParentViewState>,
+struct EraseViewState<V: 'static + Send + Sync, ParentV> {
+    view: View<V>,
+    parent_view_state_type: PhantomData<ParentV>,
 }
 
-impl<ViewState, ParentViewState> IntoAnyElement<ParentViewState>
-    for EraseViewState<ViewState, ParentViewState>
+impl<V, ParentV> IntoAnyElement<ParentV> for EraseViewState<V, ParentV>
 where
-    ViewState: 'static + Send + Sync,
-    ParentViewState: 'static + Send + Sync,
+    V: 'static + Send + Sync,
+    ParentV: 'static + Send + Sync,
 {
-    fn into_any(self) -> AnyElement<ParentViewState> {
+    fn into_any(self) -> AnyElement<ParentV> {
         AnyElement::new(self)
     }
 }
 
-impl<ViewState, ParentViewState> Element for EraseViewState<ViewState, ParentViewState>
+impl<V, ParentV> Element for EraseViewState<V, ParentV>
 where
-    ViewState: 'static + Send + Sync,
-    ParentViewState: 'static + Send + Sync,
+    V: 'static + Send + Sync,
+    ParentV: 'static + Send + Sync,
 {
-    type ViewState = ParentViewState;
+    type ViewState = ParentV;
     type ElementState = AnyBox;
 
     fn id(&self) -> Option<crate::ElementId> {
         Element::id(&self.view)
     }
 
-    fn layout(
+    fn initialize(
         &mut self,
         _: &mut Self::ViewState,
         _: Option<Self::ElementState>,
         cx: &mut ViewContext<Self::ViewState>,
-    ) -> (LayoutId, Self::ElementState) {
-        ViewObject::layout(&mut self.view, cx)
+    ) -> Self::ElementState {
+        ViewObject::initialize(&mut self.view, cx)
+    }
+
+    fn layout(
+        &mut self,
+        _: &mut Self::ViewState,
+        element: &mut Self::ElementState,
+        cx: &mut ViewContext<Self::ViewState>,
+    ) -> LayoutId {
+        ViewObject::layout(&mut self.view, element, cx)
     }
 
     fn paint(
@@ -136,22 +149,28 @@ where
 
 trait ViewObject: 'static + Send + Sync {
     fn entity_id(&self) -> EntityId;
-    fn layout(&mut self, cx: &mut WindowContext) -> (LayoutId, AnyBox);
+    fn initialize(&mut self, cx: &mut WindowContext) -> AnyBox;
+    fn layout(&mut self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId;
     fn paint(&mut self, bounds: Bounds<Pixels>, element: &mut AnyBox, cx: &mut WindowContext);
 }
 
-impl<S: Send + Sync + 'static> ViewObject for View<S> {
+impl<V: Send + Sync + 'static> ViewObject for View<V> {
     fn entity_id(&self) -> EntityId {
         self.state.id
     }
 
-    fn layout(&mut self, cx: &mut WindowContext) -> (LayoutId, AnyBox) {
+    fn initialize(&mut self, cx: &mut WindowContext) -> AnyBox {
+        cx.with_element_id(self.entity_id(), |cx| {
+            self.state
+                .update(cx, |state, cx| Box::new((self.render)(state, cx)) as AnyBox)
+        })
+    }
+
+    fn layout(&mut self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId {
         cx.with_element_id(self.entity_id(), |cx| {
             self.state.update(cx, |state, cx| {
-                let mut element = (self.render)(state, cx);
-                let layout_id = element.layout(state, cx);
-                let element = Box::new(element) as AnyBox;
-                (layout_id, element)
+                let element = element.downcast_mut::<AnyElement<V>>().unwrap();
+                element.layout(state, cx)
             })
         })
     }
@@ -159,7 +178,7 @@ impl<S: Send + Sync + 'static> ViewObject for View<S> {
     fn paint(&mut self, _: Bounds<Pixels>, element: &mut AnyBox, cx: &mut WindowContext) {
         cx.with_element_id(self.entity_id(), |cx| {
             self.state.update(cx, |state, cx| {
-                let element = element.downcast_mut::<AnyElement<S>>().unwrap();
+                let element = element.downcast_mut::<AnyElement<V>>().unwrap();
                 element.paint(state, None, cx);
             });
         });
@@ -170,11 +189,11 @@ pub struct AnyView {
     view: Arc<Mutex<dyn ViewObject>>,
 }
 
-impl<ParentViewState> IntoAnyElement<ParentViewState> for AnyView
+impl<ParentV> IntoAnyElement<ParentV> for AnyView
 where
-    ParentViewState: 'static + Send + Sync,
+    ParentV: 'static + Send + Sync,
 {
-    fn into_any(self) -> AnyElement<ParentViewState> {
+    fn into_any(self) -> AnyElement<ParentV> {
         AnyElement::new(EraseAnyViewState {
             view: self,
             parent_view_state_type: PhantomData,
@@ -190,13 +209,22 @@ impl Element for AnyView {
         Some(ElementId::View(self.view.lock().entity_id()))
     }
 
-    fn layout(
+    fn initialize(
         &mut self,
         _: &mut Self::ViewState,
         _: Option<Self::ElementState>,
         cx: &mut ViewContext<Self::ViewState>,
-    ) -> (LayoutId, Self::ElementState) {
-        self.view.lock().layout(cx)
+    ) -> Self::ElementState {
+        self.view.lock().initialize(cx)
+    }
+
+    fn layout(
+        &mut self,
+        _: &mut Self::ViewState,
+        element: &mut Self::ElementState,
+        cx: &mut ViewContext<Self::ViewState>,
+    ) -> LayoutId {
+        self.view.lock().layout(element, cx)
     }
 
     fn paint(
@@ -215,33 +243,42 @@ struct EraseAnyViewState<ParentViewState> {
     parent_view_state_type: PhantomData<ParentViewState>,
 }
 
-impl<ParentViewState> IntoAnyElement<ParentViewState> for EraseAnyViewState<ParentViewState>
+impl<ParentV> IntoAnyElement<ParentV> for EraseAnyViewState<ParentV>
 where
-    ParentViewState: 'static + Send + Sync,
+    ParentV: 'static + Send + Sync,
 {
-    fn into_any(self) -> AnyElement<ParentViewState> {
+    fn into_any(self) -> AnyElement<ParentV> {
         AnyElement::new(self)
     }
 }
 
-impl<ParentViewState> Element for EraseAnyViewState<ParentViewState>
+impl<ParentV> Element for EraseAnyViewState<ParentV>
 where
-    ParentViewState: 'static + Send + Sync,
+    ParentV: 'static + Send + Sync,
 {
-    type ViewState = ParentViewState;
+    type ViewState = ParentV;
     type ElementState = AnyBox;
 
     fn id(&self) -> Option<crate::ElementId> {
         Element::id(&self.view)
     }
 
-    fn layout(
+    fn initialize(
         &mut self,
         _: &mut Self::ViewState,
         _: Option<Self::ElementState>,
         cx: &mut ViewContext<Self::ViewState>,
-    ) -> (LayoutId, Self::ElementState) {
-        self.view.view.lock().layout(cx)
+    ) -> Self::ElementState {
+        self.view.view.lock().initialize(cx)
+    }
+
+    fn layout(
+        &mut self,
+        _: &mut Self::ViewState,
+        element: &mut Self::ElementState,
+        cx: &mut ViewContext<Self::ViewState>,
+    ) -> LayoutId {
+        self.view.view.lock().layout(element, cx)
     }
 
     fn paint(

crates/gpui3/src/window.rs 🔗

@@ -653,7 +653,8 @@ impl<'a, 'w> WindowContext<'a, 'w> {
             element_state: Option<AnyBox>,
             cx: &mut ViewContext<()>,
         ) -> AnyBox {
-            let (layout_id, mut element_state) = root_view.layout(&mut (), element_state, cx);
+            let mut element_state = root_view.initialize(&mut (), element_state, cx);
+            let layout_id = root_view.layout(&mut (), &mut element_state, cx);
             let available_space = cx.window.content_size.map(Into::into);
             cx.window
                 .layout_engine