Skip to main content

guise/layout/
group.rs

1//! `Group` — children laid out in a row with consistent spacing.
2
3use 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/// A horizontal flex container.
11#[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    /// Allow children to wrap onto multiple lines (default true).
49    pub fn wrap(mut self, wrap: bool) -> Self {
50        self.wrap = wrap;
51        self
52    }
53
54    /// Stretch children to share the available width equally.
55    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}