Skip to main content

panes/preset/
grid.rs

1use std::sync::Arc;
2
3use crate::builder::LayoutBuilder;
4use crate::error::PaneError;
5use crate::layout::Layout;
6use crate::preset::master_stack::row_style;
7use crate::preset::{collect_kinds, validate_kinds};
8
9/// Builder for the grid preset layout.
10pub struct Grid {
11    cols: usize,
12    kinds: Arc<[Arc<str>]>,
13    gap: f32,
14}
15
16impl Grid {
17    pub(crate) fn new(cols: usize, kinds: impl IntoIterator<Item = impl Into<Arc<str>>>) -> Self {
18        Self {
19            cols,
20            kinds: collect_kinds(kinds),
21            gap: 0.0,
22        }
23    }
24
25    /// Set the gap between panels.
26    pub fn gap(mut self, gap: f32) -> Self {
27        self.gap = gap;
28        self
29    }
30
31    /// Consume the builder and produce a [`Layout`].
32    pub fn build(&self) -> Result<Layout, PaneError> {
33        match self.cols {
34            0 => {
35                return Err(PaneError::InvalidTree(
36                    crate::error::TreeError::ColumnsCountZero,
37                ));
38            }
39            _ => {}
40        }
41        validate_kinds(&self.kinds)?;
42
43        let mut b = LayoutBuilder::new();
44        let gap_px = self.gap;
45
46        b.col_gap(gap_px, |outer| {
47            for chunk in self.kinds.chunks(self.cols) {
48                outer.taffy_node(row_style(1.0, gap_px), |r| {
49                    super::add_grow_panels(r, chunk);
50                });
51            }
52        })?;
53
54        b.build()
55    }
56}
57
58impl Grid {
59    /// Consume the builder and produce a [`crate::runtime::LayoutRuntime`].
60    pub fn into_runtime(self) -> Result<crate::runtime::LayoutRuntime, PaneError> {
61        let strategy = crate::strategy::StrategyKind::ColumnGrid {
62            columns: self.cols,
63            gap: self.gap,
64        };
65        crate::runtime::LayoutRuntime::from_strategy(strategy, &self.kinds)
66    }
67}
68
69super::impl_preset!(Grid);