egui_charts/ui_kit/form/
grid.rs1use crate::theme::ThemeExt;
7use egui::Ui;
8
9pub struct FormGrid {
13 id: String,
14 columns: usize,
15 spacing: Option<[f32; 2]>,
16}
17
18impl FormGrid {
19 pub fn new(id: impl Into<String>) -> Self {
21 Self {
22 id: id.into(),
23 columns: 2,
24 spacing: None,
25 }
26 }
27
28 #[must_use]
30 pub fn columns(mut self, n: usize) -> Self {
31 self.columns = n;
32 self
33 }
34
35 #[must_use]
37 pub fn spacing(mut self, h: f32, v: f32) -> Self {
38 self.spacing = Some([h, v]);
39 self
40 }
41
42 pub fn show(self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui)) {
44 let theme = ui.active_theme();
45 egui::Grid::new(self.id)
46 .num_columns(self.columns)
47 .spacing(self.spacing.unwrap_or([theme.spacing.lg, theme.spacing.md]))
48 .show(ui, add_contents);
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55 use crate::theme::{Theme, apply_to_egui};
56
57 #[test]
58 fn spacing_follows_the_theme_unless_the_host_sets_it() {
59 let ctx = egui::Context::default();
60 for custom in [false, true] {
61 let mut theme = Theme::light();
62 theme.spacing.lg = 21.0;
63 theme.spacing.md = 17.0;
64 apply_to_egui(&ctx, &theme);
65 let expected = if custom { [3.0, 5.0] } else { [21.0, 17.0] };
66 let mut cells = [egui::Rect::NOTHING; 4];
67 for _ in 0..3 {
68 ctx.run_ui(Default::default(), |ui| {
69 let grid = FormGrid::new(format!("spacing_{custom}"));
70 let grid = if custom { grid.spacing(3.0, 5.0) } else { grid };
71 grid.show(ui, |ui| {
72 for (at, cell) in cells.iter_mut().enumerate() {
73 *cell = ui
74 .allocate_exact_size(egui::vec2(80.0, 20.0), egui::Sense::hover())
75 .0;
76 if at % 2 == 1 {
77 ui.end_row();
78 }
79 }
80 });
81 })
82 .drop_without_applying_deltas();
83 }
84 assert_eq!(cells[1].left() - cells[0].right(), expected[0]);
85 assert_eq!(cells[2].top() - cells[0].bottom(), expected[1]);
86 }
87 }
88}