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