egui_macview/layout/
form.rs1use crate::theme::MacTheme;
7use egui::{vec2, Align, IdSalt, Layout, Response, Ui, Vec2, WidgetText};
8
9pub struct MacForm<'a> {
31 id_salt: IdSalt,
32 theme: Option<&'a MacTheme>,
33 spacing: Option<Vec2>,
34 min_col_width: Option<f32>,
35}
36
37impl<'a> MacForm<'a> {
38 pub fn new(id_salt: impl egui::AsIdSalt) -> Self {
40 Self {
41 id_salt: IdSalt::new(id_salt),
42 theme: None,
43 spacing: None,
44 min_col_width: None,
45 }
46 }
47
48 pub fn theme(mut self, theme: &'a MacTheme) -> Self {
50 self.theme = Some(theme);
51 self
52 }
53
54 pub fn spacing(mut self, spacing: impl Into<Vec2>) -> Self {
56 self.spacing = Some(spacing.into());
57 self
58 }
59
60 pub fn min_col_width(mut self, min_col_width: f32) -> Self {
62 self.min_col_width = Some(min_col_width);
63 self
64 }
65
66 pub fn show<R>(self, ui: &mut Ui, add_contents: impl FnOnce(&mut MacFormUi<'_>) -> R) -> R {
68 let spacing = self.spacing.unwrap_or_else(|| {
69 let s = self
70 .theme
71 .map(|t| t.stack_view().default_spacing.points())
72 .unwrap_or_else(|| {
73 MacTheme::from_ctx(ui.ctx())
74 .stack_view()
75 .default_spacing
76 .points()
77 });
78 vec2(s, s)
79 });
80
81 let mut result = None;
82 let mut grid = egui::Grid::new(self.id_salt)
83 .num_columns(2)
84 .spacing(spacing);
85 if let Some(min_w) = self.min_col_width {
86 grid = grid.min_col_width(min_w);
87 }
88 grid.show(ui, |grid_ui| {
89 let mut form_ui = MacFormUi { ui: grid_ui };
90 result = Some(add_contents(&mut form_ui));
91 });
92 result.expect("MacForm grid rendered")
93 }
94}
95
96pub struct MacFormUi<'a> {
98 pub ui: &'a mut Ui,
100}
101
102impl<'a> MacFormUi<'a> {
103 pub fn row<R1, R2>(
105 &mut self,
106 label: impl FnOnce(&mut Ui) -> R1,
107 control: impl FnOnce(&mut Ui) -> R2,
108 ) -> (R1, R2) {
109 let r1 = self
110 .ui
111 .with_layout(Layout::right_to_left(Align::Center), label)
112 .inner;
113 let r2 = self
114 .ui
115 .with_layout(Layout::left_to_right(Align::Center), control)
116 .inner;
117 self.ui.end_row();
118 (r1, r2)
119 }
120
121 pub fn row_label<R>(
123 &mut self,
124 label_text: impl Into<WidgetText>,
125 control: impl FnOnce(&mut Ui) -> R,
126 ) -> (Response, R) {
127 let text = label_text.into();
128 self.row(|ui| ui.label(text), control)
129 }
130}