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 std::{any::Any, borrow::Cow, mem};
 38
 39trait AnyElement {
 40    fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F;
 41    fn after_layout(&mut self, _: &mut AfterLayoutContext) {}
 42    fn paint(&mut self, origin: Vector2F, cx: &mut PaintContext);
 43    fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool;
 44    fn debug(&self, cx: &DebugContext) -> serde_json::Value;
 45
 46    fn size(&self) -> Vector2F;
 47    fn metadata(&self) -> Option<&dyn Any>;
 48}
 49
 50pub trait Element {
 51    type LayoutState;
 52    type PaintState;
 53
 54    fn layout(
 55        &mut self,
 56        constraint: SizeConstraint,
 57        cx: &mut LayoutContext,
 58    ) -> (Vector2F, Self::LayoutState);
 59
 60    fn after_layout(
 61        &mut self,
 62        size: Vector2F,
 63        layout: &mut Self::LayoutState,
 64        cx: &mut AfterLayoutContext,
 65    );
 66
 67    fn paint(
 68        &mut self,
 69        bounds: RectF,
 70        layout: &mut Self::LayoutState,
 71        cx: &mut PaintContext,
 72    ) -> Self::PaintState;
 73
 74    fn dispatch_event(
 75        &mut self,
 76        event: &Event,
 77        bounds: RectF,
 78        layout: &mut Self::LayoutState,
 79        paint: &mut Self::PaintState,
 80        cx: &mut EventContext,
 81    ) -> bool;
 82
 83    fn metadata(&self) -> Option<&dyn Any> {
 84        None
 85    }
 86
 87    fn debug(
 88        &self,
 89        bounds: RectF,
 90        layout: &Self::LayoutState,
 91        paint: &Self::PaintState,
 92        cx: &DebugContext,
 93    ) -> serde_json::Value;
 94
 95    fn boxed(self) -> ElementBox
 96    where
 97        Self: 'static + Sized,
 98    {
 99        ElementBox {
100            name: None,
101            element: Box::new(Lifecycle::Init { element: self }),
102        }
103    }
104
105    fn named(self, name: impl Into<Cow<'static, str>>) -> ElementBox
106    where
107        Self: 'static + Sized,
108    {
109        ElementBox {
110            name: Some(name.into()),
111            element: Box::new(Lifecycle::Init { element: self }),
112        }
113    }
114}
115
116pub enum Lifecycle<T: Element> {
117    Empty,
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 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 after_layout(&mut self, cx: &mut AfterLayoutContext) {
165        if let Lifecycle::PostLayout {
166            element,
167            size,
168            layout,
169            ..
170        } = self
171        {
172            element.after_layout(*size, layout, cx);
173        } else {
174            panic!("invalid element lifecycle state");
175        }
176    }
177
178    fn paint(&mut self, origin: Vector2F, cx: &mut PaintContext) {
179        *self = if let Lifecycle::PostLayout {
180            mut element,
181            constraint,
182            size,
183            mut layout,
184        } = mem::take(self)
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    fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool {
201        if let Lifecycle::PostPaint {
202            element,
203            bounds,
204            layout,
205            paint,
206            ..
207        } = self
208        {
209            element.dispatch_event(event, *bounds, layout, paint, cx)
210        } else {
211            panic!("invalid element lifecycle state");
212        }
213    }
214
215    fn size(&self) -> Vector2F {
216        match self {
217            Lifecycle::Empty | Lifecycle::Init { .. } => panic!("invalid element lifecycle state"),
218            Lifecycle::PostLayout { size, .. } => *size,
219            Lifecycle::PostPaint { bounds, .. } => bounds.size(),
220        }
221    }
222
223    fn metadata(&self) -> Option<&dyn Any> {
224        match self {
225            Lifecycle::Empty => unreachable!(),
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<T: Element> Default for Lifecycle<T> {
261    fn default() -> Self {
262        Self::Empty
263    }
264}
265
266impl ElementBox {
267    pub fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F {
268        self.element.layout(constraint, cx)
269    }
270
271    pub fn after_layout(&mut self, cx: &mut AfterLayoutContext) {
272        self.element.after_layout(cx);
273    }
274
275    pub fn paint(&mut self, origin: Vector2F, cx: &mut PaintContext) {
276        self.element.paint(origin, cx);
277    }
278
279    pub fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool {
280        self.element.dispatch_event(event, cx)
281    }
282
283    pub fn size(&self) -> Vector2F {
284        self.element.size()
285    }
286
287    pub fn metadata(&self) -> Option<&dyn Any> {
288        self.element.metadata()
289    }
290
291    pub fn debug(&self, cx: &DebugContext) -> json::Value {
292        let mut value = self.element.debug(cx);
293
294        if let Some(name) = &self.name {
295            if let json::Value::Object(map) = &mut value {
296                let mut new_map: crate::json::Map<String, serde_json::Value> = Default::default();
297                new_map.insert("name".into(), json::Value::String(name.to_string()));
298                new_map.append(map);
299                return json::Value::Object(new_map);
300            }
301        }
302
303        value
304    }
305}
306
307pub trait ParentElement<'a>: Extend<ElementBox> + Sized {
308    fn add_children(&mut self, children: impl IntoIterator<Item = ElementBox>) {
309        self.extend(children);
310    }
311
312    fn add_child(&mut self, child: ElementBox) {
313        self.add_children(Some(child));
314    }
315
316    fn with_children(mut self, children: impl IntoIterator<Item = ElementBox>) -> Self {
317        self.add_children(children);
318        self
319    }
320
321    fn with_child(self, child: ElementBox) -> Self {
322        self.with_children(Some(child))
323    }
324}
325
326impl<'a, T> ParentElement<'a> for T where T: Extend<ElementBox> {}