1use crate::{
4 error::TableError,
5 operations::{Row, TableProvider},
6 state::TableState,
7};
8
9pub struct TableKit<'a> {
10 id: String,
11 provider: &'a dyn TableProvider,
12 state: &'a mut TableState,
13 row_height: f32,
14 org_colors: &'a [[u8; 3]],
15 user_colors: &'a [[u8; 3]],
16 scroll_to_row: Option<(u64, egui::Align)>,
17 striped: bool,
18 striping_color: Option<egui::Color32>,
19 hover_color: Option<egui::Color32>,
20 max_height: Option<f32>,
21 max_rows: Option<u64>,
22 columns: Option<Vec<crate::layout::Column>>,
23 auto_size_mode: crate::layout::AutoSizeMode,
24}
25
26impl<'a> TableKit<'a> {
27 pub fn new(
28 id: impl Into<String>,
29 provider: &'a dyn TableProvider,
30 state: &'a mut TableState,
31 ) -> Self {
32 Self {
33 id: id.into(),
34 provider,
35 state,
36 row_height: 16.0,
37 org_colors: &[],
38 user_colors: &[],
39 scroll_to_row: None,
40 striped: false,
41 striping_color: None,
42 hover_color: None,
43 max_height: Some(400.0), max_rows: None,
45 columns: None,
46 auto_size_mode: crate::layout::AutoSizeMode::OnParentResize,
47 }
48 }
49
50 #[must_use]
51 pub fn with_columns(mut self, columns: Vec<crate::layout::Column>) -> Self {
52 self.columns = Some(columns);
53 self
54 }
55
56 #[must_use]
57 pub const fn with_row_height(mut self, height: f32) -> Self {
58 self.row_height = height;
59 self
60 }
61
62 #[must_use]
63 pub const fn with_max_height(mut self, max_height: Option<f32>) -> Self {
64 self.max_height = max_height;
65 self
66 }
67
68 #[must_use]
69 pub const fn with_colors(mut self, org: &'a [[u8; 3]], user: &'a [[u8; 3]]) -> Self {
70 self.org_colors = org;
71 self.user_colors = user;
72 self
73 }
74
75 #[must_use]
76 pub const fn with_auto_size_mode(mut self, mode: crate::layout::AutoSizeMode) -> Self {
77 self.auto_size_mode = mode;
78 self
79 }
80
81 #[must_use]
82 pub const fn with_max_rows(mut self, max_rows: u64) -> Self {
83 self.max_rows = Some(max_rows);
84 self.max_height = None; self
86 }
87
88 #[must_use]
90 pub const fn with_scroll_to_row(mut self, row_nr: u64, align: egui::Align) -> Self {
91 self.scroll_to_row = Some((row_nr, align));
92 self
93 }
94
95 #[must_use]
97 pub const fn with_striped(mut self, striped: bool) -> Self {
98 self.striped = striped;
99 self
100 }
101
102 #[must_use]
105 pub const fn with_striping_color(mut self, color: egui::Color32) -> Self {
106 self.striping_color = Some(color);
107 self
108 }
109
110 #[must_use]
112 pub const fn with_hover_color(mut self, color: egui::Color32) -> Self {
113 self.hover_color = Some(color);
114 self
115 }
116
117 pub fn show<F>(self, ui: &mut egui::Ui, custom_cell_ui: F) -> Result<egui::Response, TableError>
118 where
119 F: FnMut(
120 &mut egui::Ui,
121 &crate::layout::CellInfo,
122 &dyn Row,
123 egui::Color32,
124 ) -> Option<egui::Response>
125 + 'a,
126 {
127 let _ = self.state.refresh_view(self.provider);
129
130 let columns = self.columns.unwrap_or_else(|| {
132 (0..self.provider.column_count())
133 .map(|_| {
134 crate::layout::Column::new(120.0)
135 .range(15.0..=f32::INFINITY)
136 .resizable(true)
137 })
138 .collect::<Vec<_>>()
139 });
140
141 let mut table = crate::layout::Table::new()
142 .id_salt(&self.id)
143 .num_rows(self.state.active_rows.len() as u64)
144 .columns(columns)
145 .auto_size_mode(self.auto_size_mode) .headers([crate::layout::HeaderRow::new(self.row_height)]);
147
148 if let Some((row_nr, align)) = self.scroll_to_row {
150 table = table.scroll_to_row(row_nr, Some(align));
151 }
152
153 if let Some(max_r) = self.max_rows {
154 table = table.max_rows(max_r);
155 } else if let Some(max_h) = self.max_height {
156 table = table.max_height(max_h);
157 }
158
159 let mut collected_responses = Vec::new();
160 let mut halt_error = None;
161
162 let response = {
163 let mut item_clicked = None;
164 let mut secondary_clicked = None;
165
166 let mut delegate = crate::delegate::TableKitDelegate::new(
167 self.provider,
168 self.state,
169 self.org_colors,
170 self.user_colors,
171 &mut collected_responses,
172 &mut halt_error,
173 Some(Box::new(custom_cell_ui)),
174 &mut item_clicked,
175 &mut secondary_clicked,
176 );
177 delegate.row_height = self.row_height;
178 delegate.striped = self.striped;
179 delegate.striping_color = self.striping_color;
180 delegate.hover_color = self.hover_color;
181
182 table.show(ui, &mut delegate)
183 };
184
185 if let Some(err) = halt_error {
186 return Err(err);
187 }
188
189 self.state
190 .process_responses(self.provider, collected_responses)?;
191
192 Ok(response)
193 }
194}