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