elements.rs

  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> {}