use tabled::settings::{object::Cell, Color as TabledColor};
use tabled::Table;
use super::config::{parse_bg_color, TableStyleConfig};
pub fn parse_row_bg_colors(theme: &TableStyleConfig) -> Vec<TabledColor> {
theme.rows.colors.iter().map(|rc| parse_bg_color(&rc.bg)).collect()
}
pub fn get_data_row_bg_color(data_row_index: usize, row_bg_colors: &[TabledColor]) -> TabledColor {
let color_idx = data_row_index % row_bg_colors.len();
row_bg_colors[color_idx].clone()
}
pub fn apply_cell_color(
table: &mut Table,
row_idx: usize,
col_idx: usize,
fg_color: TabledColor,
bg_color: TabledColor,
) {
let combined = fg_color | bg_color;
table.modify(Cell::new(row_idx, col_idx), combined);
}
pub fn state_to_fg_color(state: &str) -> Option<TabledColor> {
match state.to_lowercase().as_str() {
"draft" => Some(TabledColor::FG_YELLOW),
"under review" | "under-review" => Some(TabledColor::FG_CYAN),
"revised" => Some(TabledColor::FG_BLUE),
"accepted" => Some(TabledColor::FG_GREEN),
"active" => Some(TabledColor::FG_BRIGHT_GREEN),
"final" => Some(TabledColor::FG_GREEN),
"deferred" => Some(TabledColor::FG_MAGENTA),
"rejected" => Some(TabledColor::FG_RED),
"withdrawn" => Some(TabledColor::FG_RED),
"superseded" => Some(TabledColor::FG_RED),
_ => None,
}
}
pub fn deleted_to_fg_color(deleted: bool) -> TabledColor {
if deleted {
TabledColor::FG_RED
} else {
TabledColor::FG_GREEN
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_row_bg_colors() {
let theme = TableStyleConfig::default();
let colors = parse_row_bg_colors(&theme);
assert_eq!(colors.len(), 2);
}
#[test]
fn test_get_data_row_bg_color_alternating() {
let theme = TableStyleConfig::default();
let colors = parse_row_bg_colors(&theme);
let bg0 = get_data_row_bg_color(0, &colors);
let bg1 = get_data_row_bg_color(1, &colors);
let bg2 = get_data_row_bg_color(2, &colors);
let bg3 = get_data_row_bg_color(3, &colors);
assert_eq!(format!("{:?}", bg0), format!("{:?}", bg2));
assert_eq!(format!("{:?}", bg1), format!("{:?}", bg3));
}
#[test]
fn test_state_to_fg_color_recognized() {
assert!(state_to_fg_color("active").is_some());
assert!(state_to_fg_color("Active").is_some()); assert!(state_to_fg_color("ACTIVE").is_some());
assert!(state_to_fg_color("draft").is_some());
assert!(state_to_fg_color("under review").is_some());
assert!(state_to_fg_color("under-review").is_some());
assert!(state_to_fg_color("accepted").is_some());
assert!(state_to_fg_color("final").is_some());
assert!(state_to_fg_color("rejected").is_some());
}
#[test]
fn test_state_to_fg_color_unrecognized() {
assert!(state_to_fg_color("invalid").is_none());
assert!(state_to_fg_color("").is_none());
assert!(state_to_fg_color("unknown-state").is_none());
}
#[test]
fn test_deleted_to_fg_color() {
let deleted = deleted_to_fg_color(true);
let not_deleted = deleted_to_fg_color(false);
assert_eq!(deleted, TabledColor::FG_RED);
assert_eq!(not_deleted, TabledColor::FG_GREEN);
}
#[test]
fn test_apply_cell_color_does_not_panic() {
use tabled::builder::Builder;
use tabled::Tabled;
#[derive(Tabled)]
struct TestRow {
col: String,
}
let mut builder = Builder::default();
builder.push_record(["Title"]);
builder.push_record(["Header"]);
builder.push_record(["Data"]);
let mut table = builder.build();
let theme = TableStyleConfig::default();
theme.apply_to_table::<TestRow>(&mut table);
let row_bg_colors = parse_row_bg_colors(&theme);
let bg = get_data_row_bg_color(0, &row_bg_colors);
apply_cell_color(&mut table, 2, 0, TabledColor::FG_GREEN, bg);
}
}