Skip to main content

ui_grid_core/
viewmodel.rs

1use crate::{
2    constants::SortDirection,
3    models::{GridColumnDef, GridIcon, GridIcons, GridLabels, GridOptions, GridRow},
4};
5
6pub fn resolve_grid_labels(overrides: Option<&GridLabels>) -> GridLabels {
7    overrides.cloned().unwrap_or_default()
8}
9
10pub fn resolve_grid_icons(overrides: Option<&GridIcons>) -> GridIcons {
11    overrides.cloned().unwrap_or_default()
12}
13
14pub fn is_grid_tree_enabled(options: &GridOptions) -> bool {
15    options.enable_tree_view
16}
17
18pub fn is_grid_grouping_enabled(options: &GridOptions) -> bool {
19    options.enable_grouping && !is_grid_tree_enabled(options)
20}
21
22pub fn can_grid_expand_rows(options: &GridOptions) -> bool {
23    options.enable_expandable
24}
25
26pub fn is_grid_pagination_enabled(options: &GridOptions) -> bool {
27    options.enable_pagination || options.pagination_page_size.unwrap_or(0) > 0
28}
29
30pub fn should_show_grid_pagination_controls(options: &GridOptions) -> bool {
31    is_grid_pagination_enabled(options) && options.enable_pagination_controls
32}
33
34pub fn is_grid_infinite_scroll_enabled(options: &GridOptions) -> bool {
35    options.infinite_scroll_rows_from_end.is_some()
36        || options.infinite_scroll_up
37        || options.infinite_scroll_down.is_some()
38}
39
40pub fn is_grid_sorting_enabled(options: &GridOptions) -> bool {
41    options.enable_sorting
42}
43
44pub fn is_grid_filtering_enabled(options: &GridOptions) -> bool {
45    options.enable_filtering
46}
47
48pub fn can_grid_move_columns(options: &GridOptions) -> bool {
49    options.enable_column_moving
50}
51
52pub fn is_grid_primary_column(visible_columns: &[GridColumnDef], column: &GridColumnDef) -> bool {
53    visible_columns
54        .first()
55        .is_some_and(|candidate| candidate.name == column.name)
56}
57
58pub fn is_grid_column_sortable(options: &GridOptions, column: &GridColumnDef) -> bool {
59    is_grid_sorting_enabled(options) && column.sortable && column.enable_sorting
60}
61
62pub fn is_grid_column_filterable(options: &GridOptions, column: &GridColumnDef) -> bool {
63    is_grid_filtering_enabled(options) && column.filterable && column.enable_filtering
64}
65
66pub fn should_show_grid_tree_toggle(
67    options: &GridOptions,
68    visible_columns: &[GridColumnDef],
69    row: &GridRow,
70    column: &GridColumnDef,
71) -> bool {
72    is_grid_primary_column(visible_columns, column)
73        && is_grid_tree_enabled(options)
74        && (row.has_children || options.show_tree_expand_no_children)
75}
76
77pub fn should_show_grid_expand_toggle(
78    options: &GridOptions,
79    visible_columns: &[GridColumnDef],
80    column: &GridColumnDef,
81) -> bool {
82    is_grid_primary_column(visible_columns, column) && can_grid_expand_rows(options)
83}
84
85pub fn grid_sort_button_label(direction: SortDirection, labels: &GridLabels) -> String {
86    match direction {
87        SortDirection::Asc => labels.sort_asc.clone(),
88        SortDirection::Desc => labels.sort_desc.clone(),
89        SortDirection::None => labels.sort_default.clone(),
90    }
91}
92
93pub fn grid_sort_button_icon(direction: SortDirection, icons: &GridIcons) -> GridIcon {
94    match direction {
95        SortDirection::Asc => icons.sort_asc.clone(),
96        SortDirection::Desc => icons.sort_desc.clone(),
97        SortDirection::None => icons.sort_default.clone(),
98    }
99}
100
101pub fn grid_sort_aria_sort(direction: SortDirection) -> String {
102    match direction {
103        SortDirection::Asc => "ascending".to_string(),
104        SortDirection::Desc => "descending".to_string(),
105        SortDirection::None => "none".to_string(),
106    }
107}
108
109pub fn grid_grouping_button_label(is_grouped: bool, labels: &GridLabels) -> String {
110    if is_grouped {
111        labels.ungroup_column.clone()
112    } else {
113        labels.group_column.clone()
114    }
115}
116
117pub fn grid_grouping_button_icon(is_grouped: bool, icons: &GridIcons) -> GridIcon {
118    if is_grouped {
119        icons.ungroup_column.clone()
120    } else {
121        icons.group_column.clone()
122    }
123}
124
125pub fn grid_filter_placeholder(is_filterable: bool, labels: &GridLabels) -> String {
126    if is_filterable {
127        labels.filter_placeholder.clone()
128    } else {
129        labels.filter_disabled.clone()
130    }
131}
132
133pub fn grid_group_disclosure_label(collapsed: bool, labels: &GridLabels) -> String {
134    if collapsed {
135        labels.group_expand.clone()
136    } else {
137        labels.group_collapse.clone()
138    }
139}
140
141pub fn grid_group_disclosure_icon(collapsed: bool, icons: &GridIcons) -> GridIcon {
142    if collapsed {
143        icons.group_expand.clone()
144    } else {
145        icons.group_collapse.clone()
146    }
147}
148
149pub fn grid_editor_input_type(column: &GridColumnDef) -> String {
150    match column.r#type {
151        crate::models::GridColumnType::Number => "number".to_string(),
152        crate::models::GridColumnType::Date => "date".to_string(),
153        crate::models::GridColumnType::String
154        | crate::models::GridColumnType::Boolean
155        | crate::models::GridColumnType::Object => "text".to_string(),
156    }
157}
158
159pub fn grid_column_width(column: &GridColumnDef) -> String {
160    column
161        .width
162        .clone()
163        .unwrap_or_else(|| "minmax(11rem, max-content)".to_string())
164}
165
166pub fn grid_cell_indent(
167    options: &GridOptions,
168    visible_columns: &[GridColumnDef],
169    row: &GridRow,
170    column: &GridColumnDef,
171) -> String {
172    if !is_grid_primary_column(visible_columns, column) || !is_grid_tree_enabled(options) {
173        return "0px".to_string();
174    }
175
176    format!("{}px", row.tree_level * options.tree_indent.unwrap_or(10))
177}
178
179pub fn grid_tree_toggle_label(expanded: bool, labels: &GridLabels) -> String {
180    if expanded {
181        labels.tree_collapse.clone()
182    } else {
183        labels.tree_expand.clone()
184    }
185}
186
187pub fn grid_tree_toggle_icon(expanded: bool, icons: &GridIcons) -> GridIcon {
188    if expanded {
189        icons.tree_collapse.clone()
190    } else {
191        icons.tree_expand.clone()
192    }
193}
194
195pub fn grid_expand_toggle_label(expanded: bool, labels: &GridLabels) -> String {
196    if expanded {
197        labels.collapse_detail.clone()
198    } else {
199        labels.expand_detail.clone()
200    }
201}
202
203pub fn grid_expand_toggle_icon(expanded: bool, icons: &GridIcons) -> GridIcon {
204    if expanded {
205        icons.collapse_detail.clone()
206    } else {
207        icons.expand_detail.clone()
208    }
209}
210
211pub fn grid_drag_handle_icon(icons: &GridIcons) -> GridIcon {
212    icons.drag_handle.clone()
213}
214
215pub fn grid_move_left_icon(icons: &GridIcons) -> GridIcon {
216    icons.move_left.clone()
217}
218
219pub fn grid_move_right_icon(icons: &GridIcons) -> GridIcon {
220    icons.move_right.clone()
221}
222
223pub fn grid_pin_left_icon(icons: &GridIcons) -> GridIcon {
224    icons.pin_left.clone()
225}
226
227pub fn grid_pin_right_icon(icons: &GridIcons) -> GridIcon {
228    icons.pin_right.clone()
229}
230
231pub fn grid_unpin_icon(icons: &GridIcons) -> GridIcon {
232    icons.unpin.clone()
233}
234
235pub fn is_grid_column_grouped(group_by_columns: &[String], column: &GridColumnDef) -> bool {
236    group_by_columns.iter().any(|name| name == &column.name)
237}
238
239pub fn is_grid_tree_row_expanded(
240    expanded_tree_rows: &std::collections::BTreeMap<String, bool>,
241    row: &GridRow,
242) -> bool {
243    expanded_tree_rows.get(&row.id).copied().unwrap_or(false)
244}
245
246pub fn grid_tree_toggle_label_for_row(
247    expanded_tree_rows: &std::collections::BTreeMap<String, bool>,
248    row: &GridRow,
249    labels: &GridLabels,
250) -> String {
251    grid_tree_toggle_label(is_grid_tree_row_expanded(expanded_tree_rows, row), labels)
252}
253
254pub fn grid_expand_toggle_label_for_row(row: &GridRow, labels: &GridLabels) -> String {
255    grid_expand_toggle_label(row.expanded, labels)
256}