use std::io::Cursor;
use quick_xml::{
Reader,
Writer,
events::{
BytesStart,
Event,
},
};
use super::{
Fill,
ImageData,
Path,
Shadow,
Stroke,
TextBox,
office::InsetMarginValues,
spreadsheet::ClientData,
};
use crate::{
reader::driver::{
get_attribute,
set_string_from_xml,
xml_read_loop,
},
structs::{
EnumValue,
Int32Value,
StringValue,
TrueFalseValue,
raw::RawRelationships,
},
traits::AdjustmentCoordinate,
writer::driver::{
write_end_tag,
write_start_tag,
},
};
#[derive(Clone, Default, Debug)]
pub struct Shape {
style: StringValue,
r_type: StringValue,
filled: TrueFalseValue,
fill_color: StringValue,
stroked: TrueFalseValue,
stroke_color: StringValue,
stroke_weight: StringValue,
inset_mode: EnumValue<InsetMarginValues>,
fill: Option<Box<Fill>>,
image_data: Option<Box<ImageData>>,
stroke: Option<Box<Stroke>>,
shadow: Option<Box<Shadow>>,
path: Option<Box<Path>>,
text_box: Option<Box<TextBox>>,
client_data: ClientData,
optional_number: Int32Value,
coordinate_size: StringValue,
}
impl Shape {
#[must_use]
pub fn style(&self) -> &str {
self.style.value_str()
}
#[must_use]
#[deprecated(since = "3.0.0", note = "Use style()")]
pub fn get_style(&self) -> &str {
self.style()
}
pub fn set_style<S: Into<String>>(&mut self, value: S) -> &mut Self {
self.style.set_value(value);
self
}
#[must_use]
pub fn get_type(&self) -> &str {
self.r_type.value_str()
}
pub fn set_type<S: Into<String>>(&mut self, value: S) -> &mut Self {
self.r_type.set_value(value);
self
}
#[must_use]
pub fn filled(&self) -> bool {
self.filled.value()
}
#[must_use]
#[deprecated(since = "3.0.0", note = "Use filled()")]
pub fn get_filled(&self) -> bool {
self.filled()
}
pub fn set_filled(&mut self, value: bool) -> &mut Self {
self.filled.set_value(value);
self
}
#[must_use]
pub fn fill_color(&self) -> &str {
self.fill_color.value_str()
}
#[must_use]
#[deprecated(since = "3.0.0", note = "Use fill_color()")]
pub fn get_fill_color(&self) -> &str {
self.fill_color()
}
pub fn set_fill_color<S: Into<String>>(&mut self, value: S) -> &mut Self {
self.fill_color.set_value(value);
self
}
#[must_use]
pub fn stroked(&self) -> bool {
self.stroked.value()
}
#[must_use]
#[deprecated(since = "3.0.0", note = "Use stroked()")]
pub fn get_stroked(&self) -> bool {
self.stroked()
}
pub fn set_stroked(&mut self, value: bool) -> &mut Self {
self.stroked.set_value(value);
self
}
#[must_use]
pub fn stroke_color(&self) -> &str {
self.stroke_color.value_str()
}
#[must_use]
#[deprecated(since = "3.0.0", note = "Use stroke_color()")]
pub fn get_stroke_color(&self) -> &str {
self.stroke_color()
}
pub fn set_stroke_color<S: Into<String>>(&mut self, value: S) -> &mut Self {
self.stroke_color.set_value(value);
self
}
#[must_use]
pub fn stroke_weight(&self) -> &str {
self.stroke_weight.value_str()
}
#[must_use]
#[deprecated(since = "3.0.0", note = "Use stroke_weight()")]
pub fn get_stroke_weight(&self) -> &str {
self.stroke_weight()
}
pub fn set_stroke_weight<S: Into<String>>(&mut self, value: S) -> &mut Self {
self.stroke_weight.set_value(value);
self
}
#[must_use]
pub fn inset_mode(&self) -> &InsetMarginValues {
self.inset_mode.value()
}
#[must_use]
#[deprecated(since = "3.0.0", note = "Use inset_mode()")]
pub fn get_inset_mode(&self) -> &InsetMarginValues {
self.inset_mode()
}
pub fn set_inset_mode(&mut self, value: InsetMarginValues) -> &mut Self {
self.inset_mode.set_value(value);
self
}
#[must_use]
pub fn fill(&self) -> Option<&Fill> {
self.fill.as_deref()
}
#[must_use]
#[deprecated(since = "3.0.0", note = "Use fill()")]
pub fn get_fill(&self) -> Option<&Fill> {
self.fill()
}
pub fn fill_mut(&mut self) -> Option<&mut Fill> {
self.fill.as_deref_mut()
}
#[deprecated(since = "3.0.0", note = "Use fill_mut()")]
pub fn get_fill_mut(&mut self) -> Option<&mut Fill> {
self.fill_mut()
}
pub fn set_fill(&mut self, value: Fill) -> &mut Self {
self.fill = Some(Box::new(value));
self
}
#[must_use]
pub fn image_data(&self) -> Option<&ImageData> {
self.image_data.as_deref()
}
#[must_use]
#[deprecated(since = "3.0.0", note = "Use image_data()")]
pub fn get_image_data(&self) -> Option<&ImageData> {
self.image_data()
}
pub fn image_data_mut(&mut self) -> Option<&mut ImageData> {
self.image_data.as_deref_mut()
}
#[deprecated(since = "3.0.0", note = "Use image_data_mut()")]
pub fn get_image_data_mut(&mut self) -> Option<&mut ImageData> {
self.image_data_mut()
}
pub fn set_image_data(&mut self, value: ImageData) -> &mut Self {
self.image_data = Some(Box::new(value));
self
}
#[must_use]
pub fn stroke(&self) -> Option<&Stroke> {
self.stroke.as_deref()
}
#[must_use]
#[deprecated(since = "3.0.0", note = "Use stroke()")]
pub fn get_stroke(&self) -> Option<&Stroke> {
self.stroke()
}
pub fn stroke_mut(&mut self) -> Option<&mut Stroke> {
self.stroke.as_deref_mut()
}
#[deprecated(since = "3.0.0", note = "Use stroke_mut()")]
pub fn get_stroke_mut(&mut self) -> Option<&mut Stroke> {
self.stroke_mut()
}
pub fn set_stroke(&mut self, value: Stroke) -> &mut Self {
self.stroke = Some(Box::new(value));
self
}
#[must_use]
pub fn shadow(&self) -> Option<&Shadow> {
self.shadow.as_deref()
}
#[must_use]
#[deprecated(since = "3.0.0", note = "Use shadow()")]
pub fn get_shadow(&self) -> Option<&Shadow> {
self.shadow()
}
pub fn shadow_mut(&mut self) -> Option<&mut Shadow> {
self.shadow.as_deref_mut()
}
#[deprecated(since = "3.0.0", note = "Use shadow_mut()")]
pub fn get_shadow_mut(&mut self) -> Option<&mut Shadow> {
self.shadow_mut()
}
pub fn set_shadow(&mut self, value: Shadow) -> &mut Self {
self.shadow = Some(Box::new(value));
self
}
#[must_use]
pub fn path(&self) -> Option<&Path> {
self.path.as_deref()
}
#[must_use]
#[deprecated(since = "3.0.0", note = "Use path()")]
pub fn get_path(&self) -> Option<&Path> {
self.path()
}
pub fn path_mut(&mut self) -> Option<&mut Path> {
self.path.as_deref_mut()
}
#[deprecated(since = "3.0.0", note = "Use path_mut()")]
pub fn get_path_mut(&mut self) -> Option<&mut Path> {
self.path_mut()
}
pub fn set_path(&mut self, value: Path) -> &mut Self {
self.path = Some(Box::new(value));
self
}
#[must_use]
pub fn text_box(&self) -> Option<&TextBox> {
self.text_box.as_deref()
}
#[must_use]
#[deprecated(since = "3.0.0", note = "Use text_box()")]
pub fn get_text_box(&self) -> Option<&TextBox> {
self.text_box()
}
pub fn text_box_mut(&mut self) -> Option<&mut TextBox> {
self.text_box.as_deref_mut()
}
#[deprecated(since = "3.0.0", note = "Use text_box_mut()")]
pub fn get_text_box_mut(&mut self) -> Option<&mut TextBox> {
self.text_box_mut()
}
pub fn set_text_box(&mut self, value: TextBox) -> &mut Self {
self.text_box = Some(Box::new(value));
self
}
#[must_use]
pub fn client_data(&self) -> &ClientData {
&self.client_data
}
#[must_use]
#[deprecated(since = "3.0.0", note = "Use client_data()")]
pub fn get_client_data(&self) -> &ClientData {
self.client_data()
}
pub fn client_data_mut(&mut self) -> &mut ClientData {
&mut self.client_data
}
#[deprecated(since = "3.0.0", note = "Use client_data_mut()")]
pub fn get_client_data_mut(&mut self) -> &mut ClientData {
self.client_data_mut()
}
pub fn set_client_data(&mut self, value: ClientData) -> &mut Self {
self.client_data = value;
self
}
#[must_use]
pub fn optional_number(&self) -> i32 {
self.optional_number.value()
}
#[must_use]
#[deprecated(since = "3.0.0", note = "Use optional_number()")]
pub fn get_optional_number(&self) -> i32 {
self.optional_number()
}
pub fn set_optional_number(&mut self, value: i32) -> &mut Self {
self.optional_number.set_value(value);
self
}
#[must_use]
pub fn coordinate_size(&self) -> &str {
self.coordinate_size.value_str()
}
#[must_use]
#[deprecated(since = "3.0.0", note = "Use coordinate_size()")]
pub fn get_coordinate_size(&self) -> &str {
self.coordinate_size()
}
pub fn set_coordinate_size<S: Into<String>>(&mut self, value: S) -> &mut Self {
self.coordinate_size.set_value(value);
self
}
pub(crate) fn set_attributes<R: std::io::BufRead>(
&mut self,
reader: &mut Reader<R>,
e: &BytesStart,
drawing_relationships: Option<&RawRelationships>,
) {
set_string_from_xml!(self, e, r_type, "type");
set_string_from_xml!(self, e, style, "style");
set_string_from_xml!(self, e, filled, "filled");
set_string_from_xml!(self, e, fill_color, "fillcolor");
set_string_from_xml!(self, e, stroked, "stoked");
set_string_from_xml!(self, e, stroke_color, "stokecolor");
set_string_from_xml!(self, e, stroke_weight, "stokeweight");
set_string_from_xml!(self, e, inset_mode, "o:insetmode");
set_string_from_xml!(self, e, optional_number, "o:spt");
set_string_from_xml!(self, e, coordinate_size, "coordsize");
xml_read_loop!(
reader,
Event::Empty(ref e) => {
match e.name().into_inner() {
b"v:fill" => {
let mut obj = Fill::default();
obj.set_attributes(reader, e, drawing_relationships);
self.set_fill(obj);
}
b"v:shadow" => {
let mut obj = Shadow::default();
obj.set_attributes(reader, e);
self.set_shadow(obj);
}
b"v:path" => {
let mut obj = Path::default();
obj.set_attributes(reader, e);
self.set_path(obj);
}
b"v:stroke" => {
let mut obj = Stroke::default();
obj.set_attributes(reader, e);
self.set_stroke(obj);
}
b"v:imagedata" => {
let mut obj = ImageData::default();
obj.set_attributes(reader, e, drawing_relationships);
self.set_image_data(obj);
}
_ => (),
}
},
Event::Start(ref e) => {
match e.name().into_inner() {
b"v:textbox" => {
let mut obj = TextBox::default();
obj.set_attributes(reader, e);
self.set_text_box(obj);
}
b"x:ClientData" => {
let mut obj = ClientData::default();
obj.set_attributes(reader, e);
self.set_client_data(obj);
}
_ => (),
}
},
Event::End(ref e) => {
if e.name().into_inner() == b"v:shape" {
return
}
},
Event::Eof => panic!("Error: Could not find {} end element", "v:shape")
);
}
pub(crate) fn write_to(
&self,
writer: &mut Writer<Cursor<Vec<u8>>>,
id: usize,
rel_list: &mut Vec<(String, String)>,
) {
let id_str = format!("_x0000_s{id}");
let mut attributes: crate::structs::AttrCollection = Vec::new();
attributes.push(("id", &id_str).into());
if self.r_type.has_value() {
attributes.push(("type", self.r_type.value_str()).into());
}
if self.style.has_value() {
attributes.push(("style", self.style.value_str()).into());
}
if self.filled.has_value() {
attributes.push(("filled", self.filled.value_string()).into());
}
if self.fill_color.has_value() {
attributes.push(("fillcolor", self.fill_color.value_str()).into());
}
if self.stroked.has_value() {
attributes.push(("stroked", self.stroked.value_string()).into());
}
if self.stroke_color.has_value() {
attributes.push(("strokecolor", self.stroke_color.value_str()).into());
}
if self.stroke_weight.has_value() {
attributes.push(("strokeweight", self.stroke_weight.value_str()).into());
}
if self.inset_mode.has_value() {
attributes.push(("o:insetmode", self.inset_mode.value_string()).into());
}
let optional_number_str = self.optional_number.value_string();
if self.optional_number.has_value() {
attributes.push(("o:spt", &optional_number_str).into());
}
if self.coordinate_size.has_value() {
attributes.push(("coordsize", self.coordinate_size.value_str()).into());
}
write_start_tag(writer, "v:shape", attributes, false);
if let Some(v) = &self.fill {
v.write_to(writer, rel_list);
}
if let Some(v) = &self.shadow {
v.write_to(writer);
}
if let Some(v) = &self.path {
v.write_to(writer);
}
if let Some(v) = &self.text_box {
v.write_to(writer);
}
if let Some(v) = &self.stroke {
v.write_to(writer);
}
if let Some(v) = &self.image_data {
v.write_to(writer, rel_list);
}
self.client_data.write_to(writer);
write_end_tag(writer, "v:shape");
}
}
impl AdjustmentCoordinate for Shape {
fn adjustment_insert_coordinate(
&mut self,
root_col_num: u32,
offset_col_num: u32,
root_row_num: u32,
offset_row_num: u32,
) {
self.client_data.adjustment_insert_coordinate(
root_col_num,
offset_col_num,
root_row_num,
offset_row_num,
);
}
fn adjustment_remove_coordinate(
&mut self,
root_col_num: u32,
offset_col_num: u32,
root_row_num: u32,
offset_row_num: u32,
) {
self.client_data.adjustment_remove_coordinate(
root_col_num,
offset_col_num,
root_row_num,
offset_row_num,
);
}
}