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
113pub enum Lifecycle<T: Element> {
114 Empty,
115 Init {
116 element: T,
117 },
118 PostLayout {
119 element: T,
120 constraint: SizeConstraint,
121 size: Vector2F,
122 layout: T::LayoutState,
123 },
124 PostPaint {
125 element: T,
126 constraint: SizeConstraint,
127 bounds: RectF,
128 layout: T::LayoutState,
129 paint: T::PaintState,
130 },
131}
132pub struct ElementBox(ElementRc);
133
134#[derive(Clone)]
135pub struct ElementRc {
136 name: Option<Cow<'static, str>>,
137 element: Rc<RefCell<dyn AnyElement>>,
138}
139
140impl<T: Element> AnyElement for Lifecycle<T> {
141 fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F {
142 let result;
143 *self = match mem::take(self) {
144 Lifecycle::Empty => unreachable!(),
145 Lifecycle::Init { mut element }
146 | Lifecycle::PostLayout { mut element, .. }
147 | Lifecycle::PostPaint { mut element, .. } => {
148 let (size, layout) = element.layout(constraint, cx);
149 debug_assert!(size.x().is_finite());
150 debug_assert!(size.y().is_finite());
151
152 result = size;
153 Lifecycle::PostLayout {
154 element,
155 constraint,
156 size,
157 layout,
158 }
159 }
160 };
161 result
162 }
163
164 fn paint(&mut self, origin: Vector2F, visible_bounds: RectF, cx: &mut PaintContext) {
165 *self = match mem::take(self) {
166 Lifecycle::PostLayout {
167 mut element,
168 constraint,
169 size,
170 mut layout,
171 } => {
172 let bounds = RectF::new(origin, size);
173 let visible_bounds = visible_bounds
174 .intersection(bounds)
175 .unwrap_or_else(|| RectF::new(bounds.origin(), Vector2F::default()));
176 let paint = element.paint(bounds, visible_bounds, &mut layout, cx);
177 Lifecycle::PostPaint {
178 element,
179 constraint,
180 bounds,
181 layout,
182 paint,
183 }
184 }
185 Lifecycle::PostPaint {
186 mut element,
187 constraint,
188 bounds,
189 mut layout,
190 ..
191 } => {
192 let bounds = RectF::new(origin, bounds.size());
193 let visible_bounds = visible_bounds
194 .intersection(bounds)
195 .unwrap_or_else(|| RectF::new(bounds.origin(), Vector2F::default()));
196 let paint = element.paint(bounds, visible_bounds, &mut layout, cx);
197 Lifecycle::PostPaint {
198 element,
199 constraint,
200 bounds,
201 layout,
202 paint,
203 }
204 }
205 _ => panic!("invalid element lifecycle state"),
206 }
207 }
208
209 fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool {
210 if let Lifecycle::PostPaint {
211 element,
212 bounds,
213 layout,
214 paint,
215 ..
216 } = self
217 {
218 element.dispatch_event(event, *bounds, layout, paint, cx)
219 } else {
220 panic!("invalid element lifecycle state");
221 }
222 }
223
224 fn size(&self) -> Vector2F {
225 match self {
226 Lifecycle::Empty | Lifecycle::Init { .. } => panic!("invalid element lifecycle state"),
227 Lifecycle::PostLayout { size, .. } => *size,
228 Lifecycle::PostPaint { bounds, .. } => bounds.size(),
229 }
230 }
231
232 fn metadata(&self) -> Option<&dyn Any> {
233 match self {
234 Lifecycle::Empty => unreachable!(),
235 Lifecycle::Init { element }
236 | Lifecycle::PostLayout { element, .. }
237 | Lifecycle::PostPaint { element, .. } => element.metadata(),
238 }
239 }
240
241 fn debug(&self, cx: &DebugContext) -> serde_json::Value {
242 match self {
243 Lifecycle::PostPaint {
244 element,
245 constraint,
246 bounds,
247 layout,
248 paint,
249 } => {
250 let mut value = element.debug(*bounds, layout, paint, cx);
251 if let json::Value::Object(map) = &mut value {
252 let mut new_map: crate::json::Map<String, serde_json::Value> =
253 Default::default();
254 if let Some(typ) = map.remove("type") {
255 new_map.insert("type".into(), typ);
256 }
257 new_map.insert("constraint".into(), constraint.to_json());
258 new_map.append(map);
259 json::Value::Object(new_map)
260 } else {
261 value
262 }
263 }
264 _ => panic!("invalid element lifecycle state"),
265 }
266 }
267}
268
269impl<T: Element> Default for Lifecycle<T> {
270 fn default() -> Self {
271 Self::Empty
272 }
273}
274
275impl ElementBox {
276 pub fn metadata<T: 'static>(&self) -> Option<&T> {
277 let element = unsafe { &*self.0.element.as_ptr() };
278 element.metadata().and_then(|m| m.downcast_ref())
279 }
280}
281
282impl Into<ElementRc> for ElementBox {
283 fn into(self) -> ElementRc {
284 self.0
285 }
286}
287
288impl Deref for ElementBox {
289 type Target = ElementRc;
290
291 fn deref(&self) -> &Self::Target {
292 &self.0
293 }
294}
295
296impl DerefMut for ElementBox {
297 fn deref_mut(&mut self) -> &mut Self::Target {
298 &mut self.0
299 }
300}
301
302impl ElementRc {
303 pub fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F {
304 self.element.borrow_mut().layout(constraint, cx)
305 }
306
307 pub fn paint(&mut self, origin: Vector2F, visible_bounds: RectF, cx: &mut PaintContext) {
308 self.element.borrow_mut().paint(origin, visible_bounds, cx);
309 }
310
311 pub fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool {
312 self.element.borrow_mut().dispatch_event(event, cx)
313 }
314
315 pub fn size(&self) -> Vector2F {
316 self.element.borrow().size()
317 }
318
319 pub fn debug(&self, cx: &DebugContext) -> json::Value {
320 let mut value = self.element.borrow().debug(cx);
321
322 if let Some(name) = &self.name {
323 if let json::Value::Object(map) = &mut value {
324 let mut new_map: crate::json::Map<String, serde_json::Value> = Default::default();
325 new_map.insert("name".into(), json::Value::String(name.to_string()));
326 new_map.append(map);
327 return json::Value::Object(new_map);
328 }
329 }
330
331 value
332 }
333
334 pub fn with_metadata<T, F, R>(&self, f: F) -> R
335 where
336 T: 'static,
337 F: FnOnce(Option<&T>) -> R,
338 {
339 let element = self.element.borrow();
340 f(element.metadata().and_then(|m| m.downcast_ref()))
341 }
342}
343
344pub trait ParentElement<'a>: Extend<ElementBox> + Sized {
345 fn add_children(&mut self, children: impl IntoIterator<Item = ElementBox>) {
346 self.extend(children);
347 }
348
349 fn add_child(&mut self, child: ElementBox) {
350 self.add_children(Some(child));
351 }
352
353 fn with_children(mut self, children: impl IntoIterator<Item = ElementBox>) -> Self {
354 self.add_children(children);
355 self
356 }
357
358 fn with_child(self, child: ElementBox) -> Self {
359 self.with_children(Some(child))
360 }
361}
362
363impl<'a, T> ParentElement<'a> for T where T: Extend<ElementBox> {}
364
365fn constrain_size_preserving_aspect_ratio(max_size: Vector2F, size: Vector2F) -> Vector2F {
366 if max_size.x().is_infinite() && max_size.y().is_infinite() {
367 size
368 } else if max_size.x().is_infinite() || max_size.x() / max_size.y() > size.x() / size.y() {
369 vec2f(size.x() * max_size.y() / size.y(), max_size.y())
370 } else {
371 vec2f(max_size.x(), size.y() * max_size.x() / size.x())
372 }
373}