1use parking_lot::Mutex;
2
3use crate::{
4 AnyBox, AnyElement, BorrowWindow, Bounds, Element, ElementId, Handle, IdentifiedElement,
5 IntoAnyElement, LayoutId, Pixels, ViewContext, 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 + Sync> 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<ViewState = 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: 'static + Send + Sync, P: 'static + Send + Sync> Element for View<S, P> {
53 type ViewState = P;
54 type ElementState = AnyElement<S>;
55
56 fn element_id(&self) -> Option<crate::ElementId> {
57 Some(ElementId::View(self.state.id))
58 }
59
60 fn layout(
61 &mut self,
62 _: &mut Self::ViewState,
63 _: Option<Self::ElementState>,
64 cx: &mut ViewContext<Self::ViewState>,
65 ) -> (LayoutId, Self::ElementState) {
66 self.state.update(cx, |state, cx| {
67 let mut element = (self.render)(state, cx);
68 let layout_id = element.layout(state, cx);
69 (layout_id, element)
70 })
71 }
72
73 fn paint(
74 &mut self,
75 _: Bounds<Pixels>,
76 _: &mut Self::ViewState,
77 element: &mut Self::ElementState,
78 cx: &mut ViewContext<Self::ViewState>,
79 ) {
80 self.state
81 .update(cx, |state, cx| element.paint(state, None, cx))
82 }
83}
84
85trait ViewObject: Send + 'static {
86 fn layout(&mut self, cx: &mut WindowContext) -> (LayoutId, AnyBox);
87 fn paint(&mut self, bounds: Bounds<Pixels>, element: &mut dyn Any, cx: &mut WindowContext);
88}
89
90impl<S: Send + Sync + 'static, P: Send + Sync + 'static> IdentifiedElement for View<S, P> {}
91
92impl<S: Send + Sync + 'static, P: Send + Sync + 'static> ViewObject for View<S, P> {
93 fn layout(&mut self, cx: &mut WindowContext) -> (LayoutId, AnyBox) {
94 cx.with_element_id(IdentifiedElement::element_id(self), |cx| {
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 AnyBox;
99 (layout_id, element)
100 })
101 })
102 }
103
104 fn paint(&mut self, _: Bounds<Pixels>, element: &mut dyn Any, cx: &mut WindowContext) {
105 cx.with_element_id(IdentifiedElement::element_id(self), |cx| {
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}
113
114pub struct AnyView<S> {
115 view: Arc<Mutex<dyn ViewObject>>,
116 parent_state_type: PhantomData<S>,
117}
118
119impl<S: 'static + Send + Sync> Element for AnyView<S> {
120 type ViewState = ();
121 type ElementState = AnyBox;
122
123 fn element_id(&self) -> Option<crate::ElementId> {
124 None
125 }
126
127 fn layout(
128 &mut self,
129 _: &mut Self::ViewState,
130 _: Option<Self::ElementState>,
131 cx: &mut ViewContext<Self::ViewState>,
132 ) -> (LayoutId, Self::ElementState) {
133 self.view.lock().layout(cx)
134 }
135
136 fn paint(
137 &mut self,
138 bounds: Bounds<Pixels>,
139 _: &mut (),
140 element: &mut AnyBox,
141 cx: &mut ViewContext<Self::ViewState>,
142 ) {
143 self.view.lock().paint(bounds, element.as_mut(), cx)
144 }
145}
146
147impl<S> Clone for AnyView<S> {
148 fn clone(&self) -> Self {
149 Self {
150 view: self.view.clone(),
151 parent_state_type: PhantomData,
152 }
153 }
154}