Free cookie consent management tool by TermsFeed Policy Generator

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

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

Implemented IDisposable and unified extension capabilities for all observable collections (#819)

File size: 12.4 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.Linq;
27using System.Text;
28using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
29
30namespace HeuristicLab.Collections {
31  [Serializable]
32  public class ObservableList<T> : IObservableList<T> {
33    [Storable]
34    private List<T> list;
35
36    #region Properties
37    public int Capacity {
38      get { return list.Capacity; }
39      set { list.Capacity = value; }
40    }
41    public int Count {
42      get { return list.Count; }
43    }
44    bool ICollection<T>.IsReadOnly {
45      get { return ((ICollection<T>)list).IsReadOnly; }
46    }
47    bool ICollection<IndexedItem<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        list[index] = value;
58        OnItemsReplaced(new IndexedItem<T>[] { new IndexedItem<T>(index, value) }, new IndexedItem<T>[] { new IndexedItem<T>(index, item) });
59      }
60    }
61    #endregion
62
63    #region Constructors
64    public ObservableList() {
65      list = new List<T>();
66    }
67    public ObservableList(int capacity) {
68      list = new List<T>(capacity);
69    }
70    public ObservableList(IEnumerable<T> collection) {
71      list = new List<T>(collection);
72      OnItemsAdded(GetIndexedItems());
73    }
74    #endregion
75
76    #region Destructors
77    ~ObservableList() {
78      Dispose(false);
79    }
80    protected virtual void Dispose(bool disposing) {
81      if (disposing) {
82        Clear();
83      }
84    }
85    public void Dispose() {
86      Dispose(true);
87      GC.SuppressFinalize(this);
88    }
89    #endregion
90
91    #region Access
92    public List<T> GetRange(int index, int count) {
93      return list.GetRange(index, count);
94    }
95
96    public bool Contains(T item) {
97      return list.Contains(item);
98    }
99    public bool Contains(IndexedItem<T> item) {
100      return list[item.Index].Equals(item.Value);
101    }
102
103    public int IndexOf(T item) {
104      return list.IndexOf(item);
105    }
106    public int IndexOf(T item, int index) {
107      return list.IndexOf(item, index);
108    }
109    public int IndexOf(T item, int index, int count) {
110      return list.IndexOf(item, index, count);
111    }
112
113    public int LastIndexOf(T item) {
114      return list.LastIndexOf(item);
115    }
116    public int LastIndexOf(T item, int index) {
117      return list.LastIndexOf(item, index);
118    }
119    public int LastIndexOf(T item, int index, int count) {
120      return list.LastIndexOf(item, index, count);
121    }
122
123    public int BinarySearch(T item) {
124      return list.BinarySearch(item);
125    }
126    public int BinarySearch(T item, IComparer<T> comparer) {
127      return list.BinarySearch(item, comparer);
128    }
129    public int BinarySearch(int index, int count, T item, IComparer<T> comparer) {
130      return list.BinarySearch(index, count, item, comparer);
131    }
132
133    public bool Exists(Predicate<T> match) {
134      return list.Exists(match);
135    }
136
137    public T Find(Predicate<T> match) {
138      return list.Find(match);
139    }
140    public List<T> FindAll(Predicate<T> match) {
141      return list.FindAll(match);
142    }
143    public T FindLast(Predicate<T> match) {
144      return list.FindLast(match);
145    }
146
147    public int FindIndex(Predicate<T> match) {
148      return list.FindIndex(match);
149    }
150    public int FindIndex(int startIndex, Predicate<T> match) {
151      return list.FindIndex(startIndex, match);
152    }
153    public int FindIndex(int startIndex, int count, Predicate<T> match) {
154      return list.FindIndex(startIndex, count, match);
155    }
156
157    public int FindLastIndex(Predicate<T> match) {
158      return list.FindLastIndex(match);
159    }
160    public int FindLastIndex(int startIndex, Predicate<T> match) {
161      return list.FindLastIndex(startIndex, match);
162    }
163    public int FindLastIndex(int startIndex, int count, Predicate<T> match) {
164      return list.FindLastIndex(startIndex, count, match);
165    }
166    #endregion
167
168    #region Manipulation
169    public void Add(T item) {
170      list.Add(item);
171      OnItemsAdded(new IndexedItem<T>[] { new IndexedItem<T>(list.Count - 1, item) });
172    }
173    public void Add(IndexedItem<T> item) {
174      list.Insert(item.Index, item.Value);
175      OnItemsAdded(new IndexedItem<T>[] { item });
176    }
177    public void AddRange(IEnumerable<T> collection) {
178      int index = list.Count;
179      list.AddRange(collection);
180      List<IndexedItem<T>> items = new List<IndexedItem<T>>();
181      foreach (T item in collection) {
182        items.Add(new IndexedItem<T>(index, item));
183        index++;
184      }
185      OnItemsAdded(items);
186    }
187
188    public void Insert(int index, T item) {
189      list.Insert(index, item);
190      OnItemsAdded(new IndexedItem<T>[] { new IndexedItem<T>(index, item) });
191    }
192    public void InsertRange(int index, IEnumerable<T> collection) {
193      list.InsertRange(index, collection);
194      List<IndexedItem<T>> items = new List<IndexedItem<T>>();
195      foreach (T item in collection) {
196        items.Add(new IndexedItem<T>(index, item));
197        index++;
198      }
199      OnItemsAdded(items);
200    }
201
202    public bool Remove(T item) {
203      int index = list.IndexOf(item);
204      if (index != -1) {
205        list.RemoveAt(index);
206        OnItemsRemoved(new IndexedItem<T>[] { new IndexedItem<T>(index, item) });
207        return true;
208      }
209      return false;
210    }
211    public bool Remove(IndexedItem<T> item) {
212      if (list[item.Index].Equals(item.Value)) {
213        list.RemoveAt(item.Index);
214        OnItemsRemoved(new IndexedItem<T>[] { item });
215        return true;
216      }
217      return false;
218    }
219    public int RemoveAll(Predicate<T> match) {
220      if (match == null) throw new ArgumentNullException();
221      List<IndexedItem<T>> items = new List<IndexedItem<T>>();
222      for (int i = 0; i < list.Count; i++) {
223        if (match(list[i]))
224          items.Add(new IndexedItem<T>(i, list[i]));
225      }
226      int result = list.RemoveAll(match);
227      OnItemsRemoved(items);
228      return result;
229    }
230    public void RemoveAt(int index) {
231      T item = list[index];
232      list.RemoveAt(index);
233      OnItemsRemoved(new IndexedItem<T>[] { new IndexedItem<T>(index, item) });
234    }
235    public void RemoveRange(int index, int count) {
236      IndexedItem<T>[] items = GetIndexedItems(index, count);
237      list.RemoveRange(index, count);
238      OnItemsRemoved(items);
239    }
240
241    public void Clear() {
242      IndexedItem<T>[] items = GetIndexedItems();
243      list.Clear();
244      OnCollectionReset(new IndexedItem<T>[0], items);
245    }
246
247    public void Reverse() {
248      IndexedItem<T>[] oldItems = GetIndexedItems();
249      list.Reverse();
250      OnItemsMoved(GetIndexedItems(), oldItems);
251    }
252    public void Reverse(int index, int count) {
253      IndexedItem<T>[] oldItems = GetIndexedItems(index, count);
254      list.Reverse(index, count);
255      OnItemsMoved(GetIndexedItems(index, count), oldItems);
256    }
257
258    public void Sort() {
259      IndexedItem<T>[] oldItems = GetIndexedItems();
260      list.Sort();
261      OnItemsMoved(GetIndexedItems(), oldItems);
262    }
263    public void Sort(Comparison<T> comparison) {
264      IndexedItem<T>[] oldItems = GetIndexedItems();
265      list.Sort(comparison);
266      OnItemsMoved(GetIndexedItems(), oldItems);
267    }
268    public void Sort(IComparer<T> comparer) {
269      IndexedItem<T>[] oldItems = GetIndexedItems();
270      list.Sort(comparer);
271      OnItemsMoved(GetIndexedItems(), oldItems);
272    }
273    public void Sort(int index, int count, IComparer<T> comparer) {
274      IndexedItem<T>[] oldItems = GetIndexedItems(index, count);
275      list.Sort(index, count, comparer);
276      OnItemsMoved(GetIndexedItems(index, count), oldItems);
277    }
278    #endregion
279
280    #region Conversion
281    public ReadOnlyCollection<T> AsReadOnly() {
282      return list.AsReadOnly();
283    }
284    public T[] ToArray() {
285      return list.ToArray();
286    }
287    void ICollection<T>.CopyTo(T[] array, int arrayIndex) {
288      list.CopyTo(array, arrayIndex);
289    }
290    void ICollection<IndexedItem<T>>.CopyTo(IndexedItem<T>[] array, int arrayIndex) {
291      IndexedItem<T>[] items = GetIndexedItems();
292      items.CopyTo(array, arrayIndex);
293    }
294    public List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter) {
295      return list.ConvertAll<TOutput>(converter);
296    }
297    #endregion
298
299    #region Processing
300    public void ForEach(Action<T> action) {
301      list.ForEach(action);
302    }
303    public bool TrueForAll(Predicate<T> match) {
304      return list.TrueForAll(match);
305    }
306    #endregion
307
308    #region Enumeration
309    public List<T>.Enumerator GetEnumerator() {
310      return list.GetEnumerator();
311    }
312    IEnumerator<T> IEnumerable<T>.GetEnumerator() {
313      return ((IEnumerable<T>)list).GetEnumerator();
314    }
315    IEnumerator<IndexedItem<T>> IEnumerable<IndexedItem<T>>.GetEnumerator() {
316      int index = -1;
317      foreach (T item in list) {
318        index++;
319        yield return new IndexedItem<T>(index, item);
320      }
321    }
322    IEnumerator IEnumerable.GetEnumerator() {
323      return ((IEnumerable)list).GetEnumerator();
324    }
325    #endregion
326
327    #region Helpers
328    public void TrimExcess() {
329      list.TrimExcess();
330    }
331    #endregion
332
333    #region Events
334    [field: NonSerialized]
335    public event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsAdded;
336    protected virtual void OnItemsAdded(IEnumerable<IndexedItem<T>> items) {
337      if (ItemsAdded != null)
338        ItemsAdded(this, new CollectionItemsChangedEventArgs<IndexedItem<T>>(items));
339    }
340
341    [field: NonSerialized]
342    public event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsRemoved;
343    protected virtual void OnItemsRemoved(IEnumerable<IndexedItem<T>> items) {
344      if (ItemsRemoved != null)
345        ItemsRemoved(this, new CollectionItemsChangedEventArgs<IndexedItem<T>>(items));
346    }
347
348    [field: NonSerialized]
349    public event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsReplaced;
350    protected virtual void OnItemsReplaced(IEnumerable<IndexedItem<T>> items, IEnumerable<IndexedItem<T>> oldItems) {
351      if (ItemsReplaced != null)
352        ItemsReplaced(this, new CollectionItemsChangedEventArgs<IndexedItem<T>>(items, oldItems));
353    }
354
355    [field: NonSerialized]
356    public event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsMoved;
357    protected virtual void OnItemsMoved(IEnumerable<IndexedItem<T>> items, IEnumerable<IndexedItem<T>> oldItems) {
358      if (ItemsMoved != null)
359        ItemsMoved(this, new CollectionItemsChangedEventArgs<IndexedItem<T>>(items, oldItems));
360    }
361
362    [field: NonSerialized]
363    public event CollectionItemsChangedEventHandler<IndexedItem<T>> CollectionReset;
364    protected virtual void OnCollectionReset(IEnumerable<IndexedItem<T>> items, IEnumerable<IndexedItem<T>> oldItems) {
365      if (CollectionReset != null)
366        CollectionReset(this, new CollectionItemsChangedEventArgs<IndexedItem<T>>(items, oldItems));
367    }
368    #endregion
369
370    #region Private helpers
371    private IndexedItem<T>[] GetIndexedItems() {
372      IndexedItem<T>[] items = new IndexedItem<T>[list.Count];
373      for (int i = 0; i < list.Count; i++)
374        items[i] = new IndexedItem<T>(i, list[i]);
375      return items;
376    }
377    private IndexedItem<T>[] GetIndexedItems(int index, int count) {
378      IndexedItem<T>[] items = new IndexedItem<T>[count];
379      for (int i = 0; i < count; i++)
380        items[i] = new IndexedItem<T>(index + i, list[index + i]);
381      return items;
382    }
383    #endregion
384  }
385}
Note: See TracBrowser for help on using the repository browser.