Skip to main content

zest_core/widget/
element.rs

1use super::Widget;
2use crate::{Constraints, Length, RenderError, Renderer, TouchPhase, UiAction, WidgetId};
3use alloc::{boxed::Box, vec::Vec};
4use embedded_graphics::{pixelcolor::PixelColor, prelude::*, primitives::Rectangle};
5use zest_theme::Theme;
6
7/// Heterogeneous boxed widget. `'a` is the lifetime of any data the
8/// inner widget borrows from screen state.
9pub struct Element<'a, C: PixelColor, M: Clone> {
10    inner: Box<dyn Widget<C, M> + 'a>,
11}
12
13impl<'a, C: PixelColor + 'a, M: Clone + 'a> Element<'a, C, M> {
14    /// Wrap a concrete widget.
15    pub fn new<W>(widget: W) -> Self
16    where
17        W: Widget<C, M> + 'a,
18    {
19        Self {
20            inner: Box::new(widget),
21        }
22    }
23}
24
25impl<'a, C: PixelColor, M: Clone> Widget<C, M> for Element<'a, C, M> {
26    fn measure(&mut self, constraints: Constraints) -> Size {
27        self.inner.measure(constraints)
28    }
29
30    fn preferred_size(&self) -> (Length, Length) {
31        self.inner.preferred_size()
32    }
33
34    fn arrange(&mut self, rect: Rectangle) {
35        self.inner.arrange(rect);
36    }
37
38    fn rect(&self) -> Rectangle {
39        self.inner.rect()
40    }
41
42    fn handle_touch(&mut self, point: Point, phase: TouchPhase) -> Option<M> {
43        self.inner.handle_touch(point, phase)
44    }
45
46    fn mark_pressed(&mut self, point: Point) {
47        self.inner.mark_pressed(point);
48    }
49
50    fn widget_id(&self) -> Option<WidgetId> {
51        self.inner.widget_id()
52    }
53
54    fn is_focusable(&self) -> bool {
55        self.inner.is_focusable()
56    }
57
58    fn collect_focusable(&self, out: &mut Vec<WidgetId>) {
59        self.inner.collect_focusable(out);
60    }
61
62    fn sync_focus(&mut self, focused: Option<WidgetId>) {
63        self.inner.sync_focus(focused);
64    }
65
66    fn handle_action(&mut self, action: UiAction) -> Option<M> {
67        self.inner.handle_action(action)
68    }
69
70    fn route_action(&mut self, target: WidgetId, action: UiAction) -> Option<M> {
71        self.inner.route_action(target, action)
72    }
73
74    fn navigate_focus(&self, target: WidgetId, action: UiAction) -> Option<WidgetId> {
75        self.inner.navigate_focus(target, action)
76    }
77
78    fn focus_rect(&self, target: WidgetId) -> Option<Rectangle> {
79        self.inner.focus_rect(target)
80    }
81
82    fn focus_at(&self, point: Point) -> Option<WidgetId> {
83        self.inner.focus_at(point)
84    }
85
86    fn draw<'t>(
87        &self,
88        renderer: &mut dyn Renderer<C>,
89        theme: &Theme<'t, C>,
90    ) -> Result<(), RenderError> {
91        self.inner.draw(renderer, theme)
92    }
93}
94
95/// Conversion from a concrete widget into an [`Element`].
96pub trait IntoElement<'a, C: PixelColor + 'a, M: Clone + 'a> {
97    /// Wrap `self`.
98    fn into_element(self) -> Element<'a, C, M>;
99}
100
101impl<'a, C, M, W> IntoElement<'a, C, M> for W
102where
103    C: PixelColor + 'a,
104    M: Clone + 'a,
105    W: Widget<C, M> + 'a,
106{
107    fn into_element(self) -> Element<'a, C, M> {
108        Element::new(self)
109    }
110}