Free cookie consent management tool by TermsFeed Policy Generator

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

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

Operator architecture refactoring (#95)

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