From eead352af26d0fcc5cac147d0eb5ec384854d931 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 21 Apr 2018 20:37:17 -0400 Subject: rewrite world/player state tracking (#453) --- .../FieldWatchers/ObservableCollectionWatcher.cs | 86 ++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/SMAPI/Framework/StateTracking/FieldWatchers/ObservableCollectionWatcher.cs (limited to 'src/SMAPI/Framework/StateTracking/FieldWatchers/ObservableCollectionWatcher.cs') diff --git a/src/SMAPI/Framework/StateTracking/FieldWatchers/ObservableCollectionWatcher.cs b/src/SMAPI/Framework/StateTracking/FieldWatchers/ObservableCollectionWatcher.cs new file mode 100644 index 00000000..34a97097 --- /dev/null +++ b/src/SMAPI/Framework/StateTracking/FieldWatchers/ObservableCollectionWatcher.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.Linq; + +namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers +{ + /// A watcher which detects changes to an observable collection. + internal class ObservableCollectionWatcher : BaseDisposableWatcher, ICollectionWatcher + { + /********* + ** Properties + *********/ + /// The field being watched. + private readonly ObservableCollection Field; + + /// The pairs added since the last reset. + private readonly List AddedImpl = new List(); + + /// The pairs demoved since the last reset. + private readonly List RemovedImpl = new List(); + + + /********* + ** Accessors + *********/ + /// Whether the collection changed since the last reset. + public bool IsChanged => this.AddedImpl.Count > 0 || this.RemovedImpl.Count > 0; + + /// The values added since the last reset. + public IEnumerable Added => this.AddedImpl; + + /// The values removed since the last reset. + public IEnumerable Removed => this.RemovedImpl; + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The field to watch. + public ObservableCollectionWatcher(ObservableCollection field) + { + this.Field = field; + field.CollectionChanged += this.OnCollectionChanged; + } + + /// Update the current value if needed. + public void Update() + { + this.AssertNotDisposed(); + } + + /// Set the current value as the baseline. + public void Reset() + { + this.AssertNotDisposed(); + + this.AddedImpl.Clear(); + this.RemovedImpl.Clear(); + } + + /// Stop watching the field and release all references. + public override void Dispose() + { + if (!this.IsDisposed) + this.Field.CollectionChanged -= this.OnCollectionChanged; + base.Dispose(); + } + + + /********* + ** Private methods + *********/ + /// A callback invoked when an entry is added or removed from the collection. + /// The event sender. + /// The event arguments. + private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (e.NewItems != null) + this.AddedImpl.AddRange(e.NewItems.Cast()); + if (e.OldItems != null) + this.RemovedImpl.AddRange(e.OldItems.Cast()); + } + } +} -- cgit