Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 2737 was 2623, checked in by swagner, 14 years ago

Worked on HeuristicLab.Collections (#819)

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