use msoffice_shared::error::{MissingAttributeError, MissingChildNodeError, NotGroupMemberError};
use msoffice_shared::xml::{parse_xml_bool, XmlNode};
use std::str::FromStr;
use enum_from_str::ParseEnumVariantError;
use enum_from_str_derive::FromStr;
pub type Result<T> = ::std::result::Result<T, Box<dyn (::std::error::Error)>>;
pub type Index = u32;
pub type TLTimeNodeId = u32;
pub type TLSubShapeId = msoffice_shared::drawingml::ShapeId;
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLChartSubelementType {
#[from_str = "gridLegend"]
GridLegend,
#[from_str = "series"]
Series,
#[from_str = "category"]
Category,
#[from_str = "ptInSeries"]
PointInSeries,
#[from_str = "ptInCategory"]
PointInCategory,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLParaBuildType {
#[from_str = "allAtOnce"]
AllAtOnce,
#[from_str = "p"]
Paragraph,
#[from_str = "cust"]
Custom,
#[from_str = "whole"]
Whole,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLDiagramBuildType {
#[from_str = "whole"]
Whole,
#[from_str = "depthByNode"]
DepthByNode,
#[from_str = "depthByBranch"]
DepthByBranch,
#[from_str = "breadthByNode"]
BreadthByNode,
#[from_str = "breadthByLvl"]
BreadthByLevel,
#[from_str = "cw"]
Clockwise,
#[from_str = "cwIn"]
ClockwiseIn,
#[from_str = "cwOut"]
ClockwiseOut,
#[from_str = "ccw"]
CounterClockwise,
#[from_str = "ccwIn"]
CounterClockwiseIn,
#[from_str = "ccwOut"]
CounterClockwiseOut,
#[from_str = "inByRing"]
InByRing,
#[from_str = "outByRing"]
OutByRing,
#[from_str = "up"]
Up,
#[from_str = "down"]
Down,
#[from_str = "allAtOnce"]
AllAtOnce,
#[from_str = "cust"]
Custom,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLOleChartBuildType {
#[from_str = "allAtOnce"]
AllAtOnce,
#[from_str = "series"]
Series,
#[from_str = "category"]
Category,
#[from_str = "seriesEl"]
SeriesElement,
#[from_str = "categoryEl"]
CategoryElement,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLTriggerRuntimeNode {
#[from_str = "first"]
First,
#[from_str = "last"]
Last,
#[from_str = "all"]
All,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLTriggerEvent {
#[from_str = "onBegin"]
OnBegin,
#[from_str = "onEnd"]
OnEnd,
#[from_str = "begin"]
Begin,
#[from_str = "end"]
End,
#[from_str = "onClick"]
OnClick,
#[from_str = "onDblClick"]
OnDoubleClick,
#[from_str = "onMouseOver"]
OnMouseOver,
#[from_str = "onMouseOut"]
OnMouseOut,
#[from_str = "onNext"]
OnNext,
#[from_str = "onPrev"]
OnPrev,
#[from_str = "onStopAudio"]
OnStopAudio,
}
#[derive(Debug, Copy, Clone, PartialEq, FromStr)]
pub enum IterateType {
#[from_str = "el"]
Element,
#[from_str = "wd"]
Word,
#[from_str = "lt"]
Letter,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLTimeNodePresetClassType {
#[from_str = "entr"]
Entrance,
#[from_str = "exit"]
Exit,
#[from_str = "emph"]
Emphasis,
#[from_str = "path"]
Path,
#[from_str = "verb"]
Verb,
#[from_str = "mediacall"]
Mediacall,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLTimeNodeRestartType {
#[from_str = "always"]
Always,
#[from_str = "whenNotActive"]
WhenNotActive,
#[from_str = "never"]
Never,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLTimeNodeFillType {
#[from_str = "remove"]
Remove,
#[from_str = "freeze"]
Freeze,
#[from_str = "hold"]
Hold,
#[from_str = "transition"]
Transition,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLTimeNodeSyncType {
#[from_str = "canSlip"]
CanSlip,
#[from_str = "locked"]
Locked,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLTimeNodeMasterRelation {
#[from_str = "sameClick"]
SameClick,
#[from_str = "lastClick"]
LastClick,
#[from_str = "nextClick"]
NextClick,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLTimeNodeType {
#[from_str = "clickEffect"]
ClickEffect,
#[from_str = "withEffect"]
WithEffect,
#[from_str = "afterEffect"]
AfterEffect,
#[from_str = "mainSequence"]
MainSequence,
#[from_str = "interactiveSeq"]
InteractiveSequence,
#[from_str = "clickPar"]
ClickParagraph,
#[from_str = "withGroup"]
WithGroup,
#[from_str = "afterGroup"]
AfterGroup,
#[from_str = "tmRoot"]
TimingRoot,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLNextActionType {
#[from_str = "none"]
None,
#[from_str = "seek"]
Seek,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLPreviousActionType {
#[from_str = "none"]
None,
#[from_str = "skipTimed"]
SkipTimed,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLAnimateBehaviorCalcMode {
#[from_str = "discrete"]
Discrete,
#[from_str = "fmla"]
Formula,
#[from_str = "lin"]
Linear,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLAnimateBehaviorValueType {
#[from_str = "clr"]
Color,
#[from_str = "num"]
Number,
#[from_str = "str"]
String,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLBehaviorAdditiveType {
#[from_str = "base"]
Base,
#[from_str = "sum"]
Sum,
#[from_str = "repl"]
Replace,
#[from_str = "mult"]
Multiply,
#[from_str = "none"]
None,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLBehaviorAccumulateType {
#[from_str = "none"]
None,
#[from_str = "always"]
Always,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLBehaviorTransformType {
#[from_str = "pt"]
Point,
#[from_str = "img"]
Image,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLBehaviorOverrideType {
#[from_str = "normal"]
Normal,
#[from_str = "childStyle"]
ChildStyle,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLAnimateColorSpace {
#[from_str = "rgb"]
Rgb,
#[from_str = "hsl"]
Hsl,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLAnimateColorDirection {
#[from_str = "cw"]
Clockwise,
#[from_str = "ccw"]
CounterClockwise,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLAnimateEffectTransition {
#[from_str = "in"]
In,
#[from_str = "out"]
Out,
#[from_str = "none"]
None,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLAnimateMotionBehaviorOrigin {
#[from_str = "parent"]
Parent,
#[from_str = "layout"]
Layout,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLAnimateMotionPathEditMode {
#[from_str = "relative"]
Relative,
#[from_str = "fixed"]
Fixed,
}
#[derive(Debug, Clone, Copy, PartialEq, FromStr)]
pub enum TLCommandType {
#[from_str = "evt"]
Event,
#[from_str = "call"]
Call,
#[from_str = "verb"]
Verb,
}
#[derive(Debug, Clone)]
pub struct IndexRange {
pub start: Index,
pub end: Index,
}
impl IndexRange {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut start = None;
let mut end = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"st" => start = Some(value.parse()?),
"end" => end = Some(value.parse()?),
_ => (),
}
}
let start = start.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "st"))?;
let end = end.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "end"))?;
Ok(Self { start, end })
}
}
#[derive(Debug, Clone)]
pub enum TimeNodeGroup {
Parallel(Box<TLCommonTimeNodeData>),
Sequence(Box<TLTimeNodeSequence>),
Exclusive(Box<TLCommonTimeNodeData>),
Animate(Box<TLAnimateBehavior>),
AnimateColor(Box<TLAnimateColorBehavior>),
AnimateEffect(Box<TLAnimateEffectBehavior>),
AnimateMotion(Box<TLAnimateMotionBehavior>),
AnimateRotation(Box<TLAnimateRotationBehavior>),
AnimateScale(Box<TLAnimateScaleBehavior>),
Command(Box<TLCommandBehavior>),
Set(Box<TLSetBehavior>),
Audio(Box<TLMediaNodeAudio>),
Video(Box<TLMediaNodeVideo>),
}
impl TimeNodeGroup {
pub fn is_choice_member<T>(name: T) -> bool
where
T: AsRef<str>,
{
match name.as_ref() {
"par" | "seq" | "excl" | "anim" | "animClr" | "animEffect" | "animMotion" | "animRot" | "animScale"
| "cmd" | "set" | "audio" | "video" => true,
_ => false,
}
}
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
match xml_node.local_name() {
"par" => Ok(TimeNodeGroup::Parallel(Box::new(
TLCommonTimeNodeData::from_xml_element(xml_node)?,
))),
"seq" => Ok(TimeNodeGroup::Sequence(Box::new(TLTimeNodeSequence::from_xml_element(
xml_node,
)?))),
"excl" => Ok(TimeNodeGroup::Exclusive(Box::new(
TLCommonTimeNodeData::from_xml_element(xml_node)?,
))),
"anim" => Ok(TimeNodeGroup::Animate(Box::new(TLAnimateBehavior::from_xml_element(
xml_node,
)?))),
"animClr" => Ok(TimeNodeGroup::AnimateColor(Box::new(
TLAnimateColorBehavior::from_xml_element(xml_node)?,
))),
"animEffect" => Ok(TimeNodeGroup::AnimateEffect(Box::new(
TLAnimateEffectBehavior::from_xml_element(xml_node)?,
))),
"animMotion" => Ok(TimeNodeGroup::AnimateMotion(Box::new(
TLAnimateMotionBehavior::from_xml_element(xml_node)?,
))),
"animRot" => Ok(TimeNodeGroup::AnimateRotation(Box::new(
TLAnimateRotationBehavior::from_xml_element(xml_node)?,
))),
"animScale" => Ok(TimeNodeGroup::AnimateScale(Box::new(
TLAnimateScaleBehavior::from_xml_element(xml_node)?,
))),
"cmd" => Ok(TimeNodeGroup::Command(Box::new(TLCommandBehavior::from_xml_element(
xml_node,
)?))),
"set" => Ok(TimeNodeGroup::Set(Box::new(TLSetBehavior::from_xml_element(xml_node)?))),
"audio" => Ok(TimeNodeGroup::Audio(Box::new(TLMediaNodeAudio::from_xml_element(
xml_node,
)?))),
"video" => Ok(TimeNodeGroup::Video(Box::new(TLMediaNodeVideo::from_xml_element(
xml_node,
)?))),
_ => Err(Box::new(NotGroupMemberError::new(
xml_node.name.clone(),
"TimeNodeGroup",
))),
}
}
}
#[derive(Debug, Clone)]
pub struct TLCommonBehaviorData {
pub additive: Option<TLBehaviorAdditiveType>,
pub accumulate: Option<TLBehaviorAccumulateType>,
pub transform_type: Option<TLBehaviorTransformType>,
pub from: Option<String>,
pub to: Option<String>,
pub by: Option<String>,
pub runtime_context: Option<String>,
pub override_type: Option<TLBehaviorOverrideType>,
pub common_time_node_data: Box<TLCommonTimeNodeData>,
pub target_element: TLTimeTargetElement,
pub attr_name_list: Option<Vec<String>>,
}
impl TLCommonBehaviorData {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut additive = None;
let mut accumulate = None;
let mut transform_type = None;
let mut from = None;
let mut to = None;
let mut by = None;
let mut runtime_context = None;
let mut override_type = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"additive" => additive = Some(value.parse()?),
"accumulate" => accumulate = Some(value.parse()?),
"xfrmType" => transform_type = Some(value.parse()?),
"from" => from = Some(value.clone()),
"to" => to = Some(value.clone()),
"by" => by = Some(value.clone()),
"rctx" => runtime_context = Some(value.clone()),
"override" => override_type = Some(value.parse()?),
_ => (),
}
}
let mut common_time_node_data = None;
let mut target_element = None;
let mut attr_name_list = None;
for child_node in &xml_node.child_nodes {
match child_node.local_name() {
"cTn" => common_time_node_data = Some(Box::new(TLCommonTimeNodeData::from_xml_element(child_node)?)),
"tgtEl" => target_element = Some(TLTimeTargetElement::from_xml_element(child_node)?),
"attrNameLst" => {
let mut vec = Vec::new();
for attr_name_node in &child_node.child_nodes {
vec.push(match attr_name_node.text {
Some(ref text) => text.clone(),
None => String::new(), });
}
if vec.is_empty() {
return Err(Box::new(MissingChildNodeError::new(
child_node.name.clone(),
"attrName",
)));
}
attr_name_list = Some(vec);
}
_ => (),
}
}
let common_time_node_data =
common_time_node_data.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "cTn"))?;
let target_element =
target_element.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "tgtEl"))?;
Ok(Self {
additive,
accumulate,
transform_type,
from,
to,
by,
runtime_context,
override_type,
common_time_node_data,
target_element,
attr_name_list,
})
}
}
#[derive(Debug, Clone)]
pub struct TLCommonMediaNodeData {
pub volume: Option<msoffice_shared::drawingml::PositiveFixedPercentage>,
pub mute: Option<bool>,
pub number_of_slides: Option<u32>,
pub show_when_stopped: Option<bool>,
pub common_time_node_data: Box<TLCommonTimeNodeData>,
pub target_element: TLTimeTargetElement,
}
impl TLCommonMediaNodeData {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut volume = None;
let mut mute = None;
let mut number_of_slides = None;
let mut show_when_stopped = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"vol" => volume = Some(value.parse()?),
"mute" => mute = Some(parse_xml_bool(value)?),
"numSld" => number_of_slides = Some(value.parse()?),
"showWhenStopped" => show_when_stopped = Some(parse_xml_bool(value)?),
_ => (),
}
}
let mut common_time_node_data = None;
let mut target_element = None;
for child_node in &xml_node.child_nodes {
match child_node.local_name() {
"cTn" => common_time_node_data = Some(Box::new(TLCommonTimeNodeData::from_xml_element(child_node)?)),
"tgtEl" => target_element = Some(TLTimeTargetElement::from_xml_element(child_node)?),
_ => (),
}
}
let common_time_node_data =
common_time_node_data.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "cTn"))?;
let target_element =
target_element.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "tgtEl"))?;
Ok(Self {
volume,
mute,
number_of_slides,
show_when_stopped,
common_time_node_data,
target_element,
})
}
}
#[derive(Debug, Clone)]
pub struct TLBuildParagraph {
pub build_common: TLBuildCommonAttributes,
pub build_type: Option<TLParaBuildType>,
pub build_level: Option<u32>,
pub animate_bg: Option<bool>,
pub auto_update_anim_bg: Option<bool>,
pub reverse: Option<bool>,
pub auto_advance_time: Option<TLTime>,
pub template_list: Option<Vec<TLTemplate>>, }
impl TLBuildParagraph {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut shape_id = None;
let mut group_id = None;
let mut ui_expand = None;
let mut build_type = None;
let mut build_level = None;
let mut animate_bg = None;
let mut auto_update_anim_bg = None;
let mut reverse = None;
let mut auto_advance_time = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"spid" => shape_id = Some(value.parse()?),
"grpId" => group_id = Some(value.parse()?),
"uiExpand" => ui_expand = Some(parse_xml_bool(value)?),
"build" => build_type = Some(value.parse()?),
"bldLvl" => build_level = Some(value.parse()?),
"animBg" => animate_bg = Some(parse_xml_bool(value)?),
"autoUpdateAnimBg" => auto_update_anim_bg = Some(parse_xml_bool(value)?),
"rev" => reverse = Some(parse_xml_bool(value)?),
"advAuto" => auto_advance_time = Some(value.parse()?),
_ => (),
}
}
let template_list = match xml_node.child_nodes.get(0) {
Some(child_node) => {
let mut vec = Vec::new();
for template_node in &child_node.child_nodes {
vec.push(TLTemplate::from_xml_element(template_node)?);
}
Some(vec)
}
None => None,
};
let shape_id = shape_id.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "spid"))?;
let group_id = group_id.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "grpId"))?;
Ok(Self {
build_common: TLBuildCommonAttributes {
shape_id,
group_id,
ui_expand,
},
build_type,
build_level,
animate_bg,
auto_update_anim_bg,
reverse,
auto_advance_time,
template_list,
})
}
}
#[derive(Debug, Clone)]
pub struct TLPoint {
pub x: msoffice_shared::drawingml::Percentage,
pub y: msoffice_shared::drawingml::Percentage,
}
impl TLPoint {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut x = None;
let mut y = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"x" => x = Some(value.parse()?),
"y" => y = Some(value.parse()?),
_ => (),
}
}
let x = x.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "x"))?;
let y = y.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "y"))?;
Ok(Self { x, y })
}
}
#[derive(Debug, Clone)]
pub enum TLTime {
TimePoint(u32),
Indefinite,
}
impl FromStr for TLTime {
type Err = msoffice_shared::error::ParseEnumError;
fn from_str(s: &str) -> ::std::result::Result<Self, Self::Err> {
match s {
"indefinite" => Ok(TLTime::Indefinite),
_ => Ok(TLTime::TimePoint(s.parse().map_err(|_| Self::Err::new("TLTime"))?)),
}
}
}
#[derive(Debug, Clone)]
pub struct TLTemplate {
pub level: Option<u32>,
pub time_node_list: Vec<TimeNodeGroup>,
}
impl TLTemplate {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let level = match xml_node.attribute("lvl") {
Some(value) => Some(value.parse()?),
None => None,
};
let time_node_list = match xml_node.child_nodes.get(0) {
Some(child_node) => {
let mut vec = Vec::new();
for time_node in &child_node.child_nodes {
vec.push(TimeNodeGroup::from_xml_element(time_node)?);
}
vec
}
None => return Err(Box::new(MissingChildNodeError::new(xml_node.name.clone(), "tnLst"))),
};
Ok(Self { level, time_node_list })
}
}
#[derive(Debug, Clone)]
pub struct TLBuildCommonAttributes {
pub shape_id: msoffice_shared::drawingml::DrawingElementId,
pub group_id: u32,
pub ui_expand: Option<bool>,
}
#[derive(Debug, Clone)]
pub struct TLBuildDiagram {
pub build_common: TLBuildCommonAttributes,
pub build_type: Option<TLDiagramBuildType>,
}
impl TLBuildDiagram {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut shape_id = None;
let mut group_id = None;
let mut ui_expand = None;
let mut build_type = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"spid" => shape_id = Some(value.parse()?),
"grpId" => group_id = Some(value.parse()?),
"uiExpand" => ui_expand = Some(parse_xml_bool(value)?),
"bld" => build_type = Some(value.parse()?),
_ => (),
}
}
let shape_id = shape_id.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "spid"))?;
let group_id = group_id.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "grpId"))?;
Ok(Self {
build_common: TLBuildCommonAttributes {
shape_id,
group_id,
ui_expand,
},
build_type,
})
}
}
#[derive(Debug, Clone)]
pub struct TLOleBuildChart {
pub build_common: TLBuildCommonAttributes,
pub build_type: Option<TLOleChartBuildType>,
pub animate_bg: Option<bool>,
}
impl TLOleBuildChart {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut shape_id = None;
let mut group_id = None;
let mut ui_expand = None;
let mut build_type = None;
let mut animate_bg = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"spid" => shape_id = Some(value.parse()?),
"grpId" => group_id = Some(value.parse()?),
"uiExpand" => ui_expand = Some(parse_xml_bool(value)?),
"bld" => build_type = Some(value.parse()?),
"animBg" => animate_bg = Some(parse_xml_bool(value)?),
_ => (),
}
}
let shape_id = shape_id.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "spid"))?;
let group_id = group_id.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "grpId"))?;
Ok(Self {
build_common: TLBuildCommonAttributes {
shape_id,
group_id,
ui_expand,
},
build_type,
animate_bg,
})
}
}
#[derive(Debug, Clone)]
pub struct TLGraphicalObjectBuild {
pub build_common: TLBuildCommonAttributes,
pub build_choice: TLGraphicalObjectBuildChoice,
}
impl TLGraphicalObjectBuild {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut shape_id = None;
let mut group_id = None;
let mut ui_expand = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"spid" => shape_id = Some(value.parse()?),
"grpId" => group_id = Some(value.parse()?),
"uiExpand" => ui_expand = Some(parse_xml_bool(value)?),
_ => (),
}
}
let build_choice = match xml_node.child_nodes.get(0) {
Some(child_node) => TLGraphicalObjectBuildChoice::from_xml_element(child_node)?,
None => {
return Err(Box::new(MissingChildNodeError::new(
xml_node.name.clone(),
"TLGraphicalObjectBuildChoice",
)))
}
};
let shape_id = shape_id.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "spid"))?;
let group_id = group_id.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "grpId"))?;
Ok(Self {
build_common: TLBuildCommonAttributes {
shape_id,
group_id,
ui_expand,
},
build_choice,
})
}
}
#[derive(Debug, Clone)]
pub enum TLGraphicalObjectBuildChoice {
BuildAsOne,
BuildSubElements(msoffice_shared::drawingml::AnimationGraphicalObjectBuildProperties),
}
impl TLGraphicalObjectBuildChoice {
pub fn is_choice_member<T>(name: T) -> bool
where
T: AsRef<str>,
{
match name.as_ref() {
"bldAsOne" | "bldSub" => true,
_ => false,
}
}
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
match xml_node.local_name() {
"bldAsOne" => Ok(TLGraphicalObjectBuildChoice::BuildAsOne),
"bldSub" => Ok(TLGraphicalObjectBuildChoice::BuildSubElements(
msoffice_shared::drawingml::AnimationGraphicalObjectBuildProperties::from_xml_element(xml_node)?,
)),
_ => Err(Box::new(NotGroupMemberError::new(
xml_node.name.clone(),
"TLGraphicalObjectBuildChoice",
))),
}
}
}
#[derive(Debug, Clone)]
pub struct TLTimeNodeSequence {
pub concurrent: Option<bool>,
pub prev_action_type: Option<TLPreviousActionType>,
pub next_action_type: Option<TLNextActionType>,
pub common_time_node_data: Box<TLCommonTimeNodeData>,
pub prev_condition_list: Vec<TLTimeCondition>,
pub next_condition_list: Vec<TLTimeCondition>,
}
impl TLTimeNodeSequence {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut concurrent = None;
let mut prev_action_type = None;
let mut next_action_type = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"concurrent" => concurrent = Some(parse_xml_bool(value)?),
"prevAc" => prev_action_type = Some(value.parse()?),
"nextAc" => next_action_type = Some(value.parse()?),
_ => (),
}
}
let mut common_time_node_data = None;
let mut prev_condition_list = Vec::new();
let mut next_condition_list = Vec::new();
for child_node in &xml_node.child_nodes {
match child_node.local_name() {
"cTn" => common_time_node_data = Some(Box::new(TLCommonTimeNodeData::from_xml_element(child_node)?)),
"prevCondLst" => {
for condition_node in &child_node.child_nodes {
prev_condition_list.push(TLTimeCondition::from_xml_element(condition_node)?);
}
}
"nextCondLst" => {
for condition_node in &child_node.child_nodes {
next_condition_list.push(TLTimeCondition::from_xml_element(condition_node)?);
}
}
_ => (),
}
}
let common_time_node_data =
common_time_node_data.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "cTn"))?;
Ok(Self {
concurrent,
prev_action_type,
next_action_type,
common_time_node_data,
prev_condition_list,
next_condition_list,
})
}
}
#[derive(Debug, Clone)]
pub struct TLAnimateBehavior {
pub by: Option<String>,
pub from: Option<String>,
pub to: Option<String>,
pub calc_mode: Option<TLAnimateBehaviorCalcMode>,
pub value_type: Option<TLAnimateBehaviorValueType>,
pub common_behavior_data: Box<TLCommonBehaviorData>,
pub time_animate_value_list: Option<Vec<TLTimeAnimateValue>>,
}
impl TLAnimateBehavior {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut by = None;
let mut from = None;
let mut to = None;
let mut calc_mode = None;
let mut value_type = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"by" => by = Some(value.clone()),
"from" => from = Some(value.clone()),
"to" => to = Some(value.clone()),
"calcmode" => calc_mode = Some(value.parse()?),
"valueType" => value_type = Some(value.parse()?),
_ => (),
}
}
let mut common_behavior_data = None;
let mut time_animate_value_list = None;
for child_node in &xml_node.child_nodes {
match child_node.local_name() {
"cBhvr" => common_behavior_data = Some(Box::new(TLCommonBehaviorData::from_xml_element(child_node)?)),
"tavLst" => {
let mut vec = Vec::new();
for tav_node in &child_node.child_nodes {
vec.push(TLTimeAnimateValue::from_xml_element(tav_node)?);
}
time_animate_value_list = Some(vec);
}
_ => (),
}
}
let common_behavior_data =
common_behavior_data.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "cBhvr"))?;
Ok(Self {
by,
from,
to,
calc_mode,
value_type,
common_behavior_data,
time_animate_value_list,
})
}
}
#[derive(Debug, Clone)]
pub struct TLAnimateColorBehavior {
pub color_space: Option<TLAnimateColorSpace>,
pub direction: Option<TLAnimateColorDirection>,
pub common_behavior_data: Box<TLCommonBehaviorData>,
pub by: Option<TLByAnimateColorTransform>,
pub from: Option<msoffice_shared::drawingml::Color>,
pub to: Option<msoffice_shared::drawingml::Color>,
}
impl TLAnimateColorBehavior {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
use msoffice_shared::drawingml::Color;
let mut color_space = None;
let mut direction = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"clrSpc" => color_space = Some(value.parse()?),
"dir" => direction = Some(value.parse()?),
_ => (),
}
}
let mut common_behavior_data = None;
let mut by = None;
let mut from = None;
let mut to = None;
for child_node in &xml_node.child_nodes {
match child_node.local_name() {
"cBhvr" => common_behavior_data = Some(Box::new(TLCommonBehaviorData::from_xml_element(child_node)?)),
"by" => {
let by_node = child_node.child_nodes.get(0).ok_or_else(|| {
MissingChildNodeError::new(child_node.name.clone(), "TLByAnimateColorTransform")
})?;
by = Some(TLByAnimateColorTransform::from_xml_element(by_node)?);
}
"from" => {
let color_node = child_node
.child_nodes
.get(0)
.ok_or_else(|| MissingChildNodeError::new(child_node.name.clone(), "EG_Color"))?;
from = Some(Color::from_xml_element(color_node)?);
}
"to" => {
let color_node = child_node
.child_nodes
.get(0)
.ok_or_else(|| MissingChildNodeError::new(child_node.name.clone(), "EG_Color"))?;
to = Some(Color::from_xml_element(color_node)?);
}
_ => (),
}
}
let common_behavior_data =
common_behavior_data.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "cBhvr"))?;
Ok(Self {
color_space,
direction,
common_behavior_data,
by,
from,
to,
})
}
}
#[derive(Debug, Clone)]
pub struct TLAnimateEffectBehavior {
pub transition: Option<TLAnimateEffectTransition>,
pub filter: Option<String>,
pub property_list: Option<String>,
pub common_behavior_data: Box<TLCommonBehaviorData>,
pub progress: Option<TLAnimVariant>,
}
impl TLAnimateEffectBehavior {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut transition = None;
let mut filter = None;
let mut property_list = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"transition" => transition = Some(value.parse()?),
"filter" => filter = Some(value.clone()),
"prLst" => property_list = Some(value.clone()),
_ => (),
}
}
let mut common_behavior_data = None;
let mut progress = None;
for child_node in &xml_node.child_nodes {
match child_node.local_name() {
"cBhvr" => common_behavior_data = Some(Box::new(TLCommonBehaviorData::from_xml_element(child_node)?)),
"progress" => {
let progress_node = child_node
.child_nodes
.get(0)
.ok_or_else(|| MissingChildNodeError::new(child_node.name.clone(), "CT_TLAnimVariant"))?;
progress = Some(TLAnimVariant::from_xml_element(progress_node)?);
}
_ => (),
}
}
let common_behavior_data =
common_behavior_data.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "cBhvr"))?;
Ok(Self {
transition,
filter,
property_list,
common_behavior_data,
progress,
})
}
}
#[derive(Debug, Clone)]
pub struct TLAnimateMotionBehavior {
pub origin: Option<TLAnimateMotionBehaviorOrigin>,
pub path: Option<String>,
pub path_edit_mode: Option<TLAnimateMotionPathEditMode>,
pub rotate_angle: Option<msoffice_shared::drawingml::Angle>,
pub points_types: Option<String>,
pub common_behavior_data: Box<TLCommonBehaviorData>,
pub by: Option<TLPoint>,
pub from: Option<TLPoint>,
pub to: Option<TLPoint>,
pub rotation_center: Option<TLPoint>,
}
impl TLAnimateMotionBehavior {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut origin = None;
let mut path = None;
let mut path_edit_mode = None;
let mut rotate_angle = None;
let mut points_types = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"origin" => origin = Some(value.parse()?),
"path" => path = Some(value.clone()),
"pathEditMode" => path_edit_mode = Some(value.parse()?),
"rAng" => rotate_angle = Some(value.parse()?),
"ptsTypes" => points_types = Some(value.clone()),
_ => (),
}
}
let mut common_behavior_data = None;
let mut by = None;
let mut from = None;
let mut to = None;
let mut rotation_center = None;
for child_node in &xml_node.child_nodes {
match child_node.local_name() {
"cBhvr" => common_behavior_data = Some(Box::new(TLCommonBehaviorData::from_xml_element(child_node)?)),
"by" => by = Some(TLPoint::from_xml_element(child_node)?),
"from" => from = Some(TLPoint::from_xml_element(child_node)?),
"to" => to = Some(TLPoint::from_xml_element(child_node)?),
"rCtr" => rotation_center = Some(TLPoint::from_xml_element(child_node)?),
_ => (),
}
}
let common_behavior_data =
common_behavior_data.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "cBhvr"))?;
Ok(Self {
origin,
path,
path_edit_mode,
rotate_angle,
points_types,
common_behavior_data,
by,
from,
to,
rotation_center,
})
}
}
#[derive(Debug, Clone)]
pub struct TLAnimateRotationBehavior {
pub by: Option<msoffice_shared::drawingml::Angle>,
pub from: Option<msoffice_shared::drawingml::Angle>,
pub to: Option<msoffice_shared::drawingml::Angle>,
pub common_behavior_data: Box<TLCommonBehaviorData>,
}
impl TLAnimateRotationBehavior {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut by = None;
let mut from = None;
let mut to = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"by" => by = Some(value.parse()?),
"from" => from = Some(value.parse()?),
"to" => to = Some(value.parse()?),
_ => (),
}
}
let common_behavior_data_node = xml_node
.child_nodes
.get(0)
.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "cBhvr"))?;
let common_behavior_data = Box::new(TLCommonBehaviorData::from_xml_element(common_behavior_data_node)?);
Ok(Self {
by,
from,
to,
common_behavior_data,
})
}
}
#[derive(Debug, Clone)]
pub struct TLAnimateScaleBehavior {
pub zoom_contents: Option<bool>,
pub common_behavior_data: Box<TLCommonBehaviorData>,
pub by: Option<TLPoint>,
pub from: Option<TLPoint>,
pub to: Option<TLPoint>,
}
impl TLAnimateScaleBehavior {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let zoom_contents = match xml_node.attribute("zoomContents") {
Some(value) => Some(parse_xml_bool(value)?),
None => None,
};
let mut common_behavior_data = None;
let mut by = None;
let mut from = None;
let mut to = None;
for child_node in &xml_node.child_nodes {
match child_node.local_name() {
"cBhvr" => common_behavior_data = Some(Box::new(TLCommonBehaviorData::from_xml_element(child_node)?)),
"by" => by = Some(TLPoint::from_xml_element(child_node)?),
"from" => from = Some(TLPoint::from_xml_element(child_node)?),
"to" => to = Some(TLPoint::from_xml_element(child_node)?),
_ => (),
}
}
let common_behavior_data =
common_behavior_data.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "cBhvr"))?;
Ok(Self {
zoom_contents,
common_behavior_data,
by,
from,
to,
})
}
}
#[derive(Debug, Clone)]
pub struct TLCommandBehavior {
pub command_type: Option<TLCommandType>,
pub command: Option<String>,
pub common_behavior_data: Box<TLCommonBehaviorData>,
}
impl TLCommandBehavior {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut command_type = None;
let mut command = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"type" => command_type = Some(value.parse()?),
"cmd" => command = Some(value.clone()),
_ => (),
}
}
let common_behavior_data_node = xml_node
.child_nodes
.get(0)
.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "cBhvr"))?;
let common_behavior_data = Box::new(TLCommonBehaviorData::from_xml_element(common_behavior_data_node)?);
Ok(Self {
command_type,
command,
common_behavior_data,
})
}
}
#[derive(Debug, Clone)]
pub struct TLSetBehavior {
pub common_behavior_data: Box<TLCommonBehaviorData>,
pub to: Option<TLAnimVariant>,
}
impl TLSetBehavior {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut common_behavior_data = None;
let mut to = None;
for child_node in &xml_node.child_nodes {
match child_node.local_name() {
"cBhvr" => common_behavior_data = Some(Box::new(TLCommonBehaviorData::from_xml_element(child_node)?)),
"to" => {
let to_node = child_node
.child_nodes
.get(0)
.ok_or_else(|| MissingChildNodeError::new(child_node.name.clone(), "CT_TLAnimVariant"))?;
to = Some(TLAnimVariant::from_xml_element(to_node)?);
}
_ => (),
}
}
let common_behavior_data =
common_behavior_data.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "cBhvr"))?;
Ok(Self {
common_behavior_data,
to,
})
}
}
#[derive(Debug, Clone)]
pub struct TLMediaNodeAudio {
pub is_narration: Option<bool>,
pub common_media_node_data: Box<TLCommonMediaNodeData>,
}
impl TLMediaNodeAudio {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let is_narration = match xml_node.attribute("isNarration") {
Some(value) => Some(parse_xml_bool(value)?),
None => None,
};
let common_media_node_data_node = xml_node
.child_nodes
.get(0)
.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "cMediaNode"))?;
let common_media_node_data = Box::new(TLCommonMediaNodeData::from_xml_element(common_media_node_data_node)?);
Ok(Self {
is_narration,
common_media_node_data,
})
}
}
#[derive(Debug, Clone)]
pub struct TLMediaNodeVideo {
pub fullscreen: Option<bool>,
pub common_media_node_data: Box<TLCommonMediaNodeData>,
}
impl TLMediaNodeVideo {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let fullscreen = match xml_node.attribute("fullScrn") {
Some(value) => Some(parse_xml_bool(value)?),
None => None,
};
let common_media_node_data_node = xml_node
.child_nodes
.get(0)
.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "cMediaNode"))?;
let common_media_node_data = Box::new(TLCommonMediaNodeData::from_xml_element(common_media_node_data_node)?);
Ok(Self {
fullscreen,
common_media_node_data,
})
}
}
#[derive(Default, Debug, Clone)]
pub struct TLTimeAnimateValue {
pub time: Option<TLTimeAnimateValueTime>,
pub formula: Option<String>,
pub value: Option<TLAnimVariant>,
}
impl TLTimeAnimateValue {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut instance: Self = Default::default();
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"tm" => instance.time = Some(value.parse()?),
"fmla" => instance.formula = Some(value.clone()),
_ => (),
}
}
if let Some(child_node) = xml_node.child_nodes.get(0) {
let val_node = child_node
.child_nodes
.get(0)
.ok_or_else(|| MissingChildNodeError::new(child_node.name.clone(), "CT_TLAnimVariant"))?;
instance.value = Some(TLAnimVariant::from_xml_element(val_node)?);
}
Ok(instance)
}
}
#[derive(Debug, Clone)]
pub enum TLTimeAnimateValueTime {
Percentage(msoffice_shared::drawingml::PositiveFixedPercentage),
Indefinite,
}
impl FromStr for TLTimeAnimateValueTime {
type Err = msoffice_shared::error::ParseEnumError;
fn from_str(s: &str) -> ::std::result::Result<Self, Self::Err> {
match s {
"indefinite" => Ok(TLTimeAnimateValueTime::Indefinite),
_ => Ok(TLTimeAnimateValueTime::Percentage(
s.parse().map_err(|_| Self::Err::new("TLTimeAnimateValueTime"))?,
)),
}
}
}
#[derive(Debug, Clone)]
pub enum TLAnimVariant {
Bool(bool),
Int(i32),
Float(f32),
String(String),
Color(msoffice_shared::drawingml::Color),
}
impl TLAnimVariant {
pub fn is_choice_member<T>(name: T) -> bool
where
T: AsRef<str>,
{
match name.as_ref() {
"boolVal" | "intVal" | "fltVal" | "strVal" | "clrVal" => true,
_ => false,
}
}
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
match xml_node.local_name() {
"boolVal" => {
let val_attr = xml_node
.attribute("val")
.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "val"))?;
Ok(TLAnimVariant::Bool(parse_xml_bool(val_attr)?))
}
"intVal" => {
let val_attr = xml_node
.attribute("val")
.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "val"))?;
Ok(TLAnimVariant::Int(val_attr.parse()?))
}
"fltVal" => {
let val_attr = xml_node
.attribute("val")
.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "val"))?;
Ok(TLAnimVariant::Float(val_attr.parse()?))
}
"strVal" => {
let val_attr = xml_node
.attribute("val")
.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "val"))?;
Ok(TLAnimVariant::String(val_attr.clone()))
}
"clrVal" => {
let child_node = xml_node
.child_nodes
.get(0)
.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "EG_Color"))?;
Ok(TLAnimVariant::Color(
msoffice_shared::drawingml::Color::from_xml_element(child_node)?,
))
}
_ => Err(NotGroupMemberError::new(xml_node.name.clone(), "EG_TLAnimVariant").into()),
}
}
}
#[derive(Debug, Clone)]
pub enum TLTimeConditionTriggerGroup {
TargetElement(TLTimeTargetElement),
TimeNode(TLTimeNodeId),
RuntimeNode(TLTriggerRuntimeNode),
}
impl TLTimeConditionTriggerGroup {
pub fn is_choice_member<T>(name: T) -> bool
where
T: AsRef<str>,
{
match name.as_ref() {
"tgtEl" | "tn" | "rtn" => true,
_ => false,
}
}
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
match xml_node.local_name() {
"tgtEl" => {
let target_element_node = xml_node
.child_nodes
.get(0)
.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "CT_TLTimeTargetElement"))?;
Ok(TLTimeConditionTriggerGroup::TargetElement(
TLTimeTargetElement::from_xml_element(target_element_node)?,
))
}
"tn" => {
let val_attr = xml_node
.attribute("val")
.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "val"))?;
Ok(TLTimeConditionTriggerGroup::TimeNode(val_attr.parse()?))
}
"rtn" => {
let val_attr = xml_node
.attribute("val")
.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "val"))?;
Ok(TLTimeConditionTriggerGroup::RuntimeNode(val_attr.parse()?))
}
_ => Err(Box::new(NotGroupMemberError::new(
xml_node.name.clone(),
"EG_TLTimeConditionTriggerGroup",
))),
}
}
}
#[derive(Debug, Clone)]
pub enum TLTimeTargetElement {
SlideTarget,
SoundTarget(msoffice_shared::drawingml::EmbeddedWAVAudioFile),
ShapeTarget(TLShapeTargetElement),
InkTarget(TLSubShapeId),
}
impl TLTimeTargetElement {
pub fn is_choice_member<T>(name: T) -> bool
where
T: AsRef<str>,
{
match name.as_ref() {
"sldTgt" | "sndTgt" | "spTgt" | "inkTgt" => true,
_ => false,
}
}
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
match xml_node.local_name() {
"sldTgt" => Ok(TLTimeTargetElement::SlideTarget),
"sndTgt" => Ok(TLTimeTargetElement::SoundTarget(
msoffice_shared::drawingml::EmbeddedWAVAudioFile::from_xml_element(xml_node)?,
)),
"spTgt" => {
let child_node = xml_node
.child_nodes
.get(0)
.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "CT_TLShapeTargetElement"))?;
Ok(TLTimeTargetElement::ShapeTarget(
TLShapeTargetElement::from_xml_element(child_node)?,
))
}
"inkTgt" => {
let spid_attr = xml_node
.attribute("spid")
.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "spid"))?;
Ok(TLTimeTargetElement::InkTarget(spid_attr.parse()?))
}
_ => Err(Box::new(NotGroupMemberError::new(
xml_node.name.clone(),
"CT_TLTimeTargetElement",
))),
}
}
}
#[derive(Debug, Clone)]
pub struct TLShapeTargetElement {
pub shape_id: msoffice_shared::drawingml::DrawingElementId,
pub target: Option<TLShapeTargetElementGroup>,
}
impl TLShapeTargetElement {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let shape_id_attr = xml_node
.attribute("spid")
.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "spid"))?;
let shape_id = shape_id_attr.parse()?;
let target = match xml_node.child_nodes.get(0) {
Some(child_node) => Some(TLShapeTargetElementGroup::from_xml_element(child_node)?),
None => None,
};
Ok(Self { shape_id, target })
}
}
#[derive(Debug, Clone)]
pub enum TLShapeTargetElementGroup {
Background,
SubShape(TLSubShapeId),
OleChartElement(TLOleChartTargetElement),
TextElement(Option<TLTextTargetElement>),
GraphicElement(msoffice_shared::drawingml::AnimationElementChoice),
}
impl TLShapeTargetElementGroup {
pub fn is_choice_member<T>(name: T) -> bool
where
T: AsRef<str>,
{
match name.as_ref() {
"bg" | "subSp" | "oleChartEl" | "txEl" | "graphicEl" => true,
_ => false,
}
}
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
match xml_node.local_name() {
"bg" => Ok(TLShapeTargetElementGroup::Background),
"subSp" => {
let spid_attr = xml_node
.attribute("spid")
.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "spid"))?;
Ok(TLShapeTargetElementGroup::SubShape(spid_attr.parse()?))
}
"oleChartEl" => Ok(TLShapeTargetElementGroup::OleChartElement(
TLOleChartTargetElement::from_xml_element(xml_node)?,
)),
"txEl" => Ok(TLShapeTargetElementGroup::TextElement(
match xml_node.child_nodes.get(0) {
Some(child_node) => Some(TLTextTargetElement::from_xml_element(child_node)?),
None => None,
},
)),
"graphicEl" => {
let child_node = xml_node
.child_nodes
.get(0)
.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "CT_AnimationElementChoice"))?;
Ok(TLShapeTargetElementGroup::GraphicElement(
msoffice_shared::drawingml::AnimationElementChoice::from_xml_element(child_node)?,
))
}
_ => Err(Box::new(NotGroupMemberError::new(
xml_node.name.clone(),
"TLShapeTargetElementGroup",
))),
}
}
}
#[derive(Debug, Clone)]
pub struct TLOleChartTargetElement {
pub element_type: TLChartSubelementType,
pub level: Option<u32>,
}
impl TLOleChartTargetElement {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut element_type = None;
let mut level = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"type" => element_type = Some(value.parse()?),
"lvl" => level = Some(value.parse()?),
_ => (),
}
}
let element_type = element_type.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "type"))?;
Ok(Self { element_type, level })
}
}
#[derive(Debug, Clone)]
pub enum TLTextTargetElement {
CharRange(IndexRange),
ParagraphRange(IndexRange),
}
impl TLTextTargetElement {
pub fn is_choice_member<T>(name: T) -> bool
where
T: AsRef<str>,
{
match name.as_ref() {
"charRg" | "pRg" => true,
_ => false,
}
}
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
match xml_node.local_name() {
"charRg" => Ok(TLTextTargetElement::CharRange(IndexRange::from_xml_element(xml_node)?)),
"pRg" => Ok(TLTextTargetElement::ParagraphRange(IndexRange::from_xml_element(
xml_node,
)?)),
_ => Err(Box::new(NotGroupMemberError::new(
xml_node.name.clone(),
"TLTextTargetElement",
))),
}
}
}
#[derive(Default, Debug, Clone)]
pub struct TLTimeCondition {
pub trigger_event: Option<TLTriggerEvent>,
pub delay: Option<TLTime>,
pub trigger: Option<TLTimeConditionTriggerGroup>,
}
impl TLTimeCondition {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut instance: Self = Default::default();
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"evt" => instance.trigger_event = Some(value.parse()?),
"delay" => instance.delay = Some(value.parse()?),
_ => (),
}
}
if let Some(child_node) = xml_node.child_nodes.get(0) {
instance.trigger = Some(TLTimeConditionTriggerGroup::from_xml_element(child_node)?);
}
Ok(instance)
}
}
#[derive(Default, Debug, Clone)]
pub struct TLCommonTimeNodeData {
pub id: Option<TLTimeNodeId>,
pub preset_id: Option<i32>,
pub preset_class: Option<TLTimeNodePresetClassType>,
pub preset_subtype: Option<i32>,
pub duration: Option<TLTime>,
pub repeat_count: Option<TLTime>,
pub repeat_duration: Option<TLTime>,
pub speed: Option<msoffice_shared::drawingml::Percentage>,
pub acceleration: Option<msoffice_shared::drawingml::PositiveFixedPercentage>,
pub deceleration: Option<msoffice_shared::drawingml::PositiveFixedPercentage>,
pub auto_reverse: Option<bool>,
pub restart_type: Option<TLTimeNodeRestartType>,
pub fill_type: Option<TLTimeNodeFillType>,
pub sync_behavior: Option<TLTimeNodeSyncType>,
pub time_filter: Option<String>,
pub event_filter: Option<String>,
pub display: Option<bool>,
pub master_relationship: Option<TLTimeNodeMasterRelation>,
pub build_level: Option<i32>,
pub group_id: Option<u32>,
pub after_effect: Option<bool>,
pub node_type: Option<TLTimeNodeType>,
pub node_placeholder: Option<bool>,
pub start_condition_list: Option<Vec<TLTimeCondition>>,
pub end_condition_list: Option<Vec<TLTimeCondition>>,
pub end_sync: Option<TLTimeCondition>,
pub iterate: Option<TLIterateData>,
pub child_time_node_list: Option<Vec<TimeNodeGroup>>,
pub sub_time_node_list: Option<Vec<TimeNodeGroup>>,
}
impl TLCommonTimeNodeData {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut instance: Self = Default::default();
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"id" => instance.id = Some(value.parse()?),
"presetID" => instance.preset_id = Some(value.parse()?),
"presetClass" => instance.preset_class = Some(value.parse()?),
"presetSubtype" => instance.preset_subtype = Some(value.parse()?),
"dur" => instance.duration = Some(value.parse()?),
"repeatCount" => instance.repeat_count = Some(value.parse()?),
"repeatDur" => instance.repeat_duration = Some(value.parse()?),
"spd" => instance.speed = Some(value.parse()?),
"accel" => instance.acceleration = Some(value.parse()?),
"decel" => instance.deceleration = Some(value.parse()?),
"autoRev" => instance.auto_reverse = Some(parse_xml_bool(value)?),
"restart" => instance.restart_type = Some(value.parse()?),
"fill" => instance.fill_type = Some(value.parse()?),
"syncBehavior" => instance.sync_behavior = Some(value.parse()?),
"tmFilter" => instance.time_filter = Some(value.clone()),
"evtFilter" => instance.event_filter = Some(value.clone()),
"display" => instance.display = Some(parse_xml_bool(value)?),
"masterRel" => instance.master_relationship = Some(value.parse()?),
"bldLvl" => instance.build_level = Some(value.parse()?),
"grpId" => instance.group_id = Some(value.parse()?),
"afterEffect" => instance.after_effect = Some(parse_xml_bool(value)?),
"nodeType" => instance.node_type = Some(value.parse()?),
"nodePh" => instance.node_placeholder = Some(parse_xml_bool(value)?),
_ => (),
}
}
for child_node in &xml_node.child_nodes {
match child_node.local_name() {
"stCondLst" => {
let mut vec = Vec::new();
for cond_node in &child_node.child_nodes {
vec.push(TLTimeCondition::from_xml_element(cond_node)?);
}
if vec.is_empty() {
return Err(Box::new(MissingChildNodeError::new(child_node.name.clone(), "cond")));
}
instance.start_condition_list = Some(vec);
}
"endCondLst" => {
let mut vec = Vec::new();
for cond_node in &child_node.child_nodes {
vec.push(TLTimeCondition::from_xml_element(cond_node)?);
}
if vec.is_empty() {
return Err(Box::new(MissingChildNodeError::new(child_node.name.clone(), "cond")));
}
instance.end_condition_list = Some(vec);
}
"endSync" => instance.end_sync = Some(TLTimeCondition::from_xml_element(child_node)?),
"iterate" => instance.iterate = Some(TLIterateData::from_xml_element(child_node)?),
"childTnLst" => {
let mut vec = Vec::new();
for time_node in &child_node.child_nodes {
vec.push(TimeNodeGroup::from_xml_element(time_node)?);
}
if vec.is_empty() {
return Err(Box::new(MissingChildNodeError::new(
child_node.name.clone(),
"TimeNode",
)));
}
instance.child_time_node_list = Some(vec);
}
"subTnLst" => {
let mut vec = Vec::new();
for time_node in &child_node.child_nodes {
vec.push(TimeNodeGroup::from_xml_element(time_node)?);
}
if vec.is_empty() {
return Err(Box::new(MissingChildNodeError::new(
child_node.name.clone(),
"TimeNode",
)));
}
instance.sub_time_node_list = Some(vec);
}
_ => (),
}
}
Ok(instance)
}
}
#[derive(Debug, Clone)]
pub enum TLIterateDataChoice {
Absolute(TLTime),
Percent(msoffice_shared::drawingml::PositivePercentage),
}
impl TLIterateDataChoice {
pub fn is_choice_member<T>(name: T) -> bool
where
T: AsRef<str>,
{
match name.as_ref() {
"tmAbs" | "tmPct" => true,
_ => false,
}
}
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
match xml_node.local_name() {
"tmAbs" => {
let val_attr = xml_node
.attribute("val")
.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "val"))?;
Ok(TLIterateDataChoice::Absolute(val_attr.parse()?))
}
"tmPct" => {
let val_attr = xml_node
.attribute("val")
.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "val"))?;
Ok(TLIterateDataChoice::Percent(val_attr.parse()?))
}
_ => Err(Box::new(NotGroupMemberError::new(
xml_node.name.clone(),
"TLIterateDataChoice",
))),
}
}
}
#[derive(Debug, Clone)]
pub struct TLIterateData {
pub iterate_type: Option<IterateType>,
pub backwards: Option<bool>,
pub interval: TLIterateDataChoice,
}
impl TLIterateData {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut iterate_type = None;
let mut backwards = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"type" => iterate_type = Some(value.parse()?),
"backwards" => backwards = Some(parse_xml_bool(value)?),
_ => (),
}
}
let interval_node = xml_node
.child_nodes
.get(0)
.ok_or_else(|| MissingChildNodeError::new(xml_node.name.clone(), "TLIterateDataChoice"))?;
let interval = TLIterateDataChoice::from_xml_element(interval_node)?;
Ok(Self {
iterate_type,
backwards,
interval,
})
}
}
#[derive(Debug, Clone)]
pub enum TLByAnimateColorTransform {
Rgb(TLByRgbColorTransform),
Hsl(TLByHslColorTransform),
}
impl TLByAnimateColorTransform {
pub fn is_choice_member<T>(name: T) -> bool
where
T: AsRef<str>,
{
match name.as_ref() {
"rgb" | "hsl" => true,
_ => false,
}
}
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
match xml_node.local_name() {
"rgb" => Ok(TLByAnimateColorTransform::Rgb(TLByRgbColorTransform::from_xml_element(
xml_node,
)?)),
"hsl" => Ok(TLByAnimateColorTransform::Hsl(TLByHslColorTransform::from_xml_element(
xml_node,
)?)),
_ => Err(Box::new(NotGroupMemberError::new(
xml_node.name.clone(),
"TLByAnimateColorTransform",
))),
}
}
}
#[derive(Debug, Clone)]
pub struct TLByRgbColorTransform {
pub r: msoffice_shared::drawingml::FixedPercentage,
pub g: msoffice_shared::drawingml::FixedPercentage,
pub b: msoffice_shared::drawingml::FixedPercentage,
}
impl TLByRgbColorTransform {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut r = None;
let mut g = None;
let mut b = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"r" => r = Some(value.parse()?),
"g" => g = Some(value.parse()?),
"b" => b = Some(value.parse()?),
_ => (),
}
}
let r = r.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "r"))?;
let g = g.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "g"))?;
let b = b.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "b"))?;
Ok(Self { r, g, b })
}
}
#[derive(Debug, Clone)]
pub struct TLByHslColorTransform {
pub h: msoffice_shared::drawingml::Angle,
pub s: msoffice_shared::drawingml::FixedPercentage,
pub l: msoffice_shared::drawingml::FixedPercentage,
}
impl TLByHslColorTransform {
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
let mut h = None;
let mut s = None;
let mut l = None;
for (attr, value) in &xml_node.attributes {
match attr.as_str() {
"h" => h = Some(value.parse()?),
"s" => s = Some(value.parse()?),
"l" => l = Some(value.parse()?),
_ => (),
}
}
let h = h.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "h"))?;
let s = s.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "s"))?;
let l = l.ok_or_else(|| MissingAttributeError::new(xml_node.name.clone(), "l"))?;
Ok(Self { h, s, l })
}
}
#[derive(Debug, Clone)]
pub enum Build {
Paragraph(Box<TLBuildParagraph>),
Diagram(Box<TLBuildDiagram>),
OleChart(Box<TLOleBuildChart>),
Graphic(Box<TLGraphicalObjectBuild>),
}
impl Build {
pub fn is_choice_member<T>(name: T) -> bool
where
T: AsRef<str>,
{
match name.as_ref() {
"bldP" | "bldDgm" | "bldOleChart" | "bldGraphic" => true,
_ => false,
}
}
pub fn from_xml_element(xml_node: &XmlNode) -> Result<Self> {
match xml_node.local_name() {
"bldP" => Ok(Build::Paragraph(Box::new(TLBuildParagraph::from_xml_element(
xml_node,
)?))),
"bldDgm" => Ok(Build::Diagram(Box::new(TLBuildDiagram::from_xml_element(xml_node)?))),
"bldOleChart" => Ok(Build::OleChart(Box::new(TLOleBuildChart::from_xml_element(xml_node)?))),
"bldGraphic" => Ok(Build::Graphic(Box::new(TLGraphicalObjectBuild::from_xml_element(
xml_node,
)?))),
_ => Err(Box::new(NotGroupMemberError::new(
xml_node.name.clone(),
"CT_BuildList",
))),
}
}
}