Skip to main content

densa_grid/
model.rs

1use std::ops::Range;
2
3use crate::{CellStyle, CellText, Column, Palette};
4
5/// Which way a column sorts.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7#[non_exhaustive]
8pub enum SortOrder {
9    /// Smallest first.
10    Ascending,
11    /// Largest first.
12    Descending,
13}
14
15impl SortOrder {
16    /// The other order.
17    #[must_use]
18    pub fn flipped(self) -> Self {
19        match self {
20            Self::Ascending => Self::Descending,
21            Self::Descending => Self::Ascending,
22        }
23    }
24}
25
26/// The data of a grid widget: its columns, its rows, and each cell's text and style, plus
27/// what the widget asks of it as the user works with it.
28///
29/// Rows are numbered from 0 in the order they are shown; the widget asks only for the rows
30/// on screen. [`cell`](Self::cell) runs for every visible cell every frame and formats into
31/// a stack buffer, so it must not allocate.
32pub trait GridModel {
33    /// The columns, left to right.
34    fn columns(&self) -> &[Column];
35
36    /// How many rows there are.
37    fn rows(&self) -> usize;
38
39    /// Writes the text of the cell at `row`, `column` into `text` (empty on entry) and
40    /// returns its style, in the grid's colors (`palette`, which follows the theme).
41    fn cell(&self, row: usize, column: usize, text: &mut CellText, palette: &Palette) -> CellStyle;
42
43    /// Brings the model up to date before the grid paints (taking in data that arrived, for
44    /// example). It may allocate when the data changed; it should not otherwise. It runs only
45    /// when the grid paints, not while it is hidden (an inactive tab): feed a model that
46    /// must keep up while hidden from the application, through
47    /// `DataGrid::model_mut`.
48    fn prepare(&mut self) {}
49
50    /// The rows the grid shows (every row it paints, the last perhaps cut off), each time it
51    /// paints, after [`prepare`](Self::prepare). A model that fetches its rows, from a
52    /// database or a query engine, asks for these and those around them; it should not
53    /// allocate while it has them. Does nothing by default.
54    fn showing(&mut self, rows: Range<usize>) {
55        let _ = rows;
56    }
57
58    /// The rows of `rows` that a copy of them holds (the grid's copy of selected rows), in
59    /// runs, in order: all of them by default. A model that fetches its rows gives only
60    /// those it has, so copying a billion selected rows does not build a billion lines.
61    fn copy_rows(&self, rows: Range<usize>) -> Vec<Range<usize>> {
62        vec![rows]
63    }
64
65    /// Sorts the rows by `column` (an index into [`columns`](Self::columns)) in `order`, when
66    /// the user asks for it (a click on its title); `false` if the model does not sort by
67    /// that column, which leaves the order alone.
68    fn sort(&mut self, column: usize, order: SortOrder) -> bool {
69        let _ = (column, order);
70        false
71    }
72
73    /// The column and order the rows are sorted by now, if the model knows (a model sorted
74    /// before the user clicked, or one that sorts itself); the grid shows it and reverses it
75    /// on the next click.
76    fn sort_state(&self) -> Option<(usize, SortOrder)> {
77        None
78    }
79
80    /// A value identifying the record at `row` while rows are added, removed or sorted (a
81    /// database key, an instrument id). With it, a selection follows its record; without
82    /// it (`None`, the default), a selection is a position and is cleared by sorting.
83    fn row_key(&self, row: usize) -> Option<u64> {
84        let _ = row;
85        None
86    }
87
88    /// Where the record [`row_key`](Self::row_key) gave `key` for is now, if it is still
89    /// shown. Asked once a frame while a row is selected: make it fast for large models.
90    /// `None` (the record was removed, or is filtered out) clears the selection.
91    fn row_of_key(&self, key: u64) -> Option<usize> {
92        let _ = key;
93        None
94    }
95
96    /// Changes whenever [`columns`](Self::columns) changes (another schema, new widths): the
97    /// grid then reads the columns again, keeping the widths the user dragged if the column
98    /// titles are the same as before. Checked each frame after [`prepare`](Self::prepare).
99    fn columns_revision(&self) -> u64 {
100        0
101    }
102
103    /// Changes when the rows were replaced wholesale (another table), so that keys from
104    /// before mean nothing: the grid then clears its selection and scrolls to the top.
105    /// Checked each frame after [`prepare`](Self::prepare).
106    fn generation(&self) -> u64 {
107        0
108    }
109}