use super::*;
use crate::fill_transition;
pub struct TransitionTheme {
pub transitions: ahash::HashMap<TransitionIdent, Box<dyn RocBoxClone>>,
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct TransitionIdent(usize);
pub mod transitions {
use super::*;
#[macro_export]
macro_rules! define_transition_ident {
($from: expr, $define: ident, $($ident: ident),+) => {
define_transition_ident!($from, $define);
define_transition_ident!(TransitionIdent($define.0 + 1), $($ident), +);
};
($value: expr, $define: ident) => {
pub const $define: TransitionIdent = $value;
}
}
#[macro_export]
macro_rules! fill_transition {
($transitions: ident, $($name: path: $expr: expr),+) => {
$($transitions.set_transition($name, (Box::new($expr)));)+
};
}
pub const BEGIN: TransitionIdent = TransitionIdent::new(0);
define_transition_ident!(BEGIN, EASE, LINEAR, EASE_IN, EASE_OUT, EASE_IN_OUT, THEME_EXTEND);
pub const CUSTOM_START: TransitionIdent = TransitionIdent::new(65536);
}
impl TransitionTheme {
#[inline]
pub fn set_transition(
&mut self, ident: TransitionIdent, transition: Box<dyn RocBoxClone>,
) -> Option<Box<dyn RocBoxClone>> {
self.transitions.insert(ident, transition)
}
}
impl TransitionTheme {
#[inline]
pub fn of(ctx: &impl AsRef<ProviderCtx>) -> QueryRef<Self> {
Provider::of::<Self>(ctx).unwrap()
}
#[inline]
pub fn write_of(ctx: &impl AsRef<ProviderCtx>) -> WriteRef<Self> {
Provider::write_of::<Self>(ctx).unwrap()
}
}
impl TransitionIdent {
pub const fn new(idx: usize) -> Self { Self(idx) }
pub fn of(self, ctx: &impl AsRef<ProviderCtx>) -> Box<dyn Transition> {
let panic_msg = format!(
"Neither `Transition({:?})` nor `transitions::LINEAR` are initialized in all \
`TransitionTheme` instances.",
self
);
self
.find(ctx)
.or(transitions::LINEAR.find(ctx))
.expect(&panic_msg)
}
pub fn find(self, ctx: &impl AsRef<ProviderCtx>) -> Option<Box<dyn Transition>> {
Provider::of::<TransitionTheme>(ctx)
.and_then(|t| t.transitions.get(&self).map(|t| t.box_clone()))
}
}
impl Default for TransitionTheme {
fn default() -> Self {
let mut theme = Self { transitions: Default::default() };
fill_transition! { theme,
transitions::EASE: EasingTransition {
duration: Duration::from_millis(250),
easing: easing::EASE,
},
transitions::LINEAR: EasingTransition {
duration: Duration::from_millis(200),
easing: easing::LINEAR,
},
transitions::EASE_IN: EasingTransition {
duration: Duration::from_millis(250),
easing: easing::EASE_IN,
},
transitions::EASE_OUT: EasingTransition {
duration: Duration::from_millis(200),
easing: easing::EASE_OUT,
},
transitions::EASE_IN_OUT: EasingTransition {
duration: Duration::from_millis(250),
easing: easing::EASE_IN_OUT,
}
}
theme
}
}