private protected virtual void UndoInsertNewBlock(IWriteableOperation operation) { IWriteableInsertBlockOperation InsertBlockOperation = (IWriteableInsertBlockOperation)operation; IWriteableRemoveBlockOperation RemoveBlockOperation = InsertBlockOperation.ToRemoveBlockOperation(); ExecuteRemoveBlock(RemoveBlockOperation); }
/// <summary> /// Reduces the block list. /// </summary> private protected virtual void ReduceBlockList(IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex> blockListInner, WriteableOperationList operationList, bool isNested) { if (!blockListInner.IsSingle) { return; } if (NodeHelper.IsCollectionNeverEmpty(blockListInner.Owner.Node, blockListInner.PropertyName)) { return; } if (!NodeHelper.IsCollectionWithExpand(blockListInner.Owner.Node, blockListInner.PropertyName)) { return; } Debug.Assert(blockListInner.BlockStateList.Count == 1); Debug.Assert(blockListInner.BlockStateList[0].StateList.Count == 1); IWriteableNodeState FirstState = (IWriteableNodeState)blockListInner.BlockStateList[0].StateList[0]; if (!NodeHelper.IsDefaultNode(FirstState.Node)) { return; } Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoRemoveBlock(operation); Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => UndoRemoveBlock(operation); IWriteableRemoveBlockOperation Operation = CreateRemoveBlockOperation(blockListInner.Owner.Node, blockListInner.PropertyName, 0, HandlerRedo, HandlerUndo, isNested); Operation.Redo(); operationList.Add(Operation); }
private protected virtual void UndoExpandBlockList(IWriteableOperation operation) { WriteableExpandArgumentOperation ExpandArgumentOperation = (WriteableExpandArgumentOperation)operation; IWriteableRemoveBlockOperation RemoveBlockOperation = ExpandArgumentOperation.ToRemoveBlockOperation(); ExecuteRemoveBlock(RemoveBlockOperation); }
private protected virtual void RemoveBlock(IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex> blockListInner, int blockIndex) { System.Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoRemoveBlock(operation); System.Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => UndoRemoveBlock(operation); IWriteableRemoveBlockOperation Operation = CreateRemoveBlockOperation(blockListInner.Owner.Node, blockListInner.PropertyName, blockIndex, HandlerRedo, HandlerUndo, isNested: false); Operation.Redo(); SetLastOperation(Operation); CheckInvariant(); }
/// <summary> /// Handler called every time a block state is removed from the controller. /// </summary> /// <param name="operation">Details of the operation performed.</param> private protected virtual void OnBlockStateRemoved(IWriteableRemoveBlockOperation operation) { IWriteableBlockState BlockState = operation.BlockState; Debug.Assert(BlockState != null); Debug.Assert(!BlockStateViewTable.ContainsKey(BlockState)); Debug.Assert(!StateViewTable.ContainsKey(BlockState.PatternState)); Debug.Assert(!StateViewTable.ContainsKey(BlockState.SourceState)); IWriteableNodeState RemovedState = operation.RemovedState; Debug.Assert(!StateViewTable.ContainsKey(RemovedState)); Debug.Assert(BlockState.StateList.Count == 0); }
/// <summary> /// Handler called every time a block state is removed from the controller. /// </summary> /// <param name="operation">Details of the operation performed.</param> private protected override void OnBlockStateRemoved(IWriteableRemoveBlockOperation operation) { base.OnBlockStateRemoved(operation); IFocusBlockState BlockState = ((IFocusRemoveBlockOperation)operation).BlockState; Debug.Assert(BlockState != null); Debug.Assert(!BlockStateViewTable.ContainsKey(BlockState)); Debug.Assert(!StateViewTable.ContainsKey(BlockState.PatternState)); Debug.Assert(!StateViewTable.ContainsKey(BlockState.SourceState)); IFocusNodeState RemovedState = ((IFocusRemoveBlockOperation)operation).RemovedState; Debug.Assert(!StateViewTable.ContainsKey(RemovedState)); Debug.Assert(BlockState.StateList.Count == 0); }
/// <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(); } }
private protected virtual void ExecuteRemoveBlock(IWriteableRemoveBlockOperation operation) { Node ParentNode = operation.ParentNode; string PropertyName = operation.PropertyName; IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex> Inner = GetInner(ParentNode, PropertyName) as IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex>; Inner.RemoveWithBlock(operation); IWriteableBlockState RemovedBlockState = operation.BlockState; Debug.Assert(RemovedBlockState != null); IWriteableBrowsingPatternIndex PatternIndex = RemovedBlockState.PatternIndex; IWriteableBrowsingSourceIndex SourceIndex = RemovedBlockState.SourceIndex; Debug.Assert(PatternIndex != null); Debug.Assert(StateTable.ContainsKey(PatternIndex)); Debug.Assert(SourceIndex != null); Debug.Assert(StateTable.ContainsKey(SourceIndex)); Stats.BlockCount--; RemoveState(PatternIndex); Stats.PlaceholderNodeCount--; RemoveState(SourceIndex); Stats.PlaceholderNodeCount--; IWriteableNodeState RemovedState = operation.RemovedState; Debug.Assert(RemovedState != null); PruneState(RemovedState); Stats.PlaceholderNodeCount--; NotifyBlockStateRemoved(operation); }
/// <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(); } }
private protected virtual void NotifyBlockStateRemoved(IWriteableRemoveBlockOperation operation) { BlockStateRemovedHandler?.Invoke(operation); }
private protected virtual void Remove(IWriteableRemoveBlockOperation blockOperation, WriteableRemoveNodeOperation nodeOperation, int blockIndex, int index) { Debug.Assert(blockIndex >= 0 && blockIndex < BlockStateList.Count); IWriteableBlockState BlockState = (IWriteableBlockState)BlockStateList[blockIndex]; Debug.Assert(index >= 0 && index < BlockState.StateList.Count); IBlock ChildBlock = BlockState.ChildBlock; Node ParentNode = Owner.Node; int i; IWriteablePlaceholderNodeState OldChildState = (IWriteablePlaceholderNodeState)BlockState.StateList[index]; Node RemovedNode = OldChildState.Node; BlockState.Remove((IWriteableBrowsingBlockNodeIndex)OldChildState.ParentIndex, index); NodeTreeHelperBlockList.RemoveFromBlock(ParentNode, PropertyName, blockIndex, index, out bool IsBlockRemoved); if (IsBlockRemoved) { Debug.Assert(blockOperation != null); RemoveFromBlockStateList(blockIndex); blockOperation.Update(BlockState, OldChildState); for (i = blockIndex; i < BlockStateList.Count; i++) { IWriteableBlockState NextBlockState = (IWriteableBlockState)BlockStateList[i]; foreach (IWriteablePlaceholderNodeState State in NextBlockState.StateList) { IWriteableBrowsingExistingBlockNodeIndex NodeIndex = State.ParentIndex as IWriteableBrowsingExistingBlockNodeIndex; Debug.Assert(NodeIndex != null); Debug.Assert(NodeIndex.BlockIndex == i + 1); NodeIndex.MoveBlockDown(); } } } else { Debug.Assert(nodeOperation != null); nodeOperation.Update(OldChildState); } i = index; while (i < BlockState.StateList.Count) { IWriteablePlaceholderNodeState State = (IWriteablePlaceholderNodeState)BlockState.StateList[i]; IWriteableBrowsingExistingBlockNodeIndex NodeIndex = State.ParentIndex as IWriteableBrowsingExistingBlockNodeIndex; Debug.Assert(NodeIndex != null); Debug.Assert(NodeIndex.BlockIndex == blockIndex); Debug.Assert(NodeIndex.Index == i + 1); NodeIndex.MoveDown(); i++; } }
/// <summary> /// Removes a node from a block list. This method is allowed to remove the last node of a block. /// </summary> /// <param name="blockOperation">Details of the operation performed.</param> public virtual void RemoveWithBlock(IWriteableRemoveBlockOperation blockOperation) { Remove(blockOperation, null, blockOperation.BlockIndex, 0); }
private protected virtual void RedoRemoveBlock(IWriteableOperation operation) { IWriteableRemoveBlockOperation RemoveBlockOperation = (IWriteableRemoveBlockOperation)operation; ExecuteRemoveBlock(RemoveBlockOperation); }