Files
UltimateFishing/Assets/Scripts/Assembly-CSharp/UIWidgets/ObservableList.cs
2026-02-21 16:45:37 +08:00

571 lines
11 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using UnityEngine;
namespace UIWidgets
{
[Serializable]
public class ObservableList<T> : IObservableList<T>, IList<T>, IObservable, ICollectionChanged, ICollectionItemChanged, IDisposable, IEnumerable, ICollection<T>, IEnumerable<T>
{
public bool ResortOnCollectionChanged = true;
public bool ResortOnCollectionItemChanged = true;
private Comparison<T> comparison;
[SerializeField]
protected List<T> Items;
private bool IsItemsDisposable;
private bool IsItemsObservable;
private bool IsItemsSupportNotifyPropertyChanged;
private bool isCollectionChanged;
private bool isCollectionItemChanged;
private bool isChanged;
private bool inUpdate;
private bool disposed;
public Comparison<T> Comparison
{
get
{
return comparison;
}
set
{
comparison = value;
if (comparison != null)
{
if (ResortOnCollectionChanged)
{
CollectionChanged();
}
else if (ResortOnCollectionItemChanged)
{
CollectionItemChanged();
}
}
}
}
public int Count
{
get
{
return Items.Count;
}
}
public bool IsReadOnly
{
get
{
return false;
}
}
public T this[int index]
{
get
{
return Items[index];
}
set
{
RemoveCallback(Items[index]);
Items[index] = value;
AddCallback(Items[index]);
CollectionChanged();
}
}
public event OnChange OnChange;
public event OnChange OnCollectionChange;
public event OnChange OnCollectionItemChange;
public ObservableList(bool observeItems = true)
{
IsItemsDisposable = observeItems && typeof(IDisposable).IsAssignableFrom(typeof(T));
IsItemsObservable = observeItems && typeof(IObservable).IsAssignableFrom(typeof(T));
IsItemsSupportNotifyPropertyChanged = typeof(INotifyPropertyChanged).IsAssignableFrom(typeof(T));
Items = new List<T>();
}
public ObservableList(IEnumerable<T> enumerable, bool observeItems = true)
{
IsItemsDisposable = observeItems && typeof(IDisposable).IsAssignableFrom(typeof(T));
IsItemsObservable = observeItems && typeof(IObservable).IsAssignableFrom(typeof(T));
IsItemsSupportNotifyPropertyChanged = typeof(INotifyPropertyChanged).IsAssignableFrom(typeof(T));
Items = new List<T>(enumerable);
AddCallbacks(Items);
}
private void AddCallbacks(IEnumerable<T> items)
{
items.ForEach(AddCallback);
}
private void AddCallback(T item)
{
if (IsItemsObservable)
{
(item as IObservable).OnChange += CollectionItemChanged;
}
else if (IsItemsSupportNotifyPropertyChanged)
{
(item as INotifyPropertyChanged).PropertyChanged += ItemPropertyChanged;
}
}
private void RemoveCallbacks(IEnumerable<T> items)
{
if (IsItemsObservable)
{
items.ForEach(delegate(T x)
{
(x as IObservable).OnChange -= CollectionItemChanged;
});
}
else if (IsItemsSupportNotifyPropertyChanged)
{
items.ForEach(delegate(T x)
{
(x as INotifyPropertyChanged).PropertyChanged -= ItemPropertyChanged;
});
}
}
private void RemoveCallback(T item)
{
if (IsItemsObservable)
{
(item as IObservable).OnChange -= CollectionItemChanged;
}
else if (IsItemsSupportNotifyPropertyChanged)
{
(item as INotifyPropertyChanged).PropertyChanged -= ItemPropertyChanged;
}
}
private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
CollectionItemChanged();
}
public void CollectionChanged()
{
CollectionChanged(true);
}
private void CollectionChanged(bool reSort)
{
if (inUpdate)
{
isCollectionChanged = true;
isChanged = true;
return;
}
if (reSort && ResortOnCollectionChanged && comparison != null)
{
Items.Sort(comparison);
}
if (this.OnCollectionChange != null)
{
this.OnCollectionChange();
}
if (this.OnChange != null)
{
this.OnChange();
}
}
public void CollectionItemChanged()
{
if (inUpdate)
{
isCollectionItemChanged = true;
isChanged = true;
return;
}
if (ResortOnCollectionItemChanged && comparison != null)
{
Items.Sort(comparison);
}
if (this.OnCollectionItemChange != null)
{
this.OnCollectionItemChange();
}
if (this.OnChange != null)
{
this.OnChange();
}
}
[Obsolete("Use CollectionChanged() or CollectionItemChanged()")]
public void Changed()
{
if (inUpdate)
{
isChanged = true;
}
else if (this.OnChange != null)
{
this.OnChange();
}
}
public void BeginUpdate()
{
inUpdate = true;
isChanged = false;
isCollectionChanged = false;
isCollectionItemChanged = false;
}
public void EndUpdate()
{
inUpdate = false;
if (((isCollectionChanged && ResortOnCollectionItemChanged) || (isCollectionItemChanged && ResortOnCollectionItemChanged)) && comparison != null)
{
Items.Sort(comparison);
}
if (isCollectionChanged && this.OnCollectionChange != null)
{
isCollectionChanged = false;
this.OnCollectionChange();
}
if (isCollectionItemChanged && this.OnCollectionItemChange != null)
{
isCollectionItemChanged = false;
this.OnCollectionItemChange();
}
if (isChanged && this.OnChange != null)
{
isChanged = false;
this.OnChange();
}
}
public void Add(T item)
{
Items.Add(item);
AddCallback(item);
CollectionChanged();
}
public void Clear()
{
RemoveCallbacks(Items);
Items.Clear();
CollectionChanged();
}
public bool Contains(T item)
{
return Items.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
Items.CopyTo(array, arrayIndex);
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return Items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)Items).GetEnumerator();
}
public int IndexOf(T item)
{
return Items.IndexOf(item);
}
public void Insert(int index, T item)
{
Items.Insert(index, item);
AddCallback(item);
CollectionChanged();
}
public bool Remove(T item)
{
bool flag = Items.Remove(item);
if (flag)
{
RemoveCallback(item);
CollectionChanged();
}
return flag;
}
public void RemoveAt(int index)
{
RemoveCallback(Items[index]);
Items.RemoveAt(index);
CollectionChanged();
}
public void AddRange(IEnumerable<T> items)
{
Items.AddRange(items);
AddCallbacks(items);
CollectionChanged();
}
public ReadOnlyCollection<T> AsReadOnly()
{
return Items.AsReadOnly();
}
public int BinarySearch(T item)
{
return Items.BinarySearch(item);
}
public int BinarySearch(T item, IComparer<T> comparer)
{
return Items.BinarySearch(item, comparer);
}
public int BinarySearch(int index, int count, T item, IComparer<T> comparer)
{
return Items.BinarySearch(index, count, item, comparer);
}
public ObservableList<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter, bool observeItems = true)
{
return new ObservableList<TOutput>(Items.Convert(converter), observeItems);
}
public ObservableList<TOutput> Convert<TOutput>(Converter<T, TOutput> converter, bool observeItems = true)
{
return new ObservableList<TOutput>(Items.Convert(converter), observeItems);
}
public void CopyTo(T[] array)
{
Items.CopyTo(array);
}
public void CopyTo(int index, T[] array, int arrayIndex, int count)
{
Items.CopyTo(index, array, arrayIndex, count);
}
public bool Exists(Predicate<T> match)
{
return Items.Exists(match);
}
public T Find(Predicate<T> match)
{
return Items.Find(match);
}
public ObservableList<T> FindAll(Predicate<T> match, bool observeItems = true)
{
return new ObservableList<T>(Items.FindAll(match), observeItems);
}
public int FindIndex(Predicate<T> match)
{
return Items.FindIndex(match);
}
public int FindIndex(int startIndex, Predicate<T> match)
{
return Items.FindIndex(startIndex, match);
}
public int FindIndex(int startIndex, int count, Predicate<T> match)
{
return Items.FindIndex(startIndex, count, match);
}
public T FindLast(Predicate<T> match)
{
return Items.FindLast(match);
}
public int FindLastIndex(Predicate<T> match)
{
return Items.FindLastIndex(match);
}
public int FindLastIndex(int startIndex, Predicate<T> match)
{
return Items.FindLastIndex(startIndex, match);
}
public int FindLastIndex(int startIndex, int count, Predicate<T> match)
{
return Items.FindLastIndex(startIndex, count, match);
}
public void ForEach(Action<T> action)
{
Items.ForEach(action);
}
public ObservableList<T> GetRange(int index, int count, bool observeItems = true)
{
return new ObservableList<T>(Items.GetRange(index, count), observeItems);
}
public int IndexOf(T item, int index)
{
return Items.IndexOf(item, index);
}
public int IndexOf(T item, int index, int count)
{
return Items.IndexOf(item, index, count);
}
public void InsertRange(int index, IEnumerable<T> collection)
{
Items.InsertRange(index, collection);
AddCallbacks(collection);
CollectionChanged();
}
public int LastIndexOf(T item)
{
return Items.LastIndexOf(item);
}
public int LastIndexOf(T item, int index)
{
return Items.LastIndexOf(item, index);
}
public int LastIndexOf(T item, int index, int count)
{
return Items.LastIndexOf(item, index, count);
}
public int RemoveAll(Predicate<T> match)
{
RemoveCallbacks(Items.FindAll(match));
int result = Items.RemoveAll(match);
CollectionChanged();
return result;
}
public void RemoveRange(int index, int count)
{
RemoveCallbacks(Items.GetRange(index, count));
Items.RemoveRange(index, count);
CollectionChanged();
}
public void Reverse()
{
Items.Reverse();
CollectionChanged();
}
public void Reverse(int index, int count)
{
Items.Reverse(index, count);
CollectionChanged();
}
public void Sort()
{
Items.Sort();
CollectionChanged();
}
public void Sort(Comparison<T> comparison)
{
Items.Sort(comparison);
CollectionChanged();
}
public void Sort(IComparer<T> comparer)
{
Items.Sort(comparer);
CollectionChanged();
}
public void Sort(int index, int count, IComparer<T> comparer)
{
Items.Sort(index, count, comparer);
CollectionChanged();
}
public T[] ToArray()
{
return Items.ToArray();
}
public void TrimExcess()
{
Items.TrimExcess();
}
public bool TrueForAll(Predicate<T> match)
{
return Items.TrueForAll(match);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void DisposeItem(T item)
{
RemoveCallback(item);
if (IsItemsDisposable)
{
(item as IDisposable).Dispose();
}
}
protected virtual void Dispose(bool disposing)
{
ResortOnCollectionChanged = false;
ResortOnCollectionItemChanged = false;
if (!disposed)
{
if (disposing)
{
}
if (Items != null)
{
BeginUpdate();
Items.ForEach(DisposeItem);
EndUpdate();
Items = null;
}
disposed = true;
}
}
~ObservableList()
{
Dispose(false);
}
}
}