1use densa_data::{DataError, Filter, LiveTable, Order, RecordId, View, ViewId, ViewSpec};
2use densa_grid::{CellStyle, CellText, Column, GridModel, Palette, SortOrder};
3
4use crate::live::LiveGrid;
5use crate::table::{CellState, TableError};
6
7#[derive(Debug)]
22pub struct LiveModel {
23 table: LiveTable,
24 grid: LiveGrid,
25 columns: Vec<Column>,
26 view: ViewId,
27 filter: Option<Filter>,
28 sort: Option<(usize, SortOrder)>,
29 instance: u64,
31 columns_revision: u64,
33 generation: u64,
34}
35
36impl LiveModel {
37 pub fn new(mut table: LiveTable) -> Result<Self, DataError> {
43 let view = table.add_view(ViewSpec::new())?;
44 let grid = LiveGrid::new(&table);
45 Ok(Self {
46 columns: grid.columns(),
47 grid,
48 view,
49 filter: None,
50 sort: None,
51 instance: table.instance(),
52 table,
53 columns_revision: 0,
54 generation: 0,
55 })
56 }
57
58 pub fn table(&self) -> &LiveTable {
60 &self.table
61 }
62
63 pub fn table_mut(&mut self) -> &mut LiveTable {
67 &mut self.table
68 }
69
70 pub fn view(&self) -> Option<View<'_>> {
73 self.table.view(self.view)
74 }
75
76 pub fn record(&self, index: usize) -> Option<RecordId> {
78 self.view()?.record(index)
79 }
80
81 pub fn filter(&self) -> Option<&Filter> {
83 self.filter.as_ref()
84 }
85
86 pub fn set_filter(&mut self, filter: Option<Filter>) -> Result<(), DataError> {
93 self.replace_view(filter, self.sort)
94 }
95
96 pub fn set_decimals(
102 &mut self,
103 column: usize,
104 decimals: Option<usize>,
105 ) -> Result<(), TableError> {
106 self.grid.set_decimals(column, decimals)?;
107 self.read_columns();
108 Ok(())
109 }
110
111 pub fn set_column_chars(&mut self, column: usize, chars: usize) -> Result<(), TableError> {
117 self.grid.set_column_chars(column, chars)?;
118 self.read_columns();
119 Ok(())
120 }
121
122 fn read_columns(&mut self) {
124 self.columns = self.grid.columns();
125 self.columns_revision = self.columns_revision.wrapping_add(1);
126 }
127
128 fn replace_view(
131 &mut self,
132 filter: Option<Filter>,
133 sort: Option<(usize, SortOrder)>,
134 ) -> Result<(), DataError> {
135 let view = self.table.add_view(self.spec(filter.clone(), sort))?;
136 self.table.remove_view(self.view);
137 self.view = view;
138 self.filter = filter;
139 self.sort = sort;
140 Ok(())
141 }
142
143 fn spec(&self, filter: Option<Filter>, sort: Option<(usize, SortOrder)>) -> ViewSpec {
146 let mut spec = ViewSpec::new();
147 if let Some(filter) = filter {
148 spec = spec.filter(filter);
149 }
150 if let Some((column, order)) = sort {
151 if let Some(name) = self.sort_name(column) {
152 let order = match order {
153 SortOrder::Descending => Order::Descending,
154 _ => Order::Ascending,
155 };
156 spec = spec.sort_by(name, order);
157 }
158 }
159 spec
160 }
161
162 fn sort_name(&self, column: usize) -> Option<String> {
165 let schema = self.table.schema();
166 let name = schema.fields().get(column)?.name();
167 let (first, _) = schema.column_with_name(name)?;
168 (first == column).then(|| name.clone())
169 }
170
171 fn adopt_table(&mut self) {
174 self.instance = self.table.instance();
175 self.generation = self.generation.wrapping_add(1);
176 if self
177 .sort
178 .is_some_and(|(column, _)| self.sort_name(column).is_none())
179 {
180 self.sort = None;
181 }
182 if self.view().is_none() {
183 let spec = self.spec(self.filter.clone(), self.sort);
184 let view = self.table.add_view(spec).or_else(|_| {
185 self.filter = None;
186 self.sort = None;
187 self.table.add_view(ViewSpec::new())
188 });
189 if let Ok(view) = view {
190 self.view = view;
191 }
192 }
193 }
194}
195
196impl GridModel for LiveModel {
197 fn columns(&self) -> &[Column] {
198 &self.columns
199 }
200
201 fn rows(&self) -> usize {
202 self.view().map_or(0, |view| view.len())
203 }
204
205 fn cell(&self, row: usize, column: usize, text: &mut CellText, palette: &Palette) -> CellStyle {
206 let at = self.view().and_then(|view| view.row(row));
207 let state = match at {
208 Some(at) if self.grid.is_synced(&self.table) => self.grid.write(at, column, text),
209 _ => CellState::OutOfRange,
210 };
211 let color = if state == CellState::Value {
212 palette.text
213 } else {
214 palette.dim_text
215 };
216 CellStyle::new(color)
217 }
218
219 fn prepare(&mut self) {
220 let replaced = self.instance != self.table.instance();
221 if replaced {
222 self.adopt_table();
223 }
224 let sized = self.grid.is_sized();
225 self.grid.sync(&self.table);
226 if replaced || sized != self.grid.is_sized() {
229 self.read_columns();
230 }
231 }
232
233 fn sort(&mut self, column: usize, order: SortOrder) -> bool {
234 self.sort_name(column).is_some()
235 && self
236 .replace_view(self.filter.clone(), Some((column, order)))
237 .is_ok()
238 }
239
240 fn sort_state(&self) -> Option<(usize, SortOrder)> {
241 self.sort
242 }
243
244 fn row_key(&self, row: usize) -> Option<u64> {
245 self.record(row).map(RecordId::to_bits)
246 }
247
248 fn row_of_key(&self, key: u64) -> Option<usize> {
249 self.view()?.position(RecordId::from_bits(key))
250 }
251
252 fn columns_revision(&self) -> u64 {
253 self.columns_revision
254 }
255
256 fn generation(&self) -> u64 {
257 self.generation
258 }
259}