1use crate::{
2 AnyElement, AppContext, Bounds, Element, ElementId, IdentifiedElement, Interactive,
3 IntoAnyElement, MouseEventListeners, ParentElement, Pixels, SharedString, Styled, ViewContext,
4};
5use collections::HashMap;
6use refineable::Cascade;
7use smallvec::SmallVec;
8
9#[derive(Default)]
10struct GroupBounds(HashMap<SharedString, SmallVec<[Bounds<Pixels>; 1]>>);
11
12pub fn group_bounds(name: &SharedString, cx: &mut AppContext) -> Option<Bounds<Pixels>> {
13 cx.default_global::<GroupBounds>()
14 .0
15 .get(name)
16 .and_then(|bounds_stack| bounds_stack.last().cloned())
17}
18
19pub struct Group<E> {
20 name: SharedString,
21 child: E,
22}
23
24impl<E> Group<E> {
25 pub fn new(name: SharedString, child: E) -> Self {
26 Group { name, child }
27 }
28}
29
30impl<E: Element> IntoAnyElement<E::ViewState> for Group<E> {
31 fn into_any(self) -> AnyElement<E::ViewState> {
32 AnyElement::new(self)
33 }
34}
35
36impl<E: Element> Element for Group<E> {
37 type ViewState = E::ViewState;
38 type ElementState = E::ElementState;
39
40 fn element_id(&self) -> Option<ElementId> {
41 self.child.element_id()
42 }
43
44 fn layout(
45 &mut self,
46 state: &mut Self::ViewState,
47 element_state: Option<Self::ElementState>,
48 cx: &mut ViewContext<Self::ViewState>,
49 ) -> (crate::LayoutId, Self::ElementState) {
50 self.child.layout(state, element_state, cx)
51 }
52
53 fn paint(
54 &mut self,
55 bounds: Bounds<Pixels>,
56 state: &mut Self::ViewState,
57 element_state: &mut Self::ElementState,
58 cx: &mut ViewContext<Self::ViewState>,
59 ) {
60 cx.default_global::<GroupBounds>()
61 .0
62 .entry(self.name.clone())
63 .or_default()
64 .push(bounds);
65 self.child.paint(bounds, state, element_state, cx);
66 cx.default_global::<GroupBounds>()
67 .0
68 .get_mut(&self.name)
69 .unwrap()
70 .pop();
71 }
72}
73
74impl<E: ParentElement> ParentElement for Group<E> {
75 type State = E::State;
76
77 fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::State>; 2]> {
78 self.child.children_mut()
79 }
80}
81
82impl<E> IdentifiedElement for Group<E> where E: IdentifiedElement {}
83
84impl<E> Styled for Group<E>
85where
86 E: Styled,
87{
88 type Style = E::Style;
89
90 fn style_cascade(&mut self) -> &mut Cascade<E::Style> {
91 self.child.style_cascade()
92 }
93
94 fn declared_style(&mut self) -> &mut <Self::Style as refineable::Refineable>::Refinement {
95 self.child.declared_style()
96 }
97}
98
99impl<S: 'static + Send + Sync, E: Interactive<S> + Styled> Interactive<S> for Group<E> {
100 fn listeners(&mut self) -> &mut MouseEventListeners<S> {
101 self.child.listeners()
102 }
103}