diff --git a/crates/storybook/src/sketch.rs b/crates/storybook/src/sketch.rs index de44d269df..870e6fb3c4 100644 --- a/crates/storybook/src/sketch.rs +++ b/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( + &mut self, + handle: &Handle, + 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 Handle { } } +impl Clone for Handle { + 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, @@ -316,7 +342,7 @@ pub trait ParentElement { } trait ElementObject { - fn add_layout_node(&mut self, state: &mut S, cx: &mut ViewContext) -> Result; + fn layout(&mut self, state: &mut S, cx: &mut ViewContext) -> Result; fn paint( &mut self, parent_origin: Vector2F, @@ -346,12 +372,8 @@ impl RenderedElement { } impl ElementObject for RenderedElement { - fn add_layout_node( - &mut self, - state: &mut E::State, - cx: &mut ViewContext, - ) -> Result { - let (layout_id, frame_state) = self.element.add_layout_node(state, cx)?; + fn layout(&mut self, state: &mut E::State, cx: &mut ViewContext) -> Result { + 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(Box>); impl AnyElement { pub fn layout(&mut self, state: &mut S, cx: &mut ViewContext) -> Result { - self.0.add_layout_node(state, cx) + self.0.layout(state, cx) } pub fn paint( @@ -402,37 +424,52 @@ impl IntoAnyElement for AnyElement { } } -pub struct View { - render: Rc E>, -} - -impl View { - fn render(&self, cx: &mut WindowContext) -> E { - (self.render)(cx) - } +#[derive(Clone)] +pub struct View { + state: Handle, + render: Rc) -> AnyElement>, } pub fn view>( state: Handle, render: impl 'static + Fn(&mut S, &mut ViewContext) -> E, -) -> View { +) -> View { 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 { - fn render(cx: &mut WindowContext) -> AnyElement; -} +impl Element for View { + type State = (); + type FrameState = AnyElement; -impl> ViewObject for View { - fn render(&mut self, cx: &mut WindowContext) -> AnyElement { - let element = (self.render)(cx); - AnyElement(Box::new(RenderedElement::new(element))) + fn layout( + &mut self, + _: &mut Self::State, + cx: &mut ViewContext, + ) -> 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, + ) -> Result<()> { + self.state.update(cx, |state, cx| { + element.paint(layout.bounds.origin(), state, cx) + }) } } -pub struct AnyView(Box); +pub struct AnyView(Rc>); pub struct Div(PhantomData); @@ -440,7 +477,7 @@ impl Element for Div { type State = S; type FrameState = (); - fn add_layout_node( + fn layout( &mut self, state: &mut Self::State, cx: &mut ViewContext, @@ -470,14 +507,15 @@ pub fn div() -> Div { } pub struct Workspace { - left_panel: AnyView, + // left_panel: AnyView, } fn workspace( state: &mut Workspace, cx: &mut ViewContext, ) -> impl Element { - 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 {