use crate::xml_util::WriteXml;
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TransitionType {
None,
Fade,
Push,
Wipe,
Split,
Blinds,
Checker,
Dissolve,
Cover,
Cut,
Random,
}
impl TransitionType {
#[must_use]
pub const fn to_xml_element(self) -> Option<&'static str> {
match self {
Self::None => None,
Self::Fade => Some("p:fade"),
Self::Push => Some("p:push"),
Self::Wipe => Some("p:wipe"),
Self::Split => Some("p:split"),
Self::Blinds => Some("p:blinds"),
Self::Checker => Some("p:checker"),
Self::Dissolve => Some("p:dissolve"),
Self::Cover => Some("p:cover"),
Self::Cut => Some("p:cut"),
Self::Random => Some("p:random"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SlideTransition {
pub transition_type: TransitionType,
pub duration: Option<u32>,
pub advance_on_click: bool,
pub advance_after_time: Option<u32>,
}
impl SlideTransition {
#[must_use]
pub const fn new(transition_type: TransitionType) -> Self {
Self {
transition_type,
duration: None,
advance_on_click: true,
advance_after_time: None,
}
}
#[must_use]
pub const fn fade() -> Self {
Self::new(TransitionType::Fade)
}
#[must_use]
pub const fn push() -> Self {
Self::new(TransitionType::Push)
}
#[must_use]
pub const fn wipe() -> Self {
Self::new(TransitionType::Wipe)
}
#[must_use]
pub const fn with_duration(mut self, ms: u32) -> Self {
self.duration = Some(ms);
self
}
#[must_use]
pub const fn with_advance_after(mut self, ms: u32) -> Self {
self.advance_after_time = Some(ms);
self
}
#[must_use]
pub const fn without_click_advance(mut self) -> Self {
self.advance_on_click = false;
self
}
}
impl WriteXml for SlideTransition {
fn write_xml<W: std::fmt::Write>(&self, w: &mut W) -> std::fmt::Result {
w.write_str("<p:transition")?;
if let Some(dur) = self.duration {
if dur >= 2000 {
w.write_str(r#" spd="slow""#)?;
} else if dur >= 500 {
w.write_str(r#" spd="med""#)?;
} else {
w.write_str(r#" spd="fast""#)?;
}
}
if !self.advance_on_click {
w.write_str(r#" advClick="0""#)?;
}
if let Some(adv_tm) = self.advance_after_time {
write!(w, r#" advTm="{adv_tm}""#)?;
}
if let Some(elem) = self.transition_type.to_xml_element() {
w.write_char('>')?;
write!(w, "<{elem}/>")?;
w.write_str("</p:transition>")
} else {
w.write_str("/>")
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_fade_transition_xml() {
let t = SlideTransition::fade();
let xml = t.to_xml_string();
assert!(xml.contains("<p:transition"));
assert!(xml.contains("<p:fade/>"));
assert!(xml.contains("</p:transition>"));
}
#[test]
fn test_push_transition_xml() {
let t = SlideTransition::push();
let xml = t.to_xml_string();
assert!(xml.contains("<p:push/>"));
}
#[test]
fn test_wipe_transition_xml() {
let t = SlideTransition::wipe();
let xml = t.to_xml_string();
assert!(xml.contains("<p:wipe/>"));
}
#[test]
fn test_none_transition_xml() {
let t = SlideTransition::new(TransitionType::None);
let xml = t.to_xml_string();
assert!(xml.contains("<p:transition"));
assert!(xml.ends_with("/>"));
assert!(!xml.contains("</p:transition>"));
}
#[test]
fn test_transition_with_duration() {
let t = SlideTransition::fade().with_duration(3000);
let xml = t.to_xml_string();
assert!(xml.contains(r#"spd="slow""#));
}
#[test]
fn test_transition_fast_duration() {
let t = SlideTransition::fade().with_duration(200);
let xml = t.to_xml_string();
assert!(xml.contains(r#"spd="fast""#));
}
#[test]
fn test_transition_no_click_advance() {
let t = SlideTransition::fade().without_click_advance();
let xml = t.to_xml_string();
assert!(xml.contains(r#"advClick="0""#));
}
#[test]
fn test_transition_auto_advance() {
let t = SlideTransition::fade().with_advance_after(5000);
let xml = t.to_xml_string();
assert!(xml.contains(r#"advTm="5000""#));
}
#[test]
fn test_transition_all_options() {
let t = SlideTransition::wipe()
.with_duration(1000)
.with_advance_after(3000)
.without_click_advance();
let xml = t.to_xml_string();
assert!(xml.contains("<p:wipe/>"));
assert!(xml.contains(r#"spd="med""#));
assert!(xml.contains(r#"advClick="0""#));
assert!(xml.contains(r#"advTm="3000""#));
}
#[test]
fn test_transition_type_xml_elements() {
assert_eq!(TransitionType::Fade.to_xml_element(), Some("p:fade"));
assert_eq!(TransitionType::Push.to_xml_element(), Some("p:push"));
assert_eq!(
TransitionType::Dissolve.to_xml_element(),
Some("p:dissolve")
);
assert_eq!(TransitionType::None.to_xml_element(), None);
}
}