embedded_layout/view_group/
mod.rs

1//! ViewGroup definition and implementation for common types.
2
3use embedded_graphics::{prelude::Point, primitives::Rectangle};
4
5use crate::{prelude::RectExt, View};
6
7mod object_chain;
8mod views;
9
10pub use views::Views;
11
12/// A set of operations required to implement [`View`] containers.
13pub trait ViewGroup: View {
14    /// Returns the number of [`View`] objects in this view group.
15    fn len(&self) -> usize;
16
17    /// Returns a shared reference the [`View`] object at position `idx`.
18    fn at(&self, idx: usize) -> &dyn View;
19
20    /// Returns an exclusive reference to the [`View`] object at position `idx`.
21    fn at_mut(&mut self, idx: usize) -> &mut dyn View;
22
23    /// Returns the bounding box of the given View.
24    fn bounds_of(&self, idx: usize) -> Rectangle {
25        self.at(idx).bounds()
26    }
27
28    /// Translates the given View.
29    fn translate_child(&mut self, idx: usize, by: Point) {
30        self.at_mut(idx).translate_impl(by)
31    }
32}
33
34/// A [`ViewGroup`] that contains no [`View`] objects.
35#[derive(Clone, Copy, PartialEq, Eq, Debug)]
36pub struct EmptyViewGroup;
37
38/// A single instance of [`EmptyViewGroup`].
39pub static mut EMPTY_VIEW_GROUP: EmptyViewGroup = EmptyViewGroup;
40
41impl View for EmptyViewGroup {
42    fn translate_impl(&mut self, _by: Point) {}
43
44    fn bounds(&self) -> Rectangle {
45        Rectangle::zero()
46    }
47}
48
49impl ViewGroup for EmptyViewGroup {
50    fn len(&self) -> usize {
51        0
52    }
53
54    fn at(&self, _idx: usize) -> &dyn View {
55        self
56    }
57
58    fn at_mut(&mut self, _idx: usize) -> &mut dyn View {
59        self
60    }
61}
62
63/// Utility struct to simplify implementing [`View`] operations for any [`ViewGroup`].
64pub struct ViewGroupHelper;
65
66impl ViewGroupHelper {
67    /// Translates every [`View`] object in a view group.
68    #[inline]
69    pub fn translate(vg: &mut impl ViewGroup, by: Point) {
70        for i in 0..ViewGroup::len(vg) {
71            vg.translate_child(i, by);
72        }
73    }
74
75    /// Returns the smallest bounding box that envelopes all [`View`] objects in a view group.
76    #[inline]
77    pub fn bounds(vg: &impl ViewGroup) -> Rectangle {
78        if ViewGroup::len(vg) == 0 {
79            return EmptyViewGroup.bounds();
80        }
81
82        let mut rect = vg.bounds_of(0);
83
84        for i in 1..vg.len() {
85            rect = rect.enveloping(&vg.bounds_of(i));
86        }
87
88        rect
89    }
90}