12 changed files with 263 additions and 99 deletions
@ -0,0 +1,40 @@ |
|||
using Avalonia.Media; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
public class BoxShadowsAnimator : Animator<BoxShadows> |
|||
{ |
|||
private static readonly BoxShadowAnimator s_boxShadowAnimator = new BoxShadowAnimator(); |
|||
public override BoxShadows Interpolate(double progress, BoxShadows oldValue, BoxShadows newValue) |
|||
{ |
|||
int cnt = progress >= 1d ? newValue.Count : oldValue.Count; |
|||
if (cnt == 0) |
|||
return new BoxShadows(); |
|||
|
|||
BoxShadow first; |
|||
if (oldValue.Count > 0 && newValue.Count > 0) |
|||
first = s_boxShadowAnimator.Interpolate(progress, oldValue[0], newValue[0]); |
|||
else if (oldValue.Count > 0) |
|||
first = oldValue[0]; |
|||
else |
|||
first = newValue[0]; |
|||
|
|||
if (cnt == 1) |
|||
return new BoxShadows(first); |
|||
|
|||
var rest = new BoxShadow[cnt - 1]; |
|||
for (var c = 0; c < rest.Length; c++) |
|||
{ |
|||
var idx = c + 1; |
|||
if (oldValue.Count > idx && newValue.Count > idx) |
|||
rest[c] = s_boxShadowAnimator.Interpolate(progress, oldValue[idx], newValue[idx]); |
|||
else if (oldValue.Count > idx) |
|||
rest[c] = oldValue[idx]; |
|||
else |
|||
rest[c] = newValue[idx]; |
|||
} |
|||
|
|||
return new BoxShadows(first, rest); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,137 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel; |
|||
using Avalonia.Animation.Animators; |
|||
|
|||
namespace Avalonia.Media |
|||
{ |
|||
public struct BoxShadows |
|||
{ |
|||
private readonly BoxShadow _first; |
|||
private readonly BoxShadow[] _list; |
|||
public int Count { get; } |
|||
|
|||
static BoxShadows() |
|||
{ |
|||
Animation.Animation.RegisterAnimator<BoxShadowsAnimator>(prop => |
|||
typeof(BoxShadows).IsAssignableFrom(prop.PropertyType)); |
|||
} |
|||
|
|||
public BoxShadows(BoxShadow shadow) |
|||
{ |
|||
_first = shadow; |
|||
_list = null; |
|||
Count = 1; |
|||
} |
|||
|
|||
public BoxShadows(BoxShadow first, BoxShadow[] rest) |
|||
{ |
|||
_first = first; |
|||
_list = rest; |
|||
Count = 1 + (rest?.Length ?? 0); |
|||
} |
|||
|
|||
public BoxShadow this[int c] |
|||
{ |
|||
get |
|||
{ |
|||
if (c< 0 || c >= Count) |
|||
throw new IndexOutOfRangeException(); |
|||
if (c == 0) |
|||
return _first; |
|||
return _list[c - 1]; |
|||
} |
|||
} |
|||
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public struct BoxShadowsEnumerator |
|||
{ |
|||
private int _index; |
|||
private BoxShadows _shadows; |
|||
|
|||
public BoxShadowsEnumerator(BoxShadows shadows) |
|||
{ |
|||
_shadows = shadows; |
|||
_index = -1; |
|||
} |
|||
|
|||
public BoxShadow Current => _shadows[_index]; |
|||
|
|||
public bool MoveNext() |
|||
{ |
|||
_index++; |
|||
return _index < _shadows.Count; |
|||
} |
|||
} |
|||
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public BoxShadowsEnumerator GetEnumerator() => new BoxShadowsEnumerator(this); |
|||
|
|||
private static readonly char[] s_Separators = new[] { ',' }; |
|||
public static BoxShadows Parse(string s) |
|||
{ |
|||
var sp = s.Split(s_Separators, StringSplitOptions.RemoveEmptyEntries); |
|||
if (sp.Length == 0 |
|||
|| (sp.Length == 1 && |
|||
(string.IsNullOrWhiteSpace(sp[0]) |
|||
|| sp[0] == "none"))) |
|||
return new BoxShadows(); |
|||
|
|||
var first = BoxShadow.Parse(sp[0]); |
|||
if (sp.Length == 1) |
|||
return new BoxShadows(first); |
|||
|
|||
var rest = new BoxShadow[sp.Length - 1]; |
|||
for (var c = 0; c < rest.Length; c++) |
|||
rest[c] = BoxShadow.Parse(sp[c + 1]); |
|||
return new BoxShadows(first, rest); |
|||
} |
|||
|
|||
public Rect TransformBounds(in Rect rect) |
|||
{ |
|||
var final = rect; |
|||
foreach (var shadow in this) |
|||
final = final.Union(shadow.TransformBounds(rect)); |
|||
return final; |
|||
} |
|||
|
|||
public bool HasInsetShadows |
|||
{ |
|||
get |
|||
{ |
|||
foreach(var boxShadow in this) |
|||
if (!boxShadow.IsEmpty && boxShadow.IsInset) |
|||
return true; |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
public static implicit operator BoxShadows(BoxShadow shadow) => new BoxShadows(shadow); |
|||
|
|||
public bool Equals(BoxShadows other) |
|||
{ |
|||
if (other.Count != Count) |
|||
return false; |
|||
for(var c=0; c<Count ; c++) |
|||
if (!this[c].Equals(other[c])) |
|||
return false; |
|||
return true; |
|||
} |
|||
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return obj is BoxShadows other && Equals(other); |
|||
} |
|||
|
|||
public override int GetHashCode() |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hashCode = 0; |
|||
foreach (var s in this) |
|||
hashCode = (hashCode * 397) ^ s.GetHashCode(); |
|||
return hashCode; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue