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