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