embedded_layout/view_group/
views.rs

1use core::ops::{Deref, DerefMut};
2
3use embedded_graphics::{
4    draw_target::DrawTarget, pixelcolor::PixelColor, prelude::Point, primitives::Rectangle,
5    Drawable,
6};
7
8use crate::{
9    view_group::{ViewGroup, ViewGroupHelper},
10    View,
11};
12
13/// Wrapper that implements ViewGroup for a slice of views.
14pub struct Views<'a, T>
15where
16    T: View,
17{
18    views: &'a mut [T],
19}
20
21impl<'a, T> Views<'a, T>
22where
23    T: View,
24{
25    /// Wraps the given slice.
26    #[inline]
27    pub fn new(views: &'a mut [T]) -> Self {
28        Self { views }
29    }
30}
31
32impl<T> ViewGroup for Views<'_, T>
33where
34    T: View,
35{
36    #[inline]
37    fn len(&self) -> usize {
38        self.views.len()
39    }
40
41    #[inline]
42    fn at(&self, idx: usize) -> &dyn View {
43        &self.views[idx]
44    }
45
46    #[inline]
47    fn at_mut(&mut self, idx: usize) -> &mut dyn View {
48        &mut self.views[idx]
49    }
50
51    #[inline]
52    fn bounds_of(&self, idx: usize) -> Rectangle {
53        self.views[idx].bounds()
54    }
55
56    #[inline]
57    fn translate_child(&mut self, idx: usize, by: Point) {
58        self.views[idx].translate_impl(by)
59    }
60}
61
62impl<T> View for Views<'_, T>
63where
64    T: View,
65{
66    #[inline]
67    fn translate_impl(&mut self, by: Point) {
68        ViewGroupHelper::translate(self, by)
69    }
70
71    #[inline]
72    fn bounds(&self) -> Rectangle {
73        ViewGroupHelper::bounds(self)
74    }
75}
76
77impl<'a, T> Deref for Views<'a, T>
78where
79    T: View,
80{
81    type Target = [T];
82
83    #[inline]
84    fn deref(&self) -> &[T] {
85        self.views
86    }
87}
88
89impl<'a, T> DerefMut for Views<'a, T>
90where
91    T: View,
92{
93    #[inline]
94    fn deref_mut(&mut self) -> &mut [T] {
95        self.views
96    }
97}
98
99impl<C, T> Drawable for Views<'_, T>
100where
101    C: PixelColor,
102    T: View,
103    T: Drawable<Color = C>,
104{
105    type Color = C;
106    type Output = ();
107
108    #[inline]
109    fn draw<D>(&self, display: &mut D) -> Result<(), D::Error>
110    where
111        D: DrawTarget<Color = Self::Color>,
112    {
113        for view in self.views.iter() {
114            view.draw(display)?;
115        }
116
117        Ok(())
118    }
119}
120
121#[cfg(test)]
122mod test {
123    use super::*;
124    use embedded_graphics::primitives::Line;
125
126    #[test]
127    fn len_is_slice_length() {
128        let mut views = [
129            Line::new(Point::zero(), Point::new(1, 2)),
130            Line::new(Point::new(1, 2), Point::new(3, 1)),
131            Line::new(Point::new(3, 1), Point::zero()),
132        ];
133
134        let vg = Views::new(&mut views);
135
136        assert_eq!(3, vg.len());
137    }
138
139    #[test]
140    fn views_behaves_as_slice() {
141        let mut views = [
142            Line::new(Point::zero(), Point::new(1, 2)),
143            Line::new(Point::new(1, 2), Point::new(3, 1)),
144            Line::new(Point::new(3, 1), Point::zero()),
145        ];
146
147        let vg = Views::new(&mut views);
148
149        // deliberate count() because Views only exposes `iter()` through `Deref`.
150        assert_eq!(1, vg[1..2].iter().count());
151    }
152}