private void unregisterSourceItem(int sourceIndex) { OrderingItemInfo <TOrderingValue> itemInfo = _itemInfos[sourceIndex]; Utils.disposeExpressionWatcher(itemInfo.ExpressionWatcher, itemInfo.NestedComputings, this, _orderingValueSelectorContainsParametrizedLiveLinqCalls); int orderedIndex = itemInfo.OrderedItemInfo.Index; _orderedPositions.Remove(orderedIndex); _sourcePositions.Remove(sourceIndex); _orderingValues.RemoveAt(orderedIndex); if (_thenOrderingsCount > 0) { RangePosition rangePosition = itemInfo.OrderedItemInfo.RangePosition; if (rangePosition.Length == 1) { _equalOrderingValueRangePositions.Remove(rangePosition.Index); } else { _equalOrderingValueRangePositions.ModifyLength(rangePosition.Index, -1); } } baseRemoveItem(orderedIndex); }
void ISourceCollectionChangeProcessor.processSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: int newIndex = e.NewStartingIndex; TSourceItem addedItem = (TSourceItem)e.NewItems[0]; registerSourceItem(addedItem, newIndex); break; case NotifyCollectionChangedAction.Remove: unregisterSourceItem(e.OldStartingIndex); break; case NotifyCollectionChangedAction.Replace: int replacingSourceIndex = e.NewStartingIndex; TSourceItem replacingSourceItem = (TSourceItem)e.NewItems[0]; OrderingItemInfo <TOrderingValue> replacingItemInfo = _itemInfos[replacingSourceIndex]; ExpressionWatcher oldExpressionWatcher = replacingItemInfo.ExpressionWatcher; Utils.disposeExpressionWatcher(oldExpressionWatcher, replacingItemInfo.NestedComputings, this, _orderingValueSelectorContainsParametrizedLiveLinqCalls); Utils.getItemInfoContent( new object[] { replacingSourceItem }, out ExpressionWatcher newExpressionWatcher, out Func <TOrderingValue> newGetOrderingValueFunc, out List <IComputingInternal> nestedComputings, _orderingValueSelectorExpression, out _orderingValueSelectorExpressionCallCount, this, _orderingValueSelectorContainsParametrizedLiveLinqCalls, _orderingValueSelectorExpressionInfo); replacingItemInfo.GetOrderingValueFunc = newGetOrderingValueFunc; replacingItemInfo.ExpressionWatcher = newExpressionWatcher; replacingItemInfo.ExpressionWatcher.ValueChanged = expressionWatcher_OnValueChanged; newExpressionWatcher._position = oldExpressionWatcher._position; replacingItemInfo.NestedComputings = nestedComputings; baseSetItem(replacingItemInfo.OrderedItemInfo.Index, replacingSourceItem); processSourceItemChange(replacingSourceIndex, replacingSourceItem); break; case NotifyCollectionChangedAction.Move: int oldStartingIndex = e.OldStartingIndex; int newStartingIndex = e.NewStartingIndex; if (oldStartingIndex != newStartingIndex) { _sourcePositions.Move(oldStartingIndex, newStartingIndex); } break; case NotifyCollectionChangedAction.Reset: processSource(); break; } }
private TOrderingValue getOrderingValue(OrderingItemInfo<TOrderingValue> itemInfo, TSourceItem sourceItem) { TOrderingValue getValue() => !_orderingValueSelectorContainsParametrizedLiveLinqCalls ? _orderingValueSelectorFunc(sourceItem) : itemInfo.GetOrderingValueFunc(); if (Configuration.TrackComputingsExecutingUserCode) { var currentThread = Utils.startComputingExecutingUserCode(out var computing, out _userCodeIsCalledFrom, this); TOrderingValue result = getValue(); Utils.endComputingExecutingUserCode(computing, currentThread, out _userCodeIsCalledFrom); return result; } return getValue(); }
private void registerSourceItem(TSourceItem sourceItem, int sourceIndex, bool initializing = false) { OrderingItemInfo <TOrderingValue> itemInfo = _sourcePositions.Insert(sourceIndex); Utils.getItemInfoContent( new object[] { sourceItem }, out ExpressionWatcher expressionWatcher, out Func <TOrderingValue> getOrderingValueFunc, out List <IComputingInternal> nestedComputings, _orderingValueSelectorExpression, out _orderingValueSelectorExpressionCallCount, this, _orderingValueSelectorContainsParametrizedLiveLinqCalls, _orderingValueSelectorExpressionInfo); itemInfo.GetOrderingValueFunc = getOrderingValueFunc; itemInfo.ExpressionWatcher = expressionWatcher; itemInfo.NestedComputings = nestedComputings; TOrderingValue orderingValue = getOrderingValue(itemInfo, sourceItem); int orderedIndex = getOrderedIndex(orderingValue); itemInfo.ExpressionWatcher.ValueChanged = expressionWatcher_OnValueChanged; itemInfo.ExpressionWatcher._position = itemInfo; OrderedItemInfo <TOrderingValue> orderedItemInfo = _orderedPositions.Insert(orderedIndex); itemInfo.OrderedItemInfo = orderedItemInfo; orderedItemInfo.ItemInfo = itemInfo; _orderingValues.Insert(orderedIndex, orderingValue); if (_thenOrderingsCount > 0) { adjustEqualOrderingValueRangePosition(orderingValue, orderedItemInfo, orderedIndex, orderedIndex - 1, orderedIndex); } if (initializing) { _items.Insert(orderedIndex, sourceItem); } else { baseInsertItem(orderedIndex, sourceItem); } }
public void ValidateConsistency() { IList<TSourceItem> source = _sourceScalar.getValue(_source, new ObservableCollection<TSourceItem>()) as IList<TSourceItem>; if (_itemInfos.Count != Count) throw new ObservableComputationsException(this, "Consistency violation: Ordering.7"); List<TSourceItem> copy = this.ToList(); // ReSharper disable once PossibleNullReferenceException for (int sourceIndex = 0; sourceIndex < source.Count; sourceIndex++) { TSourceItem sourceItem = source[sourceIndex]; if (!copy.Remove(sourceItem)) throw new ObservableComputationsException(this, "Consistency violation: Ordering.1"); } _orderedPositions.ValidateConsistency(); Func<TSourceItem, TOrderingValue> orderingValueSelector = _orderingValueSelectorExpression.Compile(); IComparer<TOrderingValue> comparer = _comparerScalar.getValue(_comparer) ?? Comparer<TOrderingValue>.Default; ListSortDirection listSortDirection = _sortDirectionScalar.getValue(_sortDirection); if (_orderingValues.Count != Count) throw new ObservableComputationsException(this, "Consistency violation: Ordering.14"); if (_thenOrderingsCount > 0) { _equalOrderingValueRangePositions.ValidateConsistency(); } RangePosition rangePosition = null; int equalOrderingValueItemsCount = 0; int rangePositionIndex = 0; for (int orderedIndex = 0; orderedIndex < Count; orderedIndex++) { TSourceItem orderedItem = this[orderedIndex]; if (orderedIndex > 0) { int compareResult = comparer.Compare(orderingValueSelector(this[orderedIndex - 1]), orderingValueSelector(this[orderedIndex])); if ((compareResult < 0 && listSortDirection == ListSortDirection.Descending) || (compareResult > 0 && listSortDirection == ListSortDirection.Ascending)) throw new ObservableComputationsException(this, "Consistency violation: Ordering.3"); if (_thenOrderingsCount > 0) { if (compareResult == 0) { equalOrderingValueItemsCount++; if (rangePosition != _orderedItemInfos[orderedIndex].RangePosition) throw new ObservableComputationsException(this, "Consistency violation: Ordering.17"); } else { // ReSharper disable once PossibleNullReferenceException if (rangePosition.Length != equalOrderingValueItemsCount) throw new ObservableComputationsException(this, "Consistency violation: Ordering.20"); if (rangePosition.Index != rangePositionIndex) throw new ObservableComputationsException(this, "Consistency violation: Ordering.21"); rangePositionIndex++; equalOrderingValueItemsCount = 1; rangePosition = _orderedItemInfos[orderedIndex].RangePosition; } } } else { if (_thenOrderingsCount > 0) { rangePosition = _orderedItemInfos[orderedIndex].RangePosition; equalOrderingValueItemsCount = 1; } } OrderingItemInfo<TOrderingValue> itemInfo = _orderedItemInfos[orderedIndex].ItemInfo; if (itemInfo.OrderedItemInfo.Index != orderedIndex) throw new ObservableComputationsException(this, "Consistency violation: Ordering.13"); if (!EqualityComparer<TOrderingValue>.Default.Equals(_orderingValues[orderedIndex], orderingValueSelector(orderedItem))) throw new ObservableComputationsException(this, "Consistency violation: Ordering.10"); } if (_thenOrderingsCount > 0 && Count > 0) { // ReSharper disable once PossibleNullReferenceException if (rangePosition.Length != equalOrderingValueItemsCount) throw new ObservableComputationsException(this, "Consistency violation: Ordering.22"); if (rangePosition.Index != rangePositionIndex) throw new ObservableComputationsException(this, "Consistency violation: Ordering.23"); } _sourcePositions.ValidateConsistency(); if (_sourcePositions.List.Count != source.Count) throw new ObservableComputationsException(this, "Consistency violation: Ordering.15"); for (int sourceIndex = 0; sourceIndex < source.Count; sourceIndex++) { TSourceItem sourceItem = source[sourceIndex]; OrderingItemInfo<TOrderingValue> itemInfo = _itemInfos[sourceIndex]; if (itemInfo.ExpressionWatcher._position != _sourcePositions.List[sourceIndex]) throw new ObservableComputationsException(this, "Consistency violation: Ordering.8"); if (!EqualityComparer<TOrderingValue>.Default.Equals(_orderingValues[itemInfo.OrderedItemInfo.Index], orderingValueSelector(sourceItem))) throw new ObservableComputationsException(this, "Consistency violation: Ordering.9"); if (!_orderedItemInfos.Contains(_itemInfos[sourceIndex].OrderedItemInfo)) throw new ObservableComputationsException(this, "Consistency violation: Ordering.11"); if (!_sourcePositions.List.Contains(_itemInfos[sourceIndex].ExpressionWatcher._position)) throw new ObservableComputationsException(this, "Consistency violation: Ordering.12"); if (_itemInfos[sourceIndex].ExpressionWatcher._position.Index != sourceIndex) throw new ObservableComputationsException(this, "Consistency violation: Ordering.16"); } }
private void processSourceItemChange(int sourceIndex, TSourceItem sourceItem) { void notifyThenOrderings(int newOrderedIndex) { int processedThenOrderingsCount = 0; for (int thenOrderingIndex = 0; thenOrderingIndex < _thenOrderingsCount; thenOrderingIndex++) { IThenOrderingInternal<TSourceItem> thenOrdering = _thenOrderings[thenOrderingIndex]; thenOrdering.ProcessSourceItemChange(newOrderedIndex, sourceItem); processedThenOrderingsCount++; if (processedThenOrderingsCount == _thenOrderingsCount) break; } } OrderingItemInfo<TOrderingValue> itemInfo = _itemInfos[sourceIndex]; OrderedItemInfo<TOrderingValue> orderedItemInfo = itemInfo.OrderedItemInfo; int orderedIndex = orderedItemInfo.Index; TOrderingValue orderingValue = getOrderingValue(itemInfo, sourceItem); if (_comparer.Compare(_orderingValues[orderedIndex], orderingValue) != 0) { int newOrderedIndex = getOrderedIndex(orderingValue); if (newOrderedIndex == Count) newOrderedIndex = newOrderedIndex - 1; else if (newOrderedIndex > orderedIndex) newOrderedIndex--; _orderingValues.RemoveAt(orderedIndex); _orderingValues.Insert(newOrderedIndex, orderingValue); _orderedPositions.Move(orderedIndex, newOrderedIndex); if (_thenOrderingsCount > 0) { RangePosition rangePosition = orderedItemInfo.RangePosition; if (rangePosition.Length == 1) _equalOrderingValueRangePositions.Remove(rangePosition.Index); else _equalOrderingValueRangePositions.ModifyLength(rangePosition.Index, -1); adjustEqualOrderingValueRangePosition( orderingValue, orderedItemInfo, newOrderedIndex, orderedIndex < newOrderedIndex ? newOrderedIndex : newOrderedIndex - 1, orderedIndex > newOrderedIndex ? newOrderedIndex : newOrderedIndex + 1); } if (orderedIndex != newOrderedIndex) { baseMoveItem(orderedIndex, newOrderedIndex); } else if (_thenOrderingsCount > 0) { notifyThenOrderings(newOrderedIndex); } } else if (_thenOrderingsCount > 0) { notifyThenOrderings(orderedIndex); } }