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 self.state.update(cx, |state, cx| {
63 let mut element = (self.render)(state, cx);
64 let layout_id = element.layout(state, cx)?;
65 Ok((layout_id, element))
66 })
67 }
68
69 fn paint(
70 &mut self,
71 _: Layout,
72 _: &mut Self::State,
73 element: &mut Self::FrameState,
74 cx: &mut ViewContext<Self::State>,
75 ) -> Result<()> {
76 self.state
77 .update(cx, |state, cx| element.paint(state, None, cx))
78 }
79}
80
81trait ViewObject: Send + 'static {
82 fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box<dyn Any>)>;
83 fn paint(
84 &mut self,
85 layout: Layout,
86 element: &mut dyn Any,
87 cx: &mut WindowContext,
88 ) -> Result<()>;
89}
90
91impl<S: Send + Sync + 'static, P: Send + 'static> ViewObject for View<S, P> {
92 fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box<dyn Any>)> {
93 self.state.update(cx, |state, cx| {
94 let mut element = (self.render)(state, cx);
95 let layout_id = element.layout(state, cx)?;
96 let element = Box::new(element) as Box<dyn Any>;
97 Ok((layout_id, element))
98 })
99 }
100
101 fn paint(&mut self, _: Layout, element: &mut dyn Any, cx: &mut WindowContext) -> Result<()> {
102 self.state.update(cx, |state, cx| {
103 element
104 .downcast_mut::<AnyElement<S>>()
105 .unwrap()
106 .paint(state, None, cx)
107 })
108 }
109}
110
111pub struct AnyView<S> {
112 view: Arc<Mutex<dyn ViewObject>>,
113 parent_state_type: PhantomData<S>,
114}
115
116impl<S: 'static> Element for AnyView<S> {
117 type State = ();
118 type FrameState = Box<dyn Any>;
119
120 fn layout(
121 &mut self,
122 _: &mut Self::State,
123 cx: &mut ViewContext<Self::State>,
124 ) -> Result<(LayoutId, Self::FrameState)> {
125 self.view.lock().layout(cx)
126 }
127
128 fn paint(
129 &mut self,
130 layout: Layout,
131 _: &mut Self::State,
132 element: &mut Self::FrameState,
133 cx: &mut ViewContext<Self::State>,
134 ) -> Result<()> {
135 self.view.lock().paint(layout, element, cx)
136 }
137}
138
139impl<S> Clone for AnyView<S> {
140 fn clone(&self) -> Self {
141 Self {
142 view: self.view.clone(),
143 parent_state_type: PhantomData,
144 }
145 }
146}