use crate::oxml::shape::Connector as OxmlCxn;
use crate::oxml::simpletypes::MsoConnectorType;
use crate::oxml::simpletypes::PresetGeometry;
use crate::oxml::sppr::Geometry;
use crate::shape::base::Shape;
use crate::units::{Emu, EmuPoint};
#[derive(Clone, Debug, Default)]
pub struct Connector {
pub(crate) cxn: OxmlCxn,
}
impl Connector {
pub fn from_cxn(c: OxmlCxn) -> Self {
Connector { cxn: c }
}
pub fn new(name: impl Into<String>) -> Self {
Connector {
cxn: OxmlCxn {
name: name.into(),
..Default::default()
},
}
}
pub fn new_with_type(name: impl Into<String>, connector_type: MsoConnectorType) -> Self {
let mut cxn = OxmlCxn {
name: name.into(),
..Default::default()
};
cxn.connector_type = Some(connector_type);
cxn.properties.geometry =
Some(Geometry::preset(connector_type_to_geometry(connector_type)));
Connector { cxn }
}
pub fn recompute_xfrm(&mut self) {
match (self.cxn.begin, self.cxn.end) {
(Some((bx, by)), Some((ex, ey))) => {
let min_x = bx.value().min(ex.value());
let min_y = by.value().min(ey.value());
let max_x = bx.value().max(ex.value());
let max_y = by.value().max(ey.value());
self.cxn.properties.xfrm.off_x = Some(Emu(min_x));
self.cxn.properties.xfrm.off_y = Some(Emu(min_y));
self.cxn.properties.xfrm.ext_cx = Some(Emu(max_x - min_x));
self.cxn.properties.xfrm.ext_cy = Some(Emu(max_y - min_y));
}
_ => {
self.cxn.properties.xfrm.off_x = Some(Emu(0));
self.cxn.properties.xfrm.off_y = Some(Emu(0));
self.cxn.properties.xfrm.ext_cx = Some(Emu(0));
self.cxn.properties.xfrm.ext_cy = Some(Emu(0));
}
}
}
pub fn cxn(&self) -> &OxmlCxn {
&self.cxn
}
pub fn cxn_mut(&mut self) -> &mut OxmlCxn {
&mut self.cxn
}
pub fn properties(&self) -> &crate::oxml::sppr::ShapeProperties {
&self.cxn.properties
}
pub fn properties_mut(&mut self) -> &mut crate::oxml::sppr::ShapeProperties {
&mut self.cxn.properties
}
pub fn begin(&self) -> Option<EmuPoint> {
self.cxn.begin.map(|(x, y)| EmuPoint(x.value(), y.value()))
}
pub fn set_begin(&mut self, p: EmuPoint) {
self.cxn.begin = Some((Emu(p.0), Emu(p.1)));
self.recompute_xfrm();
}
pub fn end(&self) -> Option<EmuPoint> {
self.cxn.end.map(|(x, y)| EmuPoint(x.value(), y.value()))
}
pub fn set_end(&mut self, p: EmuPoint) {
self.cxn.end = Some((Emu(p.0), Emu(p.1)));
self.recompute_xfrm();
}
pub fn connector_type(&self) -> Option<MsoConnectorType> {
self.cxn.connector_type
}
pub fn set_connector_type(&mut self, t: MsoConnectorType) {
self.cxn.connector_type = Some(t);
self.cxn.properties.geometry = Some(Geometry::preset(connector_type_to_geometry(t)));
}
pub fn begin_connection(&self) -> Option<(u32, u32)> {
self.cxn.st_cxn
}
pub fn set_begin_connection(&mut self, shape_id: u32, idx: u32) {
self.cxn.st_cxn = Some((shape_id, idx));
}
pub fn end_connection(&self) -> Option<(u32, u32)> {
self.cxn.end_cxn
}
pub fn set_end_connection(&mut self, shape_id: u32, idx: u32) {
self.cxn.end_cxn = Some((shape_id, idx));
}
}
fn connector_type_to_geometry(t: MsoConnectorType) -> PresetGeometry {
match t {
MsoConnectorType::Straight => PresetGeometry::Line,
MsoConnectorType::Elbow => PresetGeometry::BentConnector2,
MsoConnectorType::Curve => PresetGeometry::CurvedConnector2,
MsoConnectorType::BentConnector3 => PresetGeometry::BentConnector3,
MsoConnectorType::BentConnector4 => PresetGeometry::BentConnector4,
MsoConnectorType::BentConnector5 => PresetGeometry::BentConnector5,
MsoConnectorType::CurvedConnector3 => PresetGeometry::CurvedConnector3,
MsoConnectorType::CurvedConnector4 => PresetGeometry::CurvedConnector4,
MsoConnectorType::CurvedConnector5 => PresetGeometry::CurvedConnector5,
}
}
impl Shape for Connector {
fn id(&self) -> u32 {
self.cxn.id
}
fn set_id(&mut self, id: u32) {
self.cxn.id = id;
}
fn name(&self) -> &str {
&self.cxn.name
}
fn set_name(&mut self, name: String) {
self.cxn.name = name;
}
fn shape_type(&self) -> &'static str {
"connector"
}
fn left(&self) -> Emu {
self.cxn.properties.xfrm.off_x.unwrap_or_default()
}
fn set_left(&mut self, emu: Emu) {
self.cxn.properties.xfrm.off_x = Some(emu);
}
fn top(&self) -> Emu {
self.cxn.properties.xfrm.off_y.unwrap_or_default()
}
fn set_top(&mut self, emu: Emu) {
self.cxn.properties.xfrm.off_y = Some(emu);
}
fn width(&self) -> Emu {
self.cxn.properties.xfrm.ext_cx.unwrap_or_default()
}
fn set_width(&mut self, emu: Emu) {
self.cxn.properties.xfrm.ext_cx = Some(emu);
}
fn height(&self) -> Emu {
self.cxn.properties.xfrm.ext_cy.unwrap_or_default()
}
fn set_height(&mut self, emu: Emu) {
self.cxn.properties.xfrm.ext_cy = Some(emu);
}
fn rotation(&self) -> f64 {
self.cxn.properties.rot_deg.unwrap_or(0.0)
}
fn set_rotation(&mut self, deg: f64) {
self.cxn.properties.rot_deg = Some(deg);
let rot = (deg * 60_000.0) as i32;
self.cxn.properties.xfrm.rot = Some(rot);
}
}