using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Signum.Entities;
using System.Collections.ObjectModel;
using Signum.Utilities;
using Signum.Utilities.ExpressionTrees;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
namespace Signum.Entities
{
[Serializable, DebuggerTypeProxy(typeof(MListDebugging<>)), DebuggerDisplay("Count = {Count}")]
public class MList<T> : Modifiable, IList<T>, IList, INotifyCollectionChanged, INotifyPropertyChanged
{
int _hastCode = 0;
List<T> lista = new List<T>();
#region Eventos
[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
[field:NonSerialized]
public event NotifyCollectionChangedEventHandler CollectionChanged;
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Move:
case NotifyCollectionChangedAction.Replace:
OnPropertyChanged("Item[]");
break;
case NotifyCollectionChangedAction.Add:
case NotifyCollectionChangedAction.Remove:
case NotifyCollectionChangedAction.Reset:
OnPropertyChanged("Count");
OnPropertyChanged("Item[]");
break;
default:
break;
}
if (this.CollectionChanged != null)
{
this.CollectionChanged(this, e);
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
if(PropertyChanged!= null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
public override bool SelfModified
{
get
{
return _hastCode != GetHashCode();
}
internal set
{
if (value == false)
{
_hastCode = GetHashCode();
}
}
}
public override int GetHashCode()
{
long hash = 0;
foreach (var item in lista)
{
hash += item.GetHashCode();
}
return hash.GetHashCode();
}
public MList()
{
lista = new List<T>();
}
public MList(IEnumerable<T> collection)
{
lista = new List<T>(collection);
}
public MList(int capacity)
{
lista = new List<T>(capacity);
}
public int Count
{
get { return lista.Count; }
}
public T this[int index]
{
get { return lista[index]; }
set
{
T old = lista[index];
lista[index] = value;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, value, old));
}
}
public void Add(T item)
{
lista.Add(item);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
}
public void Add(params T[] items)
{
AddRange(items);
}
public void Add(IEnumerable<T> collection) // util para los inizializadores de objetos
{
AddRange(collection);
}
public void AddRange(IEnumerable<T> collection)
{
foreach (var item in collection)
Add(item);
}
public ReadOnlyCollection<T> AsReadOnly()
{
return lista.AsReadOnly();
}
public void Sort()
{
lista.Sort();
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public void Sort<S>(Func<T,S> element)
where S:IComparable<S>
{
lista.Sort((a, b) => element(a).CompareTo(element(b)));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public void SortDescending<S>(Func<T, S> element)
where S : IComparable<S>
{
lista.Sort((a, b) => element(b).CompareTo(element(a)));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public void Sort(Comparison<T> comparison)
{
lista.Sort(comparison);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public void Sort(IComparer<T> comparer)
{
lista.Sort(comparer);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public void Clear()
{
lista.Clear();
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public void CopyTo(T[] array)
{
lista.CopyTo(array);
}
public IEnumerator<T> GetEnumerator()
{
return lista.GetEnumerator();
}
public void Insert(int index, T item)
{
lista.Insert(index, item);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add,item, index));
}
public bool Remove(T item)
{
int index = lista.IndexOf(item);
if (index == -1) return false;
lista.RemoveAt(index);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item , index));
return true;
}
public int RemoveAll(Predicate<T> match)
{
var toRemove = lista.Where(a => match(a)).ToList();
foreach (var item in toRemove)
Remove(item);
return toRemove.Count;
}
public void RemoveAt(int index)
{
T item = lista[index];
lista.RemoveAt(index);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
}
public void RemoveRange(int index, int count)
{
for (int i = 0; i < count; i++)
RemoveAt(index);
}
public int IndexOf(T item)
{
return lista.IndexOf(item);
}
public bool Contains(T item)
{
return lista.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
lista.CopyTo(array, arrayIndex);
}
public bool IsReadOnly
{
get { return false; }
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public override string ToString()
{
return "{0}{{ Count = {1} }}".Formato(GetType().TypeName(), Count);
}
#region IList Members
int IList.Add(object value)
{
this.Add((T)value);
return 0;
}
bool IList.Contains(object value)
{
return this.Contains((T)value);
}
int IList.IndexOf(object value)
{
return this.IndexOf((T)value);
}
void IList.Insert(int index, object value)
{
this.Insert(index, (T)value);
}
bool IList.IsFixedSize
{
get { return false; }
}
void IList.Remove(object value)
{
this.Remove((T)value);
}
object IList.this[int index]
{
get { return this[index]; }
set { this[index] = (T)value; }
}
void ICollection.CopyTo(Array array, int index)
{
((ICollection)lista).CopyTo(array, index);
}
bool ICollection.IsSynchronized
{
get { return ((ICollection)lista).IsSynchronized; }
}
object ICollection.SyncRoot
{
get { return ((ICollection)lista).SyncRoot; }
}
#endregion
}
internal sealed class MListDebugging<T>
{
private ICollection<T> collection;
public MListDebugging(ICollection<T> collection)
{
this.collection = collection;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public T[] Items
{
get
{
T[] array = new T[this.collection.Count];
this.collection.CopyTo(array, 0);
return array;
}
}
}
public static class MListExtensions
{
public static MList<T> ToMList<T>(this IEnumerable<T> collection)
{
return new MList<T>(collection);
}
}
}