add basic codes

This commit is contained in:
NaBian committed 2019-09-26 00:32:00 +08:00
1 parent b27391b88c
commit 814bfc2d64
5 files changed
+282 -1

No files matched your search

@@ -41,6 +41,8 @@
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\NotifyIconInfoType.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interactivity\Commands\CloseWindowCommand.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interactivity\Commands\OpenLinkCommand.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Media\Animation\GeometryAnimation.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Media\Animation\GeometryAnimationBase.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tools\Converter\BorderCircularClipConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tools\Converter\ColLayoutConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tools\Converter\CornerRadiusSplitConverter.cs" />
@@ -0,0 +1,222 @@
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;
using HandyControl.Tools.Extension;
// ReSharper disable PossibleInvalidOperationException
namespace HandyControl.Media.Animation
{
public class GeometryAnimation : GeometryAnimationBase
{
private const string Rgx = @"[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?";
private string[] _strings;
private double[] _numbersFrom;
private double[] _numbersTo;
private double[] _numbersAccumulator;
private double[][] _keyValues;
private bool _isAnimationFunctionValid;
public GeometryAnimation()
{
}
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];
}
}
private static void DecomposeValue(string geometryStr, out double[] arr)
{
var collection = Regex.Matches(geometryStr, Rgx);
arr = new double[collection.Count];
for (var i = 0; i < collection.Count; i++)
{
arr[i] = collection[i].Value.Value<double>();
}
}
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();
private Geometry ConvertToGeometry(double[] arr)
{
var builder = new StringBuilder(_strings[0]);
for (var i = 0; i < _numbersAccumulator.Length; i++)
{
var s = _strings[i + 1];
var n = arr[i];
if (!double.IsNaN(n))
{
builder.Append(n).Append(s);
}
}
return Geometry.Parse(builder.ToString());
}
protected override Geometry GetCurrentValueCore(Geometry defaultOriginValue, Geometry defaultDestinationValue, AnimationClock animationClock)
{
if (!_isAnimationFunctionValid)
{
ValidateAnimationFunction();
}
var progress = animationClock.CurrentProgress.Value;
var easingFunction = EasingFunction;
if (easingFunction != null)
{
progress = easingFunction.Ease(progress);
}
var accumulated = new double[_numbersAccumulator.Length];
var foundation = new double[_numbersAccumulator.Length];
var from = _keyValues[0];
if (IsAdditive)
{
foundation = 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] = foundation[i] + accumulated[i] + from[i] + _numbersAccumulator[i] * progress;
}
return ConvertToGeometry(numbers);
}
private void ValidateAnimationFunction()
{
_keyValues = null;
_keyValues = new double[2][];
_keyValues[0] = _numbersFrom;
_keyValues[1] = _numbersTo;
_isAnimationFunctionValid = true;
}
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)
{
DecomposeValue(geometry.ToString(), 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();
DecomposeValue(geometryStr, out obj._numbersTo);
obj._strings = Regex.Split(geometryStr, Rgx);
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 IsAdditive
{
get => (bool)GetValue(IsAdditiveProperty);
set => SetValue(IsAdditiveProperty, value);
}
public bool IsCumulative
{
get => (bool)GetValue(IsCumulativeProperty);
set => SetValue(IsCumulativeProperty, value);
}
}
}
@@ -0,0 +1,56 @@
using System;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace HandyControl.Media.Animation
{
public abstract class GeometryAnimationBase : AnimationTimeline
{
public new GeometryAnimationBase Clone()
{
return (GeometryAnimationBase)base.Clone();
}
public sealed override object GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock)
{
if (defaultOriginValue == null)
{
throw new ArgumentNullException(nameof(defaultOriginValue));
}
if (defaultDestinationValue == null)
{
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)
{
ReadPreamble();
if (animationClock == null)
{
throw new ArgumentNullException(nameof(animationClock));
}
if (animationClock.CurrentState == ClockState.Stopped)
{
return defaultDestinationValue;
}
return GetCurrentValueCore(defaultOriginValue, defaultDestinationValue, animationClock);
}
protected abstract Geometry GetCurrentValueCore(Geometry defaultOriginValue, Geometry defaultDestinationValue, AnimationClock animationClock);
}
}
@@ -21,6 +21,7 @@ using System.Runtime.InteropServices;
[assembly: XmlnsDefinition("https://handyorg.github.io/handycontrol", "HandyControl.Interactivity")]
[assembly: XmlnsDefinition("https://handyorg.github.io/handycontrol", "HandyControl.Expression.Shapes")]
[assembly: XmlnsDefinition("https://handyorg.github.io/handycontrol", "HandyControl.Expression.Media")]
[assembly: XmlnsDefinition("https://handyorg.github.io/handycontrol", "HandyControl.Media.Animation")]
[assembly: XmlnsDefinition("https://handyorg.github.io/handycontrol", "HandyControl.Data")]
[assembly: XmlnsDefinition("https://handyorg.github.io/handycontrol", "HandyControl.Properties.Langs")]
[assembly: XmlnsPrefix("https://handyorg.github.io/handycontrol", "hc")]
@@ -15,7 +15,7 @@ namespace HandyControl.Tools
/// <param name="thickness"></param>
/// <param name="milliseconds"></param>
/// <returns></returns>
public static ThicknessAnimation CreateAnimation(Thickness thickness = default(Thickness), double milliseconds = 200)
public static ThicknessAnimation CreateAnimation(Thickness thickness = default, double milliseconds = 200)
{
return new ThicknessAnimation(thickness, new Duration(TimeSpan.FromMilliseconds(milliseconds)))
{