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