use crate::color::{Color, ColorMode};
pub struct Table {
width: usize, height: usize, cells: Vec<Cell>,
col_widths: Vec<usize>,
row_heights: Vec<usize>,
selected: Option<(usize, usize)>, paddings: [usize; 4],
draw_border: bool,
color_mode: ColorMode,
selection_color: Option<Color>,
primary_color: Option<Color>,
}
impl Table {
pub fn draw(&self) -> String {
debug_assert_eq!(self.col_widths.len(), self.width);
debug_assert_eq!(self.row_heights.len(), self.height);
let [
padding_top,
padding_bottom,
padding_left,
padding_right,
] = self.paddings;
let mut line_width = 0;
let mut line_count = 0;
for w in self.col_widths.iter() {
line_width += *w + 1;
}
line_width += 2 + padding_left + padding_right;
for h in self.row_heights.iter() {
line_count += *h + 1;
}
line_count += 1 + padding_top + padding_bottom;
let mut foreground: Vec<Option<Color>> = vec![None; line_width * line_count];
let mut background: Vec<Option<Color>> = vec![None; line_width * line_count];
let mut buffer = vec![' ' as u32; line_width * line_count];
for i in 0..line_count {
buffer[i * line_width + line_width - 1] = '\n' as u32;
}
if self.draw_border {
let mut curr_y = padding_top;
for h in self.row_heights.iter() {
for x in padding_left..(line_width - 2 - padding_right) {
buffer[curr_y * line_width + x] = '─' as u32;
}
buffer[curr_y * line_width + padding_left] = '├' as u32;
buffer[curr_y * line_width + line_width - 2 - padding_right] = '┤' as u32;
curr_y += *h + 1;
}
for x in (padding_left + 1)..(line_width - 2 - padding_right) {
buffer[curr_y * line_width + x] = '─' as u32;
}
let mut curr_x = padding_left;
for w in self.col_widths.iter() {
for y in padding_top..(line_count - 1 - padding_bottom) {
if buffer[y * line_width + curr_x] == ' ' as u32 {
buffer[y * line_width + curr_x] = '│' as u32;
}
else if curr_x == padding_left {
buffer[y * line_width + curr_x] = '├' as u32;
}
else {
buffer[y * line_width + curr_x] = '┼' as u32;
}
}
buffer[padding_top * line_width + curr_x] = '┬' as u32;
buffer[(line_count - 1 - padding_bottom) * line_width + curr_x] = '┴' as u32;
curr_x += *w + 1;
}
for y in padding_top..(line_count - 1 - padding_bottom) {
if buffer[y * line_width + curr_x] == ' ' as u32 {
buffer[y * line_width + curr_x] = '│' as u32;
}
}
buffer[curr_y * line_width + padding_left] = '╰' as u32;
buffer[curr_y * line_width + line_width - 2 - padding_right] = '╯' as u32;
buffer[padding_top * line_width + padding_left] = '╭' as u32;
buffer[padding_top * line_width + line_width - 2 - padding_right] = '╮' as u32;
}
for col in 0..self.width {
for row in 0..self.height {
let curr_cell = &self.cells[row * self.width + col];
let (mut x, mut y, mut w, mut h) = self.get_rect(col, row);
let [
padding_top,
padding_bottom,
padding_left,
padding_right,
] = curr_cell.paddings;
if padding_top + padding_bottom < h {
y += padding_top;
h -= padding_top + padding_bottom;
}
else {
todo!();
}
if padding_left + padding_right < w {
x += padding_left;
w -= padding_left + padding_right;
}
else {
todo!();
}
let chars = curr_cell.content.chars().collect::<Vec<_>>();
let mut ch_index = 0;
let line_break_at = w * 3 / 4;
for yy in y..(y + h) {
for xx in x..(x + w) {
if ch_index == chars.len() {
break;
}
if chars[ch_index] == '\n' || (xx - x) >= line_break_at && chars[ch_index] == ' ' {
ch_index += 1;
break;
}
buffer[yy * line_width + xx] = chars[ch_index] as u32;
ch_index += 1;
}
}
}
}
if let Some((col, row)) = self.selected {
let [
padding_top, _,
padding_left, _,
] = self.paddings;
if padding_top > 0 && padding_left > 0 {
let (x, y, w, h) = self.get_rect(col, row);
for xx in x..(x + w) {
buffer[(padding_top - 1) * line_width + xx] = '▼' as u32;
foreground[(padding_top - 1) * line_width + xx] = self.primary_color.clone();
}
for yy in y..(y + h) {
buffer[yy * line_width + padding_left - 1] = '▶' as u32;
foreground[yy * line_width + padding_left - 1] = self.primary_color.clone();
}
for yy in y..(y + h) {
for xx in x..(x + w) {
background[yy * line_width + xx] = self.selection_color.clone();
}
}
}
}
buffer.into_iter().map(
|c| char::from_u32(c).unwrap()
).collect()
}
fn get_rect(&self, col: usize, row: usize) -> (usize, usize, usize, usize) { let mut curr_x = 1;
for w in self.col_widths[..col].iter() {
curr_x += *w + 1;
}
let mut curr_y = 1;
for h in self.row_heights[..row].iter() {
curr_y += *h + 1;
}
(curr_x + self.paddings[2], curr_y + self.paddings[0], self.col_widths[col], self.row_heights[row])
}
}
#[derive(Clone)]
pub struct Cell {
content: String,
paddings: [usize; 4], }