use crate::oxml::shape::Group as OxmlGroup;
use crate::oxml::shape::GroupChild as OxmlGroupChild;
use crate::shape::autoshape::AutoShape;
use crate::shape::base::Shape;
use crate::shape::connector::Connector;
use crate::shape::picture::Picture;
use crate::shape::table::TableShape;
use crate::units::Emu;
#[derive(Clone, Debug, Default)]
pub struct Group {
pub(crate) group: OxmlGroup,
}
impl Group {
pub fn from_group(g: OxmlGroup) -> Self {
Group { group: g }
}
pub fn group(&self) -> &OxmlGroup {
&self.group
}
pub fn group_mut(&mut self) -> &mut OxmlGroup {
&mut self.group
}
pub fn children(&self) -> Vec<GroupChild> {
self.group
.children
.iter()
.map(|c| match c {
OxmlGroupChild::Sp(s) => GroupChild::Sp(AutoShape::from_sp(s.clone())),
OxmlGroupChild::Pic(p) => GroupChild::Pic(Picture::from_pic(p.clone())),
OxmlGroupChild::CxnSp(c) => GroupChild::Cx(Connector::from_cxn(c.clone())),
OxmlGroupChild::Group(g) => {
GroupChild::Grp(Box::new(Group::from_group((**g).clone())))
}
OxmlGroupChild::GraphicFrame(g) => {
GroupChild::Gfx(TableShape::from_frame(g.clone()))
}
})
.collect()
}
pub fn len(&self) -> usize {
self.group.children.len()
}
pub fn is_empty(&self) -> bool {
self.group.children.is_empty()
}
pub fn add_autoshape(&mut self, shape: AutoShape) -> &mut Self {
self.group
.children
.push(OxmlGroupChild::Sp(shape.sp.clone()));
self
}
pub fn add_picture(&mut self, pic: Picture) -> &mut Self {
self.group
.children
.push(OxmlGroupChild::Pic(pic.pic.clone()));
self
}
pub fn add_connector(&mut self, cxn: Connector) -> &mut Self {
self.group
.children
.push(OxmlGroupChild::CxnSp(cxn.cxn.clone()));
self
}
pub fn add_table(&mut self, table: TableShape) -> &mut Self {
self.group
.children
.push(OxmlGroupChild::GraphicFrame(table.frame.clone()));
self
}
pub fn add_group(&mut self, grp: Group) -> &mut Self {
self.group
.children
.push(OxmlGroupChild::Group(Box::new(grp.group.clone())));
self
}
pub fn remove_child(&mut self, id: u32) -> bool {
let pos = self.group.children.iter().position(|c| match c {
OxmlGroupChild::Sp(s) => s.id == id,
OxmlGroupChild::Pic(p) => p.id == id,
OxmlGroupChild::CxnSp(c) => c.id == id,
OxmlGroupChild::Group(g) => g.id == id,
OxmlGroupChild::GraphicFrame(g) => g.id == id,
});
if let Some(p) = pos {
self.group.children.remove(p);
return true;
}
for c in &mut self.group.children {
if let OxmlGroupChild::Group(g) = c {
let mut sub = Group::from_group((**g).clone());
if sub.remove_child(id) {
**g = sub.group;
return true;
}
}
}
false
}
pub fn clear(&mut self) {
self.group.children.clear();
}
}
#[derive(Clone, Debug)]
pub enum GroupChild {
Sp(AutoShape),
Pic(Picture),
Cx(Connector),
Grp(Box<Group>),
Gfx(TableShape),
}
impl Shape for Group {
fn id(&self) -> u32 {
self.group.id
}
fn set_id(&mut self, id: u32) {
self.group.id = id;
}
fn name(&self) -> &str {
&self.group.name
}
fn set_name(&mut self, name: String) {
self.group.name = name;
}
fn shape_type(&self) -> &'static str {
"group"
}
fn left(&self) -> Emu {
Emu::new(self.group.off.0.value())
}
fn set_left(&mut self, emu: Emu) {
self.group.off.0 = emu;
}
fn top(&self) -> Emu {
Emu::new(self.group.off.1.value())
}
fn set_top(&mut self, emu: Emu) {
self.group.off.1 = emu;
}
fn width(&self) -> Emu {
Emu::new(self.group.ext.0.value())
}
fn set_width(&mut self, emu: Emu) {
self.group.ext.0 = emu;
}
fn height(&self) -> Emu {
Emu::new(self.group.ext.1.value())
}
fn set_height(&mut self, emu: Emu) {
self.group.ext.1 = emu;
}
fn rotation(&self) -> f64 {
self.group.properties.rot_deg.unwrap_or(0.0)
}
fn set_rotation(&mut self, deg: f64) {
self.group.properties.rot_deg = Some(deg);
let rot = (deg * 60_000.0) as i32;
self.group.properties.xfrm.rot = Some(rot);
}
}