use densa_data::{LiveTable, RowRef, View, ViewId};
use densa_grid::{CellStyle, CellText, Color, Column, GridSource, Palette};
use crate::table::{ArrowTable, CellState, TableError};
#[derive(Debug, Clone)]
pub struct LiveGrid {
mirror: ArrowTable,
table: (u64, u64),
}
impl LiveGrid {
pub fn new(table: &LiveTable) -> Self {
let mut grid = Self {
mirror: ArrowTable::new(table.schema().clone()),
table: (table.instance(), table.generation()),
};
grid.sync(table);
grid
}
pub fn columns(&self) -> Vec<Column> {
self.mirror.columns()
}
pub fn set_decimals(
&mut self,
column: usize,
decimals: Option<usize>,
) -> Result<(), TableError> {
self.mirror.set_decimals(column, decimals)
}
pub fn set_column_chars(&mut self, column: usize, chars: usize) -> Result<(), TableError> {
self.mirror.set_column_chars(column, chars)
}
pub fn view<'a>(
&'a mut self,
table: &'a LiveTable,
view: ViewId,
first_row: usize,
palette: &Palette,
) -> Option<LiveGridView<'a>> {
self.sync(table);
Some(LiveGridView {
mirror: &self.mirror,
rows: table.view(view)?,
first_row,
text: palette.text,
dim: palette.dim_text,
})
}
pub(crate) fn is_sized(&self) -> bool {
self.mirror.is_sized()
}
pub(crate) fn is_synced(&self, table: &LiveTable) -> bool {
self.table == (table.instance(), table.generation())
&& self.mirror.stored_batches() == table.batches().len()
}
pub(crate) fn write(&self, at: RowRef, column: usize, text: &mut CellText) -> CellState {
self.mirror.write_at(at.batch, at.row, column, text)
}
pub(crate) fn sync(&mut self, table: &LiveTable) {
let current = (table.instance(), table.generation());
if current != self.table {
if self.mirror.schema() != table.schema() {
self.mirror = ArrowTable::new(table.schema().clone());
}
self.mirror.clear_batches();
self.table = current;
}
let new = table
.batches()
.get(self.mirror.stored_batches()..)
.unwrap_or_default();
for batch in new {
if self.mirror.push(batch.clone()).is_err() {
self.mirror.clear_batches();
return;
}
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct LiveGridView<'a> {
mirror: &'a ArrowTable,
rows: View<'a>,
first_row: usize,
text: Color,
dim: Color,
}
impl GridSource for LiveGridView<'_> {
fn rows(&self) -> usize {
self.rows.len().saturating_sub(self.first_row)
}
fn cell(&self, row: usize, column: usize, text: &mut CellText) -> CellStyle {
let state = match self.rows.row(self.first_row.saturating_add(row)) {
Some(at) => self.mirror.write_at(at.batch, at.row, column, text),
None => CellState::OutOfRange,
};
let color = if state == CellState::Value {
self.text
} else {
self.dim
};
CellStyle::new(color)
}
}