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