1use densa_data::{LiveTable, RowRef, View, ViewId};
2use densa_grid::{CellStyle, CellText, Color, Column, GridSource, Palette};
3
4use crate::table::{ArrowTable, CellState, TableError};
5
6#[derive(Debug, Clone)]
14pub struct LiveGrid {
15 mirror: ArrowTable,
16 table: (u64, u64),
18}
19
20impl LiveGrid {
21 pub fn new(table: &LiveTable) -> Self {
23 let mut grid = Self {
24 mirror: ArrowTable::new(table.schema().clone()),
25 table: (table.instance(), table.generation()),
26 };
27 grid.sync(table);
28 grid
29 }
30
31 pub fn columns(&self) -> Vec<Column> {
33 self.mirror.columns()
34 }
35
36 pub fn set_decimals(
41 &mut self,
42 column: usize,
43 decimals: Option<usize>,
44 ) -> Result<(), TableError> {
45 self.mirror.set_decimals(column, decimals)
46 }
47
48 pub fn set_column_chars(&mut self, column: usize, chars: usize) -> Result<(), TableError> {
53 self.mirror.set_column_chars(column, chars)
54 }
55
56 pub fn view<'a>(
59 &'a mut self,
60 table: &'a LiveTable,
61 view: ViewId,
62 first_row: usize,
63 palette: &Palette,
64 ) -> Option<LiveGridView<'a>> {
65 self.sync(table);
66 Some(LiveGridView {
67 mirror: &self.mirror,
68 rows: table.view(view)?,
69 first_row,
70 text: palette.text,
71 dim: palette.dim_text,
72 })
73 }
74
75 pub(crate) fn is_sized(&self) -> bool {
77 self.mirror.is_sized()
78 }
79
80 pub(crate) fn is_synced(&self, table: &LiveTable) -> bool {
83 self.table == (table.instance(), table.generation())
84 && self.mirror.stored_batches() == table.batches().len()
85 }
86
87 pub(crate) fn write(&self, at: RowRef, column: usize, text: &mut CellText) -> CellState {
89 self.mirror.write_at(at.batch, at.row, column, text)
90 }
91
92 pub(crate) fn sync(&mut self, table: &LiveTable) {
95 let current = (table.instance(), table.generation());
96 if current != self.table {
97 if self.mirror.schema() != table.schema() {
98 self.mirror = ArrowTable::new(table.schema().clone());
99 }
100 self.mirror.clear_batches();
101 self.table = current;
102 }
103 let new = table
104 .batches()
105 .get(self.mirror.stored_batches()..)
106 .unwrap_or_default();
107 for batch in new {
108 if self.mirror.push(batch.clone()).is_err() {
111 self.mirror.clear_batches();
112 return;
113 }
114 }
115 }
116}
117
118#[derive(Debug, Clone, Copy)]
120pub struct LiveGridView<'a> {
121 mirror: &'a ArrowTable,
122 rows: View<'a>,
123 first_row: usize,
124 text: Color,
125 dim: Color,
126}
127
128impl GridSource for LiveGridView<'_> {
129 fn rows(&self) -> usize {
130 self.rows.len().saturating_sub(self.first_row)
131 }
132
133 fn cell(&self, row: usize, column: usize, text: &mut CellText) -> CellStyle {
134 let state = match self.rows.row(self.first_row.saturating_add(row)) {
135 Some(at) => self.mirror.write_at(at.batch, at.row, column, text),
136 None => CellState::OutOfRange,
137 };
138 let color = if state == CellState::Value {
139 self.text
140 } else {
141 self.dim
142 };
143 CellStyle::new(color)
144 }
145}