Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2521_ProblemRefactoring/HeuristicLab.Collections/3.3/ObservableCollection.cs @ 17946

Last change on this file since 17946 was 17718, checked in by abeham, 4 years ago

#2521: completed port of VRP (needs testing though)

File size: 7.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 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 System.Linq;
27using HEAL.Attic;
28
29namespace HeuristicLab.Collections {
30  [StorableType("98A1FFF8-88D8-4A1A-BDAA-BDC3F4663C1F")]
31  [Serializable]
32  public class ObservableCollection<T> : IObservableCollection<T> {
33    [Storable]
34    protected List<T> list;
35
36    #region Properties
37    public int Capacity {
38      get { return list.Capacity; }
39      set {
40        if (list.Capacity != value) {
41          list.Capacity = value;
42          OnPropertyChanged("Capacity");
43        }
44      }
45    }
46    public int Count {
47      get { return list.Count; }
48    }
49    bool ICollection<T>.IsReadOnly {
50      get { return ((ICollection<T>)list).IsReadOnly; }
51    }
52    #endregion
53
54    #region Constructors
55    public ObservableCollection() {
56      list = new List<T>();
57    }
58    public ObservableCollection(int capacity) {
59      list = new List<T>(capacity);
60    }
61    public ObservableCollection(IEnumerable<T> collection) {
62      list = new List<T>(collection);
63    }
64    [StorableConstructor]
65    protected ObservableCollection(StorableConstructorFlag _) { }
66    #endregion
67
68    #region Access
69    public bool Contains(T item) {
70      return list.Contains(item);
71    }
72
73    public bool Exists(Predicate<T> match) {
74      return list.Exists(match);
75    }
76
77    public T Find(Predicate<T> match) {
78      return list.Find(match);
79    }
80    public ICollection<T> FindAll(Predicate<T> match) {
81      return list.FindAll(match);
82    }
83    public T FindLast(Predicate<T> match) {
84      return list.FindLast(match);
85    }
86    #endregion
87
88    #region Manipulation
89    public void Add(T item) {
90      int capacity = list.Capacity;
91      list.Add(item);
92      if (list.Capacity != capacity)
93        OnPropertyChanged("Capacity");
94      OnPropertyChanged("Count");
95      OnItemsAdded(new T[] { item });
96    }
97    public void AddRange(IEnumerable<T> collection) {
98      int capacity = list.Capacity;
99      var items = collection as ICollection<T> ?? collection.ToList();
100      list.AddRange(items);
101      if (items.Count > 0) {
102        OnItemsAdded(items);
103        if (list.Capacity != capacity)
104          OnPropertyChanged("Capacity");
105        OnPropertyChanged("Count");
106      }
107    }
108
109    /// <summary>
110    /// Performs a Clear and an AddRange, but does not fire separate events for those operations
111    /// </summary>
112    /// <param name="collection"></param>
113    public void Replace(IEnumerable<T> collection) {
114      List<T> oldItems = null;
115      if (list.Any()) oldItems = new List<T>(list);
116      else oldItems = new List<T>();
117
118      int oldCapacity = list.Capacity;
119      list.Clear();
120      list.AddRange(collection);
121
122      List<T> items = null;
123      if (list.Any()) items = new List<T>(list);
124      else items = new List<T>();
125
126      OnCollectionReset(items, oldItems);
127      if (oldCapacity != list.Capacity) OnPropertyChanged("Capacity");
128      if (oldItems.Count != items.Count) OnPropertyChanged("Count");
129    }
130
131    public bool Remove(T item) {
132      if (list.Remove(item)) {
133        OnPropertyChanged("Count");
134        OnItemsRemoved(new T[] { item });
135        return true;
136      }
137      return false;
138    }
139    public void RemoveRange(IEnumerable<T> collection) {
140      if (collection == null) throw new ArgumentNullException();
141      List<T> items = new List<T>();
142      foreach (T item in collection) {
143        if (list.Remove(item))
144          items.Add(item);
145      }
146      if (items.Count > 0) {
147        OnPropertyChanged("Count");
148        OnItemsRemoved(items);
149      }
150    }
151    public int RemoveAll(Predicate<T> match) {
152      List<T> items = list.FindAll(match);
153      int result = 0;
154      if (items.Count > 0) {
155        result = list.RemoveAll(match);
156        OnPropertyChanged("Count");
157        OnItemsRemoved(items);
158      }
159      return result;
160    }
161
162    public void Clear() {
163      if (list.Count > 0) {
164        T[] items = list.ToArray();
165        list.Clear();
166        OnPropertyChanged("Count");
167        OnCollectionReset(new T[0], items);
168      }
169    }
170    #endregion
171
172    #region Conversion
173    public ReadOnlyObservableCollection<T> AsReadOnly() {
174      return new ReadOnlyObservableCollection<T>(this);
175    }
176    public T[] ToArray() {
177      return list.ToArray();
178    }
179    public void CopyTo(T[] array, int arrayIndex) {
180      list.CopyTo(array, arrayIndex);
181    }
182    public ICollection<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter) {
183      return list.ConvertAll<TOutput>(converter);
184    }
185    #endregion
186
187    #region Processing
188    public void ForEach(Action<T> action) {
189      list.ForEach(action);
190    }
191    public bool TrueForAll(Predicate<T> match) {
192      return list.TrueForAll(match);
193    }
194    #endregion
195
196    #region Enumeration
197    public IEnumerator<T> GetEnumerator() {
198      return ((IEnumerable<T>)list).GetEnumerator();
199    }
200    IEnumerator IEnumerable.GetEnumerator() {
201      return ((IEnumerable)list).GetEnumerator();
202    }
203    #endregion
204
205    #region Helpers
206    public void TrimExcess() {
207      int capacity = list.Capacity;
208      list.TrimExcess();
209      if (list.Capacity != capacity)
210        OnPropertyChanged("Capacity");
211    }
212    #endregion
213
214    #region Events
215    [field: NonSerialized]
216    public event CollectionItemsChangedEventHandler<T> ItemsAdded;
217    protected virtual void OnItemsAdded(IEnumerable<T> items) {
218      CollectionItemsChangedEventHandler<T> handler = ItemsAdded;
219      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<T>(items));
220    }
221
222    [field: NonSerialized]
223    public event CollectionItemsChangedEventHandler<T> ItemsRemoved;
224    protected virtual void OnItemsRemoved(IEnumerable<T> items) {
225      CollectionItemsChangedEventHandler<T> handler = ItemsRemoved;
226      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<T>(items));
227    }
228
229    [field: NonSerialized]
230    public event CollectionItemsChangedEventHandler<T> CollectionReset;
231    protected virtual void OnCollectionReset(IEnumerable<T> items, IEnumerable<T> oldItems) {
232      CollectionItemsChangedEventHandler<T> handler = CollectionReset;
233      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<T>(items, oldItems));
234    }
235
236    [field: NonSerialized]
237    public event PropertyChangedEventHandler PropertyChanged;
238    protected virtual void OnPropertyChanged(string propertyName) {
239      PropertyChangedEventHandler handler = PropertyChanged;
240      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
241    }
242    #endregion
243  }
244}
Note: See TracBrowser for help on using the repository browser.