/// <summary> /// Reduces all expanded nodes, and clear all unassigned optional nodes. /// </summary> /// <param name="isChanged">True upon return if the node was changed. False if the node was already canonic.</param> public virtual void Canonicalize(out bool isChanged) { WriteableOperationList OperationList = CreateOperationList(); Canonicalize(RootState, OperationList); if (OperationList.Count > 0) { Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoRefresh(operation); Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => throw new NotImplementedException(); // Undo is not possible. WriteableGenericRefreshOperation RefreshOperation = CreateGenericRefreshOperation(RootState, HandlerRedo, HandlerUndo, isNested: false); RefreshOperation.Redo(); WriteableOperationReadOnlyList OperationReadOnlyList = OperationList.ToReadOnly(); WriteableOperationGroup OperationGroup = CreateOperationGroup(OperationReadOnlyList, RefreshOperation); SetLastOperation(OperationGroup); CheckInvariant(); isChanged = true; } else { isChanged = false; } }
/// <summary> /// Expands an existing node. In the node: /// * All optional children are assigned if they aren't /// * If the node is a feature call, with no arguments, an empty argument is inserted. /// </summary> /// <param name="expandedIndex">Index of the expanded node.</param> /// <param name="isChanged">True upon return if the node was changed. False if the node was already expanded.</param> public virtual void Expand(IWriteableNodeIndex expandedIndex, out bool isChanged) { Contract.RequireNotNull(expandedIndex, out IWriteableNodeIndex ExpandedIndex); Debug.Assert(StateTable.ContainsKey(ExpandedIndex)); Debug.Assert(StateTable[ExpandedIndex] is IWriteablePlaceholderNodeState); WriteableOperationList OperationList = CreateOperationList(); DebugObjects.AddReference(OperationList); Expand(ExpandedIndex, OperationList); if (OperationList.Count > 0) { WriteableOperationReadOnlyList OperationReadOnlyList = OperationList.ToReadOnly(); WriteableOperationGroup OperationGroup = CreateOperationGroup(OperationReadOnlyList, null); SetLastOperation(OperationGroup); CheckInvariant(); isChanged = true; } else { isChanged = false; } }
/// <summary> /// Reduces an existing node. Opposite of Expand. /// </summary> /// <param name="reducedIndex">Index of the reduced node.</param> /// <param name="isChanged">True upon return if the node was changed. False if the node was already reduced.</param> public virtual void Reduce(IWriteableNodeIndex reducedIndex, out bool isChanged) { Contract.RequireNotNull(reducedIndex, out IWriteableNodeIndex ReducedIndex); Debug.Assert(StateTable.ContainsKey(ReducedIndex)); Debug.Assert(StateTable[ReducedIndex] is IWriteablePlaceholderNodeState); WriteableOperationList OperationList = CreateOperationList(); Reduce(ReducedIndex, OperationList, isNested: false); if (OperationList.Count > 0) { WriteableOperationReadOnlyList OperationReadOnlyList = OperationList.ToReadOnly(); WriteableOperationGroup OperationGroup = CreateOperationGroup(OperationReadOnlyList, null); SetLastOperation(OperationGroup); CheckInvariant(); isChanged = true; } else { isChanged = false; } }
/// <summary></summary> public virtual void RemoveNodeRange(IWriteableListInner inner, int firstNodeIndex, int lastNodeIndex) { Contract.RequireNotNull(inner, out IWriteableListInner Inner); Debug.Assert(firstNodeIndex >= 0 && firstNodeIndex < Inner.StateList.Count); Debug.Assert(lastNodeIndex >= 0 && lastNodeIndex <= Inner.StateList.Count); Debug.Assert(firstNodeIndex <= lastNodeIndex); System.Action <IWriteableOperation> HandlerRedoNode = (IWriteableOperation operation) => RedoRemoveNode(operation); System.Action <IWriteableOperation> HandlerUndoNode = (IWriteableOperation operation) => UndoRemoveNode(operation); WriteableOperationList OperationList = CreateOperationList(); for (int i = firstNodeIndex; i < lastNodeIndex; i++) { WriteableRemoveNodeOperation OperationNode = CreateRemoveNodeOperation(Inner.Owner.Node, Inner.PropertyName, -1, firstNodeIndex, HandlerRedoNode, HandlerUndoNode, isNested: true); OperationList.Add(OperationNode); } if (OperationList.Count > 0) { WriteableOperationReadOnlyList OperationReadOnlyList = OperationList.ToReadOnly(); System.Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoRefresh(operation); System.Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => throw new NotImplementedException(); // Undo is not possible. WriteableGenericRefreshOperation RefreshOperation = CreateGenericRefreshOperation(RootState, HandlerRedo, HandlerUndo, isNested: false); WriteableOperationGroup OperationGroup = CreateOperationGroup(OperationReadOnlyList, RefreshOperation); OperationGroup.Redo(); SetLastOperation(OperationGroup); CheckInvariant(); } }
/// <summary></summary> public virtual void InsertNodeRange(IWriteableBlockListInner inner, int blockIndex, int insertedIndex, IList <IWriteableInsertionCollectionNodeIndex> indexList) { Contract.RequireNotNull(inner, out IWriteableBlockListInner Inner); Debug.Assert(blockIndex >= 0 && blockIndex < Inner.BlockStateList.Count); IWriteableBlockState BlockState = (IWriteableBlockState)Inner.BlockStateList[blockIndex]; Debug.Assert(insertedIndex >= 0 && insertedIndex <= BlockState.StateList.Count); int BlockNodeIndex = insertedIndex; foreach (IWriteableInsertionCollectionNodeIndex NodeIndex in indexList) { bool IsHandled = false; if (NodeIndex is IWriteableInsertionExistingBlockNodeIndex AsExistingBlockNodeIndex) { Debug.Assert(AsExistingBlockNodeIndex.BlockIndex == blockIndex); Debug.Assert(AsExistingBlockNodeIndex.Index == BlockNodeIndex); BlockNodeIndex++; IsHandled = true; } Debug.Assert(IsHandled); } int FinalNodeIndex = BlockNodeIndex; Action <IWriteableOperation> HandlerRedoInsertNode = (IWriteableOperation operation) => RedoInsertNewNode(operation); Action <IWriteableOperation> HandlerUndoInsertNode = (IWriteableOperation operation) => UndoInsertNewNode(operation); WriteableOperationList OperationList = CreateOperationList(); foreach (IWriteableInsertionCollectionNodeIndex NodeIndex in indexList) { if (NodeIndex is IWriteableInsertionExistingBlockNodeIndex AsExistingBlockNodeIndex) { IndexToPositionAndNode(AsExistingBlockNodeIndex, out blockIndex, out int Index, out _, out Node Node); WriteableInsertNodeOperation OperationInsertNode = CreateInsertNodeOperation(Inner.Owner.Node, Inner.PropertyName, blockIndex, Index, Node, HandlerRedoInsertNode, HandlerUndoInsertNode, isNested: true); OperationList.Add(OperationInsertNode); } } if (OperationList.Count > 0) { WriteableOperationReadOnlyList OperationReadOnlyList = OperationList.ToReadOnly(); Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoRefresh(operation); Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => throw new NotImplementedException(); // Undo is not possible. WriteableGenericRefreshOperation RefreshOperation = CreateGenericRefreshOperation(RootState, HandlerRedo, HandlerUndo, isNested: false); WriteableOperationGroup OperationGroup = CreateOperationGroup(OperationReadOnlyList, RefreshOperation); OperationGroup.Redo(); SetLastOperation(OperationGroup); CheckInvariant(); } }
private protected virtual void SetLastOperation(IWriteableOperation operation) { WriteableOperationList OperationList = CreateOperationList(); OperationList.Add(operation); WriteableOperationReadOnlyList OperationReadOnlyList = OperationList.ToReadOnly(); WriteableOperationGroup OperationGroup = CreateOperationGroup(OperationReadOnlyList, null); SetLastOperation(OperationGroup); }
/// <summary> /// Split an identifier with replace and insert indexes. /// </summary> /// <param name="inner">The inner where the node is replaced.</param> /// <param name="replaceIndex">Index for the replace operation.</param> /// <param name="insertIndex">Index for the insert operation.</param> /// <param name="firstIndex">Index of the replacing node upon return.</param> /// <param name="secondIndex">Index of the inserted node upon return.</param> public virtual void SplitIdentifier(IWriteableListInner inner, IWriteableInsertionListNodeIndex replaceIndex, IWriteableInsertionListNodeIndex insertIndex, out IWriteableBrowsingListNodeIndex firstIndex, out IWriteableBrowsingListNodeIndex secondIndex) { Contract.RequireNotNull(inner, out IWriteableListInner Inner); Contract.RequireNotNull(replaceIndex, out IWriteableInsertionListNodeIndex ReplaceIndex); Contract.RequireNotNull(insertIndex, out IWriteableInsertionListNodeIndex InsertIndex); IWriteableNodeState Owner = Inner.Owner; IWriteableIndex ParentIndex = Owner.ParentIndex; Debug.Assert(Contains(ParentIndex)); Debug.Assert(IndexToState(ParentIndex) == Owner); WriteableInnerReadOnlyDictionary <string> InnerTable = Owner.InnerTable; Debug.Assert(InnerTable.ContainsKey(Inner.PropertyName)); Debug.Assert(InnerTable[Inner.PropertyName] == Inner); int Index = ReplaceIndex.Index; Debug.Assert(InsertIndex.Index == Index + 1); Node ReplacingNode = ReplaceIndex.Node; Node InsertedNode = InsertIndex.Node; Action <IWriteableOperation> HandlerRedoReplace = (IWriteableOperation operation) => RedoReplace(operation); Action <IWriteableOperation> HandlerUndoReplace = (IWriteableOperation operation) => UndoReplace(operation); IWriteableReplaceOperation ReplaceOperation = CreateReplaceOperation(Inner.Owner.Node, Inner.PropertyName, -1, Index, clearNode: false, ReplacingNode, HandlerRedoReplace, HandlerUndoReplace, isNested: true); Action <IWriteableOperation> HandlerRedoInsert = (IWriteableOperation operation) => RedoInsertNewNode(operation); Action <IWriteableOperation> HandlerUndoInsert = (IWriteableOperation operation) => UndoInsertNewNode(operation); WriteableInsertNodeOperation InsertOperation = CreateInsertNodeOperation(Inner.Owner.Node, Inner.PropertyName, -1, Index + 1, InsertedNode, HandlerRedoInsert, HandlerUndoInsert, isNested: true); ReplaceOperation.Redo(); InsertOperation.Redo(); Action <IWriteableOperation> HandlerRedoRefresh = (IWriteableOperation operation) => RedoRefresh(operation); Action <IWriteableOperation> HandlerUndoRefresh = (IWriteableOperation operation) => throw new NotImplementedException(); // Undo is not possible. WriteableGenericRefreshOperation RefreshOperation = CreateGenericRefreshOperation(RootState, HandlerRedoRefresh, HandlerUndoRefresh, isNested: false); RefreshOperation.Redo(); WriteableOperationList OperationList = CreateOperationList(); OperationList.Add(ReplaceOperation); OperationList.Add(InsertOperation); WriteableOperationReadOnlyList OperationReadOnlyList = OperationList.ToReadOnly(); WriteableOperationGroup OperationGroup = CreateOperationGroup(OperationReadOnlyList, RefreshOperation); SetLastOperation(OperationGroup); CheckInvariant(); firstIndex = ReplaceOperation.NewBrowsingIndex as IWriteableBrowsingListNodeIndex; Debug.Assert(firstIndex != null); secondIndex = InsertOperation.BrowsingIndex as IWriteableBrowsingListNodeIndex; Debug.Assert(secondIndex != null); }
/// <summary> /// Redo the last operation undone. /// </summary> public virtual void Redo() { Debug.Assert(CanRedo); WriteableOperationGroup OperationGroup = OperationStack[RedoIndex]; OperationGroup.Redo(); RedoIndex++; CheckInvariant(); }
private protected virtual void SetLastOperation(WriteableOperationGroup operationGroup) { Debug.Assert(RedoIndex >= 0 && RedoIndex <= _OperationStack.Count); while (_OperationStack.Count > RedoIndex) { _OperationStack.RemoveAt(RedoIndex); } Debug.Assert(RedoIndex == _OperationStack.Count); _OperationStack.Add(operationGroup); RedoIndex = _OperationStack.Count; Debug.Assert(RedoIndex == _OperationStack.Count); }
/// <summary> /// Removes a range of blocks from a block list. /// </summary> /// <param name="inner">The inner for the block list from which blocks are removed.</param> /// <param name="firstBlockIndex">Index of the first block to remove.</param> /// <param name="lastBlockIndex">Index following the last block to remove.</param> public virtual void RemoveBlockRange(IWriteableBlockListInner inner, int firstBlockIndex, int lastBlockIndex) { Contract.RequireNotNull(inner, out IWriteableBlockListInner Inner); Debug.Assert(firstBlockIndex >= 0 && firstBlockIndex < Inner.BlockStateList.Count); Debug.Assert(lastBlockIndex >= 0 && lastBlockIndex <= Inner.BlockStateList.Count); Debug.Assert(firstBlockIndex <= lastBlockIndex); System.Action <IWriteableOperation> HandlerRedoNode = (IWriteableOperation operation) => RedoRemoveNode(operation); System.Action <IWriteableOperation> HandlerUndoNode = (IWriteableOperation operation) => UndoRemoveNode(operation); System.Action <IWriteableOperation> HandlerRedoBlock = (IWriteableOperation operation) => RedoRemoveBlock(operation); System.Action <IWriteableOperation> HandlerUndoBlock = (IWriteableOperation operation) => UndoRemoveBlock(operation); WriteableOperationList OperationList = CreateOperationList(); for (int i = firstBlockIndex; i < lastBlockIndex; i++) { IWriteableBlockState BlockState = (IWriteableBlockState)Inner.BlockStateList[i]; Debug.Assert(BlockState.StateList.Count >= 1); // Remove at firstBlockIndex since subsequent blocks are moved as the block at firstBlockIndex is deleted. // Same for nodes inside blokcks, delete them at 0. for (int j = 1; j < BlockState.StateList.Count; j++) { WriteableRemoveNodeOperation OperationNode = CreateRemoveNodeOperation(Inner.Owner.Node, Inner.PropertyName, firstBlockIndex, 0, HandlerRedoNode, HandlerUndoNode, isNested: true); OperationList.Add(OperationNode); } IWriteableRemoveBlockOperation OperationBlock = CreateRemoveBlockOperation(Inner.Owner.Node, Inner.PropertyName, firstBlockIndex, HandlerRedoBlock, HandlerUndoBlock, isNested: true); OperationList.Add(OperationBlock); } if (OperationList.Count > 0) { WriteableOperationReadOnlyList OperationReadOnlyList = OperationList.ToReadOnly(); System.Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoRefresh(operation); System.Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => throw new NotImplementedException(); // Undo is not possible. WriteableGenericRefreshOperation RefreshOperation = CreateGenericRefreshOperation(RootState, HandlerRedo, HandlerUndo, isNested: false); WriteableOperationGroup OperationGroup = CreateOperationGroup(OperationReadOnlyList, RefreshOperation); OperationGroup.Redo(); SetLastOperation(OperationGroup); CheckInvariant(); } }
/// <summary></summary> public virtual void ReplaceNodeRange(IWriteableListInner inner, int firstNodeIndex, int lastNodeIndex, IList <IWriteableInsertionCollectionNodeIndex> indexList) { Contract.RequireNotNull(inner, out IWriteableListInner Inner); Debug.Assert(firstNodeIndex >= 0 && firstNodeIndex < Inner.StateList.Count); Debug.Assert(lastNodeIndex >= 0 && lastNodeIndex <= Inner.StateList.Count); Debug.Assert(firstNodeIndex <= lastNodeIndex); int BlockNodeIndex = firstNodeIndex; foreach (IWriteableInsertionCollectionNodeIndex NodeIndex in indexList) { bool IsHandled = false; if (NodeIndex is IWriteableInsertionListNodeIndex AsListNodeIndex) { Debug.Assert(AsListNodeIndex.Index == BlockNodeIndex); BlockNodeIndex++; IsHandled = true; } Debug.Assert(IsHandled); } int FinalNodeIndex = BlockNodeIndex; Action <IWriteableOperation> HandlerRedoInsertNode = (IWriteableOperation operation) => RedoInsertNewNode(operation); Action <IWriteableOperation> HandlerUndoInsertNode = (IWriteableOperation operation) => UndoInsertNewNode(operation); Action <IWriteableOperation> HandlerRedoRemoveNode = (IWriteableOperation operation) => RedoRemoveNode(operation); Action <IWriteableOperation> HandlerUndoRemoveNode = (IWriteableOperation operation) => UndoRemoveNode(operation); WriteableOperationList OperationList = CreateOperationList(); // Insert first to prevent empty block lists. foreach (IWriteableInsertionCollectionNodeIndex NodeIndex in indexList) { if (NodeIndex is IWriteableInsertionListNodeIndex AsListNodeIndex) { IndexToPositionAndNode(AsListNodeIndex, out int BlockIndex, out int Index, out _, out Node Node); WriteableInsertNodeOperation OperationInsertNode = CreateInsertNodeOperation(Inner.Owner.Node, Inner.PropertyName, BlockIndex, Index, Node, HandlerRedoInsertNode, HandlerUndoInsertNode, isNested: true); OperationList.Add(OperationInsertNode); } } for (int i = FinalNodeIndex; i < FinalNodeIndex + lastNodeIndex - firstNodeIndex; i++) { WriteableRemoveNodeOperation OperationNode = CreateRemoveNodeOperation(Inner.Owner.Node, Inner.PropertyName, -1, FinalNodeIndex, HandlerRedoRemoveNode, HandlerUndoRemoveNode, isNested: true); OperationList.Add(OperationNode); } if (OperationList.Count > 0) { WriteableOperationReadOnlyList OperationReadOnlyList = OperationList.ToReadOnly(); Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoRefresh(operation); Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => throw new NotImplementedException(); // Undo is not possible. WriteableGenericRefreshOperation RefreshOperation = CreateGenericRefreshOperation(RootState, HandlerRedo, HandlerUndo, isNested: false); WriteableOperationGroup OperationGroup = CreateOperationGroup(OperationReadOnlyList, RefreshOperation); OperationGroup.Redo(); SetLastOperation(OperationGroup); CheckInvariant(); } }
/// <summary> /// Removes a range of blocks from a block list and replace them with other blocks. /// </summary> /// <param name="inner">The inner for the block list from which blocks are replaced.</param> /// <param name="firstBlockIndex">Index of the first block to remove.</param> /// <param name="lastBlockIndex">Index following the last block to remove.</param> /// <param name="indexList">List of nodes in blocks to insert.</param> public virtual void ReplaceBlockRange(IWriteableBlockListInner inner, int firstBlockIndex, int lastBlockIndex, IList <IWriteableInsertionBlockNodeIndex> indexList) { Contract.RequireNotNull(inner, out IWriteableBlockListInner Inner); Debug.Assert(firstBlockIndex >= 0 && firstBlockIndex < Inner.BlockStateList.Count); Debug.Assert(lastBlockIndex >= 0 && lastBlockIndex <= Inner.BlockStateList.Count); Debug.Assert(firstBlockIndex <= lastBlockIndex); Contract.RequireNotNull(indexList, out IList <IWriteableInsertionBlockNodeIndex> IndexList); int BlockIndex = firstBlockIndex - 1; int BlockNodeIndex = 0; foreach (IWriteableInsertionBlockNodeIndex NodeIndex in IndexList) { bool IsHandled = false; if (NodeIndex is IWriteableInsertionNewBlockNodeIndex AsNewBlockNodeIndex) { BlockIndex++; BlockNodeIndex = 0; Debug.Assert(AsNewBlockNodeIndex.BlockIndex == BlockIndex); IsHandled = true; } else if (NodeIndex is IWriteableInsertionExistingBlockNodeIndex AsExistingBlockNodeIndex) { BlockNodeIndex++; Debug.Assert(AsExistingBlockNodeIndex.BlockIndex == BlockIndex); Debug.Assert(AsExistingBlockNodeIndex.Index == BlockNodeIndex); IsHandled = true; } Debug.Assert(IsHandled); } int FinalBlockIndex = BlockIndex + 1; Action <IWriteableOperation> HandlerRedoInsertNode = (IWriteableOperation operation) => RedoInsertNewNode(operation); Action <IWriteableOperation> HandlerUndoInsertNode = (IWriteableOperation operation) => UndoInsertNewNode(operation); Action <IWriteableOperation> HandlerRedoInsertBlock = (IWriteableOperation operation) => RedoInsertNewBlock(operation); Action <IWriteableOperation> HandlerUndoInsertBlock = (IWriteableOperation operation) => UndoInsertNewBlock(operation); Action <IWriteableOperation> HandlerRedoRemoveNode = (IWriteableOperation operation) => RedoRemoveNode(operation); Action <IWriteableOperation> HandlerUndoRemoveNode = (IWriteableOperation operation) => UndoRemoveNode(operation); Action <IWriteableOperation> HandlerRedoRemoveBlock = (IWriteableOperation operation) => RedoRemoveBlock(operation); Action <IWriteableOperation> HandlerUndoRemoveBlock = (IWriteableOperation operation) => UndoRemoveBlock(operation); WriteableOperationList OperationList = CreateOperationList(); // Insert first to prevent empty block lists. foreach (IWriteableInsertionBlockNodeIndex NodeIndex in IndexList) { if (NodeIndex is IWriteableInsertionNewBlockNodeIndex AsNewBlockNodeIndex) { IBlock NewBlock = NodeTreeHelperBlockList.CreateBlock(Inner.Owner.Node, Inner.PropertyName, ReplicationStatus.Normal, AsNewBlockNodeIndex.PatternNode, AsNewBlockNodeIndex.SourceNode); IWriteableInsertBlockOperation OperationInsertBlock = CreateInsertBlockOperation(Inner.Owner.Node, Inner.PropertyName, AsNewBlockNodeIndex.BlockIndex, NewBlock, AsNewBlockNodeIndex.Node, HandlerRedoInsertBlock, HandlerUndoInsertBlock, isNested: true); OperationList.Add(OperationInsertBlock); } else if (NodeIndex is IWriteableInsertionExistingBlockNodeIndex AsExistingBlockNodeIndex) { IndexToPositionAndNode(AsExistingBlockNodeIndex, out BlockIndex, out int Index, out _, out Node Node); WriteableInsertNodeOperation OperationInsertNode = CreateInsertNodeOperation(Inner.Owner.Node, Inner.PropertyName, BlockIndex, Index, Node, HandlerRedoInsertNode, HandlerUndoInsertNode, isNested: true); OperationList.Add(OperationInsertNode); } } Debug.Assert(BlockIndex + 1 == FinalBlockIndex); for (int i = FinalBlockIndex; i < FinalBlockIndex + lastBlockIndex - firstBlockIndex; i++) { IWriteableBlockState BlockState = (IWriteableBlockState)Inner.BlockStateList[i + firstBlockIndex - FinalBlockIndex]; Debug.Assert(BlockState.StateList.Count >= 1); // Remove at FinalBlockIndex since subsequent blocks are moved as the block at FinalBlockIndex is deleted. // Same for nodes inside blokcks, delete them at 0. for (int j = 1; j < BlockState.StateList.Count; j++) { WriteableRemoveNodeOperation OperationNode = CreateRemoveNodeOperation(Inner.Owner.Node, Inner.PropertyName, FinalBlockIndex, 0, HandlerRedoRemoveNode, HandlerUndoRemoveNode, isNested: true); OperationList.Add(OperationNode); } IWriteableRemoveBlockOperation OperationBlock = CreateRemoveBlockOperation(Inner.Owner.Node, Inner.PropertyName, FinalBlockIndex, HandlerRedoRemoveBlock, HandlerUndoRemoveBlock, isNested: true); OperationList.Add(OperationBlock); } if (OperationList.Count > 0) { WriteableOperationReadOnlyList OperationReadOnlyList = OperationList.ToReadOnly(); Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoRefresh(operation); Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => throw new NotImplementedException(); // Undo is not possible. WriteableGenericRefreshOperation RefreshOperation = CreateGenericRefreshOperation(RootState, HandlerRedo, HandlerUndo, isNested: false); WriteableOperationGroup OperationGroup = CreateOperationGroup(OperationReadOnlyList, RefreshOperation); OperationGroup.Redo(); SetLastOperation(OperationGroup); CheckInvariant(); } }
/// <summary> /// Inserts a range of blocks in a block list. /// </summary> /// <param name="inner">The inner for the block list in which blocks are inserted.</param> /// <param name="insertedIndex">Index where to insert the first block.</param> /// <param name="indexList">List of nodes in blocks to insert.</param> public virtual void InsertBlockRange(IWriteableBlockListInner inner, int insertedIndex, IList <IWriteableInsertionBlockNodeIndex> indexList) { Contract.RequireNotNull(inner, out IWriteableBlockListInner Inner); Debug.Assert(insertedIndex >= 0 && insertedIndex <= Inner.BlockStateList.Count); Contract.RequireNotNull(indexList, out IList <IWriteableInsertionBlockNodeIndex> IndexList); int BlockIndex = insertedIndex - 1; int BlockNodeIndex = 0; foreach (IWriteableInsertionBlockNodeIndex NodeIndex in IndexList) { bool IsHandled = false; if (NodeIndex is IWriteableInsertionNewBlockNodeIndex AsNewBlockNodeIndex) { BlockIndex++; BlockNodeIndex = 0; Debug.Assert(AsNewBlockNodeIndex.BlockIndex == BlockIndex); IsHandled = true; } else if (NodeIndex is IWriteableInsertionExistingBlockNodeIndex AsExistingBlockNodeIndex) { BlockNodeIndex++; Debug.Assert(AsExistingBlockNodeIndex.BlockIndex == BlockIndex); Debug.Assert(AsExistingBlockNodeIndex.Index == BlockNodeIndex); IsHandled = true; } Debug.Assert(IsHandled); } int FinalBlockIndex = BlockIndex + 1; Action <IWriteableOperation> HandlerRedoInsertNode = (IWriteableOperation operation) => RedoInsertNewNode(operation); Action <IWriteableOperation> HandlerUndoInsertNode = (IWriteableOperation operation) => UndoInsertNewNode(operation); Action <IWriteableOperation> HandlerRedoInsertBlock = (IWriteableOperation operation) => RedoInsertNewBlock(operation); Action <IWriteableOperation> HandlerUndoInsertBlock = (IWriteableOperation operation) => UndoInsertNewBlock(operation); WriteableOperationList OperationList = CreateOperationList(); foreach (IWriteableInsertionBlockNodeIndex NodeIndex in IndexList) { if (NodeIndex is IWriteableInsertionNewBlockNodeIndex AsNewBlockNodeIndex) { IBlock NewBlock = NodeTreeHelperBlockList.CreateBlock(Inner.Owner.Node, Inner.PropertyName, ReplicationStatus.Normal, AsNewBlockNodeIndex.PatternNode, AsNewBlockNodeIndex.SourceNode); IWriteableInsertBlockOperation OperationInsertBlock = CreateInsertBlockOperation(Inner.Owner.Node, Inner.PropertyName, AsNewBlockNodeIndex.BlockIndex, NewBlock, AsNewBlockNodeIndex.Node, HandlerRedoInsertBlock, HandlerUndoInsertBlock, isNested: true); OperationList.Add(OperationInsertBlock); } else if (NodeIndex is IWriteableInsertionExistingBlockNodeIndex AsExistingBlockNodeIndex) { IndexToPositionAndNode(AsExistingBlockNodeIndex, out BlockIndex, out int Index, out _, out Node Node); WriteableInsertNodeOperation OperationInsertNode = CreateInsertNodeOperation(Inner.Owner.Node, Inner.PropertyName, BlockIndex, Index, Node, HandlerRedoInsertNode, HandlerUndoInsertNode, isNested: true); OperationList.Add(OperationInsertNode); } } Debug.Assert(BlockIndex + 1 == FinalBlockIndex); if (OperationList.Count > 0) { WriteableOperationReadOnlyList OperationReadOnlyList = OperationList.ToReadOnly(); Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoRefresh(operation); Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => throw new NotImplementedException(); // Undo is not possible. WriteableGenericRefreshOperation RefreshOperation = CreateGenericRefreshOperation(RootState, HandlerRedo, HandlerUndo, isNested: false); WriteableOperationGroup OperationGroup = CreateOperationGroup(OperationReadOnlyList, RefreshOperation); OperationGroup.Redo(); SetLastOperation(OperationGroup); CheckInvariant(); } }