protected void InsertRange(int index, AListBase <T> source, bool move) { if (source._root.IsLeaf || source._maxLeafSize != _maxLeafSize) { InsertRange(index, (IListSource <T>)source); if (move) { source.Clear(); } } else { AListBase <T> rightSection = null; int rightSize; if ((rightSize = Count - index) != 0) { rightSection = RemoveSection(index, rightSize); } Combine(source, move, true); if (rightSection != null) { Combine(rightSection, true, true); } } }
public ObserverMgr(AListBase <K, T> list, AListNode <K, T> root, IAListTreeObserver <K, T> existingObserver) { _list = list; _root = root; if (existingObserver != null) { _observers.Add(existingObserver); } }
void IAListTreeObserver <K, T> .RootChanged(AListBase <K, T> list, AListNode <K, T> newRoot, bool clear) { _roots[list] = newRoot; if (clear) { _hasCachedSummary = false; _cachedSummary = default(TSummary); _summaries.Clear(); } }
void IAListTreeObserver <K, T> .Detach(AListBase <K, T> list, AListNode <K, T> root) { if (_roots.TryGetValue(list, null) is AListInnerBase <K, T> ) { // Avoid a memory leak _parents.Clear(); _summaries.Clear(); } _roots.Remove(list); }
public void RootChanged(AListBase <K, T> list, AListNode <K, T> newRoot, bool clear) { Debug.Assert(_list == list); _root = newRoot; try { for (int i = 0; i < _observers.Count; i++) { _observers[i].RootChanged(list, newRoot, clear); } } catch (Exception e) { IllegalException(e); } }
public AListBase(AListBase <T> items, bool keepListChangingHandlers) : base(items, keepListChangingHandlers) { }
public static AListStatisticTracker <T> StatisticTracker <T>(this AListBase <int, T> list, Func <T, double> selector) => new AListStatisticTracker <T>(selector, list);
public static AListStatisticTracker <K, T, TStatistic> StatisticTracker <K, T, TStatistic>(this AListBase <K, T> list, Func <T, TStatistic> selector, Func <TStatistic, TStatistic, TStatistic> aggregator, TStatistic emptyResult) => new AListStatisticTracker <K, T, TStatistic>(selector, aggregator, emptyResult, list);
public static AListSumTracker <K, T> SumTracker <K, T>(this AListBase <K, T> list, Func <T, double> selector) => new AListSumTracker <K, T>(selector, list);
bool?IAListTreeObserver <K, T> .Attach(AListBase <K, T> list) => null;
protected override void Clone(out AListBase <T> clone) { clone = Clone(); }
public void Detach(AListBase <K, T> list, AListNode <K, T> root) { throw new NotImplementedException(); // should not be called }
public bool?Attach(AListBase <K, T> list) { throw new InvalidOperationException(); // should not be called }
public AListStatisticTracker(Func <T, TSummary> selector, Func <TSummary, TSummary, TSummary> aggregator, TSummary emptyResult, AListBase <K, T> list = null) { _selector = selector; _emptyResult = emptyResult; _aggregator = array => { if (array.Length == 0) { return(_emptyResult); } var total = array[0]; for (int i = 1; i < array.Length; i++) { total = aggregator(total, array[i]); } return(total); }; list?.AddObserver(this); }
public AListStatisticTracker(Func <T, TSummary> selector, Func <TSummary[], TSummary> aggregator, TSummary emptyResult, AListBase <K, T> list = null) { _selector = selector; _aggregator = aggregator; _emptyResult = emptyResult; list?.AddObserver(this); }
protected abstract void Clone(out AListBase <T> clone);
protected virtual void Combine(AListBase <T> other, bool move, bool append) { int heightDifference = _treeHeight - other._treeHeight; int insertAt = append ? Count : 0; if (!(other._root is AListInner <T>)) { goto insertRange; } else if (heightDifference < 0) { // The other tree is taller (bigger). We can only append/prepend a smaller // tree; therefore, swap the trees and then append/prepend the smaller one. // With the tree contents swapped, the notifications to ListChanging // must be fudged. If we have a tree _observer, the situation is too // complex and unusual to handle, so we fall back on InsertRange(). if (_observer != null || (other._observer != null && move)) { goto insertRange; } AListBase <T> other2 = other; if (!move) { other.Clone(out other2); } // Fire ListChanging on both lists, and block further notifications var temp = _listChanging; var tempO = other._listChanging; Exception e = null; if (temp != null) { CallListChanging(new ListChangeInfo <T>(NotifyCollectionChangedAction.Add, insertAt, other.Count, other)); } if (tempO != null) { try { other.CallListChanging(new ListChangeInfo <T>(NotifyCollectionChangedAction.Remove, 0, -other.Count, null)); } catch (Exception e_) { // Ugh. We already notified the first list about the insert, // so it is too late to abort. Finish the operation and // throw the exception afterward. e = e_; } } try { _listChanging = null; other._listChanging = null; other2.Combine(this, move, !append); } finally { _listChanging = temp; other._listChanging = tempO; } base.SwapHelper(other2, false); if (e != null) { throw e; } } else { // other tree is the same height or less tall BeginInsertRange(insertAt, other, other.Count); int amtInserted = 0; try { AListNode <int, T> splitLeft, splitRight; splitLeft = ((AListInner <T>)_root).Combine((AListInner <T>)other._root, heightDifference, out splitRight, _observer, move, append); amtInserted = other.Count; if (move) { other.ClearInternal(true); } AutoSplit(splitLeft, splitRight); } finally { DoneInsertRange(amtInserted); } } return; insertRange: InsertRange(insertAt, (IListSource <T>)other); if (move) { other.ClearInternal(true); } }
public static AListSumTracker <K, double> SumTracker <K>(this AListBase <K, double> list) => SumTracker(list, n => n);
protected SparseAList(AListBase <int, T> original, AListNode <int, T> section) : base(original, section) { }
public void Attach(AListBase <K, T> list, Action <bool> populate) { throw new InvalidOperationException(); // should not be called }