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