use std::borrow::Cow;
use crate::{
grid::config::Position,
grid::records::{ExactRecords, PeekableRecords, Records, RecordsMut, Resizable},
settings::TableOption,
Table,
};
#[cfg_attr(feature = "derive", doc = "```")]
#[cfg_attr(not(feature = "derive"), doc = "```ignore")]
#[derive(Debug)]
pub struct Concat {
table: Table,
mode: ConcatMode,
default_cell: Cow<'static, str>,
}
#[derive(Debug)]
enum ConcatMode {
Vertical,
Horizontal,
}
impl Concat {
fn new(table: Table, mode: ConcatMode) -> Self {
Self {
table,
mode,
default_cell: Cow::Borrowed(""),
}
}
pub fn vertical(table: Table) -> Self {
Self::new(table, ConcatMode::Vertical)
}
pub fn horizontal(table: Table) -> Self {
Self::new(table, ConcatMode::Horizontal)
}
pub fn default_cell(mut self, cell: impl Into<Cow<'static, str>>) -> Self {
self.default_cell = cell.into();
self
}
}
impl<R, D, C> TableOption<R, C, D> for Concat
where
R: Records + ExactRecords + Resizable + PeekableRecords + RecordsMut<String>,
{
fn change(mut self, records: &mut R, _: &mut C, _: &mut D) {
let count_rows = records.count_rows();
let count_cols = records.count_columns();
let rhs = &mut self.table;
match self.mode {
ConcatMode::Horizontal => {
for _ in 0..rhs.count_columns() {
records.push_column();
}
for row in count_rows..rhs.count_rows() {
records.push_row();
for col in 0..records.count_columns() {
let pos = Position::new(row, col);
records.set(pos, self.default_cell.to_string());
}
}
for row in 0..rhs.shape().0 {
for col in 0..rhs.shape().1 {
let pos = Position::new(row, col);
let text = rhs.get_records().get_text(pos).to_string();
let pos = pos + (0, count_cols);
records.set(pos, text);
}
}
}
ConcatMode::Vertical => {
for _ in 0..rhs.count_rows() {
records.push_row();
}
for col in count_cols..rhs.shape().1 {
records.push_column();
for row in 0..records.count_rows() {
let pos = Position::new(row, col);
records.set(pos, self.default_cell.to_string());
}
}
for row in 0..rhs.shape().0 {
for col in 0..rhs.shape().1 {
let pos = Position::new(row, col);
let text = rhs.get_records().get_text(pos).to_string();
let pos = pos + (count_rows, 0);
records.set(pos, text);
}
}
}
}
}
}