Skip to main content

densa_grid/
lib.rs

1//! A data grid over your own data, drawn onto a `densa_draw::Canvas`.
2//!
3//! Domain-agnostic: an application describes its [`Column`]s and implements [`GridSource`]
4//! (one call per visible cell, formatting into a stack buffer); [`GridPainter`] lays the
5//! columns out from font metrics, aligns text, fills overflowing numbers with `#` like a
6//! spreadsheet, and draws cell styles and glyphs. No GPU dependency: hand the canvas's
7//! instances to `densa-render` (or any other backend) to show them.
8//!
9//! A widget showing a grid asks its data through [`GridModel`] instead: the same cells, plus
10//! the rows to scroll through and sorting by column.
11//!
12//! Painting allocates nothing once the frame's characters are cached.
13//!
14//! ```
15//! use densa_draw::{Canvas, Color, InstanceBuffer};
16//! use densa_grid::{Align, CellStyle, CellText, Column, GridPainter, GridSource, Palette};
17//! use densa_text::{AtlasConfig, Font, GlyphCache};
18//!
19//! /// Your data, as the grid asks for it: a cell at a time, into a stack buffer.
20//! struct Hosts(Vec<(&'static str, f64)>);
21//!
22//! impl GridSource for Hosts {
23//!     fn rows(&self) -> usize {
24//!         self.0.len()
25//!     }
26//!
27//!     fn cell(&self, row: usize, column: usize, text: &mut CellText) -> CellStyle {
28//!         let (name, load) = self.0[row];
29//!         // A cell that does not fit its buffer stays empty rather than failing the frame.
30//!         let _ = match column {
31//!             0 => text.push_str(name),
32//!             _ => densa_fmt::write_fixed(text, load, 1),
33//!         };
34//!         CellStyle::new(Color::WHITE)
35//!     }
36//! }
37//!
38//! let columns = vec![Column::new("host", 12, Align::Left), Column::new("load", 6, Align::Right)];
39//! let mut painter = GridPainter::new(columns, 20, Font::bundled_mono()?, 13.0, Palette::new());
40//!
41//! let mut cache = GlyphCache::new(AtlasConfig::default());
42//! let mut instances = InstanceBuffer::with_capacity(4096);
43//! let mut canvas = Canvas::begin(&mut cache, &mut instances);
44//! painter.paint(&Hosts(vec![("web-1", 0.42), ("db-1", 3.5)]), &mut canvas);
45//! assert!(instances.len() > 0, "titles, cells and their glyphs");
46//! # Ok::<(), Box<dyn std::error::Error>>(())
47//! ```
48
49mod grid;
50mod layout;
51mod model;
52mod palette;
53
54pub use densa_core::{Color, Point, Rect};
55pub use grid::{CellStyle, CellText, GridPainter, GridSource, CELL_BYTES};
56pub use layout::{Align, Column, GridLayout};
57pub use model::{GridModel, SortOrder};
58pub use palette::Palette;