1use parking_lot::Mutex;
2
3use crate::{
4 AnyElement, Bounds, Element, Handle, IntoAnyElement, LayoutId, Pixels, Result, ViewContext,
5 WindowContext,
6};
7use std::{any::Any, marker::PhantomData, sync::Arc};
8
9pub struct View<S: Send + Sync, 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: Send + Sync, 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, P, E>(
37 state: Handle<S>,
38 render: impl Fn(&mut S, &mut ViewContext<S>) -> E + Send + Sync + 'static,
39) -> View<S, P>
40where
41 S: 'static + Send + Sync,
42 P: 'static,
43 E: Element<State = S>,
44{
45 View {
46 state,
47 render: Arc::new(move |state, cx| render(state, cx).into_any()),
48 parent_state_type: PhantomData,
49 }
50}
51
52impl<S: Send + Sync + 'static, P: Send + 'static> Element for View<S, P> {
53 type State = P;
54 type FrameState = AnyElement<S>;
55
56 fn layout(
57 &mut self,
58 _: &mut Self::State,
59 cx: &mut ViewContext<Self::State>,
60 ) -> Result<(LayoutId, Self::FrameState)> {
61 self.state.update(cx, |state, cx| {
62 let mut element = (self.render)(state, cx);
63 let layout_id = element.layout(state, cx)?;
64 Ok((layout_id, element))
65 })
66 }
67
68 fn paint(
69 &mut self,
70 _: Bounds<Pixels>,
71 _: &mut Self::State,
72 element: &mut Self::FrameState,
73 cx: &mut ViewContext<Self::State>,
74 ) -> Result<()> {
75 self.state
76 .update(cx, |state, cx| element.paint(state, None, cx))
77 }
78}
79
80trait ViewObject: Send + 'static {
81 fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box<dyn Any>)>;
82 fn paint(
83 &mut self,
84 bounds: Bounds<Pixels>,
85 element: &mut dyn Any,
86 cx: &mut WindowContext,
87 ) -> Result<()>;
88}
89
90impl<S: Send + Sync + 'static, P: Send + 'static> ViewObject for View<S, P> {
91 fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box<dyn Any>)> {
92 self.state.update(cx, |state, cx| {
93 let mut element = (self.render)(state, cx);
94 let layout_id = element.layout(state, cx)?;
95 let element = Box::new(element) as Box<dyn Any>;
96 Ok((layout_id, element))
97 })
98 }
99
100 fn paint(
101 &mut self,
102 _: Bounds<Pixels>,
103 element: &mut dyn Any,
104 cx: &mut WindowContext,
105 ) -> Result<()> {
106 self.state.update(cx, |state, cx| {
107 let element = element.downcast_mut::<AnyElement<S>>().unwrap();
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 bounds: Bounds<Pixels>,
133 _: &mut (),
134 element: &mut Box<dyn Any>,
135 cx: &mut ViewContext<Self::State>,
136 ) -> Result<()> {
137 self.view.lock().paint(bounds, element.as_mut(), cx)
138 }
139}
140
141impl<S> Clone for AnyView<S> {
142 fn clone(&self) -> Self {
143 Self {
144 view: self.view.clone(),
145 parent_state_type: PhantomData,
146 }
147 }
148}