diff --git a/crates/storybook/src/sketch.rs b/crates/storybook/src/sketch.rs index 870e6fb3c47d6e7aa1cefc094d5cde6c5278be77..c66b5970e87e4d3dfec6fd2a68340fdd58572914 100644 --- a/crates/storybook/src/sketch.rs +++ b/crates/storybook/src/sketch.rs @@ -1,7 +1,7 @@ use anyhow::{anyhow, Result}; use derive_more::{Deref, DerefMut}; use gpui2::{Layout, LayoutId, Reference, Vector2F}; -use std::{any::Any, collections::HashMap, marker::PhantomData, rc::Rc}; +use std::{any::Any, cell::RefCell, collections::HashMap, marker::PhantomData, rc::Rc}; pub struct AppContext { entity_count: usize, @@ -15,10 +15,9 @@ impl AppContext { unimplemented!() } - pub fn open_window( - &self, - state: S, - render: impl Fn(&mut S, &mut ViewContext) -> View, + pub fn open_window( + &mut self, + build_root_view: impl FnOnce(&mut WindowContext) -> View, ) -> WindowHandle { unimplemented!() } @@ -440,6 +439,15 @@ pub fn view>( } } +impl View { + pub fn into_any(self) -> AnyView { + AnyView { + view: Rc::new(RefCell::new(self)), + parent_state_type: PhantomData, + } + } +} + impl Element for View { type State = (); type FrameState = AnyElement; @@ -469,7 +477,69 @@ impl Element for View { } } -pub struct AnyView(Rc>); +trait ViewObject { + fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box)>; + fn paint( + &mut self, + layout: Layout, + element: &mut dyn Any, + cx: &mut WindowContext, + ) -> Result<()>; +} + +impl ViewObject for View { + fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box)> { + 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 Box; + Ok((layout_id, element)) + }) + } + + fn paint( + &mut self, + layout: Layout, + element: &mut dyn Any, + cx: &mut WindowContext, + ) -> Result<()> { + self.state.update(cx, |state, cx| { + element.downcast_mut::>().unwrap().paint( + layout.bounds.origin(), + state, + cx, + ) + }) + } +} + +pub struct AnyView { + view: Rc>, + parent_state_type: PhantomData, +} + +impl Element for AnyView { + type State = S; + type FrameState = Box; + + fn layout( + &mut self, + _: &mut Self::State, + cx: &mut ViewContext, + ) -> Result<(LayoutId, Self::FrameState)> { + self.view.borrow_mut().layout(cx) + } + + fn paint( + &mut self, + layout: Layout, + _: &mut Self::State, + element: &mut Self::FrameState, + cx: &mut ViewContext, + ) -> Result<()> { + self.view.borrow_mut().paint(layout, element, cx) + } +} pub struct Div(PhantomData); @@ -507,7 +577,7 @@ pub fn div() -> Div { } pub struct Workspace { - // left_panel: AnyView, + left_panel: AnyView, } fn workspace( @@ -555,16 +625,16 @@ 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 - // let mut workspace = Workspace { - // left_panel: view(), - // } + let mut cx = AppContext::new(); + + let workspace = cx.open_window(|cx| { + let workspace = cx.add_entity(|cx| Workspace { + left_panel: view(cx.add_entity(|cx| CollabPanel::new(cx)), |panel, cx| div()) + .into_any(), + }); + + view(workspace, |workspace, cx| div()) + }); // cx.open_window(workspace::Workspace, state) }