use super::{
AnimKey,
AnimLayer,
AnimProperty,
AnimValue,
AnimationManager,
Transition,
TransitionProperty,
};
use crate::{ Background, Color, Edges, Length, Style, WidgetId };
fn animate_length(
anim: &mut AnimationManager,
key: AnimKey,
transition: Option<Transition>,
value: Length,
animating: &mut bool
) -> Length {
let Length::Px(v) = value else {
return value;
};
anim.set_target(key, AnimValue([v, 0.0, 0.0, 0.0]), transition);
match anim.value(key) {
Some(r) => {
*animating = true;
Length::Px(r.0[0])
}
None => value,
}
}
fn animate_color(
anim: &mut AnimationManager,
key: AnimKey,
transition: Option<Transition>,
value: Color,
animating: &mut bool
) -> Color {
anim.set_color_target(key, AnimValue(value.to_f32_array()), transition);
match anim.value(key) {
Some(v) => {
*animating = true;
Color::rgba_f32(v.0[0], v.0[1], v.0[2], v.0[3])
}
None => value,
}
}
pub fn animate_computed_style(
widget_id: WidgetId,
style: &mut Style,
anim: &mut AnimationManager
) -> bool {
let Some(properties) = style.transition_properties else {
return false;
};
if properties.is_none() {
return false;
}
let default_transition = style.transition;
let overrides = style.transition_overrides;
let mut animating = false;
let key = |property: AnimProperty| AnimKey {
widget: widget_id,
layer: AnimLayer::Root,
property,
};
if properties.contains(TransitionProperty::COLORS) {
let transition = overrides.colors.or(default_transition);
if let Some(color) = style.color {
style.color = Some(
animate_color(anim, key(AnimProperty::TextColor), transition, color, &mut animating)
);
}
if let Some(Background::Color(color)) = &style.background {
let color = *color;
let animated = animate_color(
anim,
key(AnimProperty::BackgroundColor),
transition,
color,
&mut animating
);
style.background = Some(Background::Color(animated));
}
if let Some(mut border) = style.border {
border.color = animate_color(
anim,
key(AnimProperty::BorderColor),
transition,
border.color,
&mut animating
);
style.border = Some(border);
}
}
if properties.contains(TransitionProperty::TRANSFORM) {
let transition = overrides.transform.or(default_transition);
let scale_target = style.scale.unwrap_or(1.0);
let content_scale_target = style.content_scale.unwrap_or(scale_target);
let k = key(AnimProperty::Scale);
anim.set_target(k, AnimValue([scale_target, 0.0, 0.0, 0.0]), transition);
let resolved_scale = anim.value(k).map_or(scale_target, |v| {
animating = true;
v.0[0]
});
style.scale = Some(resolved_scale);
let k = key(AnimProperty::ContentScale);
anim.set_target(k, AnimValue([content_scale_target, 0.0, 0.0, 0.0]), transition);
let resolved_content_scale = anim.value(k).map_or(content_scale_target, |v| {
animating = true;
v.0[0]
});
style.content_scale = Some(resolved_content_scale);
}
if properties.contains(TransitionProperty::BOX) {
let transition = overrides.box_model.or(default_transition);
if let Some(mut size) = style.size {
if let Some(w) = size.width {
size.width = Some(
animate_length(anim, key(AnimProperty::Width), transition, w, &mut animating)
);
}
if let Some(h) = size.height {
size.height = Some(
animate_length(anim, key(AnimProperty::Height), transition, h, &mut animating)
);
}
style.size = Some(size);
}
if let Some(padding) = style.padding {
style.padding = Some(Edges {
left: animate_length(
anim,
key(AnimProperty::PaddingLeft),
transition,
padding.left,
&mut animating
),
top: animate_length(
anim,
key(AnimProperty::PaddingTop),
transition,
padding.top,
&mut animating
),
right: animate_length(
anim,
key(AnimProperty::PaddingRight),
transition,
padding.right,
&mut animating
),
bottom: animate_length(
anim,
key(AnimProperty::PaddingBottom),
transition,
padding.bottom,
&mut animating
),
});
}
if let Some(margin) = style.margin {
style.margin = Some(Edges {
left: animate_length(
anim,
key(AnimProperty::MarginLeft),
transition,
margin.left,
&mut animating
),
top: animate_length(
anim,
key(AnimProperty::MarginTop),
transition,
margin.top,
&mut animating
),
right: animate_length(
anim,
key(AnimProperty::MarginRight),
transition,
margin.right,
&mut animating
),
bottom: animate_length(
anim,
key(AnimProperty::MarginBottom),
transition,
margin.bottom,
&mut animating
),
});
}
if let Some(mut border) = style.border {
border.top = animate_length(
anim,
key(AnimProperty::BorderWidth),
transition,
border.top,
&mut animating
);
border.right = animate_length(
anim,
key(AnimProperty::BorderWidth),
transition,
border.right,
&mut animating
);
border.bottom = animate_length(
anim,
key(AnimProperty::BorderWidth),
transition,
border.bottom,
&mut animating
);
border.left = animate_length(
anim,
key(AnimProperty::BorderWidth),
transition,
border.left,
&mut animating
);
if let Some(radius) = border.radius {
border.radius = Some(
animate_length(
anim,
key(AnimProperty::BorderRadius),
transition,
radius,
&mut animating
)
);
}
style.border = Some(border);
}
if let Some((gx, gy)) = style.gap {
style.gap = Some((
animate_length(anim, key(AnimProperty::GapX), transition, gx, &mut animating),
animate_length(anim, key(AnimProperty::GapY), transition, gy, &mut animating),
));
}
}
animating
}