use super::{Alignment, Paragraph};
use serde::Serialize;
#[derive(Debug, Clone, Default, Serialize)]
pub struct Table {
pub rows: Vec<TableRow>,
pub column_widths: Vec<ColumnWidth>,
pub has_header: bool,
}
impl Table {
pub fn new() -> Self {
Self::default()
}
pub fn with_dimensions(rows: usize, cols: usize) -> Self {
let mut table = Self::new();
for _ in 0..rows {
let mut row = TableRow::new();
for _ in 0..cols {
row.cells.push(TableCell::new());
}
table.rows.push(row);
}
table
}
pub fn row_count(&self) -> usize {
self.rows.len()
}
pub fn column_count(&self) -> usize {
self.rows.first().map(|r| r.cells.len()).unwrap_or(0)
}
pub fn has_merged_cells(&self) -> bool {
self.rows.iter().any(|row| {
row.cells
.iter()
.any(|cell| cell.rowspan > 1 || cell.colspan > 1)
})
}
pub fn has_rowspan(&self) -> bool {
self.rows
.iter()
.any(|row| row.cells.iter().any(|cell| cell.rowspan > 1))
}
pub fn get_cell(&self, row: usize, col: usize) -> Option<&TableCell> {
self.rows.get(row).and_then(|r| r.cells.get(col))
}
pub fn get_cell_mut(&mut self, row: usize, col: usize) -> Option<&mut TableCell> {
self.rows.get_mut(row).and_then(|r| r.cells.get_mut(col))
}
}
#[derive(Debug, Clone, Default, Serialize)]
pub struct TableRow {
pub cells: Vec<TableCell>,
pub is_header: bool,
}
impl TableRow {
pub fn new() -> Self {
Self::default()
}
pub fn header() -> Self {
Self {
cells: Vec::new(),
is_header: true,
}
}
}
#[derive(Debug, Clone, Default, Serialize)]
pub struct TableCell {
pub content: Vec<Paragraph>,
pub rowspan: u32,
pub colspan: u32,
pub alignment: Alignment,
pub vertical_alignment: VerticalAlignment,
pub background_color: Option<String>,
}
impl TableCell {
pub fn new() -> Self {
Self {
rowspan: 1,
colspan: 1,
..Default::default()
}
}
pub fn text(text: impl Into<String>) -> Self {
Self {
content: vec![Paragraph::text(text)],
rowspan: 1,
colspan: 1,
..Default::default()
}
}
pub fn merged(rowspan: u32, colspan: u32) -> Self {
Self {
rowspan,
colspan,
..Default::default()
}
}
pub fn plain_text(&self) -> String {
self.content
.iter()
.map(|p| p.plain_text())
.collect::<Vec<_>>()
.join("\n")
}
pub fn is_merged(&self) -> bool {
self.rowspan > 1 || self.colspan > 1
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize)]
pub enum VerticalAlignment {
#[default]
Top,
Middle,
Bottom,
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Default)]
pub enum ColumnWidth {
#[default]
Auto,
Pixels(u32),
Percent(f32),
}