1use crate::{BorrowWindow, Bounds, ElementId, LayoutId, Pixels, ViewContext};
2use derive_more::{Deref, DerefMut};
3pub(crate) use smallvec::SmallVec;
4use std::{any::Any, mem};
5
6pub trait Element: IntoAnyElement<Self::ViewState> {
7 type ViewState: 'static;
8 type ElementState: 'static;
9
10 fn id(&self) -> Option<ElementId>;
11
12 fn initialize(
13 &mut self,
14 view_state: &mut Self::ViewState,
15 element_state: Option<Self::ElementState>,
16 cx: &mut ViewContext<Self::ViewState>,
17 ) -> Self::ElementState;
18 // where
19 // Self::ViewState: Any + Send + Sync;
20
21 fn layout(
22 &mut self,
23 view_state: &mut Self::ViewState,
24 element_state: &mut Self::ElementState,
25 cx: &mut ViewContext<Self::ViewState>,
26 ) -> LayoutId;
27 // where
28 // Self::ViewState: Any + Send + Sync;
29
30 fn paint(
31 &mut self,
32 bounds: Bounds<Pixels>,
33 view_state: &mut Self::ViewState,
34 element_state: &mut Self::ElementState,
35 cx: &mut ViewContext<Self::ViewState>,
36 );
37
38 // where
39 // Self::ViewState: Any + Send + Sync;
40}
41
42#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
43pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
44
45pub trait ParentElement: Element {
46 fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]>;
47
48 fn child(mut self, child: impl IntoAnyElement<Self::ViewState>) -> Self
49 where
50 Self: Sized,
51 {
52 self.children_mut().push(child.into_any());
53 self
54 }
55
56 fn children(
57 mut self,
58 iter: impl IntoIterator<Item = impl IntoAnyElement<Self::ViewState>>,
59 ) -> Self
60 where
61 Self: Sized,
62 {
63 self.children_mut()
64 .extend(iter.into_iter().map(|item| item.into_any()));
65 self
66 }
67}
68
69trait ElementObject<V> {
70 fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
71 fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId;
72 fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
73}
74
75struct RenderedElement<E: Element> {
76 element: E,
77 phase: ElementRenderPhase<E::ElementState>,
78}
79
80#[derive(Default)]
81enum ElementRenderPhase<V> {
82 #[default]
83 Start,
84 Initialized {
85 frame_state: Option<V>,
86 },
87 LayoutRequested {
88 layout_id: LayoutId,
89 frame_state: Option<V>,
90 },
91 Painted,
92}
93
94/// Internal struct that wraps an element to store Layout and ElementState after the element is rendered.
95/// It's allocated as a trait object to erase the element type and wrapped in AnyElement<E::State> for
96/// improved usability.
97impl<E: Element> RenderedElement<E> {
98 fn new(element: E) -> Self {
99 RenderedElement {
100 element,
101 phase: ElementRenderPhase::Start,
102 }
103 }
104}
105
106impl<E> ElementObject<E::ViewState> for RenderedElement<E>
107where
108 E: Element,
109 // E::ViewState: Any + Send + Sync,
110 E::ElementState: Any + Send + Sync,
111{
112 fn initialize(&mut self, view_state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) {
113 let frame_state = if let Some(id) = self.element.id() {
114 cx.with_element_state(id, |element_state, cx| {
115 let element_state = self.element.initialize(view_state, element_state, cx);
116 ((), element_state)
117 });
118 None
119 } else {
120 let frame_state = self.element.initialize(view_state, None, cx);
121 Some(frame_state)
122 };
123
124 self.phase = ElementRenderPhase::Initialized { frame_state };
125 }
126
127 fn layout(&mut self, state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) -> LayoutId {
128 let layout_id;
129 let mut frame_state;
130 match mem::take(&mut self.phase) {
131 ElementRenderPhase::Initialized {
132 frame_state: initial_frame_state,
133 } => {
134 frame_state = initial_frame_state;
135 if let Some(id) = self.element.id() {
136 layout_id = cx.with_element_state(id, |element_state, cx| {
137 let mut element_state = element_state.unwrap();
138 let layout_id = self.element.layout(state, &mut element_state, cx);
139 (layout_id, element_state)
140 });
141 } else {
142 layout_id = self
143 .element
144 .layout(state, frame_state.as_mut().unwrap(), cx);
145 }
146 }
147 _ => panic!("must call initialize before layout"),
148 };
149
150 self.phase = ElementRenderPhase::LayoutRequested {
151 layout_id,
152 frame_state,
153 };
154 layout_id
155 }
156
157 fn paint(&mut self, view_state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) {
158 self.phase = match mem::take(&mut self.phase) {
159 ElementRenderPhase::LayoutRequested {
160 layout_id,
161 mut frame_state,
162 } => {
163 let bounds = cx.layout_bounds(layout_id);
164 if let Some(id) = self.element.id() {
165 cx.with_element_state(id, |element_state, cx| {
166 let mut element_state = element_state.unwrap();
167 self.element
168 .paint(bounds, view_state, &mut element_state, cx);
169 ((), element_state)
170 });
171 } else {
172 self.element
173 .paint(bounds, view_state, frame_state.as_mut().unwrap(), cx);
174 }
175 ElementRenderPhase::Painted
176 }
177
178 _ => panic!("must call layout before paint"),
179 };
180 }
181}
182
183pub struct AnyElement<V>(Box<dyn ElementObject<V> + Send + Sync>);
184
185impl<V> AnyElement<V> {
186 pub fn new<E>(element: E) -> Self
187 where
188 E: 'static + Send + Sync,
189 E: Element<ViewState = V>,
190 E::ElementState: Any + Send + Sync,
191 {
192 AnyElement(Box::new(RenderedElement::new(element)))
193 }
194
195 pub fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
196 self.0.initialize(view_state, cx);
197 }
198
199 pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
200 self.0.layout(view_state, cx)
201 }
202
203 pub fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
204 self.0.paint(view_state, cx)
205 }
206}
207
208pub trait IntoAnyElement<V> {
209 fn into_any(self) -> AnyElement<V>;
210}
211
212impl<V> IntoAnyElement<V> for AnyElement<V> {
213 fn into_any(self) -> AnyElement<V> {
214 self
215 }
216}