1use parking_lot::Mutex;
2
3use crate::{
4 AnyElement, Element, Handle, IntoAnyElement, Layout, LayoutId, MainThread, Result, ViewContext,
5 WindowContext,
6};
7use std::{any::Any, marker::PhantomData, sync::Arc};
8
9pub struct View<S: Send + Sync, P, Thread = ()> {
10 state: Handle<S>,
11 render:
12 Arc<dyn Fn(&mut S, &mut ViewContext<S, Thread>) -> AnyElement<S> + Send + Sync + 'static>,
13 parent_state_type: PhantomData<P>,
14}
15
16impl<S: 'static + Send + Sync, P: 'static + Send> View<S, P> {
17 pub fn into_any(self) -> AnyView<P> {
18 AnyView {
19 view: Arc::new(Mutex::new(self)),
20 parent_state_type: PhantomData,
21 }
22 }
23}
24
25impl<S: Send + Sync, P> Clone for View<S, P> {
26 fn clone(&self) -> Self {
27 Self {
28 state: self.state.clone(),
29 render: self.render.clone(),
30 parent_state_type: PhantomData,
31 }
32 }
33}
34
35pub type RootView<S> = View<S, ()>;
36
37pub fn view<S, P, E>(
38 state: Handle<S>,
39 render: impl Fn(&mut S, &mut ViewContext<S>) -> E + Send + Sync + 'static,
40) -> View<S, P>
41where
42 S: 'static + Send + Sync,
43 P: 'static,
44 E: Element<State = S>,
45{
46 View {
47 state,
48 render: Arc::new(move |state, cx| render(state, cx).into_any()),
49 parent_state_type: PhantomData,
50 }
51}
52
53impl<S: Send + Sync + 'static, P: Send + 'static> Element for View<S, P> {
54 type State = P;
55 type FrameState = AnyElement<S>;
56
57 fn layout(
58 &mut self,
59 _: &mut Self::State,
60 cx: &mut ViewContext<Self::State>,
61 ) -> Result<(LayoutId, Self::FrameState)> {
62 dbg!("Layout view");
63 self.state.update(cx, |state, cx| {
64 let mut element = (self.render)(state, cx);
65 let layout_id = element.layout(state, cx)?;
66 Ok((layout_id, element))
67 })
68 }
69
70 fn paint(
71 &mut self,
72 _: Layout,
73 _: &mut Self::State,
74 element: &mut Self::FrameState,
75 cx: &mut ViewContext<Self::State>,
76 ) -> Result<()> {
77 dbg!("Paint view");
78 self.state
79 .update(cx, |state, cx| element.paint(state, None, cx))
80 }
81}
82
83trait ViewObject: Send + 'static {
84 fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box<dyn Any>)>;
85 fn paint(
86 &mut self,
87 layout: Layout,
88 element: &mut dyn Any,
89 cx: &mut WindowContext,
90 ) -> Result<()>;
91}
92
93impl<S: Send + Sync + 'static, P: Send + 'static> ViewObject for View<S, P> {
94 fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box<dyn Any>)> {
95 self.state.update(cx, |state, cx| {
96 let mut element = (self.render)(state, cx);
97 let layout_id = element.layout(state, cx)?;
98 let element = Box::new(element) as Box<dyn Any>;
99 Ok((layout_id, element))
100 })
101 }
102
103 fn paint(&mut self, _: Layout, element: &mut dyn Any, cx: &mut WindowContext) -> Result<()> {
104 self.state.update(cx, |state, cx| {
105 let boxed_element = element.downcast_mut::<Box<dyn Any>>().unwrap();
106 let element = boxed_element.downcast_mut::<AnyElement<S>>().unwrap();
107
108 element.paint(state, None, cx)
109 })
110 }
111}
112
113pub struct AnyView<S> {
114 view: Arc<Mutex<dyn ViewObject>>,
115 parent_state_type: PhantomData<S>,
116}
117
118impl<S: 'static> Element for AnyView<S> {
119 type State = ();
120 type FrameState = Box<dyn Any>;
121
122 fn layout(
123 &mut self,
124 _: &mut Self::State,
125 cx: &mut ViewContext<Self::State>,
126 ) -> Result<(LayoutId, Self::FrameState)> {
127 self.view.lock().layout(cx)
128 }
129
130 fn paint(
131 &mut self,
132 layout: Layout,
133 _: &mut Self::State,
134 element: &mut Self::FrameState,
135 cx: &mut ViewContext<Self::State>,
136 ) -> Result<()> {
137 dbg!("Element.paint for AnyView");
138 self.view.lock().paint(layout, element, cx)
139 }
140}
141
142impl<S> Clone for AnyView<S> {
143 fn clone(&self) -> Self {
144 Self {
145 view: self.view.clone(),
146 parent_state_type: PhantomData,
147 }
148 }
149}