1mod align;
2mod canvas;
3mod constrained_box;
4mod container;
5mod empty;
6mod event_handler;
7mod flex;
8mod label;
9mod line_box;
10mod list;
11mod mouse_event_handler;
12mod overlay;
13mod stack;
14mod svg;
15mod text;
16mod uniform_list;
17
18pub use crate::presenter::ChildView;
19pub use align::*;
20pub use canvas::*;
21pub use constrained_box::*;
22pub use container::*;
23pub use empty::*;
24pub use event_handler::*;
25pub use flex::*;
26pub use label::*;
27pub use line_box::*;
28pub use list::*;
29pub use mouse_event_handler::*;
30pub use overlay::*;
31pub use stack::*;
32pub use svg::*;
33pub use text::*;
34pub use uniform_list::*;
35
36use crate::{
37 geometry::{rect::RectF, vector::Vector2F},
38 json, DebugContext, Event, EventContext, LayoutContext, PaintContext, SizeConstraint,
39};
40use core::panic;
41use json::ToJson;
42use std::{
43 any::Any,
44 borrow::Cow,
45 cell::RefCell,
46 mem,
47 ops::{Deref, DerefMut},
48 rc::Rc,
49};
50
51trait AnyElement {
52 fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F;
53 fn paint(&mut self, origin: Vector2F, visible_bounds: RectF, cx: &mut PaintContext);
54 fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool;
55 fn debug(&self, cx: &DebugContext) -> serde_json::Value;
56
57 fn size(&self) -> Vector2F;
58 fn metadata(&self) -> Option<&dyn Any>;
59}
60
61pub trait Element {
62 type LayoutState;
63 type PaintState;
64
65 fn layout(
66 &mut self,
67 constraint: SizeConstraint,
68 cx: &mut LayoutContext,
69 ) -> (Vector2F, Self::LayoutState);
70
71 fn paint(
72 &mut self,
73 bounds: RectF,
74 visible_bounds: RectF,
75 layout: &mut Self::LayoutState,
76 cx: &mut PaintContext,
77 ) -> Self::PaintState;
78
79 fn dispatch_event(
80 &mut self,
81 event: &Event,
82 bounds: RectF,
83 layout: &mut Self::LayoutState,
84 paint: &mut Self::PaintState,
85 cx: &mut EventContext,
86 ) -> bool;
87
88 fn metadata(&self) -> Option<&dyn Any> {
89 None
90 }
91
92 fn debug(
93 &self,
94 bounds: RectF,
95 layout: &Self::LayoutState,
96 paint: &Self::PaintState,
97 cx: &DebugContext,
98 ) -> serde_json::Value;
99
100 fn boxed(self) -> ElementBox
101 where
102 Self: 'static + Sized,
103 {
104 ElementBox(ElementRc {
105 name: None,
106 element: Rc::new(RefCell::new(Lifecycle::Init { element: self })),
107 })
108 }
109
110 fn named(self, name: impl Into<Cow<'static, str>>) -> ElementBox
111 where
112 Self: 'static + Sized,
113 {
114 ElementBox(ElementRc {
115 name: Some(name.into()),
116 element: Rc::new(RefCell::new(Lifecycle::Init { element: self })),
117 })
118 }
119}
120
121pub enum Lifecycle<T: Element> {
122 Empty,
123 Init {
124 element: T,
125 },
126 PostLayout {
127 element: T,
128 constraint: SizeConstraint,
129 size: Vector2F,
130 layout: T::LayoutState,
131 },
132 PostPaint {
133 element: T,
134 constraint: SizeConstraint,
135 bounds: RectF,
136 layout: T::LayoutState,
137 paint: T::PaintState,
138 },
139}
140pub struct ElementBox(ElementRc);
141
142#[derive(Clone)]
143pub struct ElementRc {
144 name: Option<Cow<'static, str>>,
145 element: Rc<RefCell<dyn AnyElement>>,
146}
147
148impl<T: Element> AnyElement for Lifecycle<T> {
149 fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F {
150 let result;
151 *self = match mem::take(self) {
152 Lifecycle::Empty => unreachable!(),
153 Lifecycle::Init { mut element }
154 | Lifecycle::PostLayout { mut element, .. }
155 | Lifecycle::PostPaint { mut element, .. } => {
156 let (size, layout) = element.layout(constraint, cx);
157 debug_assert!(size.x().is_finite());
158 debug_assert!(size.y().is_finite());
159
160 result = size;
161 Lifecycle::PostLayout {
162 element,
163 constraint,
164 size,
165 layout,
166 }
167 }
168 };
169 result
170 }
171
172 fn paint(&mut self, origin: Vector2F, visible_bounds: RectF, cx: &mut PaintContext) {
173 *self = match mem::take(self) {
174 Lifecycle::PostLayout {
175 mut element,
176 constraint,
177 size,
178 mut layout,
179 } => {
180 let bounds = RectF::new(origin, size);
181 let visible_bounds = visible_bounds
182 .intersection(bounds)
183 .unwrap_or_else(|| RectF::new(bounds.origin(), Vector2F::default()));
184 let paint = element.paint(bounds, visible_bounds, &mut layout, cx);
185 Lifecycle::PostPaint {
186 element,
187 constraint,
188 bounds,
189 layout,
190 paint,
191 }
192 }
193 Lifecycle::PostPaint {
194 mut element,
195 constraint,
196 bounds,
197 mut layout,
198 ..
199 } => {
200 let bounds = RectF::new(origin, bounds.size());
201 let visible_bounds = visible_bounds
202 .intersection(bounds)
203 .unwrap_or_else(|| RectF::new(bounds.origin(), Vector2F::default()));
204 let paint = element.paint(bounds, visible_bounds, &mut layout, cx);
205 Lifecycle::PostPaint {
206 element,
207 constraint,
208 bounds,
209 layout,
210 paint,
211 }
212 }
213 _ => panic!("invalid element lifecycle state"),
214 }
215 }
216
217 fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool {
218 if let Lifecycle::PostPaint {
219 element,
220 bounds,
221 layout,
222 paint,
223 ..
224 } = self
225 {
226 element.dispatch_event(event, *bounds, layout, paint, cx)
227 } else {
228 panic!("invalid element lifecycle state");
229 }
230 }
231
232 fn size(&self) -> Vector2F {
233 match self {
234 Lifecycle::Empty | Lifecycle::Init { .. } => panic!("invalid element lifecycle state"),
235 Lifecycle::PostLayout { size, .. } => *size,
236 Lifecycle::PostPaint { bounds, .. } => bounds.size(),
237 }
238 }
239
240 fn metadata(&self) -> Option<&dyn Any> {
241 match self {
242 Lifecycle::Empty => unreachable!(),
243 Lifecycle::Init { element }
244 | Lifecycle::PostLayout { element, .. }
245 | Lifecycle::PostPaint { element, .. } => element.metadata(),
246 }
247 }
248
249 fn debug(&self, cx: &DebugContext) -> serde_json::Value {
250 match self {
251 Lifecycle::PostPaint {
252 element,
253 constraint,
254 bounds,
255 layout,
256 paint,
257 } => {
258 let mut value = element.debug(*bounds, layout, paint, cx);
259 if let json::Value::Object(map) = &mut value {
260 let mut new_map: crate::json::Map<String, serde_json::Value> =
261 Default::default();
262 if let Some(typ) = map.remove("type") {
263 new_map.insert("type".into(), typ);
264 }
265 new_map.insert("constraint".into(), constraint.to_json());
266 new_map.append(map);
267 json::Value::Object(new_map)
268 } else {
269 value
270 }
271 }
272 _ => panic!("invalid element lifecycle state"),
273 }
274 }
275}
276
277impl<T: Element> Default for Lifecycle<T> {
278 fn default() -> Self {
279 Self::Empty
280 }
281}
282
283impl ElementBox {
284 pub fn metadata<T: 'static>(&self) -> Option<&T> {
285 let element = unsafe { &*self.0.element.as_ptr() };
286 element.metadata().and_then(|m| m.downcast_ref())
287 }
288}
289
290impl Into<ElementRc> for ElementBox {
291 fn into(self) -> ElementRc {
292 self.0
293 }
294}
295
296impl Deref for ElementBox {
297 type Target = ElementRc;
298
299 fn deref(&self) -> &Self::Target {
300 &self.0
301 }
302}
303
304impl DerefMut for ElementBox {
305 fn deref_mut(&mut self) -> &mut Self::Target {
306 &mut self.0
307 }
308}
309
310impl ElementRc {
311 pub fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F {
312 self.element.borrow_mut().layout(constraint, cx)
313 }
314
315 pub fn paint(&mut self, origin: Vector2F, visible_bounds: RectF, cx: &mut PaintContext) {
316 self.element.borrow_mut().paint(origin, visible_bounds, cx);
317 }
318
319 pub fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool {
320 self.element.borrow_mut().dispatch_event(event, cx)
321 }
322
323 pub fn size(&self) -> Vector2F {
324 self.element.borrow().size()
325 }
326
327 pub fn debug(&self, cx: &DebugContext) -> json::Value {
328 let mut value = self.element.borrow().debug(cx);
329
330 if let Some(name) = &self.name {
331 if let json::Value::Object(map) = &mut value {
332 let mut new_map: crate::json::Map<String, serde_json::Value> = Default::default();
333 new_map.insert("name".into(), json::Value::String(name.to_string()));
334 new_map.append(map);
335 return json::Value::Object(new_map);
336 }
337 }
338
339 value
340 }
341
342 pub fn with_metadata<T, F, R>(&self, f: F) -> R
343 where
344 T: 'static,
345 F: FnOnce(Option<&T>) -> R,
346 {
347 let element = self.element.borrow();
348 f(element.metadata().and_then(|m| m.downcast_ref()))
349 }
350}
351
352pub trait ParentElement<'a>: Extend<ElementBox> + Sized {
353 fn add_children(&mut self, children: impl IntoIterator<Item = ElementBox>) {
354 self.extend(children);
355 }
356
357 fn add_child(&mut self, child: ElementBox) {
358 self.add_children(Some(child));
359 }
360
361 fn with_children(mut self, children: impl IntoIterator<Item = ElementBox>) -> Self {
362 self.add_children(children);
363 self
364 }
365
366 fn with_child(self, child: ElementBox) -> Self {
367 self.with_children(Some(child))
368 }
369}
370
371impl<'a, T> ParentElement<'a> for T where T: Extend<ElementBox> {}