elements.rs

  1mod align;
  2mod canvas;
  3mod constrained_box;
  4mod container;
  5mod empty;
  6mod event_handler;
  7mod flex;
  8mod label;
  9mod line_box;
 10mod list;
 11mod mouse_event_handler;
 12mod stack;
 13mod svg;
 14mod uniform_list;
 15
 16pub use crate::presenter::ChildView;
 17pub use align::*;
 18pub use canvas::*;
 19pub use constrained_box::*;
 20pub use container::*;
 21pub use empty::*;
 22pub use event_handler::*;
 23pub use flex::*;
 24pub use label::*;
 25pub use line_box::*;
 26pub use list::*;
 27pub use mouse_event_handler::*;
 28pub use stack::*;
 29pub use svg::*;
 30pub use uniform_list::*;
 31
 32use crate::{
 33    geometry::{rect::RectF, vector::Vector2F},
 34    json, AfterLayoutContext, DebugContext, Event, EventContext, LayoutContext, PaintContext,
 35    SizeConstraint,
 36};
 37use core::panic;
 38use json::ToJson;
 39use std::{any::Any, borrow::Cow, mem};
 40
 41trait AnyElement {
 42    fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F;
 43    fn after_layout(&mut self, _: &mut AfterLayoutContext) {}
 44    fn paint(&mut self, origin: Vector2F, cx: &mut PaintContext);
 45    fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool;
 46    fn debug(&self, cx: &DebugContext) -> serde_json::Value;
 47
 48    fn size(&self) -> Vector2F;
 49    fn metadata(&self) -> Option<&dyn Any>;
 50}
 51
 52pub trait Element {
 53    type LayoutState;
 54    type PaintState;
 55
 56    fn layout(
 57        &mut self,
 58        constraint: SizeConstraint,
 59        cx: &mut LayoutContext,
 60    ) -> (Vector2F, Self::LayoutState);
 61
 62    fn after_layout(
 63        &mut self,
 64        size: Vector2F,
 65        layout: &mut Self::LayoutState,
 66        cx: &mut AfterLayoutContext,
 67    );
 68
 69    fn paint(
 70        &mut self,
 71        bounds: RectF,
 72        layout: &mut Self::LayoutState,
 73        cx: &mut PaintContext,
 74    ) -> Self::PaintState;
 75
 76    fn dispatch_event(
 77        &mut self,
 78        event: &Event,
 79        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 {
102            name: None,
103            element: Box::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 {
112            name: Some(name.into()),
113            element: Box::new(Lifecycle::Init { element: self }),
114        }
115    }
116}
117
118pub enum Lifecycle<T: Element> {
119    Empty,
120    Init {
121        element: T,
122    },
123    PostLayout {
124        element: T,
125        constraint: SizeConstraint,
126        size: Vector2F,
127        layout: T::LayoutState,
128    },
129    PostPaint {
130        element: T,
131        constraint: SizeConstraint,
132        bounds: RectF,
133        layout: T::LayoutState,
134        paint: T::PaintState,
135    },
136}
137pub struct ElementBox {
138    name: Option<Cow<'static, str>>,
139    element: Box<dyn AnyElement>,
140}
141
142impl<T: Element> AnyElement for Lifecycle<T> {
143    fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F {
144        let result;
145        *self = match mem::take(self) {
146            Lifecycle::Empty => unreachable!(),
147            Lifecycle::Init { mut element }
148            | Lifecycle::PostLayout { mut element, .. }
149            | Lifecycle::PostPaint { mut element, .. } => {
150                let (size, layout) = element.layout(constraint, cx);
151                debug_assert!(size.x().is_finite());
152                debug_assert!(size.y().is_finite());
153
154                result = size;
155                Lifecycle::PostLayout {
156                    element,
157                    constraint,
158                    size,
159                    layout,
160                }
161            }
162        };
163        result
164    }
165
166    fn after_layout(&mut self, cx: &mut AfterLayoutContext) {
167        if let Lifecycle::PostLayout {
168            element,
169            size,
170            layout,
171            ..
172        } = self
173        {
174            element.after_layout(*size, layout, cx);
175        } else {
176            panic!("invalid element lifecycle state");
177        }
178    }
179
180    fn paint(&mut self, origin: Vector2F, cx: &mut PaintContext) {
181        *self = if let Lifecycle::PostLayout {
182            mut element,
183            constraint,
184            size,
185            mut layout,
186        } = mem::take(self)
187        {
188            let bounds = RectF::new(origin, size);
189            let paint = element.paint(bounds, &mut layout, cx);
190            Lifecycle::PostPaint {
191                element,
192                constraint,
193                bounds,
194                layout,
195                paint,
196            }
197        } else {
198            panic!("invalid element lifecycle state");
199        };
200    }
201
202    fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool {
203        if let Lifecycle::PostPaint {
204            element,
205            bounds,
206            layout,
207            paint,
208            ..
209        } = self
210        {
211            element.dispatch_event(event, *bounds, layout, paint, cx)
212        } else {
213            panic!("invalid element lifecycle state");
214        }
215    }
216
217    fn size(&self) -> Vector2F {
218        match self {
219            Lifecycle::Empty | Lifecycle::Init { .. } => panic!("invalid element lifecycle state"),
220            Lifecycle::PostLayout { size, .. } => *size,
221            Lifecycle::PostPaint { bounds, .. } => bounds.size(),
222        }
223    }
224
225    fn metadata(&self) -> Option<&dyn Any> {
226        match self {
227            Lifecycle::Empty => unreachable!(),
228            Lifecycle::Init { element }
229            | Lifecycle::PostLayout { element, .. }
230            | Lifecycle::PostPaint { element, .. } => element.metadata(),
231        }
232    }
233
234    fn debug(&self, cx: &DebugContext) -> serde_json::Value {
235        match self {
236            Lifecycle::PostPaint {
237                element,
238                constraint,
239                bounds,
240                layout,
241                paint,
242            } => {
243                let mut value = element.debug(*bounds, layout, paint, cx);
244                if let json::Value::Object(map) = &mut value {
245                    let mut new_map: crate::json::Map<String, serde_json::Value> =
246                        Default::default();
247                    if let Some(typ) = map.remove("type") {
248                        new_map.insert("type".into(), typ);
249                    }
250                    new_map.insert("constraint".into(), constraint.to_json());
251                    new_map.append(map);
252                    json::Value::Object(new_map)
253                } else {
254                    value
255                }
256            }
257            _ => panic!("invalid element lifecycle state"),
258        }
259    }
260}
261
262impl<T: Element> Default for Lifecycle<T> {
263    fn default() -> Self {
264        Self::Empty
265    }
266}
267
268impl ElementBox {
269    pub fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F {
270        self.element.layout(constraint, cx)
271    }
272
273    pub fn after_layout(&mut self, cx: &mut AfterLayoutContext) {
274        self.element.after_layout(cx);
275    }
276
277    pub fn paint(&mut self, origin: Vector2F, cx: &mut PaintContext) {
278        self.element.paint(origin, cx);
279    }
280
281    pub fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool {
282        self.element.dispatch_event(event, cx)
283    }
284
285    pub fn size(&self) -> Vector2F {
286        self.element.size()
287    }
288
289    pub fn metadata(&self) -> Option<&dyn Any> {
290        self.element.metadata()
291    }
292
293    pub fn debug(&self, cx: &DebugContext) -> json::Value {
294        let mut value = self.element.debug(cx);
295
296        if let Some(name) = &self.name {
297            if let json::Value::Object(map) = &mut value {
298                let mut new_map: crate::json::Map<String, serde_json::Value> = Default::default();
299                new_map.insert("name".into(), json::Value::String(name.to_string()));
300                new_map.append(map);
301                return json::Value::Object(new_map);
302            }
303        }
304
305        value
306    }
307}
308
309pub trait ParentElement<'a>: Extend<ElementBox> + Sized {
310    fn add_children(&mut self, children: impl IntoIterator<Item = ElementBox>) {
311        self.extend(children);
312    }
313
314    fn add_child(&mut self, child: ElementBox) {
315        self.add_children(Some(child));
316    }
317
318    fn with_children(mut self, children: impl IntoIterator<Item = ElementBox>) -> Self {
319        self.add_children(children);
320        self
321    }
322
323    fn with_child(self, child: ElementBox) -> Self {
324        self.with_children(Some(child))
325    }
326}
327
328impl<'a, T> ParentElement<'a> for T where T: Extend<ElementBox> {}