Skip to main content

zest_widget/widget/
space.rs

1//! Transparent filler widget. Used to push siblings to one end of a
2//! [`Row`](super::row::Row) / [`Column`](super::column::Column),
3//! create explicit fixed gaps, or reserve space.
4//!
5//! Construct via the free functions [`horizontal_space`] / [`vertical_space`]
6//! for the common cases, or build a custom [`Space`] directly.
7
8use super::Widget;
9use core::marker::PhantomData;
10use embedded_graphics::{pixelcolor::PixelColor, prelude::*, primitives::Rectangle};
11use zest_core::{Constraints, Length, RenderError, Renderer, TouchPhase};
12use zest_theme::Theme;
13
14/// Empty widget that draws nothing. Carries [`Length`] intent on both
15/// axes so it slots cleanly into the standard flex layout.
16pub struct Space<C: PixelColor, M: Clone> {
17    rect: Rectangle,
18    width: Length,
19    height: Length,
20    _phantom: PhantomData<(C, M)>,
21}
22
23impl<C: PixelColor, M: Clone> Space<C, M> {
24    /// Construct a space with explicit `width` and `height` intents.
25    pub fn new(width: impl Into<Length>, height: impl Into<Length>) -> Self {
26        Self {
27            rect: Rectangle::zero(),
28            width: width.into(),
29            height: height.into(),
30            _phantom: PhantomData,
31        }
32    }
33
34    /// Width sizing intent.
35    #[must_use]
36    pub fn width(mut self, width: impl Into<Length>) -> Self {
37        self.width = width.into();
38        self
39    }
40
41    /// Height sizing intent.
42    #[must_use]
43    pub fn height(mut self, height: impl Into<Length>) -> Self {
44        self.height = height.into();
45        self
46    }
47}
48
49/// Horizontal filler — fills available width, zero height. Useful as a
50/// spacer between [`Row`](super::row::Row) children to push them to
51/// opposite ends.
52pub fn horizontal_space<C: PixelColor, M: Clone>() -> Space<C, M> {
53    Space::new(Length::Fill, Length::Fixed(0))
54}
55
56/// Vertical filler — fills available height, zero width. Useful as a
57/// spacer between [`Column`](super::column::Column) children to push
58/// them to top and bottom.
59pub fn vertical_space<C: PixelColor, M: Clone>() -> Space<C, M> {
60    Space::new(Length::Fixed(0), Length::Fill)
61}
62
63impl<C: PixelColor, M: Clone> Widget<C, M> for Space<C, M> {
64    fn measure(&mut self, constraints: Constraints) -> Size {
65        let w = self.width.resolve(0, constraints.max.width);
66        let h = self.height.resolve(0, constraints.max.height);
67        constraints.clamp(Size::new(w, h))
68    }
69
70    fn preferred_size(&self) -> (Length, Length) {
71        (self.width, self.height)
72    }
73
74    fn arrange(&mut self, rect: Rectangle) {
75        self.rect = rect;
76    }
77
78    fn rect(&self) -> Rectangle {
79        self.rect
80    }
81
82    fn handle_touch(&mut self, _point: Point, _phase: TouchPhase) -> Option<M> {
83        None
84    }
85
86    fn draw<'t>(
87        &self,
88        _renderer: &mut dyn Renderer<C>,
89        _theme: &Theme<'t, C>,
90    ) -> Result<(), RenderError> {
91        Ok(())
92    }
93}