use crate::{
grid::config::Position,
grid::records::{ExactRecords, PeekableRecords, Records, RecordsMut},
settings::{object::Object, TableOption},
};
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Dup<Dst, Src> {
src: Src,
dst: Dst,
}
impl<Dst, Src> Dup<Dst, Src> {
pub fn new(dst: Dst, src: Src) -> Self {
Self { src, dst }
}
}
impl<Dst, Src, R, D, C> TableOption<R, C, D> for Dup<Dst, Src>
where
Dst: Object<R>,
Src: Object<R>,
R: Records + ExactRecords + PeekableRecords + RecordsMut<String>,
{
fn change(self, records: &mut R, _: &mut C, _: &mut D) {
let input = collect_input(records, self.src);
set_cells(records, &input, self.dst);
}
}
fn collect_input<R, O>(records: &mut R, src: O) -> Vec<String>
where
O: Object<R>,
R: Records + ExactRecords + PeekableRecords + RecordsMut<String>,
{
let count_rows = records.count_rows();
let count_columns = records.count_columns();
let mut input = Vec::new();
for entity in src.cells(records) {
for pos in entity.iter(count_rows, count_columns) {
if !is_valid_cell(pos, count_rows, count_columns) {
continue;
}
let text = records.get_text(pos).to_owned();
input.push(text);
}
}
input
}
fn set_cells<R, O>(records: &mut R, src: &[String], dst: O)
where
O: Object<R>,
R: Records + ExactRecords + PeekableRecords + RecordsMut<String>,
{
if src.is_empty() {
return;
}
let count_rows = records.count_rows();
let count_columns = records.count_columns();
for entity in dst.cells(records) {
let mut source = src.iter().cycle();
for pos in entity.iter(count_rows, count_columns) {
if !is_valid_cell(pos, count_rows, count_columns) {
continue;
}
let text = source.next().unwrap().clone();
records.set(pos, text);
}
}
}
fn is_valid_cell(pos: Position, count_rows: usize, count_columns: usize) -> bool {
if pos.row > count_rows {
return false;
}
if pos.col > count_columns {
return false;
}
true
}