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