Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Collections/3.3/ObservableSet.cs @ 3016

Last change on this file since 3016 was 2994, checked in by epitzer, 15 years ago

Make StorableClass attribute compulsory for StorableSerializer to work, add named property StorableClassType to choose between Empty and MarkedOnly, later other options will be added. (#548)

File size: 7.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 System.Linq;
27using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
28
29namespace HeuristicLab.Collections {
30  [Serializable]
31  [StorableClass(StorableClassType.MarkedOnly)]
32  public class ObservableSet<T> : IObservableSet<T> {
33    [Storable]
34    private HashSet<T> set;
35
36    #region Properties
37    public IEqualityComparer<T> Comparer {
38      get { return set.Comparer; }
39    }
40    public int Count {
41      get { return set.Count; }
42    }
43    bool ICollection<T>.IsReadOnly {
44      get { return ((ICollection<T>)set).IsReadOnly; }
45    }
46    #endregion
47
48    #region Constructors
49    public ObservableSet() {
50      set = new HashSet<T>();
51    }
52    public ObservableSet(IEnumerable<T> collection) {
53      set = new HashSet<T>(collection);
54    }
55    public ObservableSet(IEqualityComparer<T> comparer) {
56      set = new HashSet<T>(comparer);
57    }
58    public ObservableSet(IEnumerable<T> collection, IEqualityComparer<T> comparer) {
59      set = new HashSet<T>(collection, comparer);
60    }
61    #endregion
62
63    #region Access
64    public bool Contains(T item) {
65      return set.Contains(item);
66    }
67
68    public bool IsProperSubsetOf(IEnumerable<T> other) {
69      return set.IsProperSubsetOf(other);
70    }
71    public bool IsProperSupersetOf(IEnumerable<T> other) {
72      return set.IsProperSupersetOf(other);
73    }
74
75    public bool IsSubsetOf(IEnumerable<T> other) {
76      return set.IsSubsetOf(other);
77    }
78    public bool IsSupersetOf(IEnumerable<T> other) {
79      return set.IsSupersetOf(other);
80    }
81
82    public bool Overlaps(IEnumerable<T> other) {
83      return set.Overlaps(other);
84    }
85
86    public bool SetEquals(IEnumerable<T> other) {
87      return set.SetEquals(other);
88    }
89    #endregion
90
91    #region Manipulation
92    public bool Add(T item) {
93      if (set.Add(item)) {
94        OnPropertyChanged("Count");
95        OnItemsAdded(new T[] { item });
96        return true;
97      }
98      return false;
99    }
100    void ICollection<T>.Add(T item) {
101      Add(item);
102    }
103
104    public void ExceptWith(IEnumerable<T> other) {
105      if (other == null) throw new ArgumentNullException();
106      List<T> items = new List<T>();
107      foreach (T item in other) {
108        if (set.Remove(item))
109          items.Add(item);
110      }
111      if (items.Count > 0) {
112        OnPropertyChanged("Count");
113        OnItemsRemoved(items);
114      }
115    }
116
117    public void IntersectWith(IEnumerable<T> other) {
118      if (other == null) throw new ArgumentNullException();
119      HashSet<T> items = new HashSet<T>();
120      foreach (T item in set) {
121        if (!other.Contains(item)) items.Add(item);
122      }
123      if (items.Count > 0) {
124        set.ExceptWith(items);
125        OnPropertyChanged("Count");
126        OnItemsRemoved(items);
127      }
128    }
129
130    public bool Remove(T item) {
131      if (set.Remove(item)) {
132        OnPropertyChanged("Count");
133        OnItemsRemoved(new T[] { item });
134        return true;
135      }
136      return false;
137    }
138    public int RemoveWhere(Predicate<T> match) {
139      if (match == null) throw new ArgumentNullException();
140      HashSet<T> items = new HashSet<T>();
141      foreach (T item in set) {
142        if (match(item)) items.Add(item);
143      }
144      if (items.Count > 0) {
145        set.ExceptWith(items);
146        OnPropertyChanged("Count");
147        OnItemsRemoved(items);
148      }
149      return items.Count;
150    }
151
152    public void SymmetricExceptWith(IEnumerable<T> other) {
153      if (other == null) throw new ArgumentNullException();
154      List<T> addedItems = new List<T>();
155      List<T> removedItems = new List<T>();
156      foreach (T item in other) {
157        if (set.Contains(item)) {
158          set.Remove(item);
159          removedItems.Add(item);
160        } else {
161          set.Add(item);
162          addedItems.Add(item);
163        }
164      }
165      if ((addedItems.Count > 0) || (removedItems.Count > 0)) {
166        OnPropertyChanged("Count");
167        if (addedItems.Count > 0) OnItemsAdded(addedItems);
168        if (removedItems.Count > 0) OnItemsRemoved(removedItems);
169      }
170    }
171
172    public void UnionWith(IEnumerable<T> other) {
173      if (other == null) throw new ArgumentNullException();
174      List<T> items = new List<T>();
175      foreach (T item in other) {
176        if (set.Add(item)) {
177          items.Add(item);
178        }
179      }
180      if (items.Count > 0) {
181        OnPropertyChanged("Count");
182        OnItemsAdded(items);
183      }
184    }
185
186    public void Clear() {
187      if (set.Count > 0) {
188        T[] items = new T[set.Count];
189        set.CopyTo(items);
190        set.Clear();
191        OnPropertyChanged("Count");
192        OnCollectionReset(new T[0], items);
193      }
194    }
195    #endregion
196
197    #region Conversion
198    public ReadOnlyObservableSet<T> AsReadOnly() {
199      return new ReadOnlyObservableSet<T>(this);
200    }
201    public void CopyTo(T[] array) {
202      set.CopyTo(array);
203    }
204    public void CopyTo(T[] array, int arrayIndex) {
205      set.CopyTo(array, arrayIndex);
206    }
207    public void CopyTo(T[] array, int arrayIndex, int count) {
208      set.CopyTo(array, arrayIndex, count);
209    }
210    #endregion
211
212    #region Enumeration
213    public IEnumerator<T> GetEnumerator() {
214      return set.GetEnumerator();
215    }
216    IEnumerator IEnumerable.GetEnumerator() {
217      return set.GetEnumerator();
218    }
219    #endregion
220
221    #region Helpers
222    public void TrimExcess() {
223      set.TrimExcess();
224    }
225    #endregion
226
227    #region Events
228    [field: NonSerialized]
229    public event CollectionItemsChangedEventHandler<T> ItemsAdded;
230    protected virtual void OnItemsAdded(IEnumerable<T> items) {
231      if (ItemsAdded != null)
232        ItemsAdded(this, new CollectionItemsChangedEventArgs<T>(items));
233    }
234
235    [field: NonSerialized]
236    public event CollectionItemsChangedEventHandler<T> ItemsRemoved;
237    protected virtual void OnItemsRemoved(IEnumerable<T> items) {
238      if (ItemsRemoved != null)
239        ItemsRemoved(this, new CollectionItemsChangedEventArgs<T>(items));
240    }
241
242    [field: NonSerialized]
243    public event CollectionItemsChangedEventHandler<T> CollectionReset;
244    protected virtual void OnCollectionReset(IEnumerable<T> items, IEnumerable<T> oldItems) {
245      if (CollectionReset != null)
246        CollectionReset(this, new CollectionItemsChangedEventArgs<T>(items, oldItems));
247    }
248
249    [field: NonSerialized]
250    public event PropertyChangedEventHandler PropertyChanged;
251    protected virtual void OnPropertyChanged(string propertyName) {
252      if (PropertyChanged != null)
253        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
254    }
255    #endregion
256  }
257}
Note: See TracBrowser for help on using the repository browser.