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