Merge pull request #4198 from vkargov/vk-prevbb
[mono.git] / mcs / class / Mono.C5 / C5 / Events.cs
1 /*
2  Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
3  Permission is hereby granted, free of charge, to any person obtaining a copy
4  of this software and associated documentation files (the "Software"), to deal
5  in the Software without restriction, including without limitation the rights
6  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7  copies of the Software, and to permit persons to whom the Software is
8  furnished to do so, subject to the following conditions:
9  
10  The above copyright notice and this permission notice shall be included in
11  all copies or substantial portions of the Software.
12  
13  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19  SOFTWARE.
20 */
21
22 using System;
23 using System.Diagnostics;
24 using SCG = System.Collections.Generic;
25
26 namespace C5
27 {
28   /// <summary>
29   /// 
30   /// </summary>
31   [Flags]
32   public enum EventTypeEnum
33   {
34     /// <summary>
35     /// 
36     /// </summary>
37     None = 0x00000000,
38     /// <summary>
39     /// 
40     /// </summary>
41     Changed = 0x00000001,
42     /// <summary>
43     /// 
44     /// </summary>
45     Cleared = 0x00000002,
46     /// <summary>
47     /// 
48     /// </summary>
49     Added = 0x00000004,
50     /// <summary>
51     /// 
52     /// </summary>
53     Removed = 0x00000008,
54     /// <summary>
55     /// 
56     /// </summary>
57     Basic = 0x0000000f,
58     /// <summary>
59     /// 
60     /// </summary>
61     Inserted = 0x00000010,
62     /// <summary>
63     /// 
64     /// </summary>
65     RemovedAt = 0x00000020,
66     /// <summary>
67     /// 
68     /// </summary>
69     All = 0x0000003f
70   }
71
72   /// <summary>
73   /// Holds the real events for a collection
74   /// </summary>
75   /// <typeparam name="T"></typeparam>
76   [Serializable]
77   internal sealed class EventBlock<T>
78   {
79     internal EventTypeEnum events;
80
81     event CollectionChangedHandler<T> collectionChanged;
82     internal event CollectionChangedHandler<T> CollectionChanged
83     {
84       add
85       {
86         collectionChanged += value;
87         events |= EventTypeEnum.Changed;
88       }
89       remove
90       {
91         collectionChanged -= value;
92         if (collectionChanged == null)
93           events &= ~EventTypeEnum.Changed;
94       }
95     }
96     internal void raiseCollectionChanged(object sender)
97     { if (collectionChanged != null) collectionChanged(sender); }
98
99     event CollectionClearedHandler<T> collectionCleared;
100     internal event CollectionClearedHandler<T> CollectionCleared
101     {
102       add
103       {
104         collectionCleared += value;
105         events |= EventTypeEnum.Cleared;
106       }
107       remove
108       {
109         collectionCleared -= value;
110         if (collectionCleared == null)
111           events &= ~EventTypeEnum.Cleared;
112       }
113     }
114     internal void raiseCollectionCleared(object sender, bool full, int count)
115     { if (collectionCleared != null) collectionCleared(sender, new ClearedEventArgs(full, count)); }
116     internal void raiseCollectionCleared(object sender, bool full, int count, int? start)
117     { if (collectionCleared != null) collectionCleared(sender, new ClearedRangeEventArgs(full, count, start)); }
118
119     event ItemsAddedHandler<T> itemsAdded;
120     internal event ItemsAddedHandler<T> ItemsAdded
121     {
122       add
123       {
124         itemsAdded += value;
125         events |= EventTypeEnum.Added;
126       }
127       remove
128       {
129         itemsAdded -= value;
130         if (itemsAdded == null)
131           events &= ~EventTypeEnum.Added;
132       }
133     }
134     internal void raiseItemsAdded(object sender, T item, int count)
135     { if (itemsAdded != null) itemsAdded(sender, new ItemCountEventArgs<T>(item, count)); }
136
137     event ItemsRemovedHandler<T> itemsRemoved;
138     internal event ItemsRemovedHandler<T> ItemsRemoved
139     {
140       add
141       {
142         itemsRemoved += value;
143         events |= EventTypeEnum.Removed;
144       }
145       remove
146       {
147         itemsRemoved -= value;
148         if (itemsRemoved == null)
149           events &= ~EventTypeEnum.Removed;
150       }
151     }
152     internal void raiseItemsRemoved(object sender, T item, int count)
153     { if (itemsRemoved != null) itemsRemoved(sender, new ItemCountEventArgs<T>(item, count)); }
154
155     event ItemInsertedHandler<T> itemInserted;
156     internal event ItemInsertedHandler<T> ItemInserted
157     {
158       add
159       {
160         itemInserted += value;
161         events |= EventTypeEnum.Inserted;
162       }
163       remove
164       {
165         itemInserted -= value;
166         if (itemInserted == null)
167           events &= ~EventTypeEnum.Inserted;
168       }
169     }
170     internal void raiseItemInserted(object sender, T item, int index)
171     { if (itemInserted != null) itemInserted(sender, new ItemAtEventArgs<T>(item, index)); }
172
173     event ItemRemovedAtHandler<T> itemRemovedAt;
174     internal event ItemRemovedAtHandler<T> ItemRemovedAt
175     {
176       add
177       {
178         itemRemovedAt += value;
179         events |= EventTypeEnum.RemovedAt;
180       }
181       remove
182       {
183         itemRemovedAt -= value;
184         if (itemRemovedAt == null)
185           events &= ~EventTypeEnum.RemovedAt;
186       }
187     }
188     internal void raiseItemRemovedAt(object sender, T item, int index)
189     { if (itemRemovedAt != null) itemRemovedAt(sender, new ItemAtEventArgs<T>(item, index)); }
190   }
191
192   /// <summary>
193   /// Tentative, to conserve memory in GuardedCollectionValueBase
194   /// This should really be nested in Guarded collection value, only have a guardereal field
195   /// </summary>
196   /// <typeparam name="T"></typeparam>
197   [Serializable]
198   internal sealed class ProxyEventBlock<T>
199   {
200     ICollectionValue<T> proxy, real;
201
202     internal ProxyEventBlock(ICollectionValue<T> proxy, ICollectionValue<T> real)
203     { this.proxy = proxy; this.real = real; }
204
205     event CollectionChangedHandler<T> collectionChanged;
206     CollectionChangedHandler<T> collectionChangedProxy;
207     internal event CollectionChangedHandler<T> CollectionChanged
208     {
209       add
210       {
211         if (collectionChanged == null)
212         {
213           if (collectionChangedProxy == null)
214             collectionChangedProxy = delegate(object sender) { collectionChanged(proxy); };
215           real.CollectionChanged += collectionChangedProxy;
216         }
217         collectionChanged += value;
218       }
219       remove
220       {
221         collectionChanged -= value;
222         if (collectionChanged == null)
223           real.CollectionChanged -= collectionChangedProxy;
224       }
225     }
226
227     event CollectionClearedHandler<T> collectionCleared;
228     CollectionClearedHandler<T> collectionClearedProxy;
229     internal event CollectionClearedHandler<T> CollectionCleared
230     {
231       add
232       {
233         if (collectionCleared == null)
234         {
235           if (collectionClearedProxy == null)
236             collectionClearedProxy = delegate(object sender, ClearedEventArgs e) { collectionCleared(proxy, e); };
237           real.CollectionCleared += collectionClearedProxy;
238         }
239         collectionCleared += value;
240       }
241       remove
242       {
243         collectionCleared -= value;
244         if (collectionCleared == null)
245           real.CollectionCleared -= collectionClearedProxy;
246       }
247     }
248
249     event ItemsAddedHandler<T> itemsAdded;
250     ItemsAddedHandler<T> itemsAddedProxy;
251     internal event ItemsAddedHandler<T> ItemsAdded
252     {
253       add
254       {
255         if (itemsAdded == null)
256         {
257           if (itemsAddedProxy == null)
258             itemsAddedProxy = delegate(object sender, ItemCountEventArgs<T> e) { itemsAdded(proxy, e); };
259           real.ItemsAdded += itemsAddedProxy;
260         }
261         itemsAdded += value;
262       }
263       remove
264       {
265         itemsAdded -= value;
266         if (itemsAdded == null)
267           real.ItemsAdded -= itemsAddedProxy;
268       }
269     }
270
271     event ItemInsertedHandler<T> itemInserted;
272     ItemInsertedHandler<T> itemInsertedProxy;
273     internal event ItemInsertedHandler<T> ItemInserted
274     {
275       add
276       {
277         if (itemInserted == null)
278         {
279           if (itemInsertedProxy == null)
280             itemInsertedProxy = delegate(object sender, ItemAtEventArgs<T> e) { itemInserted(proxy, e); };
281           real.ItemInserted += itemInsertedProxy;
282         }
283         itemInserted += value;
284       }
285       remove
286       {
287         itemInserted -= value;
288         if (itemInserted == null)
289           real.ItemInserted -= itemInsertedProxy;
290       }
291     }
292
293     event ItemsRemovedHandler<T> itemsRemoved;
294     ItemsRemovedHandler<T> itemsRemovedProxy;
295     internal event ItemsRemovedHandler<T> ItemsRemoved
296     {
297       add
298       {
299         if (itemsRemoved == null)
300         {
301           if (itemsRemovedProxy == null)
302             itemsRemovedProxy = delegate(object sender, ItemCountEventArgs<T> e) { itemsRemoved(proxy, e); };
303           real.ItemsRemoved += itemsRemovedProxy;
304         }
305         itemsRemoved += value;
306       }
307       remove
308       {
309         itemsRemoved -= value;
310         if (itemsRemoved == null)
311           real.ItemsRemoved -= itemsRemovedProxy;
312       }
313     }
314
315     event ItemRemovedAtHandler<T> itemRemovedAt;
316     ItemRemovedAtHandler<T> itemRemovedAtProxy;
317     internal event ItemRemovedAtHandler<T> ItemRemovedAt
318     {
319       add
320       {
321         if (itemRemovedAt == null)
322         {
323           if (itemRemovedAtProxy == null)
324             itemRemovedAtProxy = delegate(object sender, ItemAtEventArgs<T> e) { itemRemovedAt(proxy, e); };
325           real.ItemRemovedAt += itemRemovedAtProxy;
326         }
327         itemRemovedAt += value;
328       }
329       remove
330       {
331         itemRemovedAt -= value;
332         if (itemRemovedAt == null)
333           real.ItemRemovedAt -= itemRemovedAtProxy;
334       }
335     }
336   }
337
338   /// <summary>
339   /// 
340   /// </summary>
341   /// <typeparam name="T"></typeparam>
342   public class ItemAtEventArgs<T> : EventArgs
343   {
344     /// <summary>
345     /// 
346     /// </summary>
347     public readonly T Item;
348     /// <summary>
349     /// 
350     /// </summary>
351     public readonly int Index;
352     /// <summary>
353     /// 
354     /// </summary>
355     /// <param name="item"></param>
356     /// <param name="index"></param>
357     public ItemAtEventArgs(T item, int index) { Item = item; Index = index; }
358     /// <summary>
359     /// 
360     /// </summary>
361     /// <returns></returns>
362     public override string ToString()
363     {
364       return String.Format("(ItemAtEventArgs {0} '{1}')", Index, Item);
365     }
366   }
367
368   /// <summary>
369   /// 
370   /// </summary>
371   /// <typeparam name="T"></typeparam>
372   public class ItemCountEventArgs<T> : EventArgs
373   {
374     /// <summary>
375     /// 
376     /// </summary>
377     public readonly T Item;
378     /// <summary>
379     /// 
380     /// </summary>
381     public readonly int Count;
382     /// <summary>
383     /// 
384     /// </summary>
385     /// <param name="count"></param>
386     /// <param name="item"></param>
387     public ItemCountEventArgs(T item, int count) { Item = item; Count = count; }
388     /// <summary>
389     /// 
390     /// </summary>
391     /// <returns></returns>
392     public override string ToString()
393     {
394       return String.Format("(ItemCountEventArgs {0} '{1}')", Count, Item);
395     }
396   }
397
398
399
400   /// <summary>
401   /// 
402   /// </summary>
403   public class ClearedEventArgs : EventArgs
404   {
405     /// <summary>
406     /// 
407     /// </summary>
408     public readonly bool Full;
409     /// <summary>
410     /// 
411     /// </summary>
412     public readonly int Count;
413     /// <summary>
414     /// 
415     /// </summary>
416     /// 
417     /// <param name="full">True if the operation cleared all of the collection</param>
418     /// <param name="count">The number of items removed by the clear.</param>
419     public ClearedEventArgs(bool full, int count) { Full = full; Count = count; }
420     /// <summary>
421     /// 
422     /// </summary>
423     /// <returns></returns>
424     public override string ToString()
425     {
426       return String.Format("(ClearedEventArgs {0} {1})", Count, Full);
427     }
428   }
429
430   /// <summary>
431   /// 
432   /// </summary>
433   public class ClearedRangeEventArgs : ClearedEventArgs
434   {
435     //WE could let this be of type int? to  allow 
436     /// <summary>
437     /// 
438     /// </summary>
439     public readonly int? Start;
440     /// <summary>
441     /// 
442     /// </summary>
443     /// <param name="full"></param>
444     /// <param name="count"></param>
445     /// <param name="start"></param>
446     public ClearedRangeEventArgs(bool full, int count, int? start) : base(full,count) { Start = start; }
447     /// <summary>
448     /// 
449     /// </summary>
450     /// <returns></returns>
451     public override string ToString()
452     {
453       return String.Format("(ClearedRangeEventArgs {0} {1} {2})", Count, Full, Start);
454     }
455   }
456
457   /// <summary>
458   /// The type of event raised after an operation on a collection has changed its contents.
459   /// Normally, a multioperation like AddAll, 
460   /// <see cref="M:C5.IExtensible`1.AddAll(System.Collections.Generic.IEnumerable{`0})"/> 
461   /// will only fire one CollectionChanged event. Any operation that changes the collection
462   /// must fire CollectionChanged as its last event.
463   /// </summary>
464   public delegate void CollectionChangedHandler<T>(object sender);
465
466   /// <summary>
467   /// The type of event raised after the Clear() operation on a collection.
468   /// <para/>
469   /// Note: The Clear() operation will not fire ItemsRemoved events. 
470   /// </summary>
471   /// <param name="sender"></param>
472   /// <param name="eventArgs"></param>
473   public delegate void CollectionClearedHandler<T>(object sender, ClearedEventArgs eventArgs);
474
475   /// <summary>
476   /// The type of event raised after an item has been added to a collection.
477   /// The event will be raised at a point of time, where the collection object is 
478   /// in an internally consistent state and before the corresponding CollectionChanged 
479   /// event is raised.
480   /// <para/>
481   /// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event.
482   /// <para/>
483   /// Note: When an item is inserted into a list (<see cref="T:C5.IList`1"/>), both
484   /// ItemInserted and ItemsAdded events will be fired.
485   /// </summary>
486   /// <param name="sender"></param>
487   /// <param name="eventArgs">An object with the item that was added</param>
488   public delegate void ItemsAddedHandler<T>(object sender, ItemCountEventArgs<T> eventArgs);
489
490   /// <summary>
491   /// The type of event raised after an item has been removed from a collection.
492   /// The event will be raised at a point of time, where the collection object is 
493   /// in an internally consistent state and before the corresponding CollectionChanged 
494   /// event is raised.
495   /// <para/>
496   /// Note: The Clear() operation will not fire ItemsRemoved events. 
497   /// <para/>
498   /// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event.
499   /// <para/>
500   /// Note: When an item is removed from a list by the RemoveAt operation, both an 
501   /// ItemsRemoved and an ItemRemovedAt event will be fired.
502   /// </summary>
503   /// <param name="sender"></param>
504   /// <param name="eventArgs">An object with the item that was removed</param>
505   public delegate void ItemsRemovedHandler<T>(object sender, ItemCountEventArgs<T> eventArgs);
506
507   /// <summary>
508   /// The type of event raised after an item has been inserted into a list by an Insert, 
509   /// InsertFirst or InsertLast operation.
510   /// The event will be raised at a point of time, where the collection object is 
511   /// in an internally consistent state and before the corresponding CollectionChanged 
512   /// event is raised.
513   /// <para/>
514   /// Note: an ItemsAdded event will also be fired.
515   /// </summary>
516   /// <param name="sender"></param>
517   /// <param name="eventArgs"></param>
518   public delegate void ItemInsertedHandler<T>(object sender, ItemAtEventArgs<T> eventArgs);
519
520   /// <summary>
521   /// The type of event raised after an item has been removed from a list by a RemoveAt(int i)
522   /// operation (or RemoveFirst(), RemoveLast(), Remove() operation).
523   /// The event will be raised at a point of time, where the collection object is 
524   /// in an internally consistent state and before the corresponding CollectionChanged 
525   /// event is raised.
526   /// <para/>
527   /// Note: an ItemRemoved event will also be fired.
528   /// </summary>
529   /// <param name="sender"></param>
530   /// <param name="eventArgs"></param>
531   public delegate void ItemRemovedAtHandler<T>(object sender, ItemAtEventArgs<T> eventArgs);
532 }