source: branches/2839_HiveProjectManagement/HeuristicLab.Collections/3.3/ObservableSet.cs @ 16057

Last change on this file since 16057 was 16057, checked in by jkarder, 16 months ago

#2839:

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