// -----------------------------------------------------------------------
//
// Copyright 2014 MIT Licence. See licence.md for more information.
//
// -----------------------------------------------------------------------
namespace Perspex
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
public class PerspexList : IList, IList, IReadOnlyPerspexList, INotifyCollectionChanged, INotifyPropertyChanged
{
private List inner;
public PerspexList()
: this(Enumerable.Empty())
{
}
public PerspexList(IEnumerable items)
{
this.inner = new List(items);
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
public event PropertyChangedEventHandler PropertyChanged;
public int Count
{
get { return this.inner.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
bool IList.IsFixedSize
{
get { return false; }
}
bool IList.IsReadOnly
{
get { return false; }
}
int ICollection.Count
{
get { return this.inner.Count; }
}
bool ICollection.IsSynchronized
{
get { return false; }
}
object ICollection.SyncRoot
{
get { return null; }
}
public T this[int index]
{
get
{
return this.inner[index];
}
set
{
T old = this.inner[index];
this.inner[index] = value;
if (this.CollectionChanged != null)
{
var e = new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Replace,
value,
old);
this.CollectionChanged(this, e);
}
}
}
object IList.this[int index]
{
get { return this[index]; }
set { this[index] = (T)value; }
}
public void Add(T item)
{
int index = this.inner.Count;
this.inner.Add(item);
this.NotifyAdd(new[] { item }, index);
}
public void AddRange(IEnumerable items)
{
int index = this.inner.Count;
this.inner.AddRange(items);
this.NotifyAdd((items as IList) ?? items.ToList(), index);
}
public void Clear()
{
var old = this.inner;
this.inner = new List();
this.NotifyRemove(old, 0);
}
public bool Contains(T item)
{
return this.inner.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
this.inner.CopyTo(array, arrayIndex);
}
public IEnumerator GetEnumerator()
{
return this.inner.GetEnumerator();
}
public int IndexOf(T item)
{
return this.inner.IndexOf(item);
}
public void Insert(int index, T item)
{
this.inner.Insert(index, item);
this.NotifyAdd(new[] { item }, index);
}
public void InsertRange(int index, IEnumerable items)
{
this.inner.InsertRange(index, items);
this.NotifyAdd((items as IList) ?? items.ToList(), index);
}
public bool Remove(T item)
{
int index = this.inner.IndexOf(item);
if (index != -1)
{
this.inner.RemoveAt(index);
this.NotifyRemove(new[] { item }, index);
return true;
}
return false;
}
public void RemoveAll(IEnumerable items)
{
List removed = new List();
foreach (var i in items)
{
// TODO: Optimize to only send as many notifications as necessary.
this.Remove(i);
}
}
public void RemoveAt(int index)
{
T item = this.inner[index];
this.inner.RemoveAt(index);
this.NotifyRemove(new[] { item }, index);
}
int IList.Add(object value)
{
int index = this.Count;
this.Add((T)value);
return index;
}
bool IList.Contains(object value)
{
return this.Contains((T)value);
}
void IList.Clear()
{
this.Clear();
}
int IList.IndexOf(object value)
{
return this.IndexOf((T)value);
}
void IList.Insert(int index, object value)
{
this.Insert(index, (T)value);
}
void IList.Remove(object value)
{
this.Remove((T)value);
}
void IList.RemoveAt(int index)
{
this.RemoveAt(index);
}
void ICollection.CopyTo(Array array, int index)
{
this.inner.CopyTo((T[])array, index);
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.inner.GetEnumerator();
}
private void NotifyAdd(IList t, int index)
{
if (this.CollectionChanged != null)
{
var e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, t, index);
this.CollectionChanged(this, e);
}
this.NotifyCountChanged();
}
private void NotifyCountChanged()
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs("Count"));
}
}
private void NotifyRemove(IList t, int index)
{
if (this.CollectionChanged != null)
{
var e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, t, index);
this.CollectionChanged(this, e);
}
this.NotifyCountChanged();
}
}
}