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