3 Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
\r
4 Permission is hereby granted, free of charge, to any person obtaining a copy
\r
5 of this software and associated documentation files (the "Software"), to deal
\r
6 in the Software without restriction, including without limitation the rights
\r
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
\r
8 copies of the Software, and to permit persons to whom the Software is
\r
9 furnished to do so, subject to the following conditions:
\r
11 The above copyright notice and this permission notice shall be included in
\r
12 all copies or substantial portions of the Software.
\r
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
\r
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
\r
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
\r
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\r
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
24 using System.Diagnostics;
\r
25 using SCG = System.Collections.Generic;
\r
33 public enum EventTypeEnum
\r
42 Changed = 0x00000001,
\r
46 Cleared = 0x00000002,
\r
54 Removed = 0x00000008,
\r
62 Inserted = 0x00000010,
\r
66 RemovedAt = 0x00000020,
\r
74 /// Holds the real events for a collection
\r
76 /// <typeparam name="T"></typeparam>
\r
78 internal sealed class EventBlock<T>
\r
80 internal EventTypeEnum events;
\r
82 event CollectionChangedHandler<T> collectionChanged;
\r
83 internal event CollectionChangedHandler<T> CollectionChanged
\r
87 collectionChanged += value;
\r
88 events |= EventTypeEnum.Changed;
\r
92 collectionChanged -= value;
\r
93 if (collectionChanged == null)
\r
94 events &= ~EventTypeEnum.Changed;
\r
97 internal void raiseCollectionChanged(object sender)
\r
98 { if (collectionChanged != null) collectionChanged(sender); }
\r
100 event CollectionClearedHandler<T> collectionCleared;
\r
101 internal event CollectionClearedHandler<T> CollectionCleared
\r
105 collectionCleared += value;
\r
106 events |= EventTypeEnum.Cleared;
\r
110 collectionCleared -= value;
\r
111 if (collectionCleared == null)
\r
112 events &= ~EventTypeEnum.Cleared;
\r
115 internal void raiseCollectionCleared(object sender, bool full, int count)
\r
116 { if (collectionCleared != null) collectionCleared(sender, new ClearedEventArgs(full, count)); }
\r
117 internal void raiseCollectionCleared(object sender, bool full, int count, int? start)
\r
118 { if (collectionCleared != null) collectionCleared(sender, new ClearedRangeEventArgs(full, count, start)); }
\r
120 event ItemsAddedHandler<T> itemsAdded;
\r
121 internal event ItemsAddedHandler<T> ItemsAdded
\r
125 itemsAdded += value;
\r
126 events |= EventTypeEnum.Added;
\r
130 itemsAdded -= value;
\r
131 if (itemsAdded == null)
\r
132 events &= ~EventTypeEnum.Added;
\r
135 internal void raiseItemsAdded(object sender, T item, int count)
\r
136 { if (itemsAdded != null) itemsAdded(sender, new ItemCountEventArgs<T>(item, count)); }
\r
138 event ItemsRemovedHandler<T> itemsRemoved;
\r
139 internal event ItemsRemovedHandler<T> ItemsRemoved
\r
143 itemsRemoved += value;
\r
144 events |= EventTypeEnum.Removed;
\r
148 itemsRemoved -= value;
\r
149 if (itemsRemoved == null)
\r
150 events &= ~EventTypeEnum.Removed;
\r
153 internal void raiseItemsRemoved(object sender, T item, int count)
\r
154 { if (itemsRemoved != null) itemsRemoved(sender, new ItemCountEventArgs<T>(item, count)); }
\r
156 event ItemInsertedHandler<T> itemInserted;
\r
157 internal event ItemInsertedHandler<T> ItemInserted
\r
161 itemInserted += value;
\r
162 events |= EventTypeEnum.Inserted;
\r
166 itemInserted -= value;
\r
167 if (itemInserted == null)
\r
168 events &= ~EventTypeEnum.Inserted;
\r
171 internal void raiseItemInserted(object sender, T item, int index)
\r
172 { if (itemInserted != null) itemInserted(sender, new ItemAtEventArgs<T>(item, index)); }
\r
174 event ItemRemovedAtHandler<T> itemRemovedAt;
\r
175 internal event ItemRemovedAtHandler<T> ItemRemovedAt
\r
179 itemRemovedAt += value;
\r
180 events |= EventTypeEnum.RemovedAt;
\r
184 itemRemovedAt -= value;
\r
185 if (itemRemovedAt == null)
\r
186 events &= ~EventTypeEnum.RemovedAt;
\r
189 internal void raiseItemRemovedAt(object sender, T item, int index)
\r
190 { if (itemRemovedAt != null) itemRemovedAt(sender, new ItemAtEventArgs<T>(item, index)); }
\r
194 /// Tentative, to conserve memory in GuardedCollectionValueBase
\r
195 /// This should really be nested in Guarded collection value, only have a guardereal field
\r
197 /// <typeparam name="T"></typeparam>
\r
199 internal sealed class ProxyEventBlock<T>
\r
201 ICollectionValue<T> proxy, real;
\r
203 internal ProxyEventBlock(ICollectionValue<T> proxy, ICollectionValue<T> real)
\r
204 { this.proxy = proxy; this.real = real; }
\r
206 event CollectionChangedHandler<T> collectionChanged;
\r
207 CollectionChangedHandler<T> collectionChangedProxy;
\r
208 internal event CollectionChangedHandler<T> CollectionChanged
\r
212 if (collectionChanged == null)
\r
214 if (collectionChangedProxy == null)
\r
215 collectionChangedProxy = delegate(object sender) { collectionChanged(proxy); };
\r
216 real.CollectionChanged += collectionChangedProxy;
\r
218 collectionChanged += value;
\r
222 collectionChanged -= value;
\r
223 if (collectionChanged == null)
\r
224 real.CollectionChanged -= collectionChangedProxy;
\r
228 event CollectionClearedHandler<T> collectionCleared;
\r
229 CollectionClearedHandler<T> collectionClearedProxy;
\r
230 internal event CollectionClearedHandler<T> CollectionCleared
\r
234 if (collectionCleared == null)
\r
236 if (collectionClearedProxy == null)
\r
237 collectionClearedProxy = delegate(object sender, ClearedEventArgs e) { collectionCleared(proxy, e); };
\r
238 real.CollectionCleared += collectionClearedProxy;
\r
240 collectionCleared += value;
\r
244 collectionCleared -= value;
\r
245 if (collectionCleared == null)
\r
246 real.CollectionCleared -= collectionClearedProxy;
\r
250 event ItemsAddedHandler<T> itemsAdded;
\r
251 ItemsAddedHandler<T> itemsAddedProxy;
\r
252 internal event ItemsAddedHandler<T> ItemsAdded
\r
256 if (itemsAdded == null)
\r
258 if (itemsAddedProxy == null)
\r
259 itemsAddedProxy = delegate(object sender, ItemCountEventArgs<T> e) { itemsAdded(proxy, e); };
\r
260 real.ItemsAdded += itemsAddedProxy;
\r
262 itemsAdded += value;
\r
266 itemsAdded -= value;
\r
267 if (itemsAdded == null)
\r
268 real.ItemsAdded -= itemsAddedProxy;
\r
272 event ItemInsertedHandler<T> itemInserted;
\r
273 ItemInsertedHandler<T> itemInsertedProxy;
\r
274 internal event ItemInsertedHandler<T> ItemInserted
\r
278 if (itemInserted == null)
\r
280 if (itemInsertedProxy == null)
\r
281 itemInsertedProxy = delegate(object sender, ItemAtEventArgs<T> e) { itemInserted(proxy, e); };
\r
282 real.ItemInserted += itemInsertedProxy;
\r
284 itemInserted += value;
\r
288 itemInserted -= value;
\r
289 if (itemInserted == null)
\r
290 real.ItemInserted -= itemInsertedProxy;
\r
294 event ItemsRemovedHandler<T> itemsRemoved;
\r
295 ItemsRemovedHandler<T> itemsRemovedProxy;
\r
296 internal event ItemsRemovedHandler<T> ItemsRemoved
\r
300 if (itemsRemoved == null)
\r
302 if (itemsRemovedProxy == null)
\r
303 itemsRemovedProxy = delegate(object sender, ItemCountEventArgs<T> e) { itemsRemoved(proxy, e); };
\r
304 real.ItemsRemoved += itemsRemovedProxy;
\r
306 itemsRemoved += value;
\r
310 itemsRemoved -= value;
\r
311 if (itemsRemoved == null)
\r
312 real.ItemsRemoved -= itemsRemovedProxy;
\r
316 event ItemRemovedAtHandler<T> itemRemovedAt;
\r
317 ItemRemovedAtHandler<T> itemRemovedAtProxy;
\r
318 internal event ItemRemovedAtHandler<T> ItemRemovedAt
\r
322 if (itemRemovedAt == null)
\r
324 if (itemRemovedAtProxy == null)
\r
325 itemRemovedAtProxy = delegate(object sender, ItemAtEventArgs<T> e) { itemRemovedAt(proxy, e); };
\r
326 real.ItemRemovedAt += itemRemovedAtProxy;
\r
328 itemRemovedAt += value;
\r
332 itemRemovedAt -= value;
\r
333 if (itemRemovedAt == null)
\r
334 real.ItemRemovedAt -= itemRemovedAtProxy;
\r
342 /// <typeparam name="T"></typeparam>
\r
343 public class ItemAtEventArgs<T> : EventArgs
\r
348 public readonly T Item;
\r
352 public readonly int Index;
\r
356 /// <param name="item"></param>
\r
357 /// <param name="index"></param>
\r
358 public ItemAtEventArgs(T item, int index) { Item = item; Index = index; }
\r
362 /// <returns></returns>
\r
363 public override string ToString()
\r
365 return String.Format("(ItemAtEventArgs {0} '{1}')", Index, Item);
\r
372 /// <typeparam name="T"></typeparam>
\r
373 public class ItemCountEventArgs<T> : EventArgs
\r
378 public readonly T Item;
\r
382 public readonly int Count;
\r
386 /// <param name="count"></param>
\r
387 /// <param name="item"></param>
\r
388 public ItemCountEventArgs(T item, int count) { Item = item; Count = count; }
\r
392 /// <returns></returns>
\r
393 public override string ToString()
\r
395 return String.Format("(ItemCountEventArgs {0} '{1}')", Count, Item);
\r
404 public class ClearedEventArgs : EventArgs
\r
409 public readonly bool Full;
\r
413 public readonly int Count;
\r
418 /// <param name="full">True if the operation cleared all of the collection</param>
\r
419 /// <param name="count">The number of items removed by the clear.</param>
\r
420 public ClearedEventArgs(bool full, int count) { Full = full; Count = count; }
\r
424 /// <returns></returns>
\r
425 public override string ToString()
\r
427 return String.Format("(ClearedEventArgs {0} {1})", Count, Full);
\r
434 public class ClearedRangeEventArgs : ClearedEventArgs
\r
436 //WE could let this be of type int? to allow
\r
440 public readonly int? Start;
\r
444 /// <param name="full"></param>
\r
445 /// <param name="count"></param>
\r
446 /// <param name="start"></param>
\r
447 public ClearedRangeEventArgs(bool full, int count, int? start) : base(full,count) { Start = start; }
\r
451 /// <returns></returns>
\r
452 public override string ToString()
\r
454 return String.Format("(ClearedRangeEventArgs {0} {1} {2})", Count, Full, Start);
\r
459 /// The type of event raised after an operation on a collection has changed its contents.
\r
460 /// Normally, a multioperation like AddAll,
\r
461 /// <see cref="M:C5.IExtensible`1.AddAll(System.Collections.Generic.IEnumerable{`0})"/>
\r
462 /// will only fire one CollectionChanged event. Any operation that changes the collection
\r
463 /// must fire CollectionChanged as its last event.
\r
465 public delegate void CollectionChangedHandler<T>(object sender);
\r
468 /// The type of event raised after the Clear() operation on a collection.
\r
470 /// Note: The Clear() operation will not fire ItemsRemoved events.
\r
472 /// <param name="sender"></param>
\r
473 /// <param name="eventArgs"></param>
\r
474 public delegate void CollectionClearedHandler<T>(object sender, ClearedEventArgs eventArgs);
\r
477 /// The type of event raised after an item has been added to a collection.
\r
478 /// The event will be raised at a point of time, where the collection object is
\r
479 /// in an internally consistent state and before the corresponding CollectionChanged
\r
480 /// event is raised.
\r
482 /// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event.
\r
484 /// Note: When an item is inserted into a list (<see cref="T:C5.IList`1"/>), both
\r
485 /// ItemInserted and ItemsAdded events will be fired.
\r
487 /// <param name="sender"></param>
\r
488 /// <param name="eventArgs">An object with the item that was added</param>
\r
489 public delegate void ItemsAddedHandler<T>(object sender, ItemCountEventArgs<T> eventArgs);
\r
492 /// The type of event raised after an item has been removed from a collection.
\r
493 /// The event will be raised at a point of time, where the collection object is
\r
494 /// in an internally consistent state and before the corresponding CollectionChanged
\r
495 /// event is raised.
\r
497 /// Note: The Clear() operation will not fire ItemsRemoved events.
\r
499 /// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event.
\r
501 /// Note: When an item is removed from a list by the RemoveAt operation, both an
\r
502 /// ItemsRemoved and an ItemRemovedAt event will be fired.
\r
504 /// <param name="sender"></param>
\r
505 /// <param name="eventArgs">An object with the item that was removed</param>
\r
506 public delegate void ItemsRemovedHandler<T>(object sender, ItemCountEventArgs<T> eventArgs);
\r
509 /// The type of event raised after an item has been inserted into a list by an Insert,
\r
510 /// InsertFirst or InsertLast operation.
\r
511 /// The event will be raised at a point of time, where the collection object is
\r
512 /// in an internally consistent state and before the corresponding CollectionChanged
\r
513 /// event is raised.
\r
515 /// Note: an ItemsAdded event will also be fired.
\r
517 /// <param name="sender"></param>
\r
518 /// <param name="eventArgs"></param>
\r
519 public delegate void ItemInsertedHandler<T>(object sender, ItemAtEventArgs<T> eventArgs);
\r
522 /// The type of event raised after an item has been removed from a list by a RemoveAt(int i)
\r
523 /// operation (or RemoveFirst(), RemoveLast(), Remove() operation).
\r
524 /// The event will be raised at a point of time, where the collection object is
\r
525 /// in an internally consistent state and before the corresponding CollectionChanged
\r
526 /// event is raised.
\r
528 /// Note: an ItemRemoved event will also be fired.
\r
530 /// <param name="sender"></param>
\r
531 /// <param name="eventArgs"></param>
\r
532 public delegate void ItemRemovedAtHandler<T>(object sender, ItemAtEventArgs<T> eventArgs);
\r