Skip to main content

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}