pub mod action;
pub mod autoshape;
pub mod connector;
pub mod freeform;
pub mod graphfrm;
pub mod group;
pub mod ole;
pub mod parser;
pub mod picture;
pub mod placeholder;
mod shape_accessors;
pub mod shapetree;
pub use action::{ActionSetting, Hyperlink};
pub use autoshape::AutoShape;
pub use connector::Connector;
pub use freeform::FreeformBuilder;
pub use graphfrm::GraphicFrame;
pub use group::GroupShape;
pub use ole::OleObject;
pub use picture::Picture;
pub use placeholder::PlaceholderFormat;
pub use shapetree::ShapeTree;
use std::fmt;
use crate::units::{Emu, ShapeId};
use crate::xml_util::WriteXml;
pub trait ShapeProperties {
fn shape_id(&self) -> ShapeId;
fn name(&self) -> &str;
fn left(&self) -> Emu;
fn top(&self) -> Emu;
fn width(&self) -> Emu;
fn height(&self) -> Emu;
fn rotation(&self) -> f64;
}
macro_rules! impl_shape_properties {
($ty:ty) => {
impl ShapeProperties for $ty {
#[inline]
fn shape_id(&self) -> ShapeId {
self.shape_id
}
#[inline]
fn name(&self) -> &str {
&self.name
}
#[inline]
fn left(&self) -> Emu {
self.left
}
#[inline]
fn top(&self) -> Emu {
self.top
}
#[inline]
fn width(&self) -> Emu {
self.width
}
#[inline]
fn height(&self) -> Emu {
self.height
}
#[inline]
fn rotation(&self) -> f64 {
self.rotation
}
}
};
}
impl_shape_properties!(AutoShape);
impl_shape_properties!(Picture);
impl_shape_properties!(GraphicFrame);
impl_shape_properties!(GroupShape);
impl_shape_properties!(Connector);
impl_shape_properties!(OleObject);
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub enum Shape {
AutoShape(Box<AutoShape>),
Picture(Box<Picture>),
GraphicFrame(Box<GraphicFrame>),
GroupShape(Box<GroupShape>),
Connector(Connector),
OleObject(OleObject),
}
macro_rules! dispatch_shape {
($self:expr, $method:ident) => {
match $self {
Shape::AutoShape(s) => s.$method(),
Shape::Picture(s) => s.$method(),
Shape::GraphicFrame(s) => s.$method(),
Shape::GroupShape(s) => s.$method(),
Shape::Connector(s) => s.$method(),
Shape::OleObject(s) => s.$method(),
}
};
}
impl Shape {
#[inline]
#[must_use]
pub fn shape_id(&self) -> ShapeId {
dispatch_shape!(self, shape_id)
}
#[inline]
#[must_use]
pub fn name(&self) -> &str {
dispatch_shape!(self, name)
}
#[inline]
pub fn left(&self) -> Emu {
dispatch_shape!(self, left)
}
#[inline]
pub fn top(&self) -> Emu {
dispatch_shape!(self, top)
}
#[inline]
pub fn width(&self) -> Emu {
dispatch_shape!(self, width)
}
#[inline]
pub fn height(&self) -> Emu {
dispatch_shape!(self, height)
}
#[inline]
#[must_use]
pub fn rotation(&self) -> f64 {
dispatch_shape!(self, rotation)
}
#[inline]
#[must_use]
pub const fn has_text_frame(&self) -> bool {
match self {
Self::AutoShape(a) => a.has_text_frame(),
_ => false,
}
}
#[inline]
#[must_use]
pub fn has_table(&self) -> bool {
matches!(self, Self::GraphicFrame(g) if g.has_table)
}
#[inline]
#[must_use]
pub const fn is_placeholder(&self) -> bool {
match self {
Self::AutoShape(s) => s.placeholder.is_some(),
Self::Picture(s) => s.placeholder.is_some(),
Self::GraphicFrame(s) => s.placeholder.is_some(),
Self::GroupShape(_) | Self::Connector(_) | Self::OleObject(_) => false,
}
}
#[inline]
#[must_use]
pub const fn placeholder(&self) -> Option<&PlaceholderFormat> {
match self {
Self::AutoShape(s) => s.placeholder.as_ref(),
Self::Picture(s) => s.placeholder.as_ref(),
Self::GraphicFrame(s) => s.placeholder.as_ref(),
Self::GroupShape(_) | Self::Connector(_) | Self::OleObject(_) => None,
}
}
}
impl WriteXml for Shape {
fn write_xml<W: std::fmt::Write>(&self, w: &mut W) -> std::fmt::Result {
match self {
Self::AutoShape(s) => s.write_xml(w),
Self::Picture(s) => s.write_xml(w),
Self::GroupShape(s) => s.write_xml(w),
Self::Connector(s) => s.write_xml(w),
Self::OleObject(s) => s.write_xml(w),
Self::GraphicFrame(_) => {
Ok(())
}
}
}
}
impl fmt::Display for Shape {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let kind = match self {
Self::AutoShape(_) => "AutoShape",
Self::Picture(_) => "Picture",
Self::GraphicFrame(_) => "GraphicFrame",
Self::GroupShape(_) => "GroupShape",
Self::Connector(_) => "Connector",
Self::OleObject(_) => "OleObject",
};
write!(f, "{}(\"{}\")", kind, self.name())
}
}