From 5f4d2efa6934d8a1379f1c9f8bfdb1d990872a20 Mon Sep 17 00:00:00 2001 From: Jumar Macato <16554748+jmacato@users.noreply.github.com> Date: Thu, 17 Jun 2021 15:44:50 +0800 Subject: [PATCH] Merge pull request #6082 from wieslawsoltes/feature/SetterAnimatorAttachedPropertyHack Allow setting custom Animator in property to Setter (attached property alternative) --- samples/RenderDemo/MainWindow.xaml | 3 ++ .../RenderDemo/Pages/CustomAnimatorPage.xaml | 25 ++++++++++++++++ .../Pages/CustomAnimatorPage.xaml.cs | 27 +++++++++++++++++ .../RenderDemo/Pages/CustomStringAnimator.cs | 16 ++++++++++ src/Avalonia.Animation/Animation.cs | 29 ++++++++++++++++++- 5 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 samples/RenderDemo/Pages/CustomAnimatorPage.xaml create mode 100644 samples/RenderDemo/Pages/CustomAnimatorPage.xaml.cs create mode 100644 samples/RenderDemo/Pages/CustomStringAnimator.cs diff --git a/samples/RenderDemo/MainWindow.xaml b/samples/RenderDemo/MainWindow.xaml index aa165d13f7..f37df56b73 100644 --- a/samples/RenderDemo/MainWindow.xaml +++ b/samples/RenderDemo/MainWindow.xaml @@ -36,6 +36,9 @@ + + + diff --git a/samples/RenderDemo/Pages/CustomAnimatorPage.xaml b/samples/RenderDemo/Pages/CustomAnimatorPage.xaml new file mode 100644 index 0000000000..b386636cae --- /dev/null +++ b/samples/RenderDemo/Pages/CustomAnimatorPage.xaml @@ -0,0 +1,25 @@ + + + + + + + + + diff --git a/samples/RenderDemo/Pages/CustomAnimatorPage.xaml.cs b/samples/RenderDemo/Pages/CustomAnimatorPage.xaml.cs new file mode 100644 index 0000000000..eed8ee29ce --- /dev/null +++ b/samples/RenderDemo/Pages/CustomAnimatorPage.xaml.cs @@ -0,0 +1,27 @@ +using System.Reactive.Linq; +using Avalonia; +using Avalonia.Animation; +using Avalonia.Controls; +using Avalonia.Controls.Shapes; +using Avalonia.Data; +using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.Markup.Xaml; +using Avalonia.Media; +using RenderDemo.ViewModels; + +namespace RenderDemo.Pages +{ + public class CustomAnimatorPage : UserControl + { + public CustomAnimatorPage() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/samples/RenderDemo/Pages/CustomStringAnimator.cs b/samples/RenderDemo/Pages/CustomStringAnimator.cs new file mode 100644 index 0000000000..851a2d0187 --- /dev/null +++ b/samples/RenderDemo/Pages/CustomStringAnimator.cs @@ -0,0 +1,16 @@ +using Avalonia.Animation.Animators; + +namespace RenderDemo.Pages +{ + public class CustomStringAnimator : Animator + { + public override string Interpolate(double progress, string oldValue, string newValue) + { + if (newValue.Length == 0) return ""; + var step = 1.0 / newValue.Length; + var length = (int)(progress / step); + var result = newValue.Substring(0, length + 1); + return result; + } + } +} diff --git a/src/Avalonia.Animation/Animation.cs b/src/Avalonia.Animation/Animation.cs index c42153ec4f..daa4793ef0 100644 --- a/src/Avalonia.Animation/Animation.cs +++ b/src/Avalonia.Animation/Animation.cs @@ -194,6 +194,33 @@ namespace Avalonia.Animation [Content] public KeyFrames Children { get; } = new KeyFrames(); + // Store values for the Animator attached properties for IAnimationSetter objects. + private static readonly Dictionary s_animators = new Dictionary(); + + /// + /// Gets the value of the Animator attached property for a setter. + /// + /// The animation setter. + /// The property animator type. + public static Type GetAnimator(IAnimationSetter setter) + { + if (s_animators.TryGetValue(setter, out var type)) + { + return type; + } + return null; + } + + /// + /// Sets the value of the Animator attached property for a setter. + /// + /// The animation setter. + /// The property animator value. + public static void SetAnimator(IAnimationSetter setter, Type value) + { + s_animators[setter] = value; + } + private readonly static List<(Func Condition, Type Animator)> Animators = new List<(Func, Type)> { ( prop => typeof(bool).IsAssignableFrom(prop.PropertyType), typeof(BoolAnimator) ), @@ -248,7 +275,7 @@ namespace Avalonia.Animation { foreach (var setter in keyframe.Setters) { - var handler = GetAnimatorType(setter.Property); + var handler = Animation.GetAnimator(setter) ?? GetAnimatorType(setter.Property); if (handler == null) {