Introduce #[animation]

For now, only #[animation(error)] is supported on variants and it makes
both #[derive(Animate)] and #[derive(ComputeSquaredDistance)] ignore
this particular variant.
This commit is contained in:
Anthony Ramine 2017-08-24 01:25:57 +02:00
parent 17d97cf87b
commit ff67fc751d
5 changed files with 31 additions and 45 deletions

View file

@ -787,40 +787,6 @@ impl ToAnimatedZero for Visibility {
} }
} }
/// https://drafts.csswg.org/css-transitions/#animtype-length
impl Animate for VerticalAlign {
#[inline]
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
match (self, other) {
(
&VerticalAlign::LengthOrPercentage(ref this),
&VerticalAlign::LengthOrPercentage(ref other),
) => {
Ok(VerticalAlign::LengthOrPercentage(
this.animate(other, procedure)?
))
},
_ => Err(()),
}
}
}
impl ComputeSquaredDistance for VerticalAlign {
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
match (self, other) {
(&VerticalAlign::LengthOrPercentage(ref this), &VerticalAlign::LengthOrPercentage(ref other)) => {
this.compute_squared_distance(other)
},
_ => {
// FIXME(nox): Should this return `Ok(SquaredDistance::Value(0.))`
// if `self` and `other` are the same keyword value?
Err(())
},
}
}
}
impl ToAnimatedZero for VerticalAlign { impl ToAnimatedZero for VerticalAlign {
#[inline] #[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) } fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }

View file

@ -370,10 +370,11 @@ ${helpers.single_keyword("position", "static absolute relative fixed",
/// The keywords are the same, and the `LengthOrPercentage` is computed /// The keywords are the same, and the `LengthOrPercentage` is computed
/// here. /// here.
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq)]
pub enum T { pub enum T {
% for keyword in vertical_align_keywords: % for keyword in vertical_align_keywords:
#[animation(error)] // only animatable as a length
${to_rust_ident(keyword)}, ${to_rust_ident(keyword)},
% endfor % endfor
LengthOrPercentage(computed::LengthOrPercentage), LengthOrPercentage(computed::LengthOrPercentage),

View file

@ -14,7 +14,13 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
let variants = cg::variants(&input); let variants = cg::variants(&input);
let mut match_body = quote!(); let mut match_body = quote!();
match_body.append_all(variants.iter().map(|variant| { let mut append_error_clause = variants.len() > 1;
match_body.append_all(variants.iter().flat_map(|variant| {
let attrs = cg::parse_variant_attrs::<AnimateAttrs>(variant);
if attrs.error {
append_error_clause = true;
return None;
}
let name = cg::variant_ctor(&input, variant); let name = cg::variant_ctor(&input, variant);
let (this_pattern, this_info) = cg::ref_pattern(&name, variant, "this"); let (this_pattern, this_info) = cg::ref_pattern(&name, variant, "this");
let (other_pattern, other_info) = cg::ref_pattern(&name, variant, "other"); let (other_pattern, other_info) = cg::ref_pattern(&name, variant, "other");
@ -29,15 +35,15 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
let #result = ::values::animated::Animate::animate(#this, #other, procedure)?; let #result = ::values::animated::Animate::animate(#this, #other, procedure)?;
} }
})); }));
quote! { Some(quote! {
(&#this_pattern, &#other_pattern) => { (&#this_pattern, &#other_pattern) => {
#computations #computations
Ok(#result_value) Ok(#result_value)
} }
} })
})); }));
if variants.len() > 1 { if append_error_clause {
match_body = quote! { #match_body, _ => Err(()), }; match_body = quote! { #match_body, _ => Err(()), };
} }
@ -57,3 +63,9 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
} }
} }
} }
#[derive(Default, FromVariant)]
#[darling(attributes(animate), default)]
pub struct AnimateAttrs {
pub error: bool,
}

View file

@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use animate::AnimateAttrs;
use cg; use cg;
use quote; use quote;
use syn; use syn;
@ -14,7 +15,13 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
let variants = cg::variants(&input); let variants = cg::variants(&input);
let mut match_body = quote!(); let mut match_body = quote!();
let mut append_error_clause = variants.len() > 1;
match_body.append_all(variants.iter().map(|variant| { match_body.append_all(variants.iter().map(|variant| {
let attrs = cg::parse_variant_attrs::<AnimateAttrs>(variant);
if attrs.error {
append_error_clause = true;
return None;
}
let name = cg::variant_ctor(&input, variant); let name = cg::variant_ctor(&input, variant);
let (this_pattern, this_info) = cg::ref_pattern(&name, &variant, "this"); let (this_pattern, this_info) = cg::ref_pattern(&name, &variant, "this");
let (other_pattern, other_info) = cg::ref_pattern(&name, &variant, "other"); let (other_pattern, other_info) = cg::ref_pattern(&name, &variant, "other");
@ -32,14 +39,14 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
}), "+"); }), "+");
sum sum
}; };
quote! { Some(quote! {
(&#this_pattern, &#other_pattern) => { (&#this_pattern, &#other_pattern) => {
Ok(#sum) Ok(#sum)
} }
} })
})); }));
if variants.len() > 1 { if append_error_clause {
match_body = quote! { #match_body, _ => Err(()), }; match_body = quote! { #match_body, _ => Err(()), };
} }

View file

@ -19,13 +19,13 @@ mod to_animated_zero;
mod to_computed_value; mod to_computed_value;
mod to_css; mod to_css;
#[proc_macro_derive(Animate)] #[proc_macro_derive(Animate, attributes(animation))]
pub fn derive_animate(stream: TokenStream) -> TokenStream { pub fn derive_animate(stream: TokenStream) -> TokenStream {
let input = syn::parse_derive_input(&stream.to_string()).unwrap(); let input = syn::parse_derive_input(&stream.to_string()).unwrap();
animate::derive(input).to_string().parse().unwrap() animate::derive(input).to_string().parse().unwrap()
} }
#[proc_macro_derive(ComputeSquaredDistance)] #[proc_macro_derive(ComputeSquaredDistance, attributes(animation))]
pub fn derive_compute_squared_distance(stream: TokenStream) -> TokenStream { pub fn derive_compute_squared_distance(stream: TokenStream) -> TokenStream {
let input = syn::parse_derive_input(&stream.to_string()).unwrap(); let input = syn::parse_derive_input(&stream.to_string()).unwrap();
compute_squared_distance::derive(input).to_string().parse().unwrap() compute_squared_distance::derive(input).to_string().parse().unwrap()