Checkpoint

Nathan Sobo created

Change summary

crates/storybook/src/sketch.rs | 108 ++++++++++++++++++++++++-----------
1 file changed, 73 insertions(+), 35 deletions(-)

Detailed changes

crates/storybook/src/sketch.rs 🔗

@@ -196,6 +196,23 @@ impl<'a, 'w, T: 'static> ViewContext<'a, 'w, T> {
     }
 }
 
+impl<'a, 'w, T: 'static> Context for ViewContext<'a, 'w, T> {
+    type EntityContext<'b, 'c, U: 'static> = ViewContext<'b, 'c, U>;
+
+    fn update_entity<U: 'static, R>(
+        &mut self,
+        handle: &Handle<U>,
+        update: impl FnOnce(&mut U, &mut Self::EntityContext<'_, '_, U>) -> R,
+    ) -> R {
+        ViewContext::mutable(
+            &mut *self.window_cx.app,
+            &mut *self.window_cx.window,
+            handle.id,
+        )
+        .update(update)
+    }
+}
+
 #[derive(Clone, Copy, Eq, PartialEq, Hash)]
 pub struct WindowId(usize);
 
@@ -292,11 +309,20 @@ impl<T: 'static> Handle<T> {
     }
 }
 
+impl<T> Clone for Handle<T> {
+    fn clone(&self) -> Self {
+        Self {
+            id: self.id,
+            entity_type: PhantomData,
+        }
+    }
+}
+
 pub trait Element: 'static {
     type State;
     type FrameState;
 
-    fn add_layout_node(
+    fn layout(
         &mut self,
         state: &mut Self::State,
         cx: &mut ViewContext<Self::State>,
@@ -316,7 +342,7 @@ pub trait ParentElement<S> {
 }
 
 trait ElementObject<S> {
-    fn add_layout_node(&mut self, state: &mut S, cx: &mut ViewContext<S>) -> Result<LayoutId>;
+    fn layout(&mut self, state: &mut S, cx: &mut ViewContext<S>) -> Result<LayoutId>;
     fn paint(
         &mut self,
         parent_origin: Vector2F,
@@ -346,12 +372,8 @@ impl<E: Element> RenderedElement<E> {
 }
 
 impl<E: Element> ElementObject<E::State> for RenderedElement<E> {
-    fn add_layout_node(
-        &mut self,
-        state: &mut E::State,
-        cx: &mut ViewContext<E::State>,
-    ) -> Result<LayoutId> {
-        let (layout_id, frame_state) = self.element.add_layout_node(state, cx)?;
+    fn layout(&mut self, state: &mut E::State, cx: &mut ViewContext<E::State>) -> Result<LayoutId> {
+        let (layout_id, frame_state) = self.element.layout(state, cx)?;
         self.phase = ElementRenderPhase::LayoutNodeAdded {
             layout_id,
             frame_state,
@@ -373,7 +395,7 @@ pub struct AnyElement<S>(Box<dyn ElementObject<S>>);
 
 impl<S> AnyElement<S> {
     pub fn layout(&mut self, state: &mut S, cx: &mut ViewContext<S>) -> Result<LayoutId> {
-        self.0.add_layout_node(state, cx)
+        self.0.layout(state, cx)
     }
 
     pub fn paint(
@@ -402,37 +424,52 @@ impl<S> IntoAnyElement<S> for AnyElement<S> {
     }
 }
 
-pub struct View<E> {
-    render: Rc<dyn Fn(&mut WindowContext) -> E>,
-}
-
-impl<E> View<E> {
-    fn render(&self, cx: &mut WindowContext) -> E {
-        (self.render)(cx)
-    }
+#[derive(Clone)]
+pub struct View<S> {
+    state: Handle<S>,
+    render: Rc<dyn Fn(&mut S, &mut ViewContext<S>) -> AnyElement<S>>,
 }
 
 pub fn view<S: 'static, E: Element<State = S>>(
     state: Handle<S>,
     render: impl 'static + Fn(&mut S, &mut ViewContext<S>) -> E,
-) -> View<E> {
+) -> View<S> {
     View {
-        render: Rc::new(move |cx| state.update(cx, |state, cx| render(state, cx))),
+        state,
+        render: Rc::new(move |state, cx| render(state, cx).into_any()),
     }
 }
 
-trait ViewObject<S> {
-    fn render(cx: &mut WindowContext) -> AnyElement<S>;
-}
+impl<S: 'static> Element for View<S> {
+    type State = ();
+    type FrameState = AnyElement<S>;
 
-impl<S: 'static, E: Element<State = S>> ViewObject<S> for View<E> {
-    fn render<V>(&mut self, cx: &mut WindowContext) -> AnyElement<V> {
-        let element = (self.render)(cx);
-        AnyElement(Box::new(RenderedElement::new(element)))
+    fn layout(
+        &mut self,
+        _: &mut Self::State,
+        cx: &mut ViewContext<Self::State>,
+    ) -> Result<(LayoutId, Self::FrameState)> {
+        self.state.update(cx, |state, cx| {
+            let mut element = (self.render)(state, cx);
+            let layout_id = element.layout(state, cx)?;
+            Ok((layout_id, element))
+        })
+    }
+
+    fn paint(
+        &mut self,
+        layout: Layout,
+        _: &mut Self::State,
+        element: &mut Self::FrameState,
+        cx: &mut ViewContext<Self::State>,
+    ) -> Result<()> {
+        self.state.update(cx, |state, cx| {
+            element.paint(layout.bounds.origin(), state, cx)
+        })
     }
 }
 
-pub struct AnyView(Box<dyn ViewObject<S>);
+pub struct AnyView(Rc<dyn ElementObject<()>>);
 
 pub struct Div<S>(PhantomData<S>);
 
@@ -440,7 +477,7 @@ impl<S: 'static> Element for Div<S> {
     type State = S;
     type FrameState = ();
 
-    fn add_layout_node(
+    fn layout(
         &mut self,
         state: &mut Self::State,
         cx: &mut ViewContext<Self::State>,
@@ -470,14 +507,15 @@ pub fn div<S>() -> Div<S> {
 }
 
 pub struct Workspace {
-    left_panel: AnyView,
+    // left_panel: AnyView<Self>,
 }
 
 fn workspace(
     state: &mut Workspace,
     cx: &mut ViewContext<Workspace>,
 ) -> impl Element<State = Workspace> {
-    div().child(state.left_panel.render(cx))
+    div()
+    // .child(state.left_panel.render(cx))
 }
 
 pub struct CollabPanel {
@@ -517,11 +555,11 @@ mod tests {
 
     #[test]
     fn test() {
-        let mut cx = AppContext::new();
-        let collab_panel = cx.open_window(|cx| {
-            let panel = cx.add_entity(|cx| CollabPanel::new(cx));
-            view(panel, |panel, cx| div().into_any())
-        });
+        // let mut cx = AppContext::new();
+        // let collab_panel = cx.open_window(|cx| {
+        //     let panel = cx.add_entity(|cx| CollabPanel::new(cx));
+        //     view(panel, |panel, cx| div().into_any())
+        // });
 
         // let
         // let mut workspace = Workspace {