elements.rs

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