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