/* Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ using System; using System.Diagnostics; using SCG = System.Collections.Generic; namespace C5 { /// /// /// [Flags] public enum EventTypeEnum { /// /// /// None = 0x00000000, /// /// /// Changed = 0x00000001, /// /// /// Cleared = 0x00000002, /// /// /// Added = 0x00000004, /// /// /// Removed = 0x00000008, /// /// /// Basic = 0x0000000f, /// /// /// Inserted = 0x00000010, /// /// /// RemovedAt = 0x00000020, /// /// /// All = 0x0000003f } /// /// Holds the real events for a collection /// /// [Serializable] internal sealed class EventBlock { internal EventTypeEnum events; event CollectionChangedHandler collectionChanged; internal event CollectionChangedHandler CollectionChanged { add { collectionChanged += value; events |= EventTypeEnum.Changed; } remove { collectionChanged -= value; if (collectionChanged == null) events &= ~EventTypeEnum.Changed; } } internal void raiseCollectionChanged(object sender) { if (collectionChanged != null) collectionChanged(sender); } event CollectionClearedHandler collectionCleared; internal event CollectionClearedHandler CollectionCleared { add { collectionCleared += value; events |= EventTypeEnum.Cleared; } remove { collectionCleared -= value; if (collectionCleared == null) events &= ~EventTypeEnum.Cleared; } } internal void raiseCollectionCleared(object sender, bool full, int count) { if (collectionCleared != null) collectionCleared(sender, new ClearedEventArgs(full, count)); } internal void raiseCollectionCleared(object sender, bool full, int count, int? start) { if (collectionCleared != null) collectionCleared(sender, new ClearedRangeEventArgs(full, count, start)); } event ItemsAddedHandler itemsAdded; internal event ItemsAddedHandler ItemsAdded { add { itemsAdded += value; events |= EventTypeEnum.Added; } remove { itemsAdded -= value; if (itemsAdded == null) events &= ~EventTypeEnum.Added; } } internal void raiseItemsAdded(object sender, T item, int count) { if (itemsAdded != null) itemsAdded(sender, new ItemCountEventArgs(item, count)); } event ItemsRemovedHandler itemsRemoved; internal event ItemsRemovedHandler ItemsRemoved { add { itemsRemoved += value; events |= EventTypeEnum.Removed; } remove { itemsRemoved -= value; if (itemsRemoved == null) events &= ~EventTypeEnum.Removed; } } internal void raiseItemsRemoved(object sender, T item, int count) { if (itemsRemoved != null) itemsRemoved(sender, new ItemCountEventArgs(item, count)); } event ItemInsertedHandler itemInserted; internal event ItemInsertedHandler ItemInserted { add { itemInserted += value; events |= EventTypeEnum.Inserted; } remove { itemInserted -= value; if (itemInserted == null) events &= ~EventTypeEnum.Inserted; } } internal void raiseItemInserted(object sender, T item, int index) { if (itemInserted != null) itemInserted(sender, new ItemAtEventArgs(item, index)); } event ItemRemovedAtHandler itemRemovedAt; internal event ItemRemovedAtHandler ItemRemovedAt { add { itemRemovedAt += value; events |= EventTypeEnum.RemovedAt; } remove { itemRemovedAt -= value; if (itemRemovedAt == null) events &= ~EventTypeEnum.RemovedAt; } } internal void raiseItemRemovedAt(object sender, T item, int index) { if (itemRemovedAt != null) itemRemovedAt(sender, new ItemAtEventArgs(item, index)); } } /// /// Tentative, to conserve memory in GuardedCollectionValueBase /// This should really be nested in Guarded collection value, only have a guardereal field /// /// [Serializable] internal sealed class ProxyEventBlock { ICollectionValue proxy, real; internal ProxyEventBlock(ICollectionValue proxy, ICollectionValue real) { this.proxy = proxy; this.real = real; } event CollectionChangedHandler collectionChanged; CollectionChangedHandler collectionChangedProxy; internal event CollectionChangedHandler CollectionChanged { add { if (collectionChanged == null) { if (collectionChangedProxy == null) collectionChangedProxy = delegate(object sender) { collectionChanged(proxy); }; real.CollectionChanged += collectionChangedProxy; } collectionChanged += value; } remove { collectionChanged -= value; if (collectionChanged == null) real.CollectionChanged -= collectionChangedProxy; } } event CollectionClearedHandler collectionCleared; CollectionClearedHandler collectionClearedProxy; internal event CollectionClearedHandler CollectionCleared { add { if (collectionCleared == null) { if (collectionClearedProxy == null) collectionClearedProxy = delegate(object sender, ClearedEventArgs e) { collectionCleared(proxy, e); }; real.CollectionCleared += collectionClearedProxy; } collectionCleared += value; } remove { collectionCleared -= value; if (collectionCleared == null) real.CollectionCleared -= collectionClearedProxy; } } event ItemsAddedHandler itemsAdded; ItemsAddedHandler itemsAddedProxy; internal event ItemsAddedHandler ItemsAdded { add { if (itemsAdded == null) { if (itemsAddedProxy == null) itemsAddedProxy = delegate(object sender, ItemCountEventArgs e) { itemsAdded(proxy, e); }; real.ItemsAdded += itemsAddedProxy; } itemsAdded += value; } remove { itemsAdded -= value; if (itemsAdded == null) real.ItemsAdded -= itemsAddedProxy; } } event ItemInsertedHandler itemInserted; ItemInsertedHandler itemInsertedProxy; internal event ItemInsertedHandler ItemInserted { add { if (itemInserted == null) { if (itemInsertedProxy == null) itemInsertedProxy = delegate(object sender, ItemAtEventArgs e) { itemInserted(proxy, e); }; real.ItemInserted += itemInsertedProxy; } itemInserted += value; } remove { itemInserted -= value; if (itemInserted == null) real.ItemInserted -= itemInsertedProxy; } } event ItemsRemovedHandler itemsRemoved; ItemsRemovedHandler itemsRemovedProxy; internal event ItemsRemovedHandler ItemsRemoved { add { if (itemsRemoved == null) { if (itemsRemovedProxy == null) itemsRemovedProxy = delegate(object sender, ItemCountEventArgs e) { itemsRemoved(proxy, e); }; real.ItemsRemoved += itemsRemovedProxy; } itemsRemoved += value; } remove { itemsRemoved -= value; if (itemsRemoved == null) real.ItemsRemoved -= itemsRemovedProxy; } } event ItemRemovedAtHandler itemRemovedAt; ItemRemovedAtHandler itemRemovedAtProxy; internal event ItemRemovedAtHandler ItemRemovedAt { add { if (itemRemovedAt == null) { if (itemRemovedAtProxy == null) itemRemovedAtProxy = delegate(object sender, ItemAtEventArgs e) { itemRemovedAt(proxy, e); }; real.ItemRemovedAt += itemRemovedAtProxy; } itemRemovedAt += value; } remove { itemRemovedAt -= value; if (itemRemovedAt == null) real.ItemRemovedAt -= itemRemovedAtProxy; } } } /// /// /// /// public class ItemAtEventArgs : EventArgs { /// /// /// public readonly T Item; /// /// /// public readonly int Index; /// /// /// /// /// public ItemAtEventArgs(T item, int index) { Item = item; Index = index; } /// /// /// /// public override string ToString() { return String.Format("(ItemAtEventArgs {0} '{1}')", Index, Item); } } /// /// /// /// public class ItemCountEventArgs : EventArgs { /// /// /// public readonly T Item; /// /// /// public readonly int Count; /// /// /// /// /// public ItemCountEventArgs(T item, int count) { Item = item; Count = count; } /// /// /// /// public override string ToString() { return String.Format("(ItemCountEventArgs {0} '{1}')", Count, Item); } } /// /// /// public class ClearedEventArgs : EventArgs { /// /// /// public readonly bool Full; /// /// /// public readonly int Count; /// /// /// /// /// True if the operation cleared all of the collection /// The number of items removed by the clear. public ClearedEventArgs(bool full, int count) { Full = full; Count = count; } /// /// /// /// public override string ToString() { return String.Format("(ClearedEventArgs {0} {1})", Count, Full); } } /// /// /// public class ClearedRangeEventArgs : ClearedEventArgs { //WE could let this be of type int? to allow /// /// /// public readonly int? Start; /// /// /// /// /// /// public ClearedRangeEventArgs(bool full, int count, int? start) : base(full,count) { Start = start; } /// /// /// /// public override string ToString() { return String.Format("(ClearedRangeEventArgs {0} {1} {2})", Count, Full, Start); } } /// /// The type of event raised after an operation on a collection has changed its contents. /// Normally, a multioperation like AddAll, /// /// will only fire one CollectionChanged event. Any operation that changes the collection /// must fire CollectionChanged as its last event. /// public delegate void CollectionChangedHandler(object sender); /// /// The type of event raised after the Clear() operation on a collection. /// /// Note: The Clear() operation will not fire ItemsRemoved events. /// /// /// public delegate void CollectionClearedHandler(object sender, ClearedEventArgs eventArgs); /// /// The type of event raised after an item has been added to a collection. /// The event will be raised at a point of time, where the collection object is /// in an internally consistent state and before the corresponding CollectionChanged /// event is raised. /// /// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event. /// /// Note: When an item is inserted into a list (), both /// ItemInserted and ItemsAdded events will be fired. /// /// /// An object with the item that was added public delegate void ItemsAddedHandler(object sender, ItemCountEventArgs eventArgs); /// /// The type of event raised after an item has been removed from a collection. /// The event will be raised at a point of time, where the collection object is /// in an internally consistent state and before the corresponding CollectionChanged /// event is raised. /// /// Note: The Clear() operation will not fire ItemsRemoved events. /// /// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event. /// /// Note: When an item is removed from a list by the RemoveAt operation, both an /// ItemsRemoved and an ItemRemovedAt event will be fired. /// /// /// An object with the item that was removed public delegate void ItemsRemovedHandler(object sender, ItemCountEventArgs eventArgs); /// /// The type of event raised after an item has been inserted into a list by an Insert, /// InsertFirst or InsertLast operation. /// The event will be raised at a point of time, where the collection object is /// in an internally consistent state and before the corresponding CollectionChanged /// event is raised. /// /// Note: an ItemsAdded event will also be fired. /// /// /// public delegate void ItemInsertedHandler(object sender, ItemAtEventArgs eventArgs); /// /// The type of event raised after an item has been removed from a list by a RemoveAt(int i) /// operation (or RemoveFirst(), RemoveLast(), Remove() operation). /// The event will be raised at a point of time, where the collection object is /// in an internally consistent state and before the corresponding CollectionChanged /// event is raised. /// /// Note: an ItemRemoved event will also be fired. /// /// /// public delegate void ItemRemovedAtHandler(object sender, ItemAtEventArgs eventArgs); }