Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Collections/3.3/ObservableList.cs @ 5079

Last change on this file since 5079 was 3560, checked in by swagner, 14 years ago

Fixed persistence exceptions by restoring the reference on HeuristicLab.Persistence in HeuristicLab.Collections (#977)

File size: 16.1 KB
RevLine 
[2572]1#region License Information
2/* HeuristicLab
[2790]3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[2572]4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections;
24using System.Collections.Generic;
[2620]25using System.ComponentModel;
[3560]26using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
[2572]27
28namespace HeuristicLab.Collections {
[3560]29  [StorableClass]
[2572]30  [Serializable]
[2574]31  public class ObservableList<T> : IObservableList<T> {
[3560]32    [Storable]
[3286]33    protected List<T> list;
[2572]34
35    #region Properties
36    public int Capacity {
37      get { return list.Capacity; }
[2620]38      set {
39        if (list.Capacity != value) {
40          list.Capacity = value;
41          OnPropertyChanged("Capacity");
42        }
43      }
[2572]44    }
45    public int Count {
46      get { return list.Count; }
47    }
48    bool ICollection<T>.IsReadOnly {
49      get { return ((ICollection<T>)list).IsReadOnly; }
50    }
51
52    public T this[int index] {
53      get {
54        return list[index];
55      }
56      set {
57        T item = list[index];
[2745]58        if (!((item == null) && (value == null)) && ((item == null) || (!item.Equals(value)))) {
[2620]59          list[index] = value;
60          OnItemsReplaced(new IndexedItem<T>[] { new IndexedItem<T>(index, value) }, new IndexedItem<T>[] { new IndexedItem<T>(index, item) });
61          OnPropertyChanged("Item[]");
62        }
[2572]63      }
64    }
65    #endregion
66
67    #region Constructors
68    public ObservableList() {
69      list = new List<T>();
70    }
71    public ObservableList(int capacity) {
72      list = new List<T>(capacity);
73    }
74    public ObservableList(IEnumerable<T> collection) {
75      list = new List<T>(collection);
76    }
[3560]77    [StorableConstructor]
78    protected ObservableList(bool deserializing) { }
[2572]79    #endregion
80
81    #region Access
82    public List<T> GetRange(int index, int count) {
83      return list.GetRange(index, count);
84    }
85
86    public bool Contains(T item) {
87      return list.Contains(item);
88    }
89
90    public int IndexOf(T item) {
91      return list.IndexOf(item);
92    }
93    public int IndexOf(T item, int index) {
94      return list.IndexOf(item, index);
95    }
96    public int IndexOf(T item, int index, int count) {
97      return list.IndexOf(item, index, count);
98    }
99
100    public int LastIndexOf(T item) {
101      return list.LastIndexOf(item);
102    }
103    public int LastIndexOf(T item, int index) {
104      return list.LastIndexOf(item, index);
105    }
106    public int LastIndexOf(T item, int index, int count) {
107      return list.LastIndexOf(item, index, count);
108    }
109
110    public int BinarySearch(T item) {
111      return list.BinarySearch(item);
112    }
113    public int BinarySearch(T item, IComparer<T> comparer) {
114      return list.BinarySearch(item, comparer);
115    }
116    public int BinarySearch(int index, int count, T item, IComparer<T> comparer) {
117      return list.BinarySearch(index, count, item, comparer);
118    }
119
120    public bool Exists(Predicate<T> match) {
121      return list.Exists(match);
122    }
123
124    public T Find(Predicate<T> match) {
125      return list.Find(match);
126    }
127    public List<T> FindAll(Predicate<T> match) {
128      return list.FindAll(match);
129    }
130    public T FindLast(Predicate<T> match) {
131      return list.FindLast(match);
132    }
133
134    public int FindIndex(Predicate<T> match) {
135      return list.FindIndex(match);
136    }
137    public int FindIndex(int startIndex, Predicate<T> match) {
138      return list.FindIndex(startIndex, match);
139    }
140    public int FindIndex(int startIndex, int count, Predicate<T> match) {
141      return list.FindIndex(startIndex, count, match);
142    }
143
144    public int FindLastIndex(Predicate<T> match) {
145      return list.FindLastIndex(match);
146    }
147    public int FindLastIndex(int startIndex, Predicate<T> match) {
148      return list.FindLastIndex(startIndex, match);
149    }
150    public int FindLastIndex(int startIndex, int count, Predicate<T> match) {
151      return list.FindLastIndex(startIndex, count, match);
152    }
153    #endregion
154
155    #region Manipulation
156    public void Add(T item) {
[2620]157      int capacity = list.Capacity;
[2572]158      list.Add(item);
[2620]159      if (list.Capacity != capacity)
160        OnPropertyChanged("Capacity");
161      OnPropertyChanged("Item[]");
162      OnPropertyChanged("Count");
[2572]163      OnItemsAdded(new IndexedItem<T>[] { new IndexedItem<T>(list.Count - 1, item) });
[2623]164      OnItemsAdded(new T[] { item });
[2572]165    }
166    public void AddRange(IEnumerable<T> collection) {
[2620]167      int capacity = list.Capacity;
[2572]168      int index = list.Count;
169      list.AddRange(collection);
170      List<IndexedItem<T>> items = new List<IndexedItem<T>>();
171      foreach (T item in collection) {
172        items.Add(new IndexedItem<T>(index, item));
173        index++;
174      }
[2620]175      if (items.Count > 0) {
176        if (list.Capacity != capacity)
177          OnPropertyChanged("Capacity");
178        OnPropertyChanged("Item[]");
179        OnPropertyChanged("Count");
180        OnItemsAdded(items);
[2623]181        OnItemsAdded(collection);
[2620]182      }
[2572]183    }
184
185    public void Insert(int index, T item) {
[2620]186      int capacity = list.Capacity;
[2572]187      list.Insert(index, item);
[2620]188      if (list.Capacity != capacity)
189        OnPropertyChanged("Capacity");
190      OnPropertyChanged("Item[]");
191      OnPropertyChanged("Count");
[2572]192      OnItemsAdded(new IndexedItem<T>[] { new IndexedItem<T>(index, item) });
[2623]193      OnItemsAdded(new T[] { item });
[2572]194    }
195    public void InsertRange(int index, IEnumerable<T> collection) {
[2620]196      int capacity = list.Capacity;
[2572]197      list.InsertRange(index, collection);
198      List<IndexedItem<T>> items = new List<IndexedItem<T>>();
199      foreach (T item in collection) {
200        items.Add(new IndexedItem<T>(index, item));
201        index++;
202      }
[2620]203      if (items.Count > 0) {
204        if (list.Capacity != capacity)
205          OnPropertyChanged("Capacity");
206        OnPropertyChanged("Item[]");
207        OnPropertyChanged("Count");
208        OnItemsAdded(items);
[2623]209        OnItemsAdded(collection);
[2620]210      }
[2572]211    }
212
213    public bool Remove(T item) {
214      int index = list.IndexOf(item);
215      if (index != -1) {
216        list.RemoveAt(index);
[2620]217        OnPropertyChanged("Item[]");
218        OnPropertyChanged("Count");
[2572]219        OnItemsRemoved(new IndexedItem<T>[] { new IndexedItem<T>(index, item) });
[2623]220        OnItemsRemoved(new T[] { item });
[2572]221        return true;
222      }
223      return false;
224    }
225    public int RemoveAll(Predicate<T> match) {
[2573]226      if (match == null) throw new ArgumentNullException();
[2623]227      List<IndexedItem<T>> indexedItems = new List<IndexedItem<T>>();
228      List<T> items = new List<T>();
[2572]229      for (int i = 0; i < list.Count; i++) {
[2623]230        if (match(list[i])) {
231          indexedItems.Add(new IndexedItem<T>(i, list[i]));
232          items.Add(list[i]);
233        }
[2572]234      }
[2620]235      int result = 0;
[2623]236      if (indexedItems.Count > 0) {
[2620]237        result = list.RemoveAll(match);
238        OnPropertyChanged("Item[]");
239        OnPropertyChanged("Count");
[2623]240        OnItemsRemoved(indexedItems);
[2620]241        OnItemsRemoved(items);
242      }
[2572]243      return result;
244    }
245    public void RemoveAt(int index) {
246      T item = list[index];
247      list.RemoveAt(index);
[2620]248      OnPropertyChanged("Item[]");
249      OnPropertyChanged("Count");
[2572]250      OnItemsRemoved(new IndexedItem<T>[] { new IndexedItem<T>(index, item) });
[2623]251      OnItemsRemoved(new T[] { item });
[2572]252    }
253    public void RemoveRange(int index, int count) {
[2620]254      if (count > 0) {
[2623]255        IndexedItem<T>[] indexedItems = GetIndexedItems(index, count);
256        T[] items = new T[count];
257        list.CopyTo(index, items, 0, count);
[2620]258        list.RemoveRange(index, count);
259        OnPropertyChanged("Item[]");
260        OnPropertyChanged("Count");
[2623]261        OnItemsRemoved(indexedItems);
[2620]262        OnItemsRemoved(items);
263      }
[2572]264    }
265
266    public void Clear() {
[2620]267      if (list.Count > 0) {
[2623]268        IndexedItem<T>[] indexedItems = GetIndexedItems();
269        T[] items = list.ToArray();
[2620]270        list.Clear();
271        OnPropertyChanged("Item[]");
272        OnPropertyChanged("Count");
[2623]273        OnCollectionReset(new IndexedItem<T>[0], indexedItems);
274        OnCollectionReset(new T[0], items);
[2620]275      }
[2572]276    }
277
278    public void Reverse() {
[2620]279      if (list.Count > 1) {
280        IndexedItem<T>[] oldItems = GetIndexedItems();
281        list.Reverse();
282        OnPropertyChanged("Item[]");
283        OnItemsMoved(GetIndexedItems(), oldItems);
284      }
[2572]285    }
286    public void Reverse(int index, int count) {
[2620]287      if (count > 1) {
288        IndexedItem<T>[] oldItems = GetIndexedItems(index, count);
289        list.Reverse(index, count);
290        OnPropertyChanged("Item[]");
291        OnItemsMoved(GetIndexedItems(index, count), oldItems);
292      }
[2572]293    }
294
295    public void Sort() {
[2620]296      if (list.Count > 1) {
297        IndexedItem<T>[] oldItems = GetIndexedItems();
298        list.Sort();
299        OnPropertyChanged("Item[]");
300        OnItemsMoved(GetIndexedItems(), oldItems);
301      }
[2572]302    }
303    public void Sort(Comparison<T> comparison) {
[2620]304      if (list.Count > 1) {
305        IndexedItem<T>[] oldItems = GetIndexedItems();
306        list.Sort(comparison);
307        OnPropertyChanged("Item[]");
308        OnItemsMoved(GetIndexedItems(), oldItems);
309      }
[2572]310    }
311    public void Sort(IComparer<T> comparer) {
[2620]312      if (list.Count > 1) {
313        IndexedItem<T>[] oldItems = GetIndexedItems();
314        list.Sort(comparer);
315        OnPropertyChanged("Item[]");
316        OnItemsMoved(GetIndexedItems(), oldItems);
317      }
[2572]318    }
319    public void Sort(int index, int count, IComparer<T> comparer) {
[2745]320      if (count > 1) {
[2620]321        IndexedItem<T>[] oldItems = GetIndexedItems(index, count);
322        list.Sort(index, count, comparer);
323        OnPropertyChanged("Item[]");
324        OnItemsMoved(GetIndexedItems(index, count), oldItems);
325      }
[2572]326    }
327    #endregion
328
329    #region Conversion
[2618]330    public ReadOnlyObservableList<T> AsReadOnly() {
331      return new ReadOnlyObservableList<T>(this);
[2572]332    }
333    public T[] ToArray() {
334      return list.ToArray();
335    }
[2623]336    public void CopyTo(T[] array) {
337      list.CopyTo(array);
338    }
339    public void CopyTo(T[] array, int arrayIndex) {
[2572]340      list.CopyTo(array, arrayIndex);
341    }
[2623]342    public void CopyTo(int index, T[] array, int arrayIndex, int count) {
343      list.CopyTo(index, array, arrayIndex, count);
344    }
[2572]345    public List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter) {
346      return list.ConvertAll<TOutput>(converter);
347    }
348    #endregion
349
350    #region Processing
351    public void ForEach(Action<T> action) {
352      list.ForEach(action);
353    }
354    public bool TrueForAll(Predicate<T> match) {
355      return list.TrueForAll(match);
356    }
357    #endregion
358
359    #region Enumeration
[2623]360    public IEnumerator<T> GetEnumerator() {
[2572]361      return list.GetEnumerator();
362    }
363    IEnumerator IEnumerable.GetEnumerator() {
[2623]364      return list.GetEnumerator();
[2572]365    }
366    #endregion
367
368    #region Helpers
369    public void TrimExcess() {
[2620]370      int capacity = list.Capacity;
[2572]371      list.TrimExcess();
[2620]372      if (list.Capacity != capacity)
373        OnPropertyChanged("Capacity");
[2572]374    }
375    #endregion
376
[2574]377    #region Events
378    [field: NonSerialized]
379    public event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsAdded;
380    protected virtual void OnItemsAdded(IEnumerable<IndexedItem<T>> items) {
[3317]381      CollectionItemsChangedEventHandler<IndexedItem<T>> handler = ItemsAdded;
382      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<IndexedItem<T>>(items));
[2574]383    }
384
385    [field: NonSerialized]
[2623]386    private event CollectionItemsChangedEventHandler<T> itemsAdded;
[2832]387    event CollectionItemsChangedEventHandler<T> INotifyObservableCollectionItemsChanged<T>.ItemsAdded {
[2623]388      add { itemsAdded += value; }
389      remove { itemsAdded -= value; }
390    }
391    private void OnItemsAdded(IEnumerable<T> items) {
[3317]392      CollectionItemsChangedEventHandler<T> handler = itemsAdded;
393      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<T>(items));
[2623]394    }
395
396    [field: NonSerialized]
[2574]397    public event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsRemoved;
398    protected virtual void OnItemsRemoved(IEnumerable<IndexedItem<T>> items) {
[3317]399      CollectionItemsChangedEventHandler<IndexedItem<T>> handler = ItemsRemoved;
400      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<IndexedItem<T>>(items));
[2574]401    }
402
403    [field: NonSerialized]
[2623]404    private event CollectionItemsChangedEventHandler<T> itemsRemoved;
[2832]405    event CollectionItemsChangedEventHandler<T> INotifyObservableCollectionItemsChanged<T>.ItemsRemoved {
[2623]406      add { itemsRemoved += value; }
407      remove { itemsRemoved -= value; }
408    }
409    private void OnItemsRemoved(IEnumerable<T> items) {
[3317]410      CollectionItemsChangedEventHandler<T> handler = itemsRemoved;
411      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<T>(items));
[2623]412    }
413
414    [field: NonSerialized]
[2574]415    public event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsReplaced;
416    protected virtual void OnItemsReplaced(IEnumerable<IndexedItem<T>> items, IEnumerable<IndexedItem<T>> oldItems) {
[3317]417      CollectionItemsChangedEventHandler<IndexedItem<T>> handler = ItemsReplaced;
418      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<IndexedItem<T>>(items, oldItems));
[2574]419    }
420
421    [field: NonSerialized]
422    public event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsMoved;
423    protected virtual void OnItemsMoved(IEnumerable<IndexedItem<T>> items, IEnumerable<IndexedItem<T>> oldItems) {
[3317]424      CollectionItemsChangedEventHandler<IndexedItem<T>> handler = ItemsMoved;
425      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<IndexedItem<T>>(items, oldItems));
[2574]426    }
427
428    [field: NonSerialized]
429    public event CollectionItemsChangedEventHandler<IndexedItem<T>> CollectionReset;
430    protected virtual void OnCollectionReset(IEnumerable<IndexedItem<T>> items, IEnumerable<IndexedItem<T>> oldItems) {
[3317]431      CollectionItemsChangedEventHandler<IndexedItem<T>> handler = CollectionReset;
432      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<IndexedItem<T>>(items, oldItems));
[2574]433    }
[2620]434
435    [field: NonSerialized]
[2623]436    private event CollectionItemsChangedEventHandler<T> collectionReset;
[2832]437    event CollectionItemsChangedEventHandler<T> INotifyObservableCollectionItemsChanged<T>.CollectionReset {
[2623]438      add { collectionReset += value; }
439      remove { collectionReset -= value; }
440    }
441    private void OnCollectionReset(IEnumerable<T> items, IEnumerable<T> oldItems) {
[3317]442      CollectionItemsChangedEventHandler<T> handler = collectionReset;
443      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<T>(items, oldItems));
[2623]444    }
445
446    [field: NonSerialized]
[2620]447    public event PropertyChangedEventHandler PropertyChanged;
448    protected virtual void OnPropertyChanged(string propertyName) {
[3317]449      PropertyChangedEventHandler handler = PropertyChanged;
450      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
[2620]451    }
[2574]452    #endregion
453
[2572]454    #region Private helpers
455    private IndexedItem<T>[] GetIndexedItems() {
456      IndexedItem<T>[] items = new IndexedItem<T>[list.Count];
457      for (int i = 0; i < list.Count; i++)
458        items[i] = new IndexedItem<T>(i, list[i]);
459      return items;
460    }
461    private IndexedItem<T>[] GetIndexedItems(int index, int count) {
462      IndexedItem<T>[] items = new IndexedItem<T>[count];
463      for (int i = 0; i < count; i++)
464        items[i] = new IndexedItem<T>(index + i, list[index + i]);
465      return items;
466    }
467    #endregion
468  }
469}
Note: See TracBrowser for help on using the repository browser.