void ISourceCollectionChangeProcessor.processSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { int count; switch (e.Action) { case NotifyCollectionChangedAction.Add: ItemInfo itemInfo; //if (newItems.Count > 1) throw new ObservableComputationsException(this, "Adding of multiple items is not supported"); object addedItem = e.NewItems[0]; int newStartingIndex = e.NewStartingIndex; itemInfo = _sourceRangePositions.Insert(newStartingIndex, 0); registerSourceItem(addedItem, itemInfo); int rangePositionPlainIndex1 = itemInfo.PlainIndex; IList <TSourceItem> sourceCopy = itemInfo.SourceCopy; count = sourceCopy?.Count ?? 0; _sourceRangePositions.ModifyLength(newStartingIndex, count); for (int index = 0; index < count; index++) { baseInsertItem(rangePositionPlainIndex1 + index, sourceCopy[index]); } break; case NotifyCollectionChangedAction.Remove: //if (e.OldItems.Count > 1) throw new ObservableComputationsException(this, "Removing of multiple items is not supported"); ItemInfo itemInfo1; object oldItem = e.OldItems[0]; IList removedItem = oldItem is IReadScalar <IList> scalar ? scalar.Value : (IList)oldItem; itemInfo1 = unregisterSourceItem(e.OldStartingIndex); int rangePositionPlainIndex = itemInfo1.PlainIndex; count = removedItem?.Count ?? 0; for (int index = count - 1; index >= 0; index--) { baseRemoveItem(rangePositionPlainIndex + index); } break; case NotifyCollectionChangedAction.Replace: ItemInfo itemInfo2; //if (newItems1.Count > 1) throw new ObservableComputationsException(this, "Replacing of multiple items is not supported"); object newItem = e.NewItems[0]; int oldStartingIndex = e.OldStartingIndex; unregisterSourceItem(oldStartingIndex, true); itemInfo2 = _itemInfos[oldStartingIndex]; registerSourceItem(newItem, itemInfo2); replaceItem(itemInfo2.SourceCopy, itemInfo2); break; case NotifyCollectionChangedAction.Move: int oldIndex = e.OldStartingIndex; int newIndex = e.NewStartingIndex; if (oldIndex != newIndex) { ItemInfo oldItemInfo = _itemInfos[oldIndex]; RangePosition newRangePosition = _itemInfos[newIndex]; int oldPlainIndex = oldItemInfo.PlainIndex; int newPlainIndex = newRangePosition.PlainIndex; int newRangePositionLength = newRangePosition.Length; if (oldPlainIndex != newPlainIndex) { IList <TSourceItem> movingItem = oldItemInfo.SourceCopy; count = movingItem?.Count ?? 0; if (oldIndex < newIndex) { for (int index = 0; index < count; index++) { baseMoveItem(oldPlainIndex, newPlainIndex + newRangePositionLength - 1); } } else { for (int index = 0; index < count; index++) { baseMoveItem(oldPlainIndex + index, newPlainIndex + index); } } } _sourceRangePositions.Move(oldItemInfo.Index, newRangePosition.Index); } break; case NotifyCollectionChangedAction.Reset: processSource(false); break; } }
private void handleSourcesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { checkConsistent(sender, e); _handledEventSender = sender; _handledEventArgs = e; if (_indexerPropertyChangedEventRaised || _lastProcessedSourcesChangeMarker != _sourcesAsIHasChangeMarker.ChangeMarker) { _lastProcessedSourcesChangeMarker = !_lastProcessedSourcesChangeMarker; _indexerPropertyChangedEventRaised = false; _isConsistent = false; int count; switch (e.Action) { case NotifyCollectionChangedAction.Add: ItemInfo itemInfo; IList newItems = e.NewItems; //if (newItems.Count > 1) throw new ObservableComputationsException(this, "Adding of multiple items is not supported"); IList addedItem = (IList)newItems[0]; count = addedItem?.Count ?? 0; itemInfo = _sourceRangePositions.Insert(e.NewStartingIndex, count); registerSourceItem((INotifyCollectionChanged)addedItem, itemInfo); int rangePositionPlainIndex1 = itemInfo.PlainIndex; for (int index = 0; index < count; index++) { // ReSharper disable once PossibleNullReferenceException TSourceItem item = (TSourceItem)addedItem[index]; baseInsertItem(rangePositionPlainIndex1 + index, item); } break; case NotifyCollectionChangedAction.Remove: //if (e.OldItems.Count > 1) throw new ObservableComputationsException(this, "Removing of multiple items is not supported"); ItemInfo itemInfo1; IList removedItem = (IList)e.OldItems[0]; itemInfo1 = unregisterSourceItem(e.OldStartingIndex); int rangePositionPlainIndex = itemInfo1.PlainIndex; count = removedItem?.Count ?? 0; for (int index = count - 1; index >= 0; index--) { baseRemoveItem(rangePositionPlainIndex + index); } break; case NotifyCollectionChangedAction.Replace: ItemInfo itemInfo2; IList newItems1 = e.NewItems; //if (newItems1.Count > 1) throw new ObservableComputationsException(this, "Replacing of multiple items is not supported"); INotifyCollectionChanged newItem = (INotifyCollectionChanged)newItems1[0]; itemInfo2 = _itemInfos[e.OldStartingIndex]; replaceItem((IList)newItem, itemInfo2); if (itemInfo2.Source != null) { itemInfo2.Source.CollectionChanged -= itemInfo2.SourceWeakNotifyCollectionChangedEventHandler.Handle; itemInfo2.SourceNotifyCollectionChangedEventHandler = (sender1, eventArgs) => handleSourceCollectionChanged(sender1, eventArgs, itemInfo2); } itemInfo2.Source = newItem; if (itemInfo2.Source != null) { itemInfo2.SourceWeakNotifyCollectionChangedEventHandler = new WeakNotifyCollectionChangedEventHandler(itemInfo2.SourceNotifyCollectionChangedEventHandler); itemInfo2.Source.CollectionChanged += itemInfo2.SourceWeakNotifyCollectionChangedEventHandler.Handle; } break; case NotifyCollectionChangedAction.Move: int oldIndex = e.OldStartingIndex; int newIndex = e.NewStartingIndex; if (oldIndex != newIndex) { RangePosition oldRangePosition = _sourceRangePositions.List[oldIndex]; RangePosition newRangePosition = _sourceRangePositions.List[newIndex]; int oldPlainIndex = oldRangePosition.PlainIndex; int newPlainIndex = newRangePosition.PlainIndex; if (oldPlainIndex != newPlainIndex) { IList movingItem = (IList)e.OldItems[0]; count = movingItem?.Count ?? 0; if (oldIndex < newIndex) { int newRangePositionLength = newRangePosition.Length; for (int index = 0; index < count; index++) { baseMoveItem(oldPlainIndex, newPlainIndex + newRangePositionLength - 1); } } else { for (int index = 0; index < count; index++) { baseMoveItem(oldPlainIndex + index, newPlainIndex + index); } } } _sourceRangePositions.Move(oldRangePosition.Index, newRangePosition.Index); } break; case NotifyCollectionChangedAction.Reset: initializeFromSources(); break; } _isConsistent = true; raiseConsistencyRestored(); } _handledEventSender = null; _handledEventArgs = null; }
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); } }
private void handleSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { _handledEventSender = sender; _handledEventArgs = e; if (_indexerPropertyChangedEventRaised || _lastProcessedSourceChangeMarker != _sourceAsObservableCollectionWithChangeMarker.ChangeMarkerField) { _indexerPropertyChangedEventRaised = false; _lastProcessedSourceChangeMarker = !_lastProcessedSourceChangeMarker; switch (e.Action) { case NotifyCollectionChangedAction.Add: IList newItems = e.NewItems; //if (newItems.Count > 1) throw new ObservableComputationsException(this, "Adding of multiple items is not supported"); string addedSourceItem = (string)newItems[0]; int addedSourceIndex = e.NewStartingIndex; processAddSourceItem(addedSourceItem, addedSourceIndex); setValue(_valueStringBuilder.ToString()); break; case NotifyCollectionChangedAction.Remove: //if (e.OldItems.Count > 1) throw new ObservableComputationsException(this, "Removing of multiple items is not supported"); int removedSourceIndex = e.OldStartingIndex; processRemoveSourceItem(removedSourceIndex); setValue(_valueStringBuilder.ToString()); break; case NotifyCollectionChangedAction.Replace: IList newItems1 = e.NewItems; //if (newItems1.Count > 1) throw new ObservableComputationsException(this, "Replacing of multiple items is not supported"); RangePosition replacingItemRangePosition = _resultRangePositions.List[e.NewStartingIndex * 2]; string newSourceItem = (string)newItems1[0]; int replacingSourceItemLength = replacingItemRangePosition.Length; int newSourceItemLength = newSourceItem != null ? newSourceItem.Length : 0; int plainIndex = replacingItemRangePosition.PlainIndex; for ( int charIndex = 0; charIndex < replacingSourceItemLength && charIndex < newSourceItemLength; charIndex++) { _valueStringBuilder[plainIndex + charIndex] = newSourceItem[charIndex]; } if (newSourceItemLength < replacingSourceItemLength) { _valueStringBuilder.Remove( plainIndex + newSourceItemLength, replacingSourceItemLength - newSourceItemLength); } else if (newSourceItemLength > replacingSourceItemLength) { _valueStringBuilder.Insert( plainIndex + replacingSourceItemLength, newSourceItem.Substring(replacingSourceItemLength, newSourceItemLength - replacingSourceItemLength)); } _resultRangePositions.ModifyLength(replacingItemRangePosition.Index, newSourceItemLength - replacingSourceItemLength); setValue(_valueStringBuilder.ToString()); break; case NotifyCollectionChangedAction.Move: int newSourceIndex = e.NewStartingIndex; int oldSourceIndex = e.OldStartingIndex; if (newSourceIndex != oldSourceIndex) { _moving = true; processRemoveSourceItem(oldSourceIndex); string newSourceItem1 = _sourceAsList[newSourceIndex]; processAddSourceItem(newSourceItem1, newSourceIndex); _moving = false; setValue(_valueStringBuilder.ToString()); } break; case NotifyCollectionChangedAction.Reset: initializeFromSource(); break; } } _handledEventSender = null; _handledEventArgs = null; }
private void initializeSeparator() { int oldSeparatorLength = _separatorLength; if (_separatorScalar != null) { _separator = _separatorScalar.Value; } if (_separator == null) { _separator = string.Empty; } _separatorLength = _separator.Length; int lengthIncrement = _separatorLength - oldSeparatorLength; if (_sourceAsList != null && _sourceAsList.Count > 0) { int incrementSum = 0; int count = _sourceAsList.Count; for (int sourceIndex = 0; sourceIndex <= count - 2; sourceIndex++) { int itemIndex = sourceIndex * 2; RangePosition itemRangePosition = _resultRangePositions.List[itemIndex]; RangePosition separatorRangePosition = _resultRangePositions.List[itemIndex + 1]; for ( int separatorCharIndex = 0; separatorCharIndex < oldSeparatorLength && separatorCharIndex < _separatorLength; separatorCharIndex++) { _valueStringBuilder[separatorRangePosition.PlainIndex + incrementSum + separatorCharIndex] = _separator[separatorCharIndex]; } if (_separatorLength < oldSeparatorLength) { _valueStringBuilder.Remove( separatorRangePosition.PlainIndex + incrementSum + _separatorLength, -lengthIncrement); } else if (_separatorLength > oldSeparatorLength) { _valueStringBuilder.Insert( separatorRangePosition.PlainIndex + incrementSum + oldSeparatorLength, _separator.Substring(oldSeparatorLength, lengthIncrement)); } itemRangePosition.PlainIndex = itemRangePosition.PlainIndex + incrementSum; separatorRangePosition.PlainIndex = itemRangePosition.PlainIndex + incrementSum; separatorRangePosition.Length = _separatorLength; incrementSum = incrementSum + lengthIncrement; } setValue(_valueStringBuilder.ToString()); } }
void ISourceCollectionChangeProcessor.processSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: IList newItems = e.NewItems; _sourceCount++; //if (newItems.Count > 1) throw new ObservableComputationsException(this, "Adding of multiple items is not supported"); string addedSourceItem = (string)newItems[0]; int addedSourceIndex = e.NewStartingIndex; processAddSourceItem(addedSourceItem, addedSourceIndex); setValue(_valueStringBuilder.ToString()); break; case NotifyCollectionChangedAction.Remove: //if (e.OldItems.Count > 1) throw new ObservableComputationsException(this, "Removing of multiple items is not supported"); _sourceCount--; int removedSourceIndex = e.OldStartingIndex; processRemoveSourceItem(removedSourceIndex); setValue(_valueStringBuilder.ToString()); break; case NotifyCollectionChangedAction.Replace: IList newItems1 = e.NewItems; //if (newItems1.Count > 1) throw new ObservableComputationsException(this, "Replacing of multiple items is not supported"); RangePosition replacingItemRangePosition = _resultRangePositions.List[e.NewStartingIndex * 2]; string newSourceItem = (string)newItems1[0]; int replacingSourceItemLength = replacingItemRangePosition.Length; int newSourceItemLength = newSourceItem?.Length ?? 0; int plainIndex = replacingItemRangePosition.PlainIndex; for ( int charIndex = 0; charIndex < replacingSourceItemLength && charIndex < newSourceItemLength; charIndex++) { // ReSharper disable once PossibleNullReferenceException _valueStringBuilder[plainIndex + charIndex] = newSourceItem[charIndex]; } if (newSourceItemLength < replacingSourceItemLength) { _valueStringBuilder.Remove( plainIndex + newSourceItemLength, replacingSourceItemLength - newSourceItemLength); } else if (newSourceItemLength > replacingSourceItemLength) { _valueStringBuilder.Insert( plainIndex + replacingSourceItemLength, // ReSharper disable once PossibleNullReferenceException newSourceItem.Substring(replacingSourceItemLength, newSourceItemLength - replacingSourceItemLength)); } _resultRangePositions.ModifyLength(replacingItemRangePosition.Index, newSourceItemLength - replacingSourceItemLength); setValue(_valueStringBuilder.ToString()); break; case NotifyCollectionChangedAction.Move: int newSourceIndex = e.NewStartingIndex; int oldSourceIndex = e.OldStartingIndex; if (newSourceIndex != oldSourceIndex) { _moving = true; processRemoveSourceItem(oldSourceIndex); string newSourceItem1 = (string)e.NewItems[0]; processAddSourceItem(newSourceItem1, newSourceIndex); _moving = false; setValue(_valueStringBuilder.ToString()); } break; case NotifyCollectionChangedAction.Reset: processSource(false); break; } }