New test.
[mono.git] / mcs / class / Mono.C5 / C5 / Events.cs
1 #if NET_2_0
2 /*\r
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
10  \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
13  \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
20  SOFTWARE.\r
21 */\r
22 \r
23 using System;\r
24 using System.Diagnostics;\r
25 using SCG = System.Collections.Generic;\r
26 \r
27 namespace C5\r
28 {\r
29   /// <summary>\r
30   /// \r
31   /// </summary>\r
32   [Flags]\r
33   public enum EventTypeEnum\r
34   {\r
35     /// <summary>\r
36     /// \r
37     /// </summary>\r
38     None = 0x00000000,\r
39     /// <summary>\r
40     /// \r
41     /// </summary>\r
42     Changed = 0x00000001,\r
43     /// <summary>\r
44     /// \r
45     /// </summary>\r
46     Cleared = 0x00000002,\r
47     /// <summary>\r
48     /// \r
49     /// </summary>\r
50     Added = 0x00000004,\r
51     /// <summary>\r
52     /// \r
53     /// </summary>\r
54     Removed = 0x00000008,\r
55     /// <summary>\r
56     /// \r
57     /// </summary>\r
58     Basic = 0x0000000f,\r
59     /// <summary>\r
60     /// \r
61     /// </summary>\r
62     Inserted = 0x00000010,\r
63     /// <summary>\r
64     /// \r
65     /// </summary>\r
66     RemovedAt = 0x00000020,\r
67     /// <summary>\r
68     /// \r
69     /// </summary>\r
70     All = 0x0000003f\r
71   }\r
72 \r
73   /// <summary>\r
74   /// Holds the real events for a collection\r
75   /// </summary>\r
76   /// <typeparam name="T"></typeparam>\r
77   [Serializable]\r
78   internal sealed class EventBlock<T>\r
79   {\r
80     internal EventTypeEnum events;\r
81 \r
82     event CollectionChangedHandler<T> collectionChanged;\r
83     internal event CollectionChangedHandler<T> CollectionChanged\r
84     {\r
85       add\r
86       {\r
87         collectionChanged += value;\r
88         events |= EventTypeEnum.Changed;\r
89       }\r
90       remove\r
91       {\r
92         collectionChanged -= value;\r
93         if (collectionChanged == null)\r
94           events &= ~EventTypeEnum.Changed;\r
95       }\r
96     }\r
97     internal void raiseCollectionChanged(object sender)\r
98     { if (collectionChanged != null) collectionChanged(sender); }\r
99 \r
100     event CollectionClearedHandler<T> collectionCleared;\r
101     internal event CollectionClearedHandler<T> CollectionCleared\r
102     {\r
103       add\r
104       {\r
105         collectionCleared += value;\r
106         events |= EventTypeEnum.Cleared;\r
107       }\r
108       remove\r
109       {\r
110         collectionCleared -= value;\r
111         if (collectionCleared == null)\r
112           events &= ~EventTypeEnum.Cleared;\r
113       }\r
114     }\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
119 \r
120     event ItemsAddedHandler<T> itemsAdded;\r
121     internal event ItemsAddedHandler<T> ItemsAdded\r
122     {\r
123       add\r
124       {\r
125         itemsAdded += value;\r
126         events |= EventTypeEnum.Added;\r
127       }\r
128       remove\r
129       {\r
130         itemsAdded -= value;\r
131         if (itemsAdded == null)\r
132           events &= ~EventTypeEnum.Added;\r
133       }\r
134     }\r
135     internal void raiseItemsAdded(object sender, T item, int count)\r
136     { if (itemsAdded != null) itemsAdded(sender, new ItemCountEventArgs<T>(item, count)); }\r
137 \r
138     event ItemsRemovedHandler<T> itemsRemoved;\r
139     internal event ItemsRemovedHandler<T> ItemsRemoved\r
140     {\r
141       add\r
142       {\r
143         itemsRemoved += value;\r
144         events |= EventTypeEnum.Removed;\r
145       }\r
146       remove\r
147       {\r
148         itemsRemoved -= value;\r
149         if (itemsRemoved == null)\r
150           events &= ~EventTypeEnum.Removed;\r
151       }\r
152     }\r
153     internal void raiseItemsRemoved(object sender, T item, int count)\r
154     { if (itemsRemoved != null) itemsRemoved(sender, new ItemCountEventArgs<T>(item, count)); }\r
155 \r
156     event ItemInsertedHandler<T> itemInserted;\r
157     internal event ItemInsertedHandler<T> ItemInserted\r
158     {\r
159       add\r
160       {\r
161         itemInserted += value;\r
162         events |= EventTypeEnum.Inserted;\r
163       }\r
164       remove\r
165       {\r
166         itemInserted -= value;\r
167         if (itemInserted == null)\r
168           events &= ~EventTypeEnum.Inserted;\r
169       }\r
170     }\r
171     internal void raiseItemInserted(object sender, T item, int index)\r
172     { if (itemInserted != null) itemInserted(sender, new ItemAtEventArgs<T>(item, index)); }\r
173 \r
174     event ItemRemovedAtHandler<T> itemRemovedAt;\r
175     internal event ItemRemovedAtHandler<T> ItemRemovedAt\r
176     {\r
177       add\r
178       {\r
179         itemRemovedAt += value;\r
180         events |= EventTypeEnum.RemovedAt;\r
181       }\r
182       remove\r
183       {\r
184         itemRemovedAt -= value;\r
185         if (itemRemovedAt == null)\r
186           events &= ~EventTypeEnum.RemovedAt;\r
187       }\r
188     }\r
189     internal void raiseItemRemovedAt(object sender, T item, int index)\r
190     { if (itemRemovedAt != null) itemRemovedAt(sender, new ItemAtEventArgs<T>(item, index)); }\r
191   }\r
192 \r
193   /// <summary>\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
196   /// </summary>\r
197   /// <typeparam name="T"></typeparam>\r
198   [Serializable]\r
199   internal sealed class ProxyEventBlock<T>\r
200   {\r
201     ICollectionValue<T> proxy, real;\r
202 \r
203     internal ProxyEventBlock(ICollectionValue<T> proxy, ICollectionValue<T> real)\r
204     { this.proxy = proxy; this.real = real; }\r
205 \r
206     event CollectionChangedHandler<T> collectionChanged;\r
207     CollectionChangedHandler<T> collectionChangedProxy;\r
208     internal event CollectionChangedHandler<T> CollectionChanged\r
209     {\r
210       add\r
211       {\r
212         if (collectionChanged == null)\r
213         {\r
214           if (collectionChangedProxy == null)\r
215             collectionChangedProxy = delegate(object sender) { collectionChanged(proxy); };\r
216           real.CollectionChanged += collectionChangedProxy;\r
217         }\r
218         collectionChanged += value;\r
219       }\r
220       remove\r
221       {\r
222         collectionChanged -= value;\r
223         if (collectionChanged == null)\r
224           real.CollectionChanged -= collectionChangedProxy;\r
225       }\r
226     }\r
227 \r
228     event CollectionClearedHandler<T> collectionCleared;\r
229     CollectionClearedHandler<T> collectionClearedProxy;\r
230     internal event CollectionClearedHandler<T> CollectionCleared\r
231     {\r
232       add\r
233       {\r
234         if (collectionCleared == null)\r
235         {\r
236           if (collectionClearedProxy == null)\r
237             collectionClearedProxy = delegate(object sender, ClearedEventArgs e) { collectionCleared(proxy, e); };\r
238           real.CollectionCleared += collectionClearedProxy;\r
239         }\r
240         collectionCleared += value;\r
241       }\r
242       remove\r
243       {\r
244         collectionCleared -= value;\r
245         if (collectionCleared == null)\r
246           real.CollectionCleared -= collectionClearedProxy;\r
247       }\r
248     }\r
249 \r
250     event ItemsAddedHandler<T> itemsAdded;\r
251     ItemsAddedHandler<T> itemsAddedProxy;\r
252     internal event ItemsAddedHandler<T> ItemsAdded\r
253     {\r
254       add\r
255       {\r
256         if (itemsAdded == null)\r
257         {\r
258           if (itemsAddedProxy == null)\r
259             itemsAddedProxy = delegate(object sender, ItemCountEventArgs<T> e) { itemsAdded(proxy, e); };\r
260           real.ItemsAdded += itemsAddedProxy;\r
261         }\r
262         itemsAdded += value;\r
263       }\r
264       remove\r
265       {\r
266         itemsAdded -= value;\r
267         if (itemsAdded == null)\r
268           real.ItemsAdded -= itemsAddedProxy;\r
269       }\r
270     }\r
271 \r
272     event ItemInsertedHandler<T> itemInserted;\r
273     ItemInsertedHandler<T> itemInsertedProxy;\r
274     internal event ItemInsertedHandler<T> ItemInserted\r
275     {\r
276       add\r
277       {\r
278         if (itemInserted == null)\r
279         {\r
280           if (itemInsertedProxy == null)\r
281             itemInsertedProxy = delegate(object sender, ItemAtEventArgs<T> e) { itemInserted(proxy, e); };\r
282           real.ItemInserted += itemInsertedProxy;\r
283         }\r
284         itemInserted += value;\r
285       }\r
286       remove\r
287       {\r
288         itemInserted -= value;\r
289         if (itemInserted == null)\r
290           real.ItemInserted -= itemInsertedProxy;\r
291       }\r
292     }\r
293 \r
294     event ItemsRemovedHandler<T> itemsRemoved;\r
295     ItemsRemovedHandler<T> itemsRemovedProxy;\r
296     internal event ItemsRemovedHandler<T> ItemsRemoved\r
297     {\r
298       add\r
299       {\r
300         if (itemsRemoved == null)\r
301         {\r
302           if (itemsRemovedProxy == null)\r
303             itemsRemovedProxy = delegate(object sender, ItemCountEventArgs<T> e) { itemsRemoved(proxy, e); };\r
304           real.ItemsRemoved += itemsRemovedProxy;\r
305         }\r
306         itemsRemoved += value;\r
307       }\r
308       remove\r
309       {\r
310         itemsRemoved -= value;\r
311         if (itemsRemoved == null)\r
312           real.ItemsRemoved -= itemsRemovedProxy;\r
313       }\r
314     }\r
315 \r
316     event ItemRemovedAtHandler<T> itemRemovedAt;\r
317     ItemRemovedAtHandler<T> itemRemovedAtProxy;\r
318     internal event ItemRemovedAtHandler<T> ItemRemovedAt\r
319     {\r
320       add\r
321       {\r
322         if (itemRemovedAt == null)\r
323         {\r
324           if (itemRemovedAtProxy == null)\r
325             itemRemovedAtProxy = delegate(object sender, ItemAtEventArgs<T> e) { itemRemovedAt(proxy, e); };\r
326           real.ItemRemovedAt += itemRemovedAtProxy;\r
327         }\r
328         itemRemovedAt += value;\r
329       }\r
330       remove\r
331       {\r
332         itemRemovedAt -= value;\r
333         if (itemRemovedAt == null)\r
334           real.ItemRemovedAt -= itemRemovedAtProxy;\r
335       }\r
336     }\r
337   }\r
338 \r
339   /// <summary>\r
340   /// \r
341   /// </summary>\r
342   /// <typeparam name="T"></typeparam>\r
343   public class ItemAtEventArgs<T> : EventArgs\r
344   {\r
345     /// <summary>\r
346     /// \r
347     /// </summary>\r
348     public readonly T Item;\r
349     /// <summary>\r
350     /// \r
351     /// </summary>\r
352     public readonly int Index;\r
353     /// <summary>\r
354     /// \r
355     /// </summary>\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
359     /// <summary>\r
360     /// \r
361     /// </summary>\r
362     /// <returns></returns>\r
363     public override string ToString()\r
364     {\r
365       return String.Format("(ItemAtEventArgs {0} '{1}')", Index, Item);\r
366     }\r
367   }\r
368 \r
369   /// <summary>\r
370   /// \r
371   /// </summary>\r
372   /// <typeparam name="T"></typeparam>\r
373   public class ItemCountEventArgs<T> : EventArgs\r
374   {\r
375     /// <summary>\r
376     /// \r
377     /// </summary>\r
378     public readonly T Item;\r
379     /// <summary>\r
380     /// \r
381     /// </summary>\r
382     public readonly int Count;\r
383     /// <summary>\r
384     /// \r
385     /// </summary>\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
389     /// <summary>\r
390     /// \r
391     /// </summary>\r
392     /// <returns></returns>\r
393     public override string ToString()\r
394     {\r
395       return String.Format("(ItemCountEventArgs {0} '{1}')", Count, Item);\r
396     }\r
397   }\r
398 \r
399 \r
400 \r
401   /// <summary>\r
402   /// \r
403   /// </summary>\r
404   public class ClearedEventArgs : EventArgs\r
405   {\r
406     /// <summary>\r
407     /// \r
408     /// </summary>\r
409     public readonly bool Full;\r
410     /// <summary>\r
411     /// \r
412     /// </summary>\r
413     public readonly int Count;\r
414     /// <summary>\r
415     /// \r
416     /// </summary>\r
417     /// \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
421     /// <summary>\r
422     /// \r
423     /// </summary>\r
424     /// <returns></returns>\r
425     public override string ToString()\r
426     {\r
427       return String.Format("(ClearedEventArgs {0} {1})", Count, Full);\r
428     }\r
429   }\r
430 \r
431   /// <summary>\r
432   /// \r
433   /// </summary>\r
434   public class ClearedRangeEventArgs : ClearedEventArgs\r
435   {\r
436     //WE could let this be of type int? to  allow \r
437     /// <summary>\r
438     /// \r
439     /// </summary>\r
440     public readonly int? Start;\r
441     /// <summary>\r
442     /// \r
443     /// </summary>\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
448     /// <summary>\r
449     /// \r
450     /// </summary>\r
451     /// <returns></returns>\r
452     public override string ToString()\r
453     {\r
454       return String.Format("(ClearedRangeEventArgs {0} {1} {2})", Count, Full, Start);\r
455     }\r
456   }\r
457 \r
458   /// <summary>\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
464   /// </summary>\r
465   public delegate void CollectionChangedHandler<T>(object sender);\r
466 \r
467   /// <summary>\r
468   /// The type of event raised after the Clear() operation on a collection.\r
469   /// <para/>\r
470   /// Note: The Clear() operation will not fire ItemsRemoved events. \r
471   /// </summary>\r
472   /// <param name="sender"></param>\r
473   /// <param name="eventArgs"></param>\r
474   public delegate void CollectionClearedHandler<T>(object sender, ClearedEventArgs eventArgs);\r
475 \r
476   /// <summary>\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
481   /// <para/>\r
482   /// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event.\r
483   /// <para/>\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
486   /// </summary>\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
490 \r
491   /// <summary>\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
496   /// <para/>\r
497   /// Note: The Clear() operation will not fire ItemsRemoved events. \r
498   /// <para/>\r
499   /// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event.\r
500   /// <para/>\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
503   /// </summary>\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
507 \r
508   /// <summary>\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
514   /// <para/>\r
515   /// Note: an ItemsAdded event will also be fired.\r
516   /// </summary>\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
520 \r
521   /// <summary>\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
527   /// <para/>\r
528   /// Note: an ItemRemoved event will also be fired.\r
529   /// </summary>\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
533 }
534 #endif