Last active
August 29, 2015 14:17
-
-
Save chiepomme/3057e64762f126becc62 to your computer and use it in GitHub Desktop.
まねっこ ObservableCollection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using System.Collections.ObjectModel; | |
using System.Linq; | |
using UnityEngine.Events; | |
namespace Chiepomme | |
{ | |
public enum ChangeAction | |
{ | |
Add, | |
Update, | |
Remove, | |
Reset, | |
} | |
// imitating C# ObservableCollection<T> | |
// see https://msdn.microsoft.com/ja-jp/library/ms668604(v=vs.110).aspx | |
public class CollectionChange<T> | |
{ | |
public readonly ChangeAction Action; | |
public readonly IEnumerable<T> NewItems; | |
public readonly int NewStartingIndex; | |
public readonly IEnumerable<T> OldItems; | |
public readonly int OldStartingIndex; | |
CollectionChange(ChangeAction action, | |
IEnumerable<T> newItems = null, int newStartingIndex = 0, | |
IEnumerable<T> oldItems = null, int oldStartingIndex = 0) | |
{ | |
Action = action; | |
NewItems = newItems ?? new T[0]; | |
NewStartingIndex = newStartingIndex; | |
OldItems = oldItems ?? new T[0]; | |
OldStartingIndex = oldStartingIndex; | |
} | |
static public CollectionChange<T> CreateAdd(int startingIndex, T addedItem) | |
{ | |
return new CollectionChange<T>(ChangeAction.Add, | |
newStartingIndex: startingIndex, newItems: new[] { addedItem }); | |
} | |
static public CollectionChange<T> CreateAdd(int startingIndex, IEnumerable<T> addedItems) | |
{ | |
return new CollectionChange<T>(ChangeAction.Add, | |
newStartingIndex: startingIndex, newItems: addedItems); | |
} | |
static public CollectionChange<T> CreateUpdate(int replacedIndex, T oldItem, T newItem) | |
{ | |
return new CollectionChange<T>(ChangeAction.Update, | |
oldStartingIndex: replacedIndex, oldItems: new[] { oldItem }, | |
newStartingIndex: replacedIndex, newItems: new[] { newItem }); | |
} | |
static public CollectionChange<T> CreateRemove(int startingIndex, T removedItem) | |
{ | |
return new CollectionChange<T>(ChangeAction.Remove, | |
oldStartingIndex: startingIndex, oldItems: new[] { removedItem }); | |
} | |
static public CollectionChange<T> CreateRemove(int startingIndex, IEnumerable<T> removedItems) | |
{ | |
return new CollectionChange<T>(ChangeAction.Remove, | |
oldStartingIndex: startingIndex, oldItems: removedItems); | |
} | |
static public CollectionChange<T> CreateReset(IEnumerable<T> oldItems, IEnumerable<T> newItems) | |
{ | |
return new CollectionChange<T>(ChangeAction.Reset, | |
oldStartingIndex: 0, oldItems: oldItems, | |
newStartingIndex: 0, newItems: newItems); | |
} | |
} | |
public class ObservableList<T> : UnityEvent<CollectionChange<T>>, IList<T> | |
{ | |
List<T> v; | |
public ReadOnlyCollection<T> Collection | |
{ | |
get { return v.AsReadOnly(); } | |
} | |
public ObservableList() | |
{ | |
v = new List<T>(); | |
} | |
public ObservableList(IEnumerable<T> collection) | |
{ | |
v = collection.ToList(); | |
} | |
/// <summary> event: Reset </summary> | |
public void Replace(IEnumerable<T> collection) | |
{ | |
var oldItems = v.AsEnumerable(); | |
v = collection.ToList(); | |
Notify(CollectionChange<T>.CreateReset(oldItems, v.ToArray())); | |
} | |
/// <summary> event: Add </summary> | |
public void Add(T item) | |
{ | |
var index = v.Count; | |
v.Add(item); | |
Notify(CollectionChange<T>.CreateAdd(index, item)); | |
} | |
/// <summary> event: Remove </summary> | |
public bool Remove(T item) | |
{ | |
var index = v.IndexOf(item); | |
if (index == -1) return false; | |
RemoveAt(index); | |
return true; | |
} | |
public int IndexOf(T item) | |
{ | |
return v.IndexOf(item); | |
} | |
/// <summary> event: Add </summary> | |
public void Insert(int index, T item) | |
{ | |
v.Insert(index, item); | |
Notify(CollectionChange<T>.CreateAdd(index, item)); | |
} | |
/// <summary> event: Remove </summary> | |
public void RemoveAt(int index) | |
{ | |
var removedItem = v[index]; | |
v.RemoveAt(index); | |
Notify(CollectionChange<T>.CreateRemove(index, removedItem)); | |
} | |
/// <summary> event: Update </summary> | |
public T this[int index] | |
{ | |
get | |
{ | |
return v[index]; | |
} | |
set | |
{ | |
var oldItem = v[index]; | |
v[index] = value; | |
Notify(CollectionChange<T>.CreateUpdate(index, oldItem, value)); | |
} | |
} | |
/// <summary> event: Reset </summary> | |
public void Clear() | |
{ | |
if (v.Count == 0) return; | |
var oldItems = v.ToArray(); | |
v.Clear(); | |
Notify(CollectionChange<T>.CreateReset(oldItems, new T[0])); | |
} | |
public bool Contains(T item) | |
{ | |
return v.Contains(item); | |
} | |
public void CopyTo(T[] array, int arrayIndex) | |
{ | |
v.CopyTo(array, arrayIndex); | |
} | |
public int Count | |
{ | |
get { return v.Count; } | |
} | |
public bool IsReadOnly | |
{ | |
get { return false; } | |
} | |
public IEnumerator<T> GetEnumerator() | |
{ | |
return v.GetEnumerator(); | |
} | |
IEnumerator IEnumerable.GetEnumerator() | |
{ | |
return v.GetEnumerator(); | |
} | |
void Notify(CollectionChange<T> change) | |
{ | |
Invoke(change); | |
} | |
/// <summary> event: Reset </summary> | |
public void BindListener(UnityAction<CollectionChange<T>> listener) | |
{ | |
AddListener(listener); | |
listener(CollectionChange<T>.CreateReset(new T[0], v.ToArray())); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment