mod animation_type;
mod mode;
use crate::{
spring::Motion,
transition::{Easing, Transition},
Animate, Event, Spring,
};
pub use animation_type::AnimationType;
pub use mode::Mode;
use std::time::{Duration, Instant};
pub const DEFAULT_DURATION: Duration = Duration::from_millis(500);
#[derive(Debug, Clone, PartialEq)]
pub struct Animated<T> {
animation: AnimationType<T>,
}
impl<T> Animated<T>
where
T: Animate,
{
pub fn new(value: T, mode: impl Into<Mode>) -> Self {
match mode.into() {
Mode::Spring(motion) => Self::spring(value, motion),
Mode::Transition(easing) => Self::transition(value, easing),
}
}
pub fn spring(value: T, motion: Motion) -> Self {
Self {
animation: AnimationType::Spring(Spring::new(value).with_motion(motion)),
}
}
pub fn transition(value: T, easing: Easing) -> Self {
Self {
animation: AnimationType::Transition(Transition::new(value).with_easing(easing)),
}
}
pub fn with_duration(mut self, duration: Duration) -> Self {
match &mut self.animation {
AnimationType::Spring(spring) => {
let motion = spring.motion().with_duration(duration);
spring.set_motion(motion);
}
AnimationType::Transition(transition) => {
transition.set_easing(transition.easing().with_duration(duration));
}
}
self
}
pub fn very_quick(self) -> Self {
self.with_duration(Duration::from_millis(100))
}
pub fn quick(self) -> Self {
self.with_duration(Duration::from_millis(200))
}
pub fn slow(self) -> Self {
self.with_duration(Duration::from_millis(400))
}
pub fn very_slow(self) -> Self {
self.with_duration(Duration::from_millis(500))
}
pub fn update(&mut self, event: Event<T>) {
match &mut self.animation {
AnimationType::Spring(spring) => spring.update(event),
AnimationType::Transition(transition) => transition.update(event),
}
}
pub fn is_animating(&self) -> bool {
match &self.animation {
AnimationType::Spring(spring) => spring.has_energy(),
AnimationType::Transition(transition) => transition.is_animating(),
}
}
pub fn value(&self) -> &T {
match &self.animation {
AnimationType::Spring(spring) => spring.value(),
AnimationType::Transition(transition) => transition.value(),
}
}
pub fn target(&self) -> &T {
match &self.animation {
AnimationType::Spring(spring) => spring.target(),
AnimationType::Transition(transition) => transition.target(),
}
}
pub fn set_target(&mut self, target: T) {
match &mut self.animation {
AnimationType::Spring(spring) => spring.set_target(target),
AnimationType::Transition(transition) => transition.set_target(target),
}
}
pub fn to(mut self, target: T) -> Self {
match &mut self.animation {
AnimationType::Spring(spring) => spring.set_target(target),
AnimationType::Transition(transition) => transition.set_target(target),
}
self
}
pub fn duration(&self) -> Duration {
match &self.animation {
AnimationType::Spring(spring) => spring.motion().duration(),
AnimationType::Transition(transition) => transition.duration(),
}
}
pub(crate) fn apply(&mut self, mode: Mode) {
match mode {
Mode::Spring(motion) => {
if let AnimationType::Spring(spring) = &mut self.animation {
spring.set_motion(motion);
} else {
let value = self.value().clone();
let target = self.target().clone();
self.animation =
AnimationType::Spring(Spring::new(value).to(target).with_motion(motion));
}
}
Mode::Transition(easing) => {
if let AnimationType::Transition(transition) = &mut self.animation {
transition.set_easing(easing);
} else {
let value = self.value().clone();
let target = self.target().clone();
self.animation = AnimationType::Transition(
Transition::new(value).to(target).with_easing(easing),
);
}
}
}
}
pub fn settle(&mut self) {
match &mut self.animation {
AnimationType::Spring(spring) => spring.settle(),
AnimationType::Transition(transition) => transition.settle(),
}
}
pub fn settle_at(&mut self, target: T) {
match &mut self.animation {
AnimationType::Spring(spring) => spring.settle_at(target),
AnimationType::Transition(transition) => transition.settle_at(target),
}
}
pub fn tick(&mut self, now: Instant) {
match &mut self.animation {
AnimationType::Spring(spring) => spring.tick(now),
AnimationType::Transition(transition) => transition.tick(now),
}
}
}
impl<T> From<T> for Animated<T>
where
T: Animate + Into<AnimationType<T>>,
{
fn from(value: T) -> Self {
Self {
animation: value.into(),
}
}
}
impl<T> Default for Animated<T>
where
T: Animate + Default,
{
fn default() -> Self {
Animated::new(T::default(), Mode::default())
}
}