macro_rules! with_animatable_props {
($cb:ident) => {
$cb! {
((P::TranslateX), Length, (transform translate_x), (none), Transform, Transform),
((P::TranslateY), Length, (transform translate_y), (none), Transform, Transform),
((P::Scale), Scalar, (transform scale), (none), Transform, Transform),
((P::ScaleX), Scalar, (transform scale_x), (none), Transform, Transform),
((P::ScaleY), Scalar, (transform scale_y), (none), Transform, Transform),
((P::Rotate), Angle, (transform rotate), (none), Transform, Transform),
((P::Opacity), Scalar, (base opacity), (none), Opacity, Opacity),
((P::BackgroundColor), Color, (base background_color), (color bg), Color, Background),
((P::BorderColor), Color, (base border_color), (color border), Color, None),
((P::Color), Color, (base color), (color text), Color, None),
((P::BackgroundImageTint), Color, (bg_tint), (color image_tint), Color, None),
((P::Width), Length, (base width), (node width), Node, None),
((P::Height), Length, (base height), (node height), Node, None),
((P::MinWidth), Length, (base min_width), (node min_width), Node, None),
((P::MinHeight), Length, (base min_height), (node min_height), Node, None),
((P::MaxWidth), Length, (base max_width), (node max_width), Node, None),
((P::MaxHeight), Length, (base max_height), (node max_height), Node, None),
((P::Left), Length, (base left), (node left), Node, None),
((P::Right), Length, (base right), (node right), Node, None),
((P::Top), Length, (base top), (node top), Node, None),
((P::Bottom), Length, (base bottom), (node bottom), Node, None),
((P::FlexBasis), Length, (base flex_basis), (node flex_basis), Node, None),
((P::Gap), Length, (base gap), (node_gap_both), Node, None),
((P::RowGap), Length, (base row_gap), (node row_gap), Node, None),
((P::ColumnGap), Length, (base column_gap), (node column_gap), Node, None),
((P::AspectRatio), Scalar, (base aspect_ratio), (node_aspect), Node, None),
((P::Transform3d(F::Perspective)), Length, (t3d perspective num 0.0), (none), Transform3d, Transform3d),
((P::Transform3d(F::TranslateX)), Length, (t3d translate_x num 0.0), (none), Transform3d, Transform3d),
((P::Transform3d(F::TranslateY)), Length, (t3d translate_y num 0.0), (none), Transform3d, Transform3d),
((P::Transform3d(F::TranslateZ)), Length, (t3d translate_z num 0.0), (none), Transform3d, Transform3d),
((P::Transform3d(F::RotateX)), Angle, (t3d rotate_x angle), (none), Transform3d, Transform3d),
((P::Transform3d(F::RotateY)), Angle, (t3d rotate_y angle), (none), Transform3d, Transform3d),
((P::Transform3d(F::RotateZ)), Angle, (t3d rotate_z angle), (none), Transform3d, Transform3d),
((P::Transform3d(F::Scale)), Scalar, (t3d scale num 1.0), (none), Transform3d, Transform3d),
((P::Transform3d(F::ScaleX)), Scalar, (t3d scale_x num 1.0), (none), Transform3d, Transform3d),
((P::Transform3d(F::ScaleY)), Scalar, (t3d scale_y num 1.0), (none), Transform3d, Transform3d),
((P::Transform3d(F::OriginX)), Length, (t3d_origin x), (none), Transform3d, Transform3d),
((P::Transform3d(F::OriginY)), Length, (t3d_origin y), (none), Transform3d, Transform3d),
}
};
}
pub(crate) use with_animatable_props;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum PropStage {
Transform,
Transform3d,
Opacity,
Node,
Color,
Filter,
Backdrop,
Shape,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum ChannelId {
Transform,
Opacity,
Background,
Filter,
Backdrop,
Transform3d,
}
impl super::protocol::AnimatableProperty {
#[allow(unused_parens)]
pub(crate) fn park(&self) -> Option<ChannelId> {
use super::protocol::{AnimatableProperty as P, Transform3dField as F};
macro_rules! park_of {
(None) => {
Option::<ChannelId>::None
};
($id:ident) => {
Some(ChannelId::$id)
};
}
macro_rules! park_arms {
($(($prop:tt, $kind:ident, $acc:tt, $write:tt, $stage:ident, $park:ident),)*) => {
match self {
$($prop => park_of!($park),)*
P::FilterParam { .. } => Some(ChannelId::Filter),
P::BackdropParam { .. } => Some(ChannelId::Backdrop),
P::ShapeAttr { .. } => None,
}
};
}
with_animatable_props!(park_arms)
}
#[allow(unused_parens)]
pub(crate) fn stage(&self) -> PropStage {
use super::protocol::{AnimatableProperty as P, Transform3dField as F};
macro_rules! stage_arms {
($(($prop:tt, $kind:ident, $acc:tt, $write:tt, $stage:ident, $park:ident),)*) => {
match self {
$($prop => PropStage::$stage,)*
P::FilterParam { .. } => PropStage::Filter,
P::BackdropParam { .. } => PropStage::Backdrop,
P::ShapeAttr { .. } => PropStage::Shape,
}
};
}
with_animatable_props!(stage_arms)
}
}
impl super::protocol::AnimatedBindings {
pub(crate) fn parked(&self, channel: ChannelId) -> bool {
self.0.keys().any(|p| p.park() == Some(channel))
}
}
#[cfg(test)]
mod tests {
use super::super::protocol::{AnimatableProperty as P, Transform3dField as F, ValueKind::*};
#[allow(dead_code, unused_parens)]
fn table_covers_every_variant(p: &P) {
macro_rules! check {
($(($prop:tt, $kind:ident, $acc:tt, $write:tt, $stage:ident, $park:ident),)*) => {
match p {
$($prop => {})*
P::FilterParam { .. } | P::BackdropParam { .. } | P::ShapeAttr { .. } => {}
}
};
}
with_animatable_props!(check);
}
#[test]
fn table_rows_are_in_enum_order() {
macro_rules! rows {
($(($prop:tt, $kind:ident, $acc:tt, $write:tt, $stage:ident, $park:ident),)*) => {
vec![$($prop),*]
};
}
let rows: Vec<P> = with_animatable_props!(rows);
assert_eq!(rows.len(), 38, "static row count");
for w in rows.windows(2) {
assert!(
w[0] < w[1],
"table rows out of enum order: {:?} listed before {:?}",
w[0],
w[1]
);
}
}
#[test]
fn kind_column_matches_value_kind() {
macro_rules! check_kinds {
($(($prop:tt, $kind:ident, $acc:tt, $write:tt, $stage:ident, $park:ident),)*) => {
$(assert_eq!(
($prop).value_kind(),
$kind,
"kind column disagrees for {:?}",
$prop
);)*
};
}
with_animatable_props!(check_kinds);
}
}