1use crate::{
2 AnyElement, AppContext, Bounds, Element, ElementId, IdentifiedElement, Interactive,
3 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> Element for Group<E> {
31 type ViewState = E::ViewState;
32 type ElementState = E::ElementState;
33
34 fn element_id(&self) -> Option<ElementId> {
35 self.child.element_id()
36 }
37
38 fn layout(
39 &mut self,
40 state: &mut Self::ViewState,
41 element_state: Option<Self::ElementState>,
42 cx: &mut ViewContext<Self::ViewState>,
43 ) -> (crate::LayoutId, Self::ElementState) {
44 self.child.layout(state, element_state, cx)
45 }
46
47 fn paint(
48 &mut self,
49 bounds: Bounds<Pixels>,
50 state: &mut Self::ViewState,
51 element_state: &mut Self::ElementState,
52 cx: &mut ViewContext<Self::ViewState>,
53 ) {
54 cx.default_global::<GroupBounds>()
55 .0
56 .entry(self.name.clone())
57 .or_default()
58 .push(bounds);
59 self.child.paint(bounds, state, element_state, cx);
60 cx.default_global::<GroupBounds>()
61 .0
62 .get_mut(&self.name)
63 .unwrap()
64 .pop();
65 }
66}
67
68impl<E: ParentElement> ParentElement for Group<E> {
69 type State = E::State;
70
71 fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::State>; 2]> {
72 self.child.children_mut()
73 }
74}
75
76impl<E> IdentifiedElement for Group<E> where E: IdentifiedElement {}
77
78impl<E> Styled for Group<E>
79where
80 E: Styled,
81{
82 type Style = E::Style;
83
84 fn style_cascade(&mut self) -> &mut Cascade<E::Style> {
85 self.child.style_cascade()
86 }
87
88 fn declared_style(&mut self) -> &mut <Self::Style as refineable::Refineable>::Refinement {
89 self.child.declared_style()
90 }
91}
92
93impl<S: 'static + Send + Sync, E: Interactive<S> + Styled> Interactive<S> for Group<E> {
94 fn listeners(&mut self) -> &mut MouseEventListeners<S> {
95 self.child.listeners()
96 }
97}