1use gpui::prelude::*;
4use gpui::{div, px, AnyElement, App, IntoElement, Window};
5
6use super::{apply_align, apply_justify, Align, Justify};
7use crate::devtools::Probed;
8use crate::theme::{theme, Size};
9
10#[derive(IntoElement)]
12pub struct Group {
13 children: Vec<AnyElement>,
14 gap: Size,
15 align: Align,
16 justify: Justify,
17 wrap: bool,
18 grow: bool,
19}
20
21impl Group {
22 pub fn new() -> Self {
23 Group {
24 children: Vec::new(),
25 gap: Size::Md,
26 align: Align::Center,
27 justify: Justify::Start,
28 wrap: true,
29 grow: false,
30 }
31 }
32
33 pub fn gap(mut self, gap: Size) -> Self {
34 self.gap = gap;
35 self
36 }
37
38 pub fn align(mut self, align: Align) -> Self {
39 self.align = align;
40 self
41 }
42
43 pub fn justify(mut self, justify: Justify) -> Self {
44 self.justify = justify;
45 self
46 }
47
48 pub fn wrap(mut self, wrap: bool) -> Self {
50 self.wrap = wrap;
51 self
52 }
53
54 pub fn grow(mut self, grow: bool) -> Self {
56 self.grow = grow;
57 self
58 }
59}
60
61impl Default for Group {
62 fn default() -> Self {
63 Group::new()
64 }
65}
66
67impl ParentElement for Group {
68 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
69 self.children.extend(elements);
70 }
71}
72
73impl RenderOnce for Group {
74 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
75 let gap = theme(cx).spacing(self.gap);
76 let mut base = div().flex().flex_row().gap(px(gap));
77 if self.wrap {
78 base = base.flex_wrap();
79 }
80 let grow = self.grow;
81 apply_justify(apply_align(base, self.align), self.justify)
82 .children(self.children.into_iter().map(move |c| {
83 if grow {
84 div().flex_1().child(c).into_any_element()
85 } else {
86 c
87 }
88 }))
89 .probe("Group")
90 }
91}