#region License Information /* HeuristicLab * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; namespace HeuristicLab.Collections { [StorableClass] [Serializable] public class ObservableCollection : IObservableCollection { [Storable] protected List list; #region Properties public int Capacity { get { return list.Capacity; } set { if (list.Capacity != value) { list.Capacity = value; OnPropertyChanged("Capacity"); } } } public int Count { get { return list.Count; } } bool ICollection.IsReadOnly { get { return ((ICollection)list).IsReadOnly; } } #endregion #region Constructors public ObservableCollection() { list = new List(); } public ObservableCollection(int capacity) { list = new List(capacity); } public ObservableCollection(IEnumerable collection) { list = new List(collection); } [StorableConstructor] protected ObservableCollection(bool deserializing) { } #endregion #region Access public bool Contains(T item) { return list.Contains(item); } public bool Exists(Predicate match) { return list.Exists(match); } public T Find(Predicate match) { return list.Find(match); } public ICollection FindAll(Predicate match) { return list.FindAll(match); } public T FindLast(Predicate match) { return list.FindLast(match); } #endregion #region Manipulation public void Add(T item) { int capacity = list.Capacity; list.Add(item); if (list.Capacity != capacity) OnPropertyChanged("Capacity"); OnPropertyChanged("Count"); OnItemsAdded(new T[] { item }); } public void AddRange(IEnumerable collection) { int capacity = list.Capacity; ICollection items = collection as ICollection ?? collection.ToList(); list.AddRange(items); if (items.Count > 0) { if (list.Capacity != capacity) OnPropertyChanged("Capacity"); OnPropertyChanged("Count"); OnItemsAdded(items); } } public bool Remove(T item) { if (list.Remove(item)) { OnPropertyChanged("Count"); OnItemsRemoved(new T[] { item }); return true; } return false; } public void RemoveRange(IEnumerable collection) { if (collection == null) throw new ArgumentNullException(); List items = new List(); foreach (T item in collection) { if (list.Remove(item)) items.Add(item); } if (items.Count > 0) { OnPropertyChanged("Count"); OnItemsRemoved(items); } } public int RemoveAll(Predicate match) { List items = list.FindAll(match); int result = 0; if (items.Count > 0) { result = list.RemoveAll(match); OnPropertyChanged("Count"); OnItemsRemoved(items); } return result; } public void Clear() { if (list.Count > 0) { T[] items = list.ToArray(); list.Clear(); OnPropertyChanged("Count"); OnCollectionReset(new T[0], items); } } #endregion #region Conversion public ReadOnlyObservableCollection AsReadOnly() { return new ReadOnlyObservableCollection(this); } public T[] ToArray() { return list.ToArray(); } public void CopyTo(T[] array, int arrayIndex) { list.CopyTo(array, arrayIndex); } public ICollection ConvertAll(Converter converter) { return list.ConvertAll(converter); } #endregion #region Processing public void ForEach(Action action) { list.ForEach(action); } public bool TrueForAll(Predicate match) { return list.TrueForAll(match); } #endregion #region Enumeration public IEnumerator GetEnumerator() { return ((IEnumerable)list).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)list).GetEnumerator(); } #endregion #region Helpers public void TrimExcess() { int capacity = list.Capacity; list.TrimExcess(); if (list.Capacity != capacity) OnPropertyChanged("Capacity"); } #endregion #region Events [field: NonSerialized] public event CollectionItemsChangedEventHandler ItemsAdded; protected virtual void OnItemsAdded(IEnumerable items) { CollectionItemsChangedEventHandler handler = ItemsAdded; if (handler != null) handler(this, new CollectionItemsChangedEventArgs(items)); } [field: NonSerialized] public event CollectionItemsChangedEventHandler ItemsRemoved; protected virtual void OnItemsRemoved(IEnumerable items) { CollectionItemsChangedEventHandler handler = ItemsRemoved; if (handler != null) handler(this, new CollectionItemsChangedEventArgs(items)); } [field: NonSerialized] public event CollectionItemsChangedEventHandler CollectionReset; protected virtual void OnCollectionReset(IEnumerable items, IEnumerable oldItems) { CollectionItemsChangedEventHandler handler = CollectionReset; if (handler != null) handler(this, new CollectionItemsChangedEventArgs(items, oldItems)); } [field: NonSerialized] public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } #endregion } }