using System;
|
using System.Collections.Generic;
|
using System.Drawing;
|
using System.Windows.Forms;
|
using Timer = System.Windows.Forms.Timer;
|
|
namespace HotelPms.Share.Windows.Animations
|
{
|
class AnimationManager
|
{
|
public bool InterruptAnimation { get; set; }
|
public double Increment { get; set; }
|
public double SecondaryIncrement { get; set; }
|
public AnimationType AnimationType { get; set; }
|
public bool Singular { get; set; }
|
|
public delegate void AnimationFinished(object sender);
|
public event AnimationFinished OnAnimationFinished;
|
|
public delegate void AnimationProgress(object sender);
|
public event AnimationProgress OnAnimationProgress;
|
|
private readonly List<double> _animationProgresses;
|
private readonly List<Point> _animationSources;
|
private readonly List<AnimationDirection> _animationDirections;
|
private readonly List<object[]> _animationDatas;
|
|
private const double MIN_VALUE = 0.00;
|
private const double MAX_VALUE = 1.00;
|
|
private readonly Timer _animationTimer = new Timer { Interval = 5, Enabled = false };
|
|
/// <summary>
|
/// Constructor
|
/// </summary>
|
/// <param name="singular">If true, only one animation is supported. The current animation will be replaced with the new one. If false, a new animation is added to the list.</param>
|
public AnimationManager(bool singular = true)
|
{
|
_animationProgresses = new List<double>();
|
_animationSources = new List<Point>();
|
_animationDirections = new List<AnimationDirection>();
|
_animationDatas = new List<object[]>();
|
|
Increment = 0.03;
|
SecondaryIncrement = 0.03;
|
AnimationType = AnimationType.Linear;
|
InterruptAnimation = true;
|
Singular = singular;
|
|
if (Singular)
|
{
|
_animationProgresses.Add(0);
|
_animationSources.Add(new Point(0, 0));
|
_animationDirections.Add(AnimationDirection.In);
|
}
|
|
_animationTimer.Tick += AnimationTimerOnTick;
|
}
|
|
private void AnimationTimerOnTick(object sender, EventArgs eventArgs)
|
{
|
for (var i = 0; i < _animationProgresses.Count; i++)
|
{
|
UpdateProgress(i);
|
|
if (!Singular)
|
{
|
if ((_animationDirections[i] == AnimationDirection.InOutIn && _animationProgresses[i] == MAX_VALUE))
|
{
|
_animationDirections[i] = AnimationDirection.InOutOut;
|
}
|
else if ((_animationDirections[i] == AnimationDirection.InOutRepeatingIn && _animationProgresses[i] == MIN_VALUE))
|
{
|
_animationDirections[i] = AnimationDirection.InOutRepeatingOut;
|
}
|
else if ((_animationDirections[i] == AnimationDirection.InOutRepeatingOut && _animationProgresses[i] == MIN_VALUE))
|
{
|
_animationDirections[i] = AnimationDirection.InOutRepeatingIn;
|
}
|
else if (
|
(_animationDirections[i] == AnimationDirection.In && _animationProgresses[i] == MAX_VALUE) ||
|
(_animationDirections[i] == AnimationDirection.Out && _animationProgresses[i] == MIN_VALUE) ||
|
(_animationDirections[i] == AnimationDirection.InOutOut && _animationProgresses[i] == MIN_VALUE))
|
{
|
_animationProgresses.RemoveAt(i);
|
_animationSources.RemoveAt(i);
|
_animationDirections.RemoveAt(i);
|
_animationDatas.RemoveAt(i);
|
}
|
}
|
else
|
{
|
if ((_animationDirections[i] == AnimationDirection.InOutIn && _animationProgresses[i] == MAX_VALUE))
|
{
|
_animationDirections[i] = AnimationDirection.InOutOut;
|
}
|
else if ((_animationDirections[i] == AnimationDirection.InOutRepeatingIn && _animationProgresses[i] == MAX_VALUE))
|
{
|
_animationDirections[i] = AnimationDirection.InOutRepeatingOut;
|
}
|
else if ((_animationDirections[i] == AnimationDirection.InOutRepeatingOut && _animationProgresses[i] == MIN_VALUE))
|
{
|
_animationDirections[i] = AnimationDirection.InOutRepeatingIn;
|
}
|
}
|
}
|
|
OnAnimationProgress?.Invoke(this);
|
}
|
|
public bool IsAnimating()
|
{
|
return _animationTimer.Enabled;
|
}
|
|
public void StartNewAnimation(AnimationDirection animationDirection, object[] data = null)
|
{
|
StartNewAnimation(animationDirection, new Point(0, 0), data);
|
}
|
|
public void StartNewAnimation(AnimationDirection animationDirection, Point animationSource, object[] data = null)
|
{
|
if (!IsAnimating() || InterruptAnimation)
|
{
|
if (Singular && _animationDirections.Count > 0)
|
{
|
_animationDirections[0] = animationDirection;
|
}
|
else
|
{
|
_animationDirections.Add(animationDirection);
|
}
|
|
if (Singular && _animationSources.Count > 0)
|
{
|
_animationSources[0] = animationSource;
|
}
|
else
|
{
|
_animationSources.Add(animationSource);
|
}
|
|
if (!(Singular && _animationProgresses.Count > 0))
|
{
|
switch (_animationDirections[_animationDirections.Count - 1])
|
{
|
case AnimationDirection.InOutRepeatingIn:
|
case AnimationDirection.InOutIn:
|
case AnimationDirection.In:
|
_animationProgresses.Add(MIN_VALUE);
|
break;
|
case AnimationDirection.InOutRepeatingOut:
|
case AnimationDirection.InOutOut:
|
case AnimationDirection.Out:
|
_animationProgresses.Add(MAX_VALUE);
|
break;
|
default:
|
throw new Exception("Invalid AnimationDirection");
|
}
|
}
|
|
if (Singular && _animationDatas.Count > 0)
|
{
|
_animationDatas[0] = data ?? new object[] { };
|
}
|
else
|
{
|
_animationDatas.Add(data ?? new object[] { });
|
}
|
|
}
|
|
_animationTimer.Start();
|
}
|
|
public void UpdateProgress(int index)
|
{
|
switch (_animationDirections[index])
|
{
|
case AnimationDirection.InOutRepeatingIn:
|
case AnimationDirection.InOutIn:
|
case AnimationDirection.In:
|
IncrementProgress(index);
|
break;
|
case AnimationDirection.InOutRepeatingOut:
|
case AnimationDirection.InOutOut:
|
case AnimationDirection.Out:
|
DecrementProgress(index);
|
break;
|
default:
|
throw new Exception("No AnimationDirection has been set");
|
}
|
}
|
|
private void IncrementProgress(int index)
|
{
|
_animationProgresses[index] += Increment;
|
if (_animationProgresses[index] > MAX_VALUE)
|
{
|
_animationProgresses[index] = MAX_VALUE;
|
|
for (int i = 0; i < GetAnimationCount(); i++)
|
{
|
if (_animationDirections[i] == AnimationDirection.InOutIn) return;
|
if (_animationDirections[i] == AnimationDirection.InOutRepeatingIn) return;
|
if (_animationDirections[i] == AnimationDirection.InOutRepeatingOut) return;
|
if (_animationDirections[i] == AnimationDirection.InOutOut && _animationProgresses[i] != MAX_VALUE) return;
|
if (_animationDirections[i] == AnimationDirection.In && _animationProgresses[i] != MAX_VALUE) return;
|
}
|
|
_animationTimer.Stop();
|
OnAnimationFinished?.Invoke(this);
|
}
|
}
|
|
private void DecrementProgress(int index)
|
{
|
_animationProgresses[index] -= (_animationDirections[index] == AnimationDirection.InOutOut || _animationDirections[index] == AnimationDirection.InOutRepeatingOut) ? SecondaryIncrement : Increment;
|
if (_animationProgresses[index] < MIN_VALUE)
|
{
|
_animationProgresses[index] = MIN_VALUE;
|
|
for (var i = 0; i < GetAnimationCount(); i++)
|
{
|
if (_animationDirections[i] == AnimationDirection.InOutIn) return;
|
if (_animationDirections[i] == AnimationDirection.InOutRepeatingIn) return;
|
if (_animationDirections[i] == AnimationDirection.InOutRepeatingOut) return;
|
if (_animationDirections[i] == AnimationDirection.InOutOut && _animationProgresses[i] != MIN_VALUE) return;
|
if (_animationDirections[i] == AnimationDirection.Out && _animationProgresses[i] != MIN_VALUE) return;
|
}
|
|
_animationTimer.Stop();
|
OnAnimationFinished?.Invoke(this);
|
}
|
}
|
|
public double GetProgress()
|
{
|
if (!Singular)
|
throw new Exception("Animation is not set to Singular.");
|
|
if (_animationProgresses.Count == 0)
|
throw new Exception("Invalid animation");
|
|
return GetProgress(0);
|
}
|
|
public double GetProgress(int index)
|
{
|
if (!(index < GetAnimationCount()))
|
throw new IndexOutOfRangeException("Invalid animation index");
|
|
switch (AnimationType)
|
{
|
case AnimationType.Linear:
|
return AnimationLinear.CalculateProgress(_animationProgresses[index]);
|
case AnimationType.EaseInOut:
|
return AnimationEaseInOut.CalculateProgress(_animationProgresses[index]);
|
case AnimationType.EaseOut:
|
return AnimationEaseOut.CalculateProgress(_animationProgresses[index]);
|
case AnimationType.CustomQuadratic:
|
return AnimationCustomQuadratic.CalculateProgress(_animationProgresses[index]);
|
default:
|
throw new NotImplementedException("The given AnimationType is not implemented");
|
}
|
|
}
|
|
public Point GetSource(int index)
|
{
|
if (!(index < GetAnimationCount()))
|
throw new IndexOutOfRangeException("Invalid animation index");
|
|
return _animationSources[index];
|
}
|
|
public Point GetSource()
|
{
|
if (!Singular)
|
throw new Exception("Animation is not set to Singular.");
|
|
if (_animationSources.Count == 0)
|
throw new Exception("Invalid animation");
|
|
return _animationSources[0];
|
}
|
|
public AnimationDirection GetDirection()
|
{
|
if (!Singular)
|
throw new Exception("Animation is not set to Singular.");
|
|
if (_animationDirections.Count == 0)
|
throw new Exception("Invalid animation");
|
|
return _animationDirections[0];
|
}
|
|
public AnimationDirection GetDirection(int index)
|
{
|
if (!(index < _animationDirections.Count))
|
throw new IndexOutOfRangeException("Invalid animation index");
|
|
return _animationDirections[index];
|
}
|
|
public object[] GetData()
|
{
|
if (!Singular)
|
throw new Exception("Animation is not set to Singular.");
|
|
if (_animationDatas.Count == 0)
|
throw new Exception("Invalid animation");
|
|
return _animationDatas[0];
|
}
|
|
public object[] GetData(int index)
|
{
|
if (!(index < _animationDatas.Count))
|
throw new IndexOutOfRangeException("Invalid animation index");
|
|
return _animationDatas[index];
|
}
|
|
public int GetAnimationCount()
|
{
|
return _animationProgresses.Count;
|
}
|
|
public void SetProgress(double progress)
|
{
|
if (!Singular)
|
throw new Exception("Animation is not set to Singular.");
|
|
if (_animationProgresses.Count == 0)
|
throw new Exception("Invalid animation");
|
|
_animationProgresses[0] = progress;
|
}
|
|
public void SetDirection(AnimationDirection direction)
|
{
|
if (!Singular)
|
throw new Exception("Animation is not set to Singular.");
|
|
if (_animationProgresses.Count == 0)
|
throw new Exception("Invalid animation");
|
|
_animationDirections[0] = direction;
|
}
|
|
public void SetData(object[] data)
|
{
|
if (!Singular)
|
throw new Exception("Animation is not set to Singular.");
|
|
if (_animationDatas.Count == 0)
|
throw new Exception("Invalid animation");
|
|
_animationDatas[0] = data;
|
}
|
}
|
}
|