1//! This module defines core operations and config of tabular data view (CSV table)
2//! It operates in 2 coordinate systems:
3//! - `DataCellId` - indices of src data cells
4//! - `DisplayCellId` - indices of data after applied transformations like sorting/filtering, which is used to render cell on the screen
5//!
6//! It's designed to contain core logic of operations without relying on `CsvPreviewView`, context or window handles.
7
8use std::{collections::HashMap, sync::Arc};
9
10use ui::table_row::TableRow;
11
12use crate::{
13 table_data_engine::sorting_by_column::{AppliedSorting, sort_data_rows},
14 types::{DataRow, DisplayRow, TableCell, TableLikeContent},
15};
16
17pub mod sorting_by_column;
18
19#[derive(Default)]
20pub(crate) struct TableDataEngine {
21 pub applied_sorting: Option<AppliedSorting>,
22 d2d_mapping: DisplayToDataMapping,
23 pub contents: TableLikeContent,
24}
25
26impl TableDataEngine {
27 pub(crate) fn d2d_mapping(&self) -> &DisplayToDataMapping {
28 &self.d2d_mapping
29 }
30
31 pub(crate) fn apply_sort(&mut self) {
32 self.d2d_mapping
33 .apply_sorting(self.applied_sorting, &self.contents.rows);
34 self.d2d_mapping.merge_mappings();
35 }
36
37 /// Applies sorting and filtering to the data and produces display to data mapping
38 pub(crate) fn calculate_d2d_mapping(&mut self) {
39 self.d2d_mapping
40 .apply_sorting(self.applied_sorting, &self.contents.rows);
41 self.d2d_mapping.merge_mappings();
42 }
43}
44
45/// Relation of Display (rendered) rows to Data (src) rows with applied transformations
46/// Transformations applied:
47/// - sorting by column
48#[derive(Debug, Default)]
49pub struct DisplayToDataMapping {
50 /// All rows sorted, regardless of applied filtering. Applied every time sorting changes
51 pub sorted_rows: Vec<DataRow>,
52 /// Filtered and sorted rows. Computed cheaply from `sorted_mapping` and `filtered_out_rows`
53 pub mapping: Arc<HashMap<DisplayRow, DataRow>>,
54}
55
56impl DisplayToDataMapping {
57 /// Get the data row for a given display row
58 pub fn get_data_row(&self, display_row: DisplayRow) -> Option<DataRow> {
59 self.mapping.get(&display_row).copied()
60 }
61
62 /// Get the number of filtered rows
63 pub fn visible_row_count(&self) -> usize {
64 self.mapping.len()
65 }
66
67 /// Computes sorting
68 fn apply_sorting(&mut self, sorting: Option<AppliedSorting>, rows: &[TableRow<TableCell>]) {
69 let data_rows: Vec<DataRow> = (0..rows.len()).map(DataRow).collect();
70
71 let sorted_rows = if let Some(sorting) = sorting {
72 sort_data_rows(&rows, data_rows, sorting)
73 } else {
74 data_rows
75 };
76
77 self.sorted_rows = sorted_rows;
78 }
79
80 /// Take pre-computed sorting and filtering results, and apply them to the mapping
81 fn merge_mappings(&mut self) {
82 self.mapping = Arc::new(
83 self.sorted_rows
84 .iter()
85 .enumerate()
86 .map(|(display, data)| (DisplayRow(display), *data))
87 .collect(),
88 );
89 }
90}