Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T02:30:35.134Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

table_data_engine.rs

121 lines · 4.2 KB · rust
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::{
9    collections::{HashMap, HashSet},
10    sync::Arc,
11};
12
13use ui::table_row::TableRow;
14
15use crate::{
16    table_data_engine::{
17        filtering_by_column::{FilterEntry, FilterStack, calculate_available_filters, retain_rows},
18        sorting_by_column::{AppliedSorting, sort_data_rows},
19    },
20    types::{AnyColumn, DataRow, DisplayRow, TableCell, TableLikeContent},
21};
22
23pub mod filtering_by_column;
24pub mod sorting_by_column;
25
26#[derive(Default)]
27pub(crate) struct TableDataEngine {
28    pub filter_stack: FilterStack,
29    /// Pre-computed unique values per column, used to populate filter menus
30    all_filters: HashMap<AnyColumn, Vec<FilterEntry>>,
31    pub applied_sorting: Option<AppliedSorting>,
32    d2d_mapping: DisplayToDataMapping,
33    pub contents: Arc<TableLikeContent>,
34}
35
36impl TableDataEngine {
37    pub(crate) fn d2d_mapping(&self) -> &DisplayToDataMapping {
38        &self.d2d_mapping
39    }
40
41    pub(crate) fn set_d2d_mapping(&mut self, mapping: DisplayToDataMapping) {
42        self.d2d_mapping = mapping;
43    }
44
45    /// Recomputes the unique filter entries for every column from the current table data.
46    /// Must be called after content changes (e.g. after parsing).
47    pub fn calculate_available_filters(&mut self) {
48        self.all_filters =
49            calculate_available_filters(&self.contents.rows, self.contents.number_of_cols);
50    }
51}
52
53/// Relation of Display (rendered) rows to Data (src) rows with applied transformations
54/// Transformations applied:
55/// - sorting by column
56/// - filtering by column values
57#[derive(Debug, Default)]
58pub struct DisplayToDataMapping {
59    /// All rows sorted, regardless of applied filtering. Recomputed every time sorting changes
60    pub sorted_rows: Vec<DataRow>,
61    /// Rows that survive the active filters. Recomputed every time filters change
62    pub retained_rows: HashSet<DataRow>,
63    /// Merged result: sorted rows intersected with retained rows
64    pub mapping: Arc<HashMap<DisplayRow, DataRow>>,
65}
66
67impl DisplayToDataMapping {
68    /// Computes the full display-to-data mapping from owned inputs.
69    /// Intended to be called from a background thread.
70    pub(crate) fn compute(
71        contents: &Arc<TableLikeContent>,
72        filter_stack: &FilterStack,
73        sorting: Option<AppliedSorting>,
74    ) -> Self {
75        let mut mapping = Self::default();
76        mapping.apply_sorting(sorting, &contents.rows);
77        mapping.apply_filtering(filter_stack, &contents.rows);
78        mapping.merge_mappings();
79        mapping
80    }
81
82    /// Get the data row for a given display row
83    pub fn get_data_row(&self, display_row: DisplayRow) -> Option<DataRow> {
84        self.mapping.get(&display_row).copied()
85    }
86
87    /// Get the number of filtered rows
88    pub fn visible_row_count(&self) -> usize {
89        self.mapping.len()
90    }
91
92    /// Computes sorting
93    fn apply_sorting(&mut self, sorting: Option<AppliedSorting>, rows: &[TableRow<TableCell>]) {
94        let data_rows: Vec<DataRow> = (0..rows.len()).map(DataRow).collect();
95
96        let sorted_rows = if let Some(sorting) = sorting {
97            sort_data_rows(&rows, data_rows, sorting)
98        } else {
99            data_rows
100        };
101
102        self.sorted_rows = sorted_rows;
103    }
104
105    fn apply_filtering(&mut self, filter_stack: &FilterStack, rows: &[TableRow<TableCell>]) {
106        self.retained_rows = retain_rows(rows, filter_stack);
107    }
108
109    /// Merges pre-computed sorting and filtering into the final display mapping
110    fn merge_mappings(&mut self) {
111        self.mapping = Arc::new(
112            self.sorted_rows
113                .iter()
114                .filter(|data_row| self.retained_rows.contains(data_row))
115                .enumerate()
116                .map(|(display, data)| (DisplayRow(display), *data))
117                .collect(),
118        );
119    }
120}
121
Served at tenant.openagents/omega Member data and write actions are omitted.