yew_datatable_core/table/data_table.rs
1//! Main table instance that coordinates all table functionality.
2//!
3//! `DataTable` is the primary entry point for interacting with the data table.
4//! It manages columns, data, and state, and provides methods for all table operations.
5
6use crate::column::column_def::ColumnDef;
7use crate::column::column_id::ColumnId;
8use crate::row::data_table_row::DataTableRow;
9use crate::row::data_table_row_id::DataTableRowId;
10use crate::row::data_table_row_model::DataTableRowModel;
11use crate::state::data_table_state::DataTableState;
12use crate::table::data_table_options::DataTableOptions;
13use crate::table::data_table_options_builder::DataTableOptionsBuilder;
14
15/// Main table instance that coordinates all table functionality.
16///
17/// Manages columns, data, and state, providing methods for sorting,
18/// filtering, pagination, selection, and all other table operations.
19pub struct DataTable<T: Clone> {
20 /// Column definitions.
21 columns: Vec<ColumnDef<T>>,
22
23 /// Row model containing processed rows.
24 row_model: DataTableRowModel<T>,
25
26 /// Combined table state.
27 state: DataTableState,
28
29 /// Table options.
30 options: DataTableOptions,
31}
32
33impl<T: Clone> DataTable<T> {
34 /// Creates a new table with the given options.
35 ///
36 /// # Parameters
37 ///
38 /// - `options`: The table configuration options.
39 ///
40 /// # Returns
41 ///
42 /// - `DataTable<T>`: A new empty table instance.
43 pub fn new(options: DataTableOptions) -> Self {
44 Self {
45 columns: Vec::new(),
46 row_model: DataTableRowModel::default(),
47 state: DataTableState::new(),
48 options,
49 }
50 }
51
52 /// Creates a table with columns and data.
53 ///
54 /// # Parameters
55 ///
56 /// - `columns`: The column definitions.
57 /// - `data`: The raw data rows.
58 /// - `id_fn`: A function that generates a row ID from row data and index.
59 ///
60 /// # Returns
61 ///
62 /// - `DataTable<T>`: A new table with the provided columns and data.
63 pub fn with_data<F>(columns: Vec<ColumnDef<T>>, data: Vec<T>, id_fn: F) -> Self
64 where
65 F: Fn(&T, usize) -> DataTableRowId,
66 {
67 Self {
68 columns,
69 row_model: DataTableRowModel::new(data, id_fn),
70 state: DataTableState::new(),
71 options: DataTableOptions::default(),
72 }
73 }
74
75 /// Creates a table builder.
76 ///
77 /// # Returns
78 ///
79 /// - `DataTableOptionsBuilder`: A new options builder instance.
80 pub fn builder() -> DataTableOptionsBuilder {
81 DataTableOptionsBuilder::new()
82 }
83
84 /// Sets the column definitions.
85 ///
86 /// # Parameters
87 ///
88 /// - `columns`: The new column definitions.
89 pub fn set_columns(&mut self, columns: Vec<ColumnDef<T>>) {
90 // Replace the column definitions.
91 self.columns = columns;
92
93 // Mark the row model as needing reprocessing.
94 self.row_model.invalidate();
95 }
96
97 /// Sets the table data.
98 ///
99 /// # Parameters
100 ///
101 /// - `data`: The new raw data rows.
102 /// - `id_fn`: A function that generates a row ID from row data and index.
103 pub fn set_data<F>(&mut self, data: Vec<T>, id_fn: F)
104 where
105 F: Fn(&T, usize) -> DataTableRowId,
106 {
107 // Update the row model with new data.
108 self.row_model.set_data(data, id_fn);
109 }
110
111 /// Sets the data using index as row ID.
112 ///
113 /// # Parameters
114 ///
115 /// - `data`: The new raw data rows.
116 pub fn set_data_indexed(&mut self, data: Vec<T>) {
117 // Update the row model using index-based IDs.
118 self.row_model.set_data(data, |_, idx| DataTableRowId::from_index(idx));
119 }
120
121 /// Returns the column definitions.
122 ///
123 /// # Returns
124 ///
125 /// - `&[ColumnDef<T>]`: A slice of column definitions.
126 pub fn columns(&self) -> &[ColumnDef<T>] {
127 &self.columns
128 }
129
130 /// Returns a mutable reference to the state.
131 ///
132 /// # Returns
133 ///
134 /// - `&mut DataTableState`: A mutable reference to the table state.
135 pub fn state_mut(&mut self) -> &mut DataTableState {
136 &mut self.state
137 }
138
139 /// Returns the table state.
140 ///
141 /// # Returns
142 ///
143 /// - `&DataTableState`: A reference to the table state.
144 pub fn state(&self) -> &DataTableState {
145 &self.state
146 }
147
148 /// Returns the table options.
149 ///
150 /// # Returns
151 ///
152 /// - `&DataTableOptions`: A reference to the table options.
153 pub fn options(&self) -> &DataTableOptions {
154 &self.options
155 }
156
157 /// Returns the row model.
158 ///
159 /// # Returns
160 ///
161 /// - `&DataTableRowModel<T>`: A reference to the row model.
162 pub fn row_model(&self) -> &DataTableRowModel<T> {
163 &self.row_model
164 }
165
166 /// Processes the row model with current state.
167 pub fn process(&mut self) {
168 // Run the full processing pipeline.
169 self.row_model.process(
170 &self.columns,
171 &self.state.filtering,
172 &self.state.sorting,
173 &self.state.expanding,
174 &self.state.grouping,
175 &self.state.pagination,
176 &self.state.row_selection,
177 );
178 }
179
180 /// Returns visible rows after processing.
181 ///
182 /// # Returns
183 ///
184 /// - `impl Iterator<Item = &DataTableRow<T>>`: An iterator over visible rows.
185 pub fn visible_rows(&self) -> impl Iterator<Item = &DataTableRow<T>> {
186 self.row_model.visible_rows()
187 }
188
189 /// Returns the total number of rows.
190 ///
191 /// # Returns
192 ///
193 /// - `usize`: The total row count.
194 pub fn total_row_count(&self) -> usize {
195 self.row_model.total_row_count()
196 }
197
198 /// Returns the number of filtered rows.
199 ///
200 /// # Returns
201 ///
202 /// - `usize`: The filtered row count.
203 pub fn filtered_row_count(&self) -> usize {
204 self.row_model.filtered_row_count()
205 }
206
207 /// Returns the number of rows on the current page.
208 ///
209 /// # Returns
210 ///
211 /// - `usize`: The page row count.
212 pub fn page_row_count(&self) -> usize {
213 self.row_model.page_row_count()
214 }
215
216 /// Gets a row by ID.
217 ///
218 /// # Parameters
219 ///
220 /// - `id`: The row identifier to look up.
221 ///
222 /// # Returns
223 ///
224 /// - `Option<&DataTableRow<T>>`: The row if found.
225 pub fn get_row(&self, id: &DataTableRowId) -> Option<&DataTableRow<T>> {
226 self.row_model.get_row(id)
227 }
228
229 /// Returns visible column IDs in order.
230 ///
231 /// # Returns
232 ///
233 /// - `Vec<ColumnId>`: The ordered list of visible column IDs.
234 pub fn visible_column_ids(&self) -> Vec<ColumnId> {
235 // Collect all column IDs.
236 let all_ids: Vec<ColumnId> = self.columns.iter().map(|c| c.id().clone()).collect();
237
238 // Apply custom ordering.
239 let ordered = self.state.column_ordering.apply_order(&all_ids);
240
241 // Apply pinning to reorder left/center/right.
242 let pinned = self.state.column_pinning.apply_pinning(&ordered);
243
244 // Filter by visibility.
245 pinned
246 .into_iter()
247 .filter(|id| self.state.column_visibility.is_visible(id))
248 .collect()
249 }
250
251 /// Returns visible columns in order.
252 ///
253 /// # Returns
254 ///
255 /// - `Vec<&ColumnDef<T>>`: References to visible column definitions.
256 pub fn visible_columns(&self) -> Vec<&ColumnDef<T>> {
257 // Get visible column IDs and look up their definitions.
258 let visible_ids = self.visible_column_ids();
259 visible_ids
260 .iter()
261 .filter_map(|id| self.columns.iter().find(|c| c.id() == id))
262 .collect()
263 }
264
265 /// Gets a column by ID.
266 ///
267 /// # Parameters
268 ///
269 /// - `id`: The column identifier to look up.
270 ///
271 /// # Returns
272 ///
273 /// - `Option<&ColumnDef<T>>`: The column definition if found.
274 pub fn get_column(&self, id: &ColumnId) -> Option<&ColumnDef<T>> {
275 // Search for the column by ID.
276 self.columns.iter().find(|c| c.id() == id)
277 }
278
279 /// Toggles sorting for a column.
280 ///
281 /// # Parameters
282 ///
283 /// - `column_id`: The column identifier to toggle sorting for.
284 /// - `multi`: Whether to add to multi-sort list.
285 pub fn toggle_sort(&mut self, column_id: impl Into<ColumnId>, multi: bool) {
286 // Toggle the sort and invalidate the row model.
287 self.state.sorting.toggle_sort(column_id, multi);
288 self.row_model.invalidate();
289 }
290
291 /// Sets a column filter.
292 ///
293 /// # Parameters
294 ///
295 /// - `column_id`: The column identifier.
296 /// - `value`: The filter value text.
297 pub fn set_column_filter(&mut self, column_id: impl Into<ColumnId>, value: impl Into<String>) {
298 // Set the filter, reset pagination, and invalidate.
299 self.state.filtering.set_text_filter(column_id, value);
300 self.state.pagination.go_to_first();
301 self.row_model.invalidate();
302 }
303
304 /// Sets the global filter.
305 ///
306 /// # Parameters
307 ///
308 /// - `value`: The global search text.
309 pub fn set_global_filter(&mut self, value: impl Into<String>) {
310 // Set the global filter, reset pagination, and invalidate.
311 self.state.filtering.set_global_filter(value);
312 self.state.pagination.go_to_first();
313 self.row_model.invalidate();
314 }
315
316 /// Toggles row selection.
317 ///
318 /// # Parameters
319 ///
320 /// - `row_id`: The row identifier to toggle selection for.
321 pub fn toggle_row_selection(&mut self, row_id: DataTableRowId) {
322 // Toggle the row selection state.
323 self.state.row_selection.toggle(row_id);
324 }
325
326 /// Selects all filtered rows.
327 pub fn select_all_rows(&mut self) {
328 // Get filtered row IDs and select them all.
329 let ids = self.row_model.filtered_row_ids();
330 self.state.row_selection.select_all(ids);
331 }
332
333 /// Clears row selection.
334 pub fn clear_selection(&mut self) {
335 // Clear all selections.
336 self.state.row_selection.clear();
337 }
338
339 /// Toggles row expansion.
340 ///
341 /// # Parameters
342 ///
343 /// - `row_id`: The row identifier to toggle expansion for.
344 pub fn toggle_row_expansion(&mut self, row_id: DataTableRowId) {
345 // Toggle the expansion state and invalidate.
346 self.state.expanding.toggle(row_id);
347 self.row_model.invalidate();
348 }
349
350 /// Toggles column visibility.
351 ///
352 /// # Parameters
353 ///
354 /// - `column_id`: The column identifier to toggle visibility for.
355 pub fn toggle_column_visibility(&mut self, column_id: ColumnId) {
356 // Toggle the column visibility state.
357 self.state.column_visibility.toggle(column_id);
358 }
359
360 /// Goes to a specific page.
361 ///
362 /// # Parameters
363 ///
364 /// - `page`: The zero-based page index.
365 pub fn go_to_page(&mut self, page: usize) {
366 // Navigate to the specified page.
367 let row_count = self.filtered_row_count();
368 self.state.pagination.go_to_page(page, row_count);
369 }
370
371 /// Goes to the next page.
372 pub fn next_page(&mut self) {
373 // Navigate to the next page.
374 let row_count = self.filtered_row_count();
375 self.state.pagination.go_to_next(row_count);
376 }
377
378 /// Goes to the previous page.
379 pub fn previous_page(&mut self) {
380 // Navigate to the previous page.
381 self.state.pagination.go_to_previous();
382 }
383
384 /// Sets the page size.
385 ///
386 /// # Parameters
387 ///
388 /// - `size`: The new page size.
389 pub fn set_page_size(&mut self, size: usize) {
390 // Update the page size.
391 let row_count = self.filtered_row_count();
392 self.state.pagination.set_page_size(size, row_count);
393 }
394
395 /// Resets all table state.
396 pub fn reset(&mut self) {
397 // Reset all state and invalidate.
398 self.state.reset_all();
399 self.row_model.invalidate();
400 }
401}