1use gpui::prelude::*;
8use gpui::{div, px, relative, AnyElement, App, IntoElement, Window};
9
10use crate::devtools::Probed;
11use crate::theme::{theme, Size};
12
13#[derive(IntoElement)]
15pub struct SimpleGrid {
16 children: Vec<AnyElement>,
17 cols: usize,
18 spacing: Size,
19}
20
21impl SimpleGrid {
22 pub fn new(cols: usize) -> Self {
23 SimpleGrid {
24 children: Vec::new(),
25 cols: cols.max(1),
26 spacing: Size::Md,
27 }
28 }
29
30 pub fn spacing(mut self, spacing: Size) -> Self {
31 self.spacing = spacing;
32 self
33 }
34}
35
36impl ParentElement for SimpleGrid {
37 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
38 self.children.extend(elements);
39 }
40}
41
42fn cell() -> gpui::Div {
44 div().flex_grow().flex_shrink().flex_basis(relative(0.0))
45}
46
47impl RenderOnce for SimpleGrid {
48 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
49 let gap = theme(cx).spacing(self.spacing);
50 let cols = self.cols;
51
52 let mut column = div().flex().flex_col().gap(px(gap));
53 let mut iter = self.children.into_iter();
54 loop {
55 let mut row_cells: Vec<AnyElement> = Vec::with_capacity(cols);
56 for _ in 0..cols {
57 match iter.next() {
58 Some(child) => row_cells.push(cell().child(child).into_any_element()),
59 None => break,
60 }
61 }
62 if row_cells.is_empty() {
63 break;
64 }
65 while row_cells.len() < cols {
67 row_cells.push(cell().into_any_element());
68 }
69 column = column.child(div().flex().flex_row().gap(px(gap)).children(row_cells));
70 }
71 column.probe("SimpleGrid")
72 }
73}