yew_datatable_core/column/column_def_builder.rs
1//! Builder pattern for creating column definitions with a fluent API.
2//!
3//! Provides a convenient way to construct `ColumnDef` instances
4//! with various configuration options.
5
6use crate::column::column_def::ColumnDef;
7use crate::column::column_id::ColumnId;
8use crate::column::column_meta::ColumnMeta;
9use crate::column::data_table_dyn_accessor::DataTableDynAccessor;
10use crate::column::data_table_dyn_value::DataTableDynValue;
11use crate::features::aggregation::aggregation_fn::AggregationFn;
12use crate::features::filtering::filter_fn::FilterFn;
13use crate::features::sorting::sorting_fn::SortingFn;
14
15/// Builder for creating column definitions with a fluent API.
16///
17/// Allows step-by-step configuration of column properties
18/// before building the final `ColumnDef` instance.
19pub struct ColumnDefBuilder<T> {
20 /// Column metadata being constructed.
21 meta: ColumnMeta,
22
23 /// Optional dynamic accessor for cell values.
24 accessor: Option<DataTableDynAccessor<T>>,
25
26 /// Optional custom sorting function.
27 sorting_fn: Option<SortingFn<T>>,
28
29 /// Optional custom filter function.
30 filter_fn: Option<FilterFn<T>>,
31
32 /// Optional aggregation function for grouped rows.
33 aggregation_fn: Option<AggregationFn<T>>,
34
35 /// Child columns for group columns.
36 columns: Vec<ColumnDef<T>>,
37
38 /// Whether multi-column sorting is enabled.
39 enable_multi_sort: bool,
40
41 /// Whether to invert the sort direction.
42 invert_sorting: bool,
43
44 /// Whether undefined values should be sorted last.
45 sort_undefined_last: bool,
46}
47
48impl<T> ColumnDefBuilder<T> {
49 /// Creates a new column builder with the given ID and header.
50 ///
51 /// # Parameters
52 ///
53 /// - `id`: The column identifier.
54 /// - `header`: The display header text.
55 ///
56 /// # Returns
57 ///
58 /// - `ColumnDefBuilder<T>`: A new builder instance with default settings.
59 pub fn new(id: impl Into<ColumnId>, header: impl Into<String>) -> Self {
60 Self {
61 meta: ColumnMeta::new(id, header),
62 accessor: None,
63 sorting_fn: None,
64 filter_fn: None,
65 aggregation_fn: None,
66 columns: Vec::new(),
67 enable_multi_sort: true,
68 invert_sorting: false,
69 sort_undefined_last: true,
70 }
71 }
72
73 /// Sets the accessor function for this column.
74 ///
75 /// # Parameters
76 ///
77 /// - `f`: A function that extracts a value from row data.
78 ///
79 /// # Returns
80 ///
81 /// - `Self`: The modified builder.
82 pub fn accessor<V, F>(mut self, f: F) -> Self
83 where
84 V: DataTableDynValue + 'static,
85 F: Fn(&T) -> V + Send + Sync + 'static,
86 {
87 // Create a dynamic accessor from the provided function.
88 self.accessor = Some(DataTableDynAccessor::new(f));
89 self
90 }
91
92 /// Sets the footer text.
93 ///
94 /// # Parameters
95 ///
96 /// - `footer`: The footer text to display.
97 ///
98 /// # Returns
99 ///
100 /// - `Self`: The modified builder.
101 pub fn footer(mut self, footer: impl Into<String>) -> Self {
102 // Update the footer in the metadata.
103 self.meta = self.meta.with_footer(footer);
104 self
105 }
106
107 /// Sets whether the column is sortable.
108 ///
109 /// # Parameters
110 ///
111 /// - `sortable`: Whether sorting is enabled.
112 ///
113 /// # Returns
114 ///
115 /// - `Self`: The modified builder.
116 pub fn sortable(mut self, sortable: bool) -> Self {
117 // Update the sortable flag in the metadata.
118 self.meta = self.meta.with_sortable(sortable);
119 self
120 }
121
122 /// Sets whether the column is filterable.
123 ///
124 /// # Parameters
125 ///
126 /// - `filterable`: Whether filtering is enabled.
127 ///
128 /// # Returns
129 ///
130 /// - `Self`: The modified builder.
131 pub fn filterable(mut self, filterable: bool) -> Self {
132 // Update the filterable flag in the metadata.
133 self.meta = self.meta.with_filterable(filterable);
134 self
135 }
136
137 /// Sets whether the column is resizable.
138 ///
139 /// # Parameters
140 ///
141 /// - `resizable`: Whether resizing is enabled.
142 ///
143 /// # Returns
144 ///
145 /// - `Self`: The modified builder.
146 pub fn resizable(mut self, resizable: bool) -> Self {
147 // Update the resizable flag in the metadata.
148 self.meta = self.meta.with_resizable(resizable);
149 self
150 }
151
152 /// Sets whether the column is visible by default.
153 ///
154 /// # Parameters
155 ///
156 /// - `visible`: Whether the column is visible.
157 ///
158 /// # Returns
159 ///
160 /// - `Self`: The modified builder.
161 pub fn visible(mut self, visible: bool) -> Self {
162 // Update the visible flag in the metadata.
163 self.meta = self.meta.with_visible(visible);
164 self
165 }
166
167 /// Sets the minimum column width.
168 ///
169 /// # Parameters
170 ///
171 /// - `width`: The minimum width in pixels.
172 ///
173 /// # Returns
174 ///
175 /// - `Self`: The modified builder.
176 pub fn min_width(mut self, width: f64) -> Self {
177 // Set the minimum width constraint.
178 self.meta = self.meta.with_min_width(width);
179 self
180 }
181
182 /// Sets the maximum column width.
183 ///
184 /// # Parameters
185 ///
186 /// - `width`: The maximum width in pixels.
187 ///
188 /// # Returns
189 ///
190 /// - `Self`: The modified builder.
191 pub fn max_width(mut self, width: f64) -> Self {
192 // Set the maximum width constraint.
193 self.meta = self.meta.with_max_width(width);
194 self
195 }
196
197 /// Sets the default column width.
198 ///
199 /// # Parameters
200 ///
201 /// - `width`: The default width in pixels.
202 ///
203 /// # Returns
204 ///
205 /// - `Self`: The modified builder.
206 pub fn default_width(mut self, width: f64) -> Self {
207 // Set the default width.
208 self.meta = self.meta.with_default_width(width);
209 self
210 }
211
212 /// Sets the filter placeholder text.
213 ///
214 /// # Parameters
215 ///
216 /// - `placeholder`: The placeholder text for the filter input.
217 ///
218 /// # Returns
219 ///
220 /// - `Self`: The modified builder.
221 pub fn filter_placeholder(mut self, placeholder: impl Into<String>) -> Self {
222 // Set the filter placeholder text.
223 self.meta = self.meta.with_filter_placeholder(placeholder);
224 self
225 }
226
227 /// Sets a custom sorting function.
228 ///
229 /// # Parameters
230 ///
231 /// - `f`: The custom sorting function.
232 ///
233 /// # Returns
234 ///
235 /// - `Self`: The modified builder.
236 pub fn sorting_fn(mut self, f: SortingFn<T>) -> Self {
237 // Set the custom sorting function.
238 self.sorting_fn = Some(f);
239 self
240 }
241
242 /// Sets a custom filter function.
243 ///
244 /// # Parameters
245 ///
246 /// - `f`: The custom filter function.
247 ///
248 /// # Returns
249 ///
250 /// - `Self`: The modified builder.
251 pub fn filter_fn(mut self, f: FilterFn<T>) -> Self {
252 // Set the custom filter function.
253 self.filter_fn = Some(f);
254 self
255 }
256
257 /// Sets an aggregation function for grouped rows.
258 ///
259 /// # Parameters
260 ///
261 /// - `f`: The aggregation function.
262 ///
263 /// # Returns
264 ///
265 /// - `Self`: The modified builder.
266 pub fn aggregation_fn(mut self, f: AggregationFn<T>) -> Self {
267 // Set the aggregation function.
268 self.aggregation_fn = Some(f);
269 self
270 }
271
272 /// Enables or disables multi-column sorting for this column.
273 ///
274 /// # Parameters
275 ///
276 /// - `enable`: Whether multi-sort is enabled.
277 ///
278 /// # Returns
279 ///
280 /// - `Self`: The modified builder.
281 pub fn enable_multi_sort(mut self, enable: bool) -> Self {
282 // Update the multi-sort flag.
283 self.enable_multi_sort = enable;
284 self
285 }
286
287 /// Inverts the sort direction for this column.
288 ///
289 /// # Parameters
290 ///
291 /// - `invert`: Whether to invert the sort direction.
292 ///
293 /// # Returns
294 ///
295 /// - `Self`: The modified builder.
296 pub fn invert_sorting(mut self, invert: bool) -> Self {
297 // Update the invert sorting flag.
298 self.invert_sorting = invert;
299 self
300 }
301
302 /// Sets whether undefined values should be sorted last.
303 ///
304 /// # Parameters
305 ///
306 /// - `last`: Whether undefined values sort last.
307 ///
308 /// # Returns
309 ///
310 /// - `Self`: The modified builder.
311 pub fn sort_undefined_last(mut self, last: bool) -> Self {
312 // Update the sort undefined last flag.
313 self.sort_undefined_last = last;
314 self
315 }
316
317 /// Adds child columns to make this a group column.
318 ///
319 /// # Parameters
320 ///
321 /// - `columns`: The child column definitions.
322 ///
323 /// # Returns
324 ///
325 /// - `Self`: The modified builder.
326 pub fn columns(mut self, columns: Vec<ColumnDef<T>>) -> Self {
327 // Mark as group column and set child columns.
328 self.meta = self.meta.as_group();
329 self.columns = columns;
330 self
331 }
332
333 /// Builds the column definition.
334 ///
335 /// # Returns
336 ///
337 /// - `ColumnDef<T>`: The constructed column definition.
338 pub fn build(self) -> ColumnDef<T> {
339 // Construct the final column definition from the builder state.
340 ColumnDef {
341 meta: self.meta,
342 accessor: self.accessor,
343 sorting_fn: self.sorting_fn,
344 filter_fn: self.filter_fn,
345 aggregation_fn: self.aggregation_fn,
346 columns: self.columns,
347 enable_multi_sort: self.enable_multi_sort,
348 invert_sorting: self.invert_sorting,
349 sort_undefined_last: self.sort_undefined_last,
350 }
351 }
352}
353
354/// Provides a default column definition builder with empty ID and header.
355impl<T> Default for ColumnDefBuilder<T> {
356 fn default() -> Self {
357 Self::new("", "")
358 }
359}