use crate::reader::driver::*;
use crate::structs::Cells;
use crate::structs::Column;
use crate::structs::MergeCells;
use crate::structs::Stylesheet;
use crate::traits::AdjustmentValue;
use crate::writer::driver::*;
use quick_xml::events::{BytesStart, Event};
use quick_xml::Reader;
use quick_xml::Writer;
use std::io::Cursor;
use thin_vec::ThinVec;
#[derive(Clone, Default, Debug)]
pub(crate) struct Columns {
column: ThinVec<Column>,
}
impl Columns {
#[inline]
pub(crate) fn get_column_collection(&self) -> &[Column] {
&self.column
}
#[inline]
pub(crate) fn get_column_collection_mut(&mut self) -> &mut ThinVec<Column> {
&mut self.column
}
#[inline]
pub(crate) fn get_column(&self, value: &u32) -> Option<&Column> {
self.column
.iter()
.find(|&column| value == column.get_col_num())
}
pub(crate) fn get_column_mut(&mut self, value: &u32) -> &mut Column {
if self.get_column(value).is_none() {
let mut obj = Column::default();
obj.set_col_num(*value);
self.set_column(obj);
}
for column in self.get_column_collection_mut() {
if value == column.get_col_num() {
return column;
}
}
panic!("Column not found.");
}
#[inline]
pub(crate) fn set_column(&mut self, value: Column) -> &mut Self {
self.column.push(value);
self
}
pub(crate) fn calculation_auto_width(
&mut self,
cells: &Cells,
merge_cells: &MergeCells,
) -> &mut Self {
for column in self.get_column_collection_mut() {
let has_horizontal = merge_cells.has_horizontal(column.get_col_num());
if has_horizontal {
continue;
}
column.calculation_auto_width(cells);
}
self
}
pub(crate) fn set_attributes<R: std::io::BufRead>(
&mut self,
reader: &mut Reader<R>,
_e: &BytesStart,
stylesheet: &Stylesheet,
) {
xml_read_loop!(
reader,
Event::Empty(ref e) => {
if e.name().into_inner() == b"col" {
let mut obj = Column::default();
obj.set_attributes(reader, e, stylesheet);
let min = get_attribute(e, b"min").unwrap().parse::<u32>().unwrap();
let max = get_attribute(e, b"max").unwrap().parse::<u32>().unwrap();
for i in min..=max {
obj.set_col_num(i);
self.set_column(obj.clone());
}
}
},
Event::End(ref e) => {
if e.name().into_inner() == b"cols" {
return
}
},
Event::Eof => panic!("Error: Could not find {} end element", "cols")
);
}
pub(crate) fn write_to(
&self,
writer: &mut Writer<Cursor<Vec<u8>>>,
stylesheet: &mut Stylesheet,
) {
if self.column.is_empty() {
return;
}
write_start_tag(writer, "cols", vec![], false);
let mut column_copy = self.column.clone();
column_copy.sort_by(|a, b| a.get_col_num().cmp(b.get_col_num()));
let mut column_iter = column_copy.iter();
let mut column_raw = column_iter.next();
let mut obj = column_raw.unwrap();
let mut min = *obj.get_col_num();
let mut max = min;
loop {
column_raw = column_iter.next();
match column_raw {
Some(column) => {
if column.get_col_num() == &(max + 1)
&& column.get_hash_code() == obj.get_hash_code()
&& column.get_style() == obj.get_style()
{
max += 1;
} else {
self.write_to_column(writer, &min, &max, obj, stylesheet);
obj = column;
min = *obj.get_col_num();
max = min;
}
}
None => {
self.write_to_column(writer, &min, &max, obj, stylesheet);
break;
}
}
}
write_end_tag(writer, "cols");
}
pub(crate) fn write_to_column(
&self,
writer: &mut Writer<Cursor<Vec<u8>>>,
min: &u32,
max: &u32,
column: &Column,
stylesheet: &mut Stylesheet,
) {
let mut attributes: Vec<(&str, &str)> = Vec::new();
let min_str = min.to_string();
let max_str = max.to_string();
attributes.push(("min", &min_str));
attributes.push(("max", &max_str));
let width = column.width.get_value_string();
attributes.push(("width", &width));
if *column.hidden.get_value() {
attributes.push(("hidden", column.hidden.get_value_string()));
}
if *column.best_fit.get_value() {
attributes.push(("bestFit", column.best_fit.get_value_string()));
}
attributes.push(("customWidth", "1"));
let xf_index_str: String;
let xf_index = stylesheet.set_style(column.get_style());
if xf_index > 0 {
xf_index_str = xf_index.to_string();
attributes.push(("style", &xf_index_str));
}
write_start_tag(writer, "col", attributes, true);
}
}
impl AdjustmentValue for Columns {
fn adjustment_insert_value(&mut self, root_num: &u32, offset_num: &u32) {
for column_dimension in &mut self.column {
column_dimension.adjustment_insert_value(root_num, offset_num);
}
}
fn adjustment_remove_value(&mut self, root_num: &u32, offset_num: &u32) {
self.get_column_collection_mut()
.retain(|x| !(x.is_remove_value(root_num, offset_num)));
for column_dimension in &mut self.column {
column_dimension.adjustment_remove_value(root_num, offset_num);
}
}
}