diff --git a/Dashboard.Common/Gradient.cs b/Dashboard.Common/Drawing/Gradient.cs similarity index 67% rename from Dashboard.Common/Gradient.cs rename to Dashboard.Common/Drawing/Gradient.cs index cf27537..ff59c7e 100644 --- a/Dashboard.Common/Gradient.cs +++ b/Dashboard.Common/Drawing/Gradient.cs @@ -1,9 +1,11 @@ using System.Collections; -using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; using System.Drawing; using System.Numerics; +using System.Runtime.CompilerServices; -namespace Dashboard +namespace Dashboard.Drawing { /// /// Enumeration of the kinds of gradients available. @@ -25,29 +27,41 @@ namespace Dashboard /// /// The position of the gradient stop. Must be [0,1]. /// The color value for the stop. - public record struct GradientStop(float Position, Color Color); + public readonly record struct GradientStop(float Position, Color Color); /// /// Represents a linear gradient. /// - public struct Gradient : ICollection, ICloneable, IEquatable + public class Gradient : ICollection, ICloneable, IEquatable, INotifyPropertyChanged, INotifyCollectionChanged { private readonly List _stops = new List(); /// /// Gradient type. /// - public GradientType Type { get; set; } = GradientType.Axial; + public GradientType Type + { + get; + set => SetField(ref field, value); + } = GradientType.Axial; /// /// First gradient control point. /// - public Vector2 C0 { get; set; } = Vector2.Zero; + public Vector2 C0 + { + get; + set => SetField(ref field, value); + } = Vector2.Zero; /// /// Second gradient control point. /// - public Vector2 C1 { get; set; } = Vector2.One; + public Vector2 C1 + { + get; + set => SetField(ref field, value); + } = Vector2.One; /// /// Number of stops in a gradient. @@ -69,6 +83,10 @@ namespace Dashboard } } + public event PropertyChangedEventHandler? PropertyChanged; + public event NotifyCollectionChangedEventHandler? CollectionChanged; + + public Gradient() { } @@ -164,11 +182,13 @@ namespace Dashboard index = _stops.Count; _stops.Insert(index, item); + OnCollectionChanged(NotifyCollectionChangedAction.Add); } public void Clear() { _stops.Clear(); + OnCollectionChanged(NotifyCollectionChangedAction.Reset); } public bool Contains(GradientStop item) @@ -183,30 +203,51 @@ namespace Dashboard public bool Remove(GradientStop item) { - return _stops.Remove(item); + if (!_stops.Remove(item)) + return false; + + OnCollectionChanged(NotifyCollectionChangedAction.Remove); + return true; } public void RemoveAt(int index) { _stops.RemoveAt(index); + OnCollectionChanged(NotifyCollectionChangedAction.Remove); } public override int GetHashCode() { HashCode code = new HashCode(); + code.Add(Count); + code.Add(Type); + code.Add(C0); + code.Add(C1); + foreach (GradientStop item in this) code.Add(item.GetHashCode()); return code.ToHashCode(); } - public bool Equals(Gradient other) + public bool Equals(Gradient? other) { return + other != null && Type == other.Type && C0 == other.C0 && C1 == other.C1 && - _stops.Equals(other._stops); + _stops.SequenceEqual(other._stops); + } + + private bool NotEquals(Gradient? other) + { + return + other == null || + Type != other.Type || + C0 != other.C0 || + C1 != other.C1 || + !_stops.SequenceEqual(other._stops); } public override bool Equals(object? obj) @@ -214,14 +255,30 @@ namespace Dashboard return obj is Gradient other && Equals(other); } - public static bool operator ==(Gradient left, Gradient right) + public static bool operator ==(Gradient? left, Gradient? right) { - return left.Equals(right); + return left?.Equals(right) ?? right == null; } - public static bool operator !=(Gradient left, Gradient right) + public static bool operator !=(Gradient? left, Gradient? right) { - return !left.Equals(right); + return left?.NotEquals(right) ?? right != null; + } + + protected void SetField(ref T field, T value, [CallerMemberName] string name = "") + { + field = value; + OnPropertyChanged(name); + } + + protected virtual void OnPropertyChanged(string property) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); + } + + protected virtual void OnCollectionChanged(NotifyCollectionChangedAction action) + { + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(action)); } } }