use papergrid::{
config::{AlignmentHorizontal, AlignmentVertical},
dimension::iterable::IterGridDimension,
records::{ExactRecords, IntoRecords, PeekableRecords, Records},
};
#[cfg(feature = "std")]
use crate::{
grid::{config::ColoredConfig, config::Entity},
settings::CellOption,
};
use super::TableOption;
#[cfg_attr(feature = "ansi", doc = "```")]
#[cfg_attr(not(feature = "ansi"), doc = "```ignore")]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum PaddingExpand {
Horizontal,
Vertical,
}
impl<R, D> TableOption<R, ColoredConfig, D> for PaddingExpand
where
R: Records + ExactRecords + PeekableRecords,
for<'a> &'a R: Records,
for<'a> <<&'a R as Records>::Iter as IntoRecords>::Cell: AsRef<str>,
{
fn change(self, records: &mut R, cfg: &mut ColoredConfig, _: &mut D) {
<Self as CellOption<R, ColoredConfig>>::change(self, records, cfg, Entity::Global)
}
}
impl<R> CellOption<R, ColoredConfig> for PaddingExpand
where
R: Records + ExactRecords + PeekableRecords,
for<'a> &'a R: Records,
for<'a> <<&'a R as Records>::Iter as IntoRecords>::Cell: AsRef<str>,
{
fn change(self, records: &mut R, cfg: &mut ColoredConfig, entity: Entity) {
match self {
PaddingExpand::Vertical => expand_vertical(records, cfg, entity),
PaddingExpand::Horizontal => expand_horizontal(records, cfg, entity),
}
}
}
fn expand_horizontal<R>(records: &mut R, cfg: &mut ColoredConfig, entity: Entity)
where
R: Records + ExactRecords + PeekableRecords,
for<'a> &'a R: Records,
for<'a> <<&'a R as Records>::Iter as IntoRecords>::Cell: AsRef<str>,
{
let widths = IterGridDimension::width(&*records, cfg);
let count_rows = records.count_rows();
let count_cols = records.count_columns();
for pos in entity.iter(count_rows, count_cols) {
let col = pos.col;
let column_width = widths[col];
let width = records.get_width(pos);
if width < column_width {
let alignment = *cfg.get_alignment_horizontal(pos);
let available_width = column_width - width;
let (left, right) = split_horizontal_space(alignment, available_width);
let mut pad = *cfg.get_padding(pos);
pad.left.size = left;
pad.right.size = right;
cfg.set_padding(Entity::from(pos), pad);
}
}
}
fn expand_vertical<R>(records: &mut R, cfg: &mut ColoredConfig, entity: Entity)
where
R: Records + ExactRecords + PeekableRecords,
for<'a> &'a R: Records,
for<'a> <<&'a R as Records>::Iter as IntoRecords>::Cell: AsRef<str>,
{
let heights = IterGridDimension::height(&*records, cfg);
let count_rows = records.count_rows();
let count_cols = records.count_columns();
for pos in entity.iter(count_rows, count_cols) {
let row = pos.row;
let row_height = heights[row];
let cell_height = records.count_lines(pos);
if cell_height < row_height {
let alignment = *cfg.get_alignment_vertical(pos);
let available_width = row_height - cell_height;
let (top, bottom) = split_vertical_space(alignment, available_width);
let mut pad = *cfg.get_padding(pos);
pad.top.size = top;
pad.bottom.size = bottom;
cfg.set_padding(Entity::from(pos), pad);
}
}
}
fn split_horizontal_space(al: AlignmentHorizontal, space: usize) -> (usize, usize) {
match al {
AlignmentHorizontal::Center => {
let left = space / 2;
let right = space - left;
(left, right)
}
AlignmentHorizontal::Left => (0, space),
AlignmentHorizontal::Right => (space, 0),
}
}
fn split_vertical_space(al: AlignmentVertical, space: usize) -> (usize, usize) {
match al {
AlignmentVertical::Center => {
let left = space / 2;
let right = space - left;
(left, right)
}
AlignmentVertical::Top => (0, space),
AlignmentVertical::Bottom => (space, 0),
}
}