egui_macview/layout/
form.rs1use crate::theme::MacTheme;
7use egui::{vec2, Align, IdSalt, Layout, Response, Ui, Vec2, WidgetText};
8
9pub struct MacForm<'a> {
11 id_salt: IdSalt,
12 theme: Option<&'a MacTheme>,
13 spacing: Option<Vec2>,
14 min_col_width: Option<f32>,
15}
16
17impl<'a> MacForm<'a> {
18 pub fn new(id_salt: impl egui::AsIdSalt) -> Self {
20 Self {
21 id_salt: IdSalt::new(id_salt),
22 theme: None,
23 spacing: None,
24 min_col_width: None,
25 }
26 }
27
28 pub fn theme(mut self, theme: &'a MacTheme) -> Self {
30 self.theme = Some(theme);
31 self
32 }
33
34 pub fn spacing(mut self, spacing: impl Into<Vec2>) -> Self {
36 self.spacing = Some(spacing.into());
37 self
38 }
39
40 pub fn min_col_width(mut self, min_col_width: f32) -> Self {
42 self.min_col_width = Some(min_col_width);
43 self
44 }
45
46 pub fn show<R>(self, ui: &mut Ui, add_contents: impl FnOnce(&mut MacFormUi<'_>) -> R) -> R {
48 let spacing = self.spacing.unwrap_or_else(|| {
49 let s = self
50 .theme
51 .map(|t| t.stack_view().default_spacing.points())
52 .unwrap_or_else(|| {
53 MacTheme::from_ctx(ui.ctx())
54 .stack_view()
55 .default_spacing
56 .points()
57 });
58 vec2(s, s)
59 });
60
61 let mut result = None;
62 let mut grid = egui::Grid::new(self.id_salt)
63 .num_columns(2)
64 .spacing(spacing);
65 if let Some(min_w) = self.min_col_width {
66 grid = grid.min_col_width(min_w);
67 }
68 grid.show(ui, |grid_ui| {
69 let mut form_ui = MacFormUi { ui: grid_ui };
70 result = Some(add_contents(&mut form_ui));
71 });
72 result.expect("MacForm grid rendered")
73 }
74}
75
76pub struct MacFormUi<'a> {
78 pub ui: &'a mut Ui,
80}
81
82impl<'a> MacFormUi<'a> {
83 pub fn row<R1, R2>(
85 &mut self,
86 label: impl FnOnce(&mut Ui) -> R1,
87 control: impl FnOnce(&mut Ui) -> R2,
88 ) -> (R1, R2) {
89 let r1 = self
90 .ui
91 .with_layout(Layout::right_to_left(Align::Center), label)
92 .inner;
93 let r2 = self
94 .ui
95 .with_layout(Layout::left_to_right(Align::Center), control)
96 .inner;
97 self.ui.end_row();
98 (r1, r2)
99 }
100
101 pub fn row_label<R>(
103 &mut self,
104 label_text: impl Into<WidgetText>,
105 control: impl FnOnce(&mut Ui) -> R,
106 ) -> (Response, R) {
107 let text = label_text.into();
108 self.row(|ui| ui.label(text), control)
109 }
110}