2 Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
\r
3 Permission is hereby granted, free of charge, to any person obtaining a copy
\r
4 of this software and associated documentation files (the "Software"), to deal
\r
5 in the Software without restriction, including without limitation the rights
\r
6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
\r
7 copies of the Software, and to permit persons to whom the Software is
\r
8 furnished to do so, subject to the following conditions:
\r
10 The above copyright notice and this permission notice shall be included in
\r
11 all copies or substantial portions of the Software.
\r
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
\r
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
\r
16 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
\r
17 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\r
18 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
23 using System.Diagnostics;
\r
24 using SCG = System.Collections.Generic;
\r
32 public enum EventTypeEnum
\r
41 Changed = 0x00000001,
\r
45 Cleared = 0x00000002,
\r
53 Removed = 0x00000008,
\r
61 Inserted = 0x00000010,
\r
65 RemovedAt = 0x00000020,
\r
73 /// Holds the real events for a collection
\r
75 /// <typeparam name="T"></typeparam>
\r
77 internal sealed class EventBlock<T>
\r
79 internal EventTypeEnum events;
\r
81 event CollectionChangedHandler<T> collectionChanged;
\r
82 internal event CollectionChangedHandler<T> CollectionChanged
\r
86 collectionChanged += value;
\r
87 events |= EventTypeEnum.Changed;
\r
91 collectionChanged -= value;
\r
92 if (collectionChanged == null)
\r
93 events &= ~EventTypeEnum.Changed;
\r
96 internal void raiseCollectionChanged(object sender)
\r
97 { if (collectionChanged != null) collectionChanged(sender); }
\r
99 event CollectionClearedHandler<T> collectionCleared;
\r
100 internal event CollectionClearedHandler<T> CollectionCleared
\r
104 collectionCleared += value;
\r
105 events |= EventTypeEnum.Cleared;
\r
109 collectionCleared -= value;
\r
110 if (collectionCleared == null)
\r
111 events &= ~EventTypeEnum.Cleared;
\r
114 internal void raiseCollectionCleared(object sender, bool full, int count)
\r
115 { if (collectionCleared != null) collectionCleared(sender, new ClearedEventArgs(full, count)); }
\r
116 internal void raiseCollectionCleared(object sender, bool full, int count, int? start)
\r
117 { if (collectionCleared != null) collectionCleared(sender, new ClearedRangeEventArgs(full, count, start)); }
\r
119 event ItemsAddedHandler<T> itemsAdded;
\r
120 internal event ItemsAddedHandler<T> ItemsAdded
\r
124 itemsAdded += value;
\r
125 events |= EventTypeEnum.Added;
\r
129 itemsAdded -= value;
\r
130 if (itemsAdded == null)
\r
131 events &= ~EventTypeEnum.Added;
\r
134 internal void raiseItemsAdded(object sender, T item, int count)
\r
135 { if (itemsAdded != null) itemsAdded(sender, new ItemCountEventArgs<T>(item, count)); }
\r
137 event ItemsRemovedHandler<T> itemsRemoved;
\r
138 internal event ItemsRemovedHandler<T> ItemsRemoved
\r
142 itemsRemoved += value;
\r
143 events |= EventTypeEnum.Removed;
\r
147 itemsRemoved -= value;
\r
148 if (itemsRemoved == null)
\r
149 events &= ~EventTypeEnum.Removed;
\r
152 internal void raiseItemsRemoved(object sender, T item, int count)
\r
153 { if (itemsRemoved != null) itemsRemoved(sender, new ItemCountEventArgs<T>(item, count)); }
\r
155 event ItemInsertedHandler<T> itemInserted;
\r
156 internal event ItemInsertedHandler<T> ItemInserted
\r
160 itemInserted += value;
\r
161 events |= EventTypeEnum.Inserted;
\r
165 itemInserted -= value;
\r
166 if (itemInserted == null)
\r
167 events &= ~EventTypeEnum.Inserted;
\r
170 internal void raiseItemInserted(object sender, T item, int index)
\r
171 { if (itemInserted != null) itemInserted(sender, new ItemAtEventArgs<T>(item, index)); }
\r
173 event ItemRemovedAtHandler<T> itemRemovedAt;
\r
174 internal event ItemRemovedAtHandler<T> ItemRemovedAt
\r
178 itemRemovedAt += value;
\r
179 events |= EventTypeEnum.RemovedAt;
\r
183 itemRemovedAt -= value;
\r
184 if (itemRemovedAt == null)
\r
185 events &= ~EventTypeEnum.RemovedAt;
\r
188 internal void raiseItemRemovedAt(object sender, T item, int index)
\r
189 { if (itemRemovedAt != null) itemRemovedAt(sender, new ItemAtEventArgs<T>(item, index)); }
\r
193 /// Tentative, to conserve memory in GuardedCollectionValueBase
\r
194 /// This should really be nested in Guarded collection value, only have a guardereal field
\r
196 /// <typeparam name="T"></typeparam>
\r
198 internal sealed class ProxyEventBlock<T>
\r
200 ICollectionValue<T> proxy, real;
\r
202 internal ProxyEventBlock(ICollectionValue<T> proxy, ICollectionValue<T> real)
\r
203 { this.proxy = proxy; this.real = real; }
\r
205 event CollectionChangedHandler<T> collectionChanged;
\r
206 CollectionChangedHandler<T> collectionChangedProxy;
\r
207 internal event CollectionChangedHandler<T> CollectionChanged
\r
211 if (collectionChanged == null)
\r
213 if (collectionChangedProxy == null)
\r
214 collectionChangedProxy = delegate(object sender) { collectionChanged(proxy); };
\r
215 real.CollectionChanged += collectionChangedProxy;
\r
217 collectionChanged += value;
\r
221 collectionChanged -= value;
\r
222 if (collectionChanged == null)
\r
223 real.CollectionChanged -= collectionChangedProxy;
\r
227 event CollectionClearedHandler<T> collectionCleared;
\r
228 CollectionClearedHandler<T> collectionClearedProxy;
\r
229 internal event CollectionClearedHandler<T> CollectionCleared
\r
233 if (collectionCleared == null)
\r
235 if (collectionClearedProxy == null)
\r
236 collectionClearedProxy = delegate(object sender, ClearedEventArgs e) { collectionCleared(proxy, e); };
\r
237 real.CollectionCleared += collectionClearedProxy;
\r
239 collectionCleared += value;
\r
243 collectionCleared -= value;
\r
244 if (collectionCleared == null)
\r
245 real.CollectionCleared -= collectionClearedProxy;
\r
249 event ItemsAddedHandler<T> itemsAdded;
\r
250 ItemsAddedHandler<T> itemsAddedProxy;
\r
251 internal event ItemsAddedHandler<T> ItemsAdded
\r
255 if (itemsAdded == null)
\r
257 if (itemsAddedProxy == null)
\r
258 itemsAddedProxy = delegate(object sender, ItemCountEventArgs<T> e) { itemsAdded(proxy, e); };
\r
259 real.ItemsAdded += itemsAddedProxy;
\r
261 itemsAdded += value;
\r
265 itemsAdded -= value;
\r
266 if (itemsAdded == null)
\r
267 real.ItemsAdded -= itemsAddedProxy;
\r
271 event ItemInsertedHandler<T> itemInserted;
\r
272 ItemInsertedHandler<T> itemInsertedProxy;
\r
273 internal event ItemInsertedHandler<T> ItemInserted
\r
277 if (itemInserted == null)
\r
279 if (itemInsertedProxy == null)
\r
280 itemInsertedProxy = delegate(object sender, ItemAtEventArgs<T> e) { itemInserted(proxy, e); };
\r
281 real.ItemInserted += itemInsertedProxy;
\r
283 itemInserted += value;
\r
287 itemInserted -= value;
\r
288 if (itemInserted == null)
\r
289 real.ItemInserted -= itemInsertedProxy;
\r
293 event ItemsRemovedHandler<T> itemsRemoved;
\r
294 ItemsRemovedHandler<T> itemsRemovedProxy;
\r
295 internal event ItemsRemovedHandler<T> ItemsRemoved
\r
299 if (itemsRemoved == null)
\r
301 if (itemsRemovedProxy == null)
\r
302 itemsRemovedProxy = delegate(object sender, ItemCountEventArgs<T> e) { itemsRemoved(proxy, e); };
\r
303 real.ItemsRemoved += itemsRemovedProxy;
\r
305 itemsRemoved += value;
\r
309 itemsRemoved -= value;
\r
310 if (itemsRemoved == null)
\r
311 real.ItemsRemoved -= itemsRemovedProxy;
\r
315 event ItemRemovedAtHandler<T> itemRemovedAt;
\r
316 ItemRemovedAtHandler<T> itemRemovedAtProxy;
\r
317 internal event ItemRemovedAtHandler<T> ItemRemovedAt
\r
321 if (itemRemovedAt == null)
\r
323 if (itemRemovedAtProxy == null)
\r
324 itemRemovedAtProxy = delegate(object sender, ItemAtEventArgs<T> e) { itemRemovedAt(proxy, e); };
\r
325 real.ItemRemovedAt += itemRemovedAtProxy;
\r
327 itemRemovedAt += value;
\r
331 itemRemovedAt -= value;
\r
332 if (itemRemovedAt == null)
\r
333 real.ItemRemovedAt -= itemRemovedAtProxy;
\r
341 /// <typeparam name="T"></typeparam>
\r
342 public class ItemAtEventArgs<T> : EventArgs
\r
347 public readonly T Item;
\r
351 public readonly int Index;
\r
355 /// <param name="item"></param>
\r
356 /// <param name="index"></param>
\r
357 public ItemAtEventArgs(T item, int index) { Item = item; Index = index; }
\r
361 /// <returns></returns>
\r
362 public override string ToString()
\r
364 return String.Format("(ItemAtEventArgs {0} '{1}')", Index, Item);
\r
371 /// <typeparam name="T"></typeparam>
\r
372 public class ItemCountEventArgs<T> : EventArgs
\r
377 public readonly T Item;
\r
381 public readonly int Count;
\r
385 /// <param name="count"></param>
\r
386 /// <param name="item"></param>
\r
387 public ItemCountEventArgs(T item, int count) { Item = item; Count = count; }
\r
391 /// <returns></returns>
\r
392 public override string ToString()
\r
394 return String.Format("(ItemCountEventArgs {0} '{1}')", Count, Item);
\r
403 public class ClearedEventArgs : EventArgs
\r
408 public readonly bool Full;
\r
412 public readonly int Count;
\r
417 /// <param name="full">True if the operation cleared all of the collection</param>
\r
418 /// <param name="count">The number of items removed by the clear.</param>
\r
419 public ClearedEventArgs(bool full, int count) { Full = full; Count = count; }
\r
423 /// <returns></returns>
\r
424 public override string ToString()
\r
426 return String.Format("(ClearedEventArgs {0} {1})", Count, Full);
\r
433 public class ClearedRangeEventArgs : ClearedEventArgs
\r
435 //WE could let this be of type int? to allow
\r
439 public readonly int? Start;
\r
443 /// <param name="full"></param>
\r
444 /// <param name="count"></param>
\r
445 /// <param name="start"></param>
\r
446 public ClearedRangeEventArgs(bool full, int count, int? start) : base(full,count) { Start = start; }
\r
450 /// <returns></returns>
\r
451 public override string ToString()
\r
453 return String.Format("(ClearedRangeEventArgs {0} {1} {2})", Count, Full, Start);
\r
458 /// The type of event raised after an operation on a collection has changed its contents.
\r
459 /// Normally, a multioperation like AddAll,
\r
460 /// <see cref="M:C5.IExtensible`1.AddAll(System.Collections.Generic.IEnumerable{`0})"/>
\r
461 /// will only fire one CollectionChanged event. Any operation that changes the collection
\r
462 /// must fire CollectionChanged as its last event.
\r
464 public delegate void CollectionChangedHandler<T>(object sender);
\r
467 /// The type of event raised after the Clear() operation on a collection.
\r
469 /// Note: The Clear() operation will not fire ItemsRemoved events.
\r
471 /// <param name="sender"></param>
\r
472 /// <param name="eventArgs"></param>
\r
473 public delegate void CollectionClearedHandler<T>(object sender, ClearedEventArgs eventArgs);
\r
476 /// The type of event raised after an item has been added to a collection.
\r
477 /// The event will be raised at a point of time, where the collection object is
\r
478 /// in an internally consistent state and before the corresponding CollectionChanged
\r
479 /// event is raised.
\r
481 /// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event.
\r
483 /// Note: When an item is inserted into a list (<see cref="T:C5.IList`1"/>), both
\r
484 /// ItemInserted and ItemsAdded events will be fired.
\r
486 /// <param name="sender"></param>
\r
487 /// <param name="eventArgs">An object with the item that was added</param>
\r
488 public delegate void ItemsAddedHandler<T>(object sender, ItemCountEventArgs<T> eventArgs);
\r
491 /// The type of event raised after an item has been removed from a collection.
\r
492 /// The event will be raised at a point of time, where the collection object is
\r
493 /// in an internally consistent state and before the corresponding CollectionChanged
\r
494 /// event is raised.
\r
496 /// Note: The Clear() operation will not fire ItemsRemoved events.
\r
498 /// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event.
\r
500 /// Note: When an item is removed from a list by the RemoveAt operation, both an
\r
501 /// ItemsRemoved and an ItemRemovedAt event will be fired.
\r
503 /// <param name="sender"></param>
\r
504 /// <param name="eventArgs">An object with the item that was removed</param>
\r
505 public delegate void ItemsRemovedHandler<T>(object sender, ItemCountEventArgs<T> eventArgs);
\r
508 /// The type of event raised after an item has been inserted into a list by an Insert,
\r
509 /// InsertFirst or InsertLast operation.
\r
510 /// The event will be raised at a point of time, where the collection object is
\r
511 /// in an internally consistent state and before the corresponding CollectionChanged
\r
512 /// event is raised.
\r
514 /// Note: an ItemsAdded event will also be fired.
\r
516 /// <param name="sender"></param>
\r
517 /// <param name="eventArgs"></param>
\r
518 public delegate void ItemInsertedHandler<T>(object sender, ItemAtEventArgs<T> eventArgs);
\r
521 /// The type of event raised after an item has been removed from a list by a RemoveAt(int i)
\r
522 /// operation (or RemoveFirst(), RemoveLast(), Remove() operation).
\r
523 /// The event will be raised at a point of time, where the collection object is
\r
524 /// in an internally consistent state and before the corresponding CollectionChanged
\r
525 /// event is raised.
\r
527 /// Note: an ItemRemoved event will also be fired.
\r
529 /// <param name="sender"></param>
\r
530 /// <param name="eventArgs"></param>
\r
531 public delegate void ItemRemovedAtHandler<T>(object sender, ItemAtEventArgs<T> eventArgs);
\r