chore: use file-scoped namespace

This commit is contained in:
NaBian committed 2022-03-13 20:28:58 +08:00
1 parent 99d2fafb72
commit bbf1b7d4c6
748 files changed
+57929 -58678

No files matched your search

@@ -2,24 +2,23 @@
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace HandyControl.Media.Animation
namespace HandyControl.Media.Animation;
public class DiscreteGeometryKeyFrame : GeometryKeyFrame
{
public class DiscreteGeometryKeyFrame : GeometryKeyFrame
public DiscreteGeometryKeyFrame()
{
public DiscreteGeometryKeyFrame()
{
}
public DiscreteGeometryKeyFrame(Geometry value) : base(value)
{
}
public DiscreteGeometryKeyFrame(Geometry value, KeyTime keyTime) : base(value, keyTime)
{
}
protected override Freezable CreateInstanceCore() => new DiscreteGeometryKeyFrame();
protected override double[] InterpolateValueCore(double[] baseValue, double keyFrameProgress) => keyFrameProgress < 1.0 ? baseValue : Numbers;
}
}
public DiscreteGeometryKeyFrame(Geometry value) : base(value)
{
}
public DiscreteGeometryKeyFrame(Geometry value, KeyTime keyTime) : base(value, keyTime)
{
}
protected override Freezable CreateInstanceCore() => new DiscreteGeometryKeyFrame();
protected override double[] InterpolateValueCore(double[] baseValue, double keyFrameProgress) => keyFrameProgress < 1.0 ? baseValue : Numbers;
}
@@ -4,60 +4,59 @@ using System.Windows.Media.Animation;
using HandyControl.Expression.Drawing;
using HandyControl.Tools;
namespace HandyControl.Media.Animation
namespace HandyControl.Media.Animation;
public class EasingGeometryKeyFrame : GeometryKeyFrame
{
public class EasingGeometryKeyFrame : GeometryKeyFrame
public EasingGeometryKeyFrame()
{
public EasingGeometryKeyFrame()
{
}
public EasingGeometryKeyFrame(Geometry value) : base(value)
{
}
public EasingGeometryKeyFrame(Geometry value, KeyTime keyTime) : base(value, keyTime)
{
}
public EasingGeometryKeyFrame(Geometry value, KeyTime keyTime, IEasingFunction easingFunction) : base(value, keyTime)
{
EasingFunction = easingFunction;
}
protected override Freezable CreateInstanceCore() => new EasingGeometryKeyFrame();
protected override double[] InterpolateValueCore(double[] baseValue, double keyFrameProgress)
{
var easingFunction = EasingFunction;
if (easingFunction != null)
{
keyFrameProgress = easingFunction.Ease(keyFrameProgress);
}
if (MathHelper.IsVerySmall(keyFrameProgress))
{
return baseValue;
}
if (MathHelper.AreClose(keyFrameProgress, 1))
{
return Numbers;
}
return AnimationHelper.InterpolateGeometryValue(baseValue, Numbers, keyFrameProgress);
}
public static readonly DependencyProperty EasingFunctionProperty = DependencyProperty.Register(
"EasingFunction", typeof(IEasingFunction), typeof(EasingGeometryKeyFrame), new PropertyMetadata(default(IEasingFunction)));
public IEasingFunction EasingFunction
{
get => (IEasingFunction) GetValue(EasingFunctionProperty);
set => SetValue(EasingFunctionProperty, value);
}
}
}
public EasingGeometryKeyFrame(Geometry value) : base(value)
{
}
public EasingGeometryKeyFrame(Geometry value, KeyTime keyTime) : base(value, keyTime)
{
}
public EasingGeometryKeyFrame(Geometry value, KeyTime keyTime, IEasingFunction easingFunction) : base(value, keyTime)
{
EasingFunction = easingFunction;
}
protected override Freezable CreateInstanceCore() => new EasingGeometryKeyFrame();
protected override double[] InterpolateValueCore(double[] baseValue, double keyFrameProgress)
{
var easingFunction = EasingFunction;
if (easingFunction != null)
{
keyFrameProgress = easingFunction.Ease(keyFrameProgress);
}
if (MathHelper.IsVerySmall(keyFrameProgress))
{
return baseValue;
}
if (MathHelper.AreClose(keyFrameProgress, 1))
{
return Numbers;
}
return AnimationHelper.InterpolateGeometryValue(baseValue, Numbers, keyFrameProgress);
}
public static readonly DependencyProperty EasingFunctionProperty = DependencyProperty.Register(
"EasingFunction", typeof(IEasingFunction), typeof(EasingGeometryKeyFrame), new PropertyMetadata(default(IEasingFunction)));
public IEasingFunction EasingFunction
{
get => (IEasingFunction) GetValue(EasingFunctionProperty);
set => SetValue(EasingFunctionProperty, value);
}
}
@@ -7,174 +7,173 @@ using HandyControl.Data;
using HandyControl.Tools;
// ReSharper disable PossibleInvalidOperationException
namespace HandyControl.Media.Animation
namespace HandyControl.Media.Animation;
public class GeometryAnimation : GeometryAnimationBase
{
public class GeometryAnimation : GeometryAnimationBase
private string[] _strings;
private double[] _numbersFrom;
private double[] _numbersTo;
private double[] _numbersAccumulator;
public GeometryAnimation()
{
private string[] _strings;
private double[] _numbersFrom;
}
private double[] _numbersTo;
public GeometryAnimation(string fromValue, string toValue) : this()
{
From = Geometry.Parse(fromValue);
To = Geometry.Parse(toValue);
}
private double[] _numbersAccumulator;
private void UpdateValue()
{
if (_numbersFrom == null || _numbersTo == null || _numbersFrom.Length != _numbersTo.Length) return;
public GeometryAnimation()
_numbersAccumulator = new double[_numbersFrom.Length];
for (var i = 0; i < _numbersFrom.Length; i++)
{
}
public GeometryAnimation(string fromValue, string toValue) : this()
{
From = Geometry.Parse(fromValue);
To = Geometry.Parse(toValue);
}
private void UpdateValue()
{
if (_numbersFrom == null || _numbersTo == null || _numbersFrom.Length != _numbersTo.Length) return;
_numbersAccumulator = new double[_numbersFrom.Length];
for (var i = 0; i < _numbersFrom.Length; i++)
{
_numbersAccumulator[i] = _numbersTo[i] - _numbersFrom[i];
}
}
public GeometryAnimation(Geometry fromValue, Geometry toValue) : this()
{
From = fromValue;
To = toValue;
}
public GeometryAnimation(Geometry fromValue, Geometry toValue, Duration duration) : this()
{
From = fromValue;
To = toValue;
Duration = duration;
}
public GeometryAnimation(Geometry fromValue, Geometry toValue, Duration duration, FillBehavior fillBehavior) : this()
{
From = fromValue;
To = toValue;
Duration = duration;
FillBehavior = fillBehavior;
}
public new GeometryAnimation Clone() => (GeometryAnimation) base.Clone();
protected override Freezable CreateInstanceCore() => new GeometryAnimation();
protected override Geometry GetCurrentValueCore(Geometry defaultOriginValue, Geometry defaultDestinationValue, AnimationClock animationClock)
{
if (_numbersAccumulator == null)
{
if (_numbersFrom == null)
{
var geometryStr = defaultOriginValue.ToString(CultureInfo.InvariantCulture);
AnimationHelper.DecomposeGeometryStr(geometryStr, out _numbersFrom);
}
if (_numbersTo == null)
{
var geometryStr = defaultDestinationValue.ToString(CultureInfo.InvariantCulture);
AnimationHelper.DecomposeGeometryStr(geometryStr, out _numbersTo);
_strings = Regex.Split(geometryStr, RegexPatterns.DigitsPattern);
}
UpdateValue();
}
if (_numbersAccumulator == null) return defaultOriginValue;
var progress = animationClock.CurrentProgress.Value;
var easingFunction = EasingFunction;
if (easingFunction != null)
{
progress = easingFunction.Ease(progress);
}
var accumulated = new double[_numbersAccumulator.Length];
if (IsCumulative)
{
var currentRepeat = (double) (animationClock.CurrentIteration - 1);
if (currentRepeat > 0.0)
{
accumulated = new double[_numbersAccumulator.Length];
for (var i = 0; i < _numbersAccumulator.Length; i++)
{
accumulated[i] = _numbersAccumulator[i] * currentRepeat;
}
}
}
var numbers = new double[_numbersAccumulator.Length];
for (var i = 0; i < _numbersAccumulator.Length; i++)
{
numbers[i] = accumulated[i] + _numbersFrom[i] + _numbersAccumulator[i] * progress;
}
return AnimationHelper.ComposeGeometry(_strings, numbers);
}
public static readonly DependencyProperty FromProperty = DependencyProperty.Register(
"From", typeof(Geometry), typeof(GeometryAnimation), new PropertyMetadata(default(Geometry), OnFromChanged));
private static void OnFromChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var obj = (GeometryAnimation) d;
if (e.NewValue is Geometry geometry)
{
AnimationHelper.DecomposeGeometryStr(geometry.ToString(CultureInfo.InvariantCulture), out obj._numbersFrom);
obj.UpdateValue();
}
}
public Geometry From
{
get => (Geometry) GetValue(FromProperty);
set => SetValue(FromProperty, value);
}
public static readonly DependencyProperty ToProperty = DependencyProperty.Register(
"To", typeof(Geometry), typeof(GeometryAnimation), new PropertyMetadata(default(Geometry), OnToChanged));
private static void OnToChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var obj = (GeometryAnimation) d;
if (e.NewValue is Geometry geometry)
{
var geometryStr = geometry.ToString(CultureInfo.InvariantCulture);
AnimationHelper.DecomposeGeometryStr(geometryStr, out obj._numbersTo);
obj._strings = Regex.Split(geometryStr, RegexPatterns.DigitsPattern);
obj.UpdateValue();
}
}
public Geometry To
{
get => (Geometry) GetValue(ToProperty);
set => SetValue(ToProperty, value);
}
public static readonly DependencyProperty EasingFunctionProperty = DependencyProperty.Register(
"EasingFunction", typeof(IEasingFunction), typeof(GeometryAnimation), new PropertyMetadata(default(IEasingFunction)));
public IEasingFunction EasingFunction
{
get => (IEasingFunction) GetValue(EasingFunctionProperty);
set => SetValue(EasingFunctionProperty, value);
}
public bool IsCumulative
{
get => (bool) GetValue(IsCumulativeProperty);
set => SetValue(IsCumulativeProperty, ValueBoxes.BooleanBox(value));
_numbersAccumulator[i] = _numbersTo[i] - _numbersFrom[i];
}
}
}
public GeometryAnimation(Geometry fromValue, Geometry toValue) : this()
{
From = fromValue;
To = toValue;
}
public GeometryAnimation(Geometry fromValue, Geometry toValue, Duration duration) : this()
{
From = fromValue;
To = toValue;
Duration = duration;
}
public GeometryAnimation(Geometry fromValue, Geometry toValue, Duration duration, FillBehavior fillBehavior) : this()
{
From = fromValue;
To = toValue;
Duration = duration;
FillBehavior = fillBehavior;
}
public new GeometryAnimation Clone() => (GeometryAnimation) base.Clone();
protected override Freezable CreateInstanceCore() => new GeometryAnimation();
protected override Geometry GetCurrentValueCore(Geometry defaultOriginValue, Geometry defaultDestinationValue, AnimationClock animationClock)
{
if (_numbersAccumulator == null)
{
if (_numbersFrom == null)
{
var geometryStr = defaultOriginValue.ToString(CultureInfo.InvariantCulture);
AnimationHelper.DecomposeGeometryStr(geometryStr, out _numbersFrom);
}
if (_numbersTo == null)
{
var geometryStr = defaultDestinationValue.ToString(CultureInfo.InvariantCulture);
AnimationHelper.DecomposeGeometryStr(geometryStr, out _numbersTo);
_strings = Regex.Split(geometryStr, RegexPatterns.DigitsPattern);
}
UpdateValue();
}
if (_numbersAccumulator == null) return defaultOriginValue;
var progress = animationClock.CurrentProgress.Value;
var easingFunction = EasingFunction;
if (easingFunction != null)
{
progress = easingFunction.Ease(progress);
}
var accumulated = new double[_numbersAccumulator.Length];
if (IsCumulative)
{
var currentRepeat = (double) (animationClock.CurrentIteration - 1);
if (currentRepeat > 0.0)
{
accumulated = new double[_numbersAccumulator.Length];
for (var i = 0; i < _numbersAccumulator.Length; i++)
{
accumulated[i] = _numbersAccumulator[i] * currentRepeat;
}
}
}
var numbers = new double[_numbersAccumulator.Length];
for (var i = 0; i < _numbersAccumulator.Length; i++)
{
numbers[i] = accumulated[i] + _numbersFrom[i] + _numbersAccumulator[i] * progress;
}
return AnimationHelper.ComposeGeometry(_strings, numbers);
}
public static readonly DependencyProperty FromProperty = DependencyProperty.Register(
"From", typeof(Geometry), typeof(GeometryAnimation), new PropertyMetadata(default(Geometry), OnFromChanged));
private static void OnFromChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var obj = (GeometryAnimation) d;
if (e.NewValue is Geometry geometry)
{
AnimationHelper.DecomposeGeometryStr(geometry.ToString(CultureInfo.InvariantCulture), out obj._numbersFrom);
obj.UpdateValue();
}
}
public Geometry From
{
get => (Geometry) GetValue(FromProperty);
set => SetValue(FromProperty, value);
}
public static readonly DependencyProperty ToProperty = DependencyProperty.Register(
"To", typeof(Geometry), typeof(GeometryAnimation), new PropertyMetadata(default(Geometry), OnToChanged));
private static void OnToChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var obj = (GeometryAnimation) d;
if (e.NewValue is Geometry geometry)
{
var geometryStr = geometry.ToString(CultureInfo.InvariantCulture);
AnimationHelper.DecomposeGeometryStr(geometryStr, out obj._numbersTo);
obj._strings = Regex.Split(geometryStr, RegexPatterns.DigitsPattern);
obj.UpdateValue();
}
}
public Geometry To
{
get => (Geometry) GetValue(ToProperty);
set => SetValue(ToProperty, value);
}
public static readonly DependencyProperty EasingFunctionProperty = DependencyProperty.Register(
"EasingFunction", typeof(IEasingFunction), typeof(GeometryAnimation), new PropertyMetadata(default(IEasingFunction)));
public IEasingFunction EasingFunction
{
get => (IEasingFunction) GetValue(EasingFunctionProperty);
set => SetValue(EasingFunctionProperty, value);
}
public bool IsCumulative
{
get => (bool) GetValue(IsCumulativeProperty);
set => SetValue(IsCumulativeProperty, ValueBoxes.BooleanBox(value));
}
}
@@ -4,57 +4,56 @@ using System.Threading;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace HandyControl.Media.Animation
namespace HandyControl.Media.Animation;
public abstract class GeometryAnimationBase : AnimationTimeline
{
public abstract class GeometryAnimationBase : AnimationTimeline
protected GeometryAnimationBase()
{
protected GeometryAnimationBase()
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
}
public new GeometryAnimationBase Clone() => (GeometryAnimationBase) base.Clone();
public sealed override object GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock)
{
if (defaultOriginValue == null)
{
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
throw new ArgumentNullException(nameof(defaultOriginValue));
}
public new GeometryAnimationBase Clone() => (GeometryAnimationBase) base.Clone();
public sealed override object GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock)
if (defaultDestinationValue == null)
{
if (defaultOriginValue == null)
{
throw new ArgumentNullException(nameof(defaultOriginValue));
}
if (defaultDestinationValue == null)
{
throw new ArgumentNullException(nameof(defaultDestinationValue));
}
return GetCurrentValue((Geometry) defaultOriginValue, (Geometry) defaultDestinationValue, animationClock);
throw new ArgumentNullException(nameof(defaultDestinationValue));
}
return GetCurrentValue((Geometry) defaultOriginValue, (Geometry) defaultDestinationValue, animationClock);
}
public override Type TargetPropertyType
{
get
{
ReadPreamble();
return typeof(Geometry);
}
}
public Geometry GetCurrentValue(Geometry defaultOriginValue, Geometry defaultDestinationValue, AnimationClock animationClock)
public override Type TargetPropertyType
{
get
{
ReadPreamble();
if (animationClock == null)
{
throw new ArgumentNullException(nameof(animationClock));
}
return typeof(Geometry);
}
}
if (animationClock.CurrentState == ClockState.Stopped)
{
return defaultDestinationValue;
}
public Geometry GetCurrentValue(Geometry defaultOriginValue, Geometry defaultDestinationValue, AnimationClock animationClock)
{
ReadPreamble();
return GetCurrentValueCore(defaultOriginValue, defaultDestinationValue, animationClock);
if (animationClock == null)
{
throw new ArgumentNullException(nameof(animationClock));
}
protected abstract Geometry GetCurrentValueCore(Geometry defaultOriginValue, Geometry defaultDestinationValue, AnimationClock animationClock);
if (animationClock.CurrentState == ClockState.Stopped)
{
return defaultDestinationValue;
}
return GetCurrentValueCore(defaultOriginValue, defaultDestinationValue, animationClock);
}
}
protected abstract Geometry GetCurrentValueCore(Geometry defaultOriginValue, Geometry defaultDestinationValue, AnimationClock animationClock);
}
@@ -11,511 +11,510 @@ using System.Windows.Media.Animation;
using HandyControl.Tools;
// ReSharper disable PossibleInvalidOperationException
namespace HandyControl.Media.Animation
namespace HandyControl.Media.Animation;
[ContentProperty("KeyFrames")]
public class GeometryAnimationUsingKeyFrames : GeometryAnimationBase, IKeyFrameAnimation, IAddChild
{
[ContentProperty("KeyFrames")]
public class GeometryAnimationUsingKeyFrames : GeometryAnimationBase, IKeyFrameAnimation, IAddChild
private string[] _strings;
public string[] Strings
{
private string[] _strings;
public string[] Strings
get
{
get
if (_keyFrames == null || _keyFrames.Count == 0)
{
if (_keyFrames == null || _keyFrames.Count == 0)
{
return null;
}
return _strings ??= Regex.Split(_keyFrames[0].Value.ToString(CultureInfo.InvariantCulture), RegexPatterns.DigitsPattern);
}
}
private GeometryKeyFrameCollection _keyFrames;
private ResolvedKeyFrameEntry[] _sortedResolvedKeyFrames;
private bool _areKeyTimesValid;
public GeometryAnimationUsingKeyFrames()
{
_areKeyTimesValid = true;
}
public new GeometryAnimationUsingKeyFrames Clone() => (GeometryAnimationUsingKeyFrames) base.Clone();
public new GeometryAnimationUsingKeyFrames CloneCurrentValue() => (GeometryAnimationUsingKeyFrames) base.CloneCurrentValue();
protected override bool FreezeCore(bool isChecking)
{
var canFreeze = base.FreezeCore(isChecking);
canFreeze &= Freeze(_keyFrames, isChecking);
if (canFreeze & !_areKeyTimesValid)
{
ResolveKeyTimes();
return null;
}
return canFreeze;
return _strings ??= Regex.Split(_keyFrames[0].Value.ToString(CultureInfo.InvariantCulture), RegexPatterns.DigitsPattern);
}
}
private GeometryKeyFrameCollection _keyFrames;
private ResolvedKeyFrameEntry[] _sortedResolvedKeyFrames;
private bool _areKeyTimesValid;
public GeometryAnimationUsingKeyFrames()
{
_areKeyTimesValid = true;
}
public new GeometryAnimationUsingKeyFrames Clone() => (GeometryAnimationUsingKeyFrames) base.Clone();
public new GeometryAnimationUsingKeyFrames CloneCurrentValue() => (GeometryAnimationUsingKeyFrames) base.CloneCurrentValue();
protected override bool FreezeCore(bool isChecking)
{
var canFreeze = base.FreezeCore(isChecking);
canFreeze &= Freeze(_keyFrames, isChecking);
if (canFreeze & !_areKeyTimesValid)
{
ResolveKeyTimes();
}
protected override void OnChanged()
{
_areKeyTimesValid = false;
return canFreeze;
}
base.OnChanged();
protected override void OnChanged()
{
_areKeyTimesValid = false;
base.OnChanged();
}
protected override Freezable CreateInstanceCore() => new GeometryAnimationUsingKeyFrames();
protected override void CloneCore(Freezable sourceFreezable)
{
var sourceAnimation = (GeometryAnimationUsingKeyFrames) sourceFreezable;
base.CloneCore(sourceFreezable);
CopyCommon(sourceAnimation, false);
}
protected override void CloneCurrentValueCore(Freezable sourceFreezable)
{
var sourceAnimation = (GeometryAnimationUsingKeyFrames) sourceFreezable;
base.CloneCurrentValueCore(sourceFreezable);
CopyCommon(sourceAnimation, true);
}
protected override void GetAsFrozenCore(Freezable source)
{
var sourceAnimation = (GeometryAnimationUsingKeyFrames) source;
base.GetAsFrozenCore(source);
CopyCommon(sourceAnimation, false);
}
protected override void GetCurrentValueAsFrozenCore(Freezable source)
{
var sourceAnimation = (GeometryAnimationUsingKeyFrames) source;
base.GetCurrentValueAsFrozenCore(source);
CopyCommon(sourceAnimation, true);
}
private void CopyCommon(GeometryAnimationUsingKeyFrames sourceAnimation, bool isCurrentValueClone)
{
_areKeyTimesValid = sourceAnimation._areKeyTimesValid;
if (_areKeyTimesValid && sourceAnimation._sortedResolvedKeyFrames != null)
{
_sortedResolvedKeyFrames = (ResolvedKeyFrameEntry[]) sourceAnimation._sortedResolvedKeyFrames.Clone();
}
protected override Freezable CreateInstanceCore() => new GeometryAnimationUsingKeyFrames();
protected override void CloneCore(Freezable sourceFreezable)
if (sourceAnimation._keyFrames != null)
{
var sourceAnimation = (GeometryAnimationUsingKeyFrames) sourceFreezable;
base.CloneCore(sourceFreezable);
CopyCommon(sourceAnimation, false);
}
protected override void CloneCurrentValueCore(Freezable sourceFreezable)
{
var sourceAnimation = (GeometryAnimationUsingKeyFrames) sourceFreezable;
base.CloneCurrentValueCore(sourceFreezable);
CopyCommon(sourceAnimation, true);
}
protected override void GetAsFrozenCore(Freezable source)
{
var sourceAnimation = (GeometryAnimationUsingKeyFrames) source;
base.GetAsFrozenCore(source);
CopyCommon(sourceAnimation, false);
}
protected override void GetCurrentValueAsFrozenCore(Freezable source)
{
var sourceAnimation = (GeometryAnimationUsingKeyFrames) source;
base.GetCurrentValueAsFrozenCore(source);
CopyCommon(sourceAnimation, true);
}
private void CopyCommon(GeometryAnimationUsingKeyFrames sourceAnimation, bool isCurrentValueClone)
{
_areKeyTimesValid = sourceAnimation._areKeyTimesValid;
if (_areKeyTimesValid && sourceAnimation._sortedResolvedKeyFrames != null)
if (isCurrentValueClone)
{
_sortedResolvedKeyFrames = (ResolvedKeyFrameEntry[]) sourceAnimation._sortedResolvedKeyFrames.Clone();
}
if (sourceAnimation._keyFrames != null)
{
if (isCurrentValueClone)
{
_keyFrames = (GeometryKeyFrameCollection) sourceAnimation._keyFrames.CloneCurrentValue();
}
else
{
_keyFrames = sourceAnimation._keyFrames.Clone();
}
OnFreezablePropertyChanged(null, _keyFrames);
}
}
void IAddChild.AddChild(object child)
{
WritePreamble();
if (child == null)
{
throw new ArgumentNullException(nameof(child));
}
AddChild(child);
WritePostscript();
}
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected virtual void AddChild(object child)
{
if (child is GeometryKeyFrame keyFrame)
{
KeyFrames.Add(keyFrame);
_keyFrames = (GeometryKeyFrameCollection) sourceAnimation._keyFrames.CloneCurrentValue();
}
else
{
throw new ArgumentException("Animation_ChildMustBeKeyFrame", nameof(child));
_keyFrames = sourceAnimation._keyFrames.Clone();
}
OnFreezablePropertyChanged(null, _keyFrames);
}
}
void IAddChild.AddChild(object child)
{
WritePreamble();
if (child == null)
{
throw new ArgumentNullException(nameof(child));
}
void IAddChild.AddText(string childText)
AddChild(child);
WritePostscript();
}
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected virtual void AddChild(object child)
{
if (child is GeometryKeyFrame keyFrame)
{
if (childText == null)
KeyFrames.Add(keyFrame);
}
else
{
throw new ArgumentException("Animation_ChildMustBeKeyFrame", nameof(child));
}
}
void IAddChild.AddText(string childText)
{
if (childText == null)
{
throw new ArgumentNullException(nameof(childText));
}
AddText(childText);
}
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected virtual void AddText(string childText) => throw new InvalidOperationException("Animation_NoTextChildren");
protected override Geometry GetCurrentValueCore(Geometry defaultOriginValue, Geometry defaultDestinationValue, AnimationClock animationClock)
{
if (_keyFrames == null)
{
return defaultDestinationValue;
}
if (!_areKeyTimesValid)
{
ResolveKeyTimes();
}
if (_sortedResolvedKeyFrames == null)
{
return defaultDestinationValue;
}
var currentTime = animationClock.CurrentTime.Value;
var keyFrameCount = _sortedResolvedKeyFrames.Length;
var maxKeyFrameIndex = keyFrameCount - 1;
double[] currentIterationValue;
var currentResolvedKeyFrameIndex = 0;
while (currentResolvedKeyFrameIndex < keyFrameCount && currentTime > _sortedResolvedKeyFrames[currentResolvedKeyFrameIndex]._resolvedKeyTime)
{
currentResolvedKeyFrameIndex++;
}
while (currentResolvedKeyFrameIndex < maxKeyFrameIndex && currentTime == _sortedResolvedKeyFrames[currentResolvedKeyFrameIndex + 1]._resolvedKeyTime)
{
currentResolvedKeyFrameIndex++;
}
if (currentResolvedKeyFrameIndex == keyFrameCount)
{
currentIterationValue = GetResolvedKeyFrameValue(maxKeyFrameIndex);
}
else if (currentTime == _sortedResolvedKeyFrames[currentResolvedKeyFrameIndex]._resolvedKeyTime)
{
currentIterationValue = GetResolvedKeyFrameValue(currentResolvedKeyFrameIndex);
}
else
{
double currentSegmentProgress;
double[] fromValue;
if (currentResolvedKeyFrameIndex == 0)
{
throw new ArgumentNullException(nameof(childText));
AnimationHelper.DecomposeGeometryStr(defaultOriginValue.ToString(CultureInfo.InvariantCulture), out fromValue);
currentSegmentProgress = currentTime.TotalMilliseconds / _sortedResolvedKeyFrames[0]._resolvedKeyTime.TotalMilliseconds;
}
else
{
var previousResolvedKeyFrameIndex = currentResolvedKeyFrameIndex - 1;
var previousResolvedKeyTime = _sortedResolvedKeyFrames[previousResolvedKeyFrameIndex]._resolvedKeyTime;
fromValue = GetResolvedKeyFrameValue(previousResolvedKeyFrameIndex);
var segmentCurrentTime = currentTime - previousResolvedKeyTime;
var segmentDuration = _sortedResolvedKeyFrames[currentResolvedKeyFrameIndex]._resolvedKeyTime - previousResolvedKeyTime;
currentSegmentProgress = segmentCurrentTime.TotalMilliseconds / segmentDuration.TotalMilliseconds;
}
AddText(childText);
currentIterationValue = GetResolvedKeyFrame(currentResolvedKeyFrameIndex).InterpolateValue(fromValue, currentSegmentProgress);
}
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected virtual void AddText(string childText) => throw new InvalidOperationException("Animation_NoTextChildren");
return AnimationHelper.ComposeGeometry(Strings, currentIterationValue);
}
protected override Geometry GetCurrentValueCore(Geometry defaultOriginValue, Geometry defaultDestinationValue, AnimationClock animationClock)
protected sealed override Duration GetNaturalDurationCore(Clock clock) => new(LargestTimeSpanKeyTime);
IList IKeyFrameAnimation.KeyFrames
{
get => KeyFrames;
set => KeyFrames = (GeometryKeyFrameCollection) value;
}
public GeometryKeyFrameCollection KeyFrames
{
get
{
ReadPreamble();
if (_keyFrames == null)
{
return defaultDestinationValue;
}
if (!_areKeyTimesValid)
{
ResolveKeyTimes();
}
if (_sortedResolvedKeyFrames == null)
{
return defaultDestinationValue;
}
var currentTime = animationClock.CurrentTime.Value;
var keyFrameCount = _sortedResolvedKeyFrames.Length;
var maxKeyFrameIndex = keyFrameCount - 1;
double[] currentIterationValue;
var currentResolvedKeyFrameIndex = 0;
while (currentResolvedKeyFrameIndex < keyFrameCount && currentTime > _sortedResolvedKeyFrames[currentResolvedKeyFrameIndex]._resolvedKeyTime)
{
currentResolvedKeyFrameIndex++;
}
while (currentResolvedKeyFrameIndex < maxKeyFrameIndex && currentTime == _sortedResolvedKeyFrames[currentResolvedKeyFrameIndex + 1]._resolvedKeyTime)
{
currentResolvedKeyFrameIndex++;
}
if (currentResolvedKeyFrameIndex == keyFrameCount)
{
currentIterationValue = GetResolvedKeyFrameValue(maxKeyFrameIndex);
}
else if (currentTime == _sortedResolvedKeyFrames[currentResolvedKeyFrameIndex]._resolvedKeyTime)
{
currentIterationValue = GetResolvedKeyFrameValue(currentResolvedKeyFrameIndex);
}
else
{
double currentSegmentProgress;
double[] fromValue;
if (currentResolvedKeyFrameIndex == 0)
if (IsFrozen)
{
AnimationHelper.DecomposeGeometryStr(defaultOriginValue.ToString(CultureInfo.InvariantCulture), out fromValue);
currentSegmentProgress = currentTime.TotalMilliseconds / _sortedResolvedKeyFrames[0]._resolvedKeyTime.TotalMilliseconds;
_keyFrames = GeometryKeyFrameCollection.Empty;
}
else
{
var previousResolvedKeyFrameIndex = currentResolvedKeyFrameIndex - 1;
var previousResolvedKeyTime = _sortedResolvedKeyFrames[previousResolvedKeyFrameIndex]._resolvedKeyTime;
WritePreamble();
fromValue = GetResolvedKeyFrameValue(previousResolvedKeyFrameIndex);
_keyFrames = new GeometryKeyFrameCollection();
var segmentCurrentTime = currentTime - previousResolvedKeyTime;
var segmentDuration = _sortedResolvedKeyFrames[currentResolvedKeyFrameIndex]._resolvedKeyTime - previousResolvedKeyTime;
currentSegmentProgress = segmentCurrentTime.TotalMilliseconds / segmentDuration.TotalMilliseconds;
}
currentIterationValue = GetResolvedKeyFrame(currentResolvedKeyFrameIndex).InterpolateValue(fromValue, currentSegmentProgress);
}
return AnimationHelper.ComposeGeometry(Strings, currentIterationValue);
}
protected sealed override Duration GetNaturalDurationCore(Clock clock) => new(LargestTimeSpanKeyTime);
IList IKeyFrameAnimation.KeyFrames
{
get => KeyFrames;
set => KeyFrames = (GeometryKeyFrameCollection) value;
}
public GeometryKeyFrameCollection KeyFrames
{
get
{
ReadPreamble();
if (_keyFrames == null)
{
if (IsFrozen)
{
_keyFrames = GeometryKeyFrameCollection.Empty;
}
else
{
WritePreamble();
_keyFrames = new GeometryKeyFrameCollection();
OnFreezablePropertyChanged(null, _keyFrames);
WritePostscript();
}
}
return _keyFrames;
}
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
WritePreamble();
if (value != _keyFrames)
{
OnFreezablePropertyChanged(_keyFrames, value);
_keyFrames = value;
OnFreezablePropertyChanged(null, _keyFrames);
WritePostscript();
}
}
return _keyFrames;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeKeyFrames()
set
{
ReadPreamble();
return _keyFrames != null && _keyFrames.Count > 0;
}
private struct KeyTimeBlock
{
public int BeginIndex;
public int EndIndex;
}
private double[] GetResolvedKeyFrameValue(int resolvedKeyFrameIndex) =>
GetResolvedKeyFrame(resolvedKeyFrameIndex).Numbers;
private GeometryKeyFrame GetResolvedKeyFrame(int resolvedKeyFrameIndex) =>
_keyFrames[_sortedResolvedKeyFrames[resolvedKeyFrameIndex]._originalKeyFrameIndex];
private TimeSpan LargestTimeSpanKeyTime
{
get
if (value == null)
{
var hasTimeSpanKeyTime = false;
var largestTimeSpanKeyTime = TimeSpan.Zero;
throw new ArgumentNullException(nameof(value));
}
if (_keyFrames != null)
{
var keyFrameCount = _keyFrames.Count;
WritePreamble();
for (var index = 0; index < keyFrameCount; index++)
{
var keyTime = _keyFrames[index].KeyTime;
if (value != _keyFrames)
{
OnFreezablePropertyChanged(_keyFrames, value);
_keyFrames = value;
if (keyTime.Type == KeyTimeType.TimeSpan)
{
hasTimeSpanKeyTime = true;
if (keyTime.TimeSpan > largestTimeSpanKeyTime)
{
largestTimeSpanKeyTime = keyTime.TimeSpan;
}
}
}
}
return hasTimeSpanKeyTime ? largestTimeSpanKeyTime : TimeSpan.FromSeconds(1.0);
WritePostscript();
}
}
}
private void ResolveKeyTimes()
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeKeyFrames()
{
ReadPreamble();
return _keyFrames != null && _keyFrames.Count > 0;
}
private struct KeyTimeBlock
{
public int BeginIndex;
public int EndIndex;
}
private double[] GetResolvedKeyFrameValue(int resolvedKeyFrameIndex) =>
GetResolvedKeyFrame(resolvedKeyFrameIndex).Numbers;
private GeometryKeyFrame GetResolvedKeyFrame(int resolvedKeyFrameIndex) =>
_keyFrames[_sortedResolvedKeyFrames[resolvedKeyFrameIndex]._originalKeyFrameIndex];
private TimeSpan LargestTimeSpanKeyTime
{
get
{
var keyFrameCount = 0;
var hasTimeSpanKeyTime = false;
var largestTimeSpanKeyTime = TimeSpan.Zero;
if (_keyFrames != null)
{
keyFrameCount = _keyFrames.Count;
}
var keyFrameCount = _keyFrames.Count;
if (keyFrameCount == 0)
{
_sortedResolvedKeyFrames = null;
_areKeyTimesValid = true;
return;
}
_sortedResolvedKeyFrames = new ResolvedKeyFrameEntry[keyFrameCount];
var index = 0;
for (; index < keyFrameCount; index++)
{
_sortedResolvedKeyFrames[index]._originalKeyFrameIndex = index;
}
var duration = Duration;
var calculationDuration = duration.HasTimeSpan ? duration.TimeSpan : LargestTimeSpanKeyTime;
var maxKeyFrameIndex = keyFrameCount - 1;
var unspecifiedBlocks = new List<KeyTimeBlock>();
var hasPacedKeyTimes = false;
index = 0;
while (index < keyFrameCount)
{
// ReSharper disable once PossibleNullReferenceException
var keyTime = _keyFrames[index].KeyTime;
switch (keyTime.Type)
for (var index = 0; index < keyFrameCount; index++)
{
case KeyTimeType.Percent:
var keyTime = _keyFrames[index].KeyTime;
_sortedResolvedKeyFrames[index]._resolvedKeyTime = TimeSpan.FromMilliseconds(keyTime.Percent * calculationDuration.TotalMilliseconds);
index++;
break;
if (keyTime.Type == KeyTimeType.TimeSpan)
{
hasTimeSpanKeyTime = true;
case KeyTimeType.TimeSpan:
_sortedResolvedKeyFrames[index]._resolvedKeyTime = keyTime.TimeSpan;
index++;
break;
case KeyTimeType.Paced:
case KeyTimeType.Uniform:
if (index == maxKeyFrameIndex)
if (keyTime.TimeSpan > largestTimeSpanKeyTime)
{
_sortedResolvedKeyFrames[index]._resolvedKeyTime = calculationDuration;
index++;
largestTimeSpanKeyTime = keyTime.TimeSpan;
}
else if (index == 0 && keyTime.Type == KeyTimeType.Paced)
}
}
}
return hasTimeSpanKeyTime ? largestTimeSpanKeyTime : TimeSpan.FromSeconds(1.0);
}
}
private void ResolveKeyTimes()
{
var keyFrameCount = 0;
if (_keyFrames != null)
{
keyFrameCount = _keyFrames.Count;
}
if (keyFrameCount == 0)
{
_sortedResolvedKeyFrames = null;
_areKeyTimesValid = true;
return;
}
_sortedResolvedKeyFrames = new ResolvedKeyFrameEntry[keyFrameCount];
var index = 0;
for (; index < keyFrameCount; index++)
{
_sortedResolvedKeyFrames[index]._originalKeyFrameIndex = index;
}
var duration = Duration;
var calculationDuration = duration.HasTimeSpan ? duration.TimeSpan : LargestTimeSpanKeyTime;
var maxKeyFrameIndex = keyFrameCount - 1;
var unspecifiedBlocks = new List<KeyTimeBlock>();
var hasPacedKeyTimes = false;
index = 0;
while (index < keyFrameCount)
{
// ReSharper disable once PossibleNullReferenceException
var keyTime = _keyFrames[index].KeyTime;
switch (keyTime.Type)
{
case KeyTimeType.Percent:
_sortedResolvedKeyFrames[index]._resolvedKeyTime = TimeSpan.FromMilliseconds(keyTime.Percent * calculationDuration.TotalMilliseconds);
index++;
break;
case KeyTimeType.TimeSpan:
_sortedResolvedKeyFrames[index]._resolvedKeyTime = keyTime.TimeSpan;
index++;
break;
case KeyTimeType.Paced:
case KeyTimeType.Uniform:
if (index == maxKeyFrameIndex)
{
_sortedResolvedKeyFrames[index]._resolvedKeyTime = calculationDuration;
index++;
}
else if (index == 0 && keyTime.Type == KeyTimeType.Paced)
{
_sortedResolvedKeyFrames[index]._resolvedKeyTime = TimeSpan.Zero;
index++;
}
else
{
if (keyTime.Type == KeyTimeType.Paced)
{
_sortedResolvedKeyFrames[index]._resolvedKeyTime = TimeSpan.Zero;
index++;
hasPacedKeyTimes = true;
}
else
var block = new KeyTimeBlock
{
if (keyTime.Type == KeyTimeType.Paced)
BeginIndex = index
};
while (++index < maxKeyFrameIndex)
{
var type = _keyFrames[index].KeyTime.Type;
if (type == KeyTimeType.Percent || type == KeyTimeType.TimeSpan)
{
break;
}
if (type == KeyTimeType.Paced)
{
hasPacedKeyTimes = true;
}
var block = new KeyTimeBlock
{
BeginIndex = index
};
while (++index < maxKeyFrameIndex)
{
var type = _keyFrames[index].KeyTime.Type;
if (type == KeyTimeType.Percent || type == KeyTimeType.TimeSpan)
{
break;
}
if (type == KeyTimeType.Paced)
{
hasPacedKeyTimes = true;
}
}
block.EndIndex = index;
unspecifiedBlocks.Add(block);
}
break;
}
block.EndIndex = index;
unspecifiedBlocks.Add(block);
}
break;
}
foreach (var block in unspecifiedBlocks)
{
var blockBeginTime = TimeSpan.Zero;
if (block.BeginIndex > 0)
{
blockBeginTime = _sortedResolvedKeyFrames[block.BeginIndex - 1]._resolvedKeyTime;
}
long segmentCount = block.EndIndex - block.BeginIndex + 1;
var uniformTimeStep = TimeSpan.FromTicks((_sortedResolvedKeyFrames[block.EndIndex]._resolvedKeyTime - blockBeginTime).Ticks / segmentCount);
index = block.BeginIndex;
var resolvedTime = blockBeginTime + uniformTimeStep;
while (index < block.EndIndex)
{
_sortedResolvedKeyFrames[index]._resolvedKeyTime = resolvedTime;
resolvedTime += uniformTimeStep;
index++;
}
}
if (hasPacedKeyTimes)
{
ResolvePacedKeyTimes();
}
Array.Sort(_sortedResolvedKeyFrames);
_areKeyTimesValid = true;
}
private void ResolvePacedKeyTimes()
foreach (var block in unspecifiedBlocks)
{
var index = 1;
var maxKeyFrameIndex = _sortedResolvedKeyFrames.Length - 1;
var blockBeginTime = TimeSpan.Zero;
do
if (block.BeginIndex > 0)
{
if (_keyFrames[index].KeyTime.Type == KeyTimeType.Paced)
{
var firstPacedBlockKeyFrameIndex = index;
var segmentLengths = new List<double>();
var prePacedBlockKeyTime = _sortedResolvedKeyFrames[index - 1]._resolvedKeyTime;
var totalLength = 0.0;
var prevKeyValue = _keyFrames[index - 1].Numbers;
do
{
var currentKeyValue = _keyFrames[index].Numbers;
totalLength += Math.Abs(currentKeyValue[0] - prevKeyValue[0]);
segmentLengths.Add(totalLength);
prevKeyValue = currentKeyValue;
index++;
}
while (index < maxKeyFrameIndex && _keyFrames[index].KeyTime.Type == KeyTimeType.Paced);
totalLength += Math.Abs(_keyFrames[index].Numbers[0] - prevKeyValue[0]);
var pacedBlockDuration = _sortedResolvedKeyFrames[index]._resolvedKeyTime - prePacedBlockKeyTime;
for (int i = 0, currentKeyFrameIndex = firstPacedBlockKeyFrameIndex; i < segmentLengths.Count; i++, currentKeyFrameIndex++)
{
_sortedResolvedKeyFrames[currentKeyFrameIndex]._resolvedKeyTime = prePacedBlockKeyTime + TimeSpan.FromMilliseconds(segmentLengths[i] / totalLength * pacedBlockDuration.TotalMilliseconds);
}
}
else
blockBeginTime = _sortedResolvedKeyFrames[block.BeginIndex - 1]._resolvedKeyTime;
}
long segmentCount = block.EndIndex - block.BeginIndex + 1;
var uniformTimeStep = TimeSpan.FromTicks((_sortedResolvedKeyFrames[block.EndIndex]._resolvedKeyTime - blockBeginTime).Ticks / segmentCount);
index = block.BeginIndex;
var resolvedTime = blockBeginTime + uniformTimeStep;
while (index < block.EndIndex)
{
_sortedResolvedKeyFrames[index]._resolvedKeyTime = resolvedTime;
resolvedTime += uniformTimeStep;
index++;
}
}
if (hasPacedKeyTimes)
{
ResolvePacedKeyTimes();
}
Array.Sort(_sortedResolvedKeyFrames);
_areKeyTimesValid = true;
}
private void ResolvePacedKeyTimes()
{
var index = 1;
var maxKeyFrameIndex = _sortedResolvedKeyFrames.Length - 1;
do
{
if (_keyFrames[index].KeyTime.Type == KeyTimeType.Paced)
{
var firstPacedBlockKeyFrameIndex = index;
var segmentLengths = new List<double>();
var prePacedBlockKeyTime = _sortedResolvedKeyFrames[index - 1]._resolvedKeyTime;
var totalLength = 0.0;
var prevKeyValue = _keyFrames[index - 1].Numbers;
do
{
var currentKeyValue = _keyFrames[index].Numbers;
totalLength += Math.Abs(currentKeyValue[0] - prevKeyValue[0]);
segmentLengths.Add(totalLength);
prevKeyValue = currentKeyValue;
index++;
}
while (index < maxKeyFrameIndex && _keyFrames[index].KeyTime.Type == KeyTimeType.Paced);
totalLength += Math.Abs(_keyFrames[index].Numbers[0] - prevKeyValue[0]);
var pacedBlockDuration = _sortedResolvedKeyFrames[index]._resolvedKeyTime - prePacedBlockKeyTime;
for (int i = 0, currentKeyFrameIndex = firstPacedBlockKeyFrameIndex; i < segmentLengths.Count; i++, currentKeyFrameIndex++)
{
_sortedResolvedKeyFrames[currentKeyFrameIndex]._resolvedKeyTime = prePacedBlockKeyTime + TimeSpan.FromMilliseconds(segmentLengths[i] / totalLength * pacedBlockDuration.TotalMilliseconds);
}
}
else
{
index++;
}
while (index < maxKeyFrameIndex);
}
while (index < maxKeyFrameIndex);
}
}
}
@@ -4,320 +4,319 @@ using System.Collections.Generic;
using System.Globalization;
using System.Windows;
namespace HandyControl.Media.Animation
namespace HandyControl.Media.Animation;
public class GeometryKeyFrameCollection : Freezable, IList
{
public class GeometryKeyFrameCollection : Freezable, IList
private List<GeometryKeyFrame> _keyFrames;
private static GeometryKeyFrameCollection s_emptyCollection;
public GeometryKeyFrameCollection()
{
private List<GeometryKeyFrame> _keyFrames;
_keyFrames = new List<GeometryKeyFrame>(2);
}
private static GeometryKeyFrameCollection s_emptyCollection;
public GeometryKeyFrameCollection()
public static GeometryKeyFrameCollection Empty
{
get
{
_keyFrames = new List<GeometryKeyFrame>(2);
}
public static GeometryKeyFrameCollection Empty
{
get
if (s_emptyCollection == null)
{
if (s_emptyCollection == null)
var emptyCollection = new GeometryKeyFrameCollection
{
var emptyCollection = new GeometryKeyFrameCollection
{
_keyFrames = new List<GeometryKeyFrame>(0)
};
_keyFrames = new List<GeometryKeyFrame>(0)
};
emptyCollection.Freeze();
emptyCollection.Freeze();
s_emptyCollection = emptyCollection;
}
return s_emptyCollection;
}
}
public new GeometryKeyFrameCollection Clone() => (GeometryKeyFrameCollection) base.Clone();
protected override Freezable CreateInstanceCore() => new GeometryKeyFrameCollection();
protected override void CloneCore(Freezable sourceFreezable)
{
var sourceCollection = (GeometryKeyFrameCollection) sourceFreezable;
base.CloneCore(sourceFreezable);
var count = sourceCollection._keyFrames.Count;
_keyFrames = new List<GeometryKeyFrame>(count);
for (var i = 0; i < count; i++)
{
var keyFrame = (GeometryKeyFrame) sourceCollection._keyFrames[i].Clone();
_keyFrames.Add(keyFrame);
OnFreezablePropertyChanged(null, keyFrame);
}
}
protected override void CloneCurrentValueCore(Freezable sourceFreezable)
{
var sourceCollection = (GeometryKeyFrameCollection) sourceFreezable;
base.CloneCurrentValueCore(sourceFreezable);
var count = sourceCollection._keyFrames.Count;
_keyFrames = new List<GeometryKeyFrame>(count);
for (var i = 0; i < count; i++)
{
var keyFrame = (GeometryKeyFrame) sourceCollection._keyFrames[i].CloneCurrentValue();
_keyFrames.Add(keyFrame);
OnFreezablePropertyChanged(null, keyFrame);
}
}
protected override void GetAsFrozenCore(Freezable sourceFreezable)
{
var sourceCollection = (GeometryKeyFrameCollection) sourceFreezable;
base.GetAsFrozenCore(sourceFreezable);
var count = sourceCollection._keyFrames.Count;
_keyFrames = new List<GeometryKeyFrame>(count);
for (var i = 0; i < count; i++)
{
var keyFrame = (GeometryKeyFrame) sourceCollection._keyFrames[i].GetAsFrozen();
_keyFrames.Add(keyFrame);
OnFreezablePropertyChanged(null, keyFrame);
}
}
protected override void GetCurrentValueAsFrozenCore(Freezable sourceFreezable)
{
var sourceCollection = (GeometryKeyFrameCollection) sourceFreezable;
base.GetCurrentValueAsFrozenCore(sourceFreezable);
var count = sourceCollection._keyFrames.Count;
_keyFrames = new List<GeometryKeyFrame>(count);
for (var i = 0; i < count; i++)
{
var keyFrame = (GeometryKeyFrame) sourceCollection._keyFrames[i].GetCurrentValueAsFrozen();
_keyFrames.Add(keyFrame);
OnFreezablePropertyChanged(null, keyFrame);
}
}
protected override bool FreezeCore(bool isChecking)
{
var canFreeze = base.FreezeCore(isChecking);
for (var i = 0; i < _keyFrames.Count && canFreeze; i++)
{
canFreeze &= Freeze(_keyFrames[i], isChecking);
s_emptyCollection = emptyCollection;
}
return canFreeze;
return s_emptyCollection;
}
}
public IEnumerator GetEnumerator()
public new GeometryKeyFrameCollection Clone() => (GeometryKeyFrameCollection) base.Clone();
protected override Freezable CreateInstanceCore() => new GeometryKeyFrameCollection();
protected override void CloneCore(Freezable sourceFreezable)
{
var sourceCollection = (GeometryKeyFrameCollection) sourceFreezable;
base.CloneCore(sourceFreezable);
var count = sourceCollection._keyFrames.Count;
_keyFrames = new List<GeometryKeyFrame>(count);
for (var i = 0; i < count; i++)
{
ReadPreamble();
return _keyFrames.GetEnumerator();
}
void ICollection.CopyTo(Array array, int index)
{
ReadPreamble();
((ICollection) _keyFrames).CopyTo(array, index);
}
public void CopyTo(GeometryKeyFrame[] array, int index)
{
ReadPreamble();
_keyFrames.CopyTo(array, index);
}
public int Count
{
get
{
ReadPreamble();
return _keyFrames.Count;
}
}
public object SyncRoot
{
get
{
ReadPreamble();
return ((ICollection) _keyFrames).SyncRoot;
}
}
public bool IsSynchronized
{
get
{
ReadPreamble();
return IsFrozen || Dispatcher != null;
}
}
int IList.Add(object keyFrame) => Add((GeometryKeyFrame) keyFrame);
public int Add(GeometryKeyFrame keyFrame)
{
if (keyFrame == null)
{
throw new ArgumentNullException(nameof(keyFrame));
}
WritePreamble();
OnFreezablePropertyChanged(null, keyFrame);
var keyFrame = (GeometryKeyFrame) sourceCollection._keyFrames[i].Clone();
_keyFrames.Add(keyFrame);
WritePostscript();
return _keyFrames.Count - 1;
}
public void Clear()
{
WritePreamble();
if (_keyFrames.Count <= 0) return;
foreach (var frame in _keyFrames)
{
OnFreezablePropertyChanged(frame, null);
}
_keyFrames.Clear();
WritePostscript();
}
bool IList.Contains(object keyFrame) => Contains((GeometryKeyFrame) keyFrame);
public bool Contains(GeometryKeyFrame keyFrame)
{
ReadPreamble();
return _keyFrames.Contains(keyFrame);
}
int IList.IndexOf(object keyFrame) => IndexOf((GeometryKeyFrame) keyFrame);
public int IndexOf(GeometryKeyFrame keyFrame)
{
ReadPreamble();
return _keyFrames.IndexOf(keyFrame);
}
void IList.Insert(int index, object keyFrame) => Insert(index, (GeometryKeyFrame) keyFrame);
public void Insert(int index, GeometryKeyFrame keyFrame)
{
if (keyFrame == null)
{
throw new ArgumentNullException(nameof(keyFrame));
}
WritePreamble();
OnFreezablePropertyChanged(null, keyFrame);
_keyFrames.Insert(index, keyFrame);
}
}
protected override void CloneCurrentValueCore(Freezable sourceFreezable)
{
var sourceCollection = (GeometryKeyFrameCollection) sourceFreezable;
base.CloneCurrentValueCore(sourceFreezable);
var count = sourceCollection._keyFrames.Count;
_keyFrames = new List<GeometryKeyFrame>(count);
for (var i = 0; i < count; i++)
{
var keyFrame = (GeometryKeyFrame) sourceCollection._keyFrames[i].CloneCurrentValue();
_keyFrames.Add(keyFrame);
OnFreezablePropertyChanged(null, keyFrame);
}
}
protected override void GetAsFrozenCore(Freezable sourceFreezable)
{
var sourceCollection = (GeometryKeyFrameCollection) sourceFreezable;
base.GetAsFrozenCore(sourceFreezable);
var count = sourceCollection._keyFrames.Count;
_keyFrames = new List<GeometryKeyFrame>(count);
for (var i = 0; i < count; i++)
{
var keyFrame = (GeometryKeyFrame) sourceCollection._keyFrames[i].GetAsFrozen();
_keyFrames.Add(keyFrame);
OnFreezablePropertyChanged(null, keyFrame);
}
}
protected override void GetCurrentValueAsFrozenCore(Freezable sourceFreezable)
{
var sourceCollection = (GeometryKeyFrameCollection) sourceFreezable;
base.GetCurrentValueAsFrozenCore(sourceFreezable);
var count = sourceCollection._keyFrames.Count;
_keyFrames = new List<GeometryKeyFrame>(count);
for (var i = 0; i < count; i++)
{
var keyFrame = (GeometryKeyFrame) sourceCollection._keyFrames[i].GetCurrentValueAsFrozen();
_keyFrames.Add(keyFrame);
OnFreezablePropertyChanged(null, keyFrame);
}
}
protected override bool FreezeCore(bool isChecking)
{
var canFreeze = base.FreezeCore(isChecking);
for (var i = 0; i < _keyFrames.Count && canFreeze; i++)
{
canFreeze &= Freeze(_keyFrames[i], isChecking);
}
return canFreeze;
}
public IEnumerator GetEnumerator()
{
ReadPreamble();
return _keyFrames.GetEnumerator();
}
void ICollection.CopyTo(Array array, int index)
{
ReadPreamble();
((ICollection) _keyFrames).CopyTo(array, index);
}
public void CopyTo(GeometryKeyFrame[] array, int index)
{
ReadPreamble();
_keyFrames.CopyTo(array, index);
}
public int Count
{
get
{
ReadPreamble();
return _keyFrames.Count;
}
}
public object SyncRoot
{
get
{
ReadPreamble();
return ((ICollection) _keyFrames).SyncRoot;
}
}
public bool IsSynchronized
{
get
{
ReadPreamble();
return IsFrozen || Dispatcher != null;
}
}
int IList.Add(object keyFrame) => Add((GeometryKeyFrame) keyFrame);
public int Add(GeometryKeyFrame keyFrame)
{
if (keyFrame == null)
{
throw new ArgumentNullException(nameof(keyFrame));
}
WritePreamble();
OnFreezablePropertyChanged(null, keyFrame);
_keyFrames.Add(keyFrame);
WritePostscript();
return _keyFrames.Count - 1;
}
public void Clear()
{
WritePreamble();
if (_keyFrames.Count <= 0) return;
foreach (var frame in _keyFrames)
{
OnFreezablePropertyChanged(frame, null);
}
_keyFrames.Clear();
WritePostscript();
}
bool IList.Contains(object keyFrame) => Contains((GeometryKeyFrame) keyFrame);
public bool Contains(GeometryKeyFrame keyFrame)
{
ReadPreamble();
return _keyFrames.Contains(keyFrame);
}
int IList.IndexOf(object keyFrame) => IndexOf((GeometryKeyFrame) keyFrame);
public int IndexOf(GeometryKeyFrame keyFrame)
{
ReadPreamble();
return _keyFrames.IndexOf(keyFrame);
}
void IList.Insert(int index, object keyFrame) => Insert(index, (GeometryKeyFrame) keyFrame);
public void Insert(int index, GeometryKeyFrame keyFrame)
{
if (keyFrame == null)
{
throw new ArgumentNullException(nameof(keyFrame));
}
WritePreamble();
OnFreezablePropertyChanged(null, keyFrame);
_keyFrames.Insert(index, keyFrame);
WritePostscript();
}
void IList.Remove(object keyFrame) => Remove((GeometryKeyFrame) keyFrame);
public void Remove(GeometryKeyFrame keyFrame)
{
WritePreamble();
if (_keyFrames.Contains(keyFrame))
{
OnFreezablePropertyChanged(keyFrame, null);
_keyFrames.Remove(keyFrame);
WritePostscript();
}
}
void IList.Remove(object keyFrame) => Remove((GeometryKeyFrame) keyFrame);
public void RemoveAt(int index)
{
WritePreamble();
public void Remove(GeometryKeyFrame keyFrame)
OnFreezablePropertyChanged(_keyFrames[index], null);
_keyFrames.RemoveAt(index);
WritePostscript();
}
object IList.this[int index]
{
get => this[index];
set => this[index] = (GeometryKeyFrame) value;
}
public GeometryKeyFrame this[int index]
{
get
{
ReadPreamble();
return _keyFrames[index];
}
set
{
if (value == null)
{
throw new ArgumentNullException(string.Format(CultureInfo.InvariantCulture, "DoubleKeyFrameCollection[{0}]", index));
}
WritePreamble();
if (_keyFrames.Contains(keyFrame))
if (value != _keyFrames[index])
{
OnFreezablePropertyChanged(keyFrame, null);
_keyFrames.Remove(keyFrame);
OnFreezablePropertyChanged(_keyFrames[index], value);
_keyFrames[index] = value;
WritePostscript();
}
}
}
public void RemoveAt(int index)
public bool IsReadOnly
{
get
{
WritePreamble();
ReadPreamble();
OnFreezablePropertyChanged(_keyFrames[index], null);
_keyFrames.RemoveAt(index);
WritePostscript();
}
object IList.this[int index]
{
get => this[index];
set => this[index] = (GeometryKeyFrame) value;
}
public GeometryKeyFrame this[int index]
{
get
{
ReadPreamble();
return _keyFrames[index];
}
set
{
if (value == null)
{
throw new ArgumentNullException(string.Format(CultureInfo.InvariantCulture, "DoubleKeyFrameCollection[{0}]", index));
}
WritePreamble();
if (value != _keyFrames[index])
{
OnFreezablePropertyChanged(_keyFrames[index], value);
_keyFrames[index] = value;
WritePostscript();
}
}
}
public bool IsReadOnly
{
get
{
ReadPreamble();
return IsFrozen;
}
}
public bool IsFixedSize
{
get
{
ReadPreamble();
return IsFrozen;
}
return IsFrozen;
}
}
}
public bool IsFixedSize
{
get
{
ReadPreamble();
return IsFrozen;
}
}
}
@@ -4,40 +4,39 @@ using System.Windows.Media.Animation;
using HandyControl.Expression.Drawing;
using HandyControl.Tools;
namespace HandyControl.Media.Animation
namespace HandyControl.Media.Animation;
public class LinearGeometryKeyFrame : GeometryKeyFrame
{
public class LinearGeometryKeyFrame : GeometryKeyFrame
public LinearGeometryKeyFrame()
{
public LinearGeometryKeyFrame()
{
}
public LinearGeometryKeyFrame(Geometry value) : base(value)
{
}
public LinearGeometryKeyFrame(Geometry value, KeyTime keyTime) : base(value, keyTime)
{
}
protected override Freezable CreateInstanceCore() => new LinearGeometryKeyFrame();
protected override double[] InterpolateValueCore(double[] baseValue, double keyFrameProgress)
{
if (MathHelper.IsVerySmall(keyFrameProgress))
{
return baseValue;
}
if (MathHelper.AreClose(keyFrameProgress, 1))
{
return Numbers;
}
return AnimationHelper.InterpolateGeometryValue(baseValue, Numbers, keyFrameProgress);
}
}
}
public LinearGeometryKeyFrame(Geometry value) : base(value)
{
}
public LinearGeometryKeyFrame(Geometry value, KeyTime keyTime) : base(value, keyTime)
{
}
protected override Freezable CreateInstanceCore() => new LinearGeometryKeyFrame();
protected override double[] InterpolateValueCore(double[] baseValue, double keyFrameProgress)
{
if (MathHelper.IsVerySmall(keyFrameProgress))
{
return baseValue;
}
if (MathHelper.AreClose(keyFrameProgress, 1))
{
return Numbers;
}
return AnimationHelper.InterpolateGeometryValue(baseValue, Numbers, keyFrameProgress);
}
}
@@ -1,38 +1,37 @@
using System;
namespace HandyControl.Media.Animation
namespace HandyControl.Media.Animation;
internal struct ResolvedKeyFrameEntry : IComparable
{
internal struct ResolvedKeyFrameEntry : IComparable
internal int _originalKeyFrameIndex;
internal TimeSpan _resolvedKeyTime;
public int CompareTo(object other)
{
internal int _originalKeyFrameIndex;
var otherEntry = (ResolvedKeyFrameEntry) other;
internal TimeSpan _resolvedKeyTime;
public int CompareTo(object other)
if (otherEntry._resolvedKeyTime > _resolvedKeyTime)
{
var otherEntry = (ResolvedKeyFrameEntry) other;
if (otherEntry._resolvedKeyTime > _resolvedKeyTime)
{
return -1;
}
if (otherEntry._resolvedKeyTime < _resolvedKeyTime)
{
return 1;
}
if (otherEntry._originalKeyFrameIndex > _originalKeyFrameIndex)
{
return -1;
}
if (otherEntry._originalKeyFrameIndex < _originalKeyFrameIndex)
{
return 1;
}
return 0;
return -1;
}
if (otherEntry._resolvedKeyTime < _resolvedKeyTime)
{
return 1;
}
if (otherEntry._originalKeyFrameIndex > _originalKeyFrameIndex)
{
return -1;
}
if (otherEntry._originalKeyFrameIndex < _originalKeyFrameIndex)
{
return 1;
}
return 0;
}
}
}
@@ -5,55 +5,54 @@ using System.Windows.Media.Animation;
using HandyControl.Expression.Drawing;
using HandyControl.Tools;
namespace HandyControl.Media.Animation
namespace HandyControl.Media.Animation;
public class SplineGeometryKeyFrame : GeometryKeyFrame
{
public class SplineGeometryKeyFrame : GeometryKeyFrame
public SplineGeometryKeyFrame()
{
public SplineGeometryKeyFrame()
{
}
public SplineGeometryKeyFrame(Geometry value) : base(value)
{
}
public SplineGeometryKeyFrame(Geometry value, KeyTime keyTime) : base(value, keyTime)
{
}
public SplineGeometryKeyFrame(Geometry value, KeyTime keyTime, KeySpline keySpline) : base(value, keyTime)
{
KeySpline = keySpline ?? throw new ArgumentNullException(nameof(keySpline));
}
protected override Freezable CreateInstanceCore() => new SplineGeometryKeyFrame();
protected override double[] InterpolateValueCore(double[] baseValue, double keyFrameProgress)
{
if (MathHelper.IsVerySmall(keyFrameProgress))
{
return baseValue;
}
if (MathHelper.AreClose(keyFrameProgress, 1))
{
return Numbers;
}
var splineProgress = KeySpline.GetSplineProgress(keyFrameProgress);
return AnimationHelper.InterpolateGeometryValue(baseValue, Numbers, splineProgress);
}
public static readonly DependencyProperty KeySplineProperty = DependencyProperty.Register(
"KeySpline", typeof(KeySpline), typeof(SplineGeometryKeyFrame), new PropertyMetadata(new KeySpline()));
public KeySpline KeySpline
{
get => (KeySpline) GetValue(KeySplineProperty);
set => SetValue(KeySplineProperty, value);
}
}
}
public SplineGeometryKeyFrame(Geometry value) : base(value)
{
}
public SplineGeometryKeyFrame(Geometry value, KeyTime keyTime) : base(value, keyTime)
{
}
public SplineGeometryKeyFrame(Geometry value, KeyTime keyTime, KeySpline keySpline) : base(value, keyTime)
{
KeySpline = keySpline ?? throw new ArgumentNullException(nameof(keySpline));
}
protected override Freezable CreateInstanceCore() => new SplineGeometryKeyFrame();
protected override double[] InterpolateValueCore(double[] baseValue, double keyFrameProgress)
{
if (MathHelper.IsVerySmall(keyFrameProgress))
{
return baseValue;
}
if (MathHelper.AreClose(keyFrameProgress, 1))
{
return Numbers;
}
var splineProgress = KeySpline.GetSplineProgress(keyFrameProgress);
return AnimationHelper.InterpolateGeometryValue(baseValue, Numbers, splineProgress);
}
public static readonly DependencyProperty KeySplineProperty = DependencyProperty.Register(
"KeySpline", typeof(KeySpline), typeof(SplineGeometryKeyFrame), new PropertyMetadata(new KeySpline()));
public KeySpline KeySpline
{
get => (KeySpline) GetValue(KeySplineProperty);
set => SetValue(KeySplineProperty, value);
}
}