use anyhow::bail;
use quick_xml::events::{BytesStart, Event};
use std::io::Read;
use crate::excel::XmlReader;
use crate::helper::string_to_unsignedint;
use crate::raw::drawing::st_types::STPositiveCoordinate;
use crate::{
helper::extract_val_attribute,
raw::drawing::fill::{
gradient_fill::XlsxGradientFill, no_fill::XlsxNoFill, pattern_fill::XlsxPatternFill,
solid_fill::XlsxSolidFill,
},
};
use super::{
custom_dash::XlsxCustomDash, head_end::XlsxHeadEnd, line_join_bevel::XlsxLineJoinBevel,
miter::XlsxMiter, round_line_join::XlsxRoundLineJoin, tail_end::XlsxTailEnd,
};
#[derive(Debug, Clone, PartialEq)]
pub struct XlsxOutline {
pub bevel: Option<XlsxLineJoinBevel>,
pub custom_dash: Option<XlsxCustomDash>,
pub gradient_fill: Option<XlsxGradientFill>,
pub head_end: Option<XlsxHeadEnd>,
pub miter: Option<XlsxMiter>,
pub no_fill: Option<XlsxNoFill>,
pub pattern_fill: Option<XlsxPatternFill>,
pub present_dash: Option<String>,
pub round: Option<XlsxRoundLineJoin>,
pub solid_fill: Option<XlsxSolidFill>,
pub tail_end: Option<XlsxTailEnd>,
pub alignment: Option<String>,
pub cap: Option<String>,
pub compound: Option<String>,
pub w: Option<STPositiveCoordinate>,
}
impl XlsxOutline {
pub(crate) fn load(reader: &mut XmlReader<impl Read>, e: &BytesStart) -> anyhow::Result<Self> {
let mut buf = Vec::new();
let mut scheme = Self {
bevel: None,
custom_dash: None,
gradient_fill: None,
head_end: None,
miter: None,
no_fill: None,
pattern_fill: None,
present_dash: None,
round: None,
solid_fill: None,
tail_end: None,
alignment: None,
cap: None,
compound: None,
w: None,
};
let attributes = e.attributes();
for a in attributes {
match a {
Ok(a) => {
let string_value = String::from_utf8(a.value.to_vec())?;
match a.key.local_name().as_ref() {
b"algn" => {
scheme.alignment = Some(string_value);
}
b"cap" => {
scheme.cap = Some(string_value);
}
b"cmpd" => {
scheme.compound = Some(string_value);
}
b"w" => {
scheme.w = string_to_unsignedint(&string_value);
}
_ => {}
}
}
Err(error) => {
bail!(error.to_string())
}
}
}
loop {
buf.clear();
match reader.read_event_into(&mut buf) {
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"extLst" => {
let _ = reader.read_to_end_into(e.to_end().to_owned().name(), &mut Vec::new());
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"bevel" => {
scheme.bevel = Some(true);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"custDash" => {
scheme.custom_dash = Some(XlsxCustomDash::load(reader)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"gradFill" => {
scheme.gradient_fill = Some(XlsxGradientFill::load(reader, e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"headEnd" => {
scheme.head_end = Some(XlsxHeadEnd::load(e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"miter" => {
scheme.miter = Some(XlsxMiter::load(e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"noFill" => {
scheme.no_fill = Some(true);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"pattFill" => {
scheme.pattern_fill = Some(XlsxPatternFill::load(reader, e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"prstDash" => {
let val = extract_val_attribute(e)?;
scheme.present_dash = val;
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"round" => {
scheme.round = Some(true);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"solidFill" => {
scheme.solid_fill = XlsxSolidFill::load(reader, e)?;
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"tailEnd" => {
scheme.tail_end = Some(XlsxTailEnd::load(e)?);
}
Ok(Event::End(ref e)) if e.local_name().as_ref() == b"ln" => break,
Ok(Event::Eof) => bail!("unexpected end of file."),
Err(e) => bail!(e.to_string()),
_ => (),
}
}
Ok(scheme)
}
}