Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 3080 was 3017, checked in by epitzer, 15 years ago

Merge StorableClassType.Empty into StorableClassType.MarkedOnly and make it the default if not specified (#548)

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