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