Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 3484 was 3390, checked in by swagner, 15 years ago

Refactored HeuristicLab.Collections (#977)

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