using System;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;
using AntDesignWPF.Contracts;
namespace AntDesignWPF.Utils
{
///
/// Provides the ability to spin for controls.
/// Known defects:
/// Using trigger to change control RenderTransform property will result in animation lose.
/// Try adding the Spin property Setter after the RenderTransform property Setter for notification purposes.
/// Example: Theme/Switch.xaml
///
public static class Spinner
{
private const string storyBoardName = "AntDesignWPF.SpinnerStoryBoard";
///
/// Start the spinning animation.
///
public static void BeginSpin(this T control, double seconds) where T : FrameworkElement, ISpinable
{
var transform = control.RenderTransform;
control.SetCurrentValue(UIElement.RenderTransformOriginProperty, new Point(0.5, 0.5));
TransformGroup transformGroup;
if (transform is TransformGroup)
{
if (!(((TransformGroup)transform).Children.FirstOrDefault() is RotateTransform))
{
transformGroup = (TransformGroup)transform.Clone();
transformGroup.Children.Insert(0, new RotateTransform(0.0));
control.SetCurrentValue(UIElement.RenderTransformProperty, transformGroup);
}
}
else
{
transformGroup = new TransformGroup();
if (transform is RotateTransform)
{
transformGroup.Children.Add(transform);
}
else
{
transformGroup.Children.Add(new RotateTransform(0.0));
if (transform != null && transform != Transform.Identity)
{
transformGroup.Children.Add(transform);
}
}
control.SetCurrentValue(UIElement.RenderTransformProperty, transformGroup);
}
if (!(control.Resources[storyBoardName] is Storyboard storyboard))
{
storyboard = new Storyboard();
var animation = new DoubleAnimation
{
From = 0,
To = 360,
AutoReverse = false,
Duration = TimeSpan.FromSeconds(seconds),
RepeatBehavior = RepeatBehavior.Forever
};
Storyboard.SetTarget(animation, control);
Storyboard.SetTargetProperty(animation,
new PropertyPath("(0).(1)[0].(2)", UIElement.RenderTransformProperty,
TransformGroup.ChildrenProperty, RotateTransform.AngleProperty));
storyboard.Children.Add(animation);
control.Resources.Add(storyBoardName, storyboard);
}
storyboard.Begin();
}
///
/// Stop the spinning animation.
///
public static void StopSpin(this T control) where T : FrameworkElement, ISpinable
{
(control.Resources[storyBoardName] as Storyboard)?.Stop();
}
}
}