private protected virtual void ExecuteMergeBlocks(WriteableMergeBlocksOperation operation) { Node ParentNode = operation.ParentNode; string PropertyName = operation.PropertyName; IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex> Inner = GetInner(ParentNode, PropertyName) as IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex>; int BlockIndex = operation.BlockIndex; IWriteableBlockState FirstBlockState = (IWriteableBlockState)Inner.BlockStateList[BlockIndex - 1]; IWriteableBlockState SecondBlockState = (IWriteableBlockState)Inner.BlockStateList[BlockIndex]; IReadOnlyBrowsingSourceIndex SourceIndex = FirstBlockState.SourceIndex; RemoveState(SourceIndex); Stats.PlaceholderNodeCount--; IReadOnlyBrowsingPatternIndex PatternIndex = FirstBlockState.PatternIndex; RemoveState(PatternIndex); Stats.PlaceholderNodeCount--; int OldNodeCount = FirstBlockState.StateList.Count + SecondBlockState.StateList.Count; int FirstNodeIndex = FirstBlockState.StateList.Count; Inner.MergeBlocks(operation); Stats.BlockCount--; IWriteableBlockState BlockState = (IWriteableBlockState)Inner.BlockStateList[BlockIndex - 1]; Debug.Assert(BlockState.StateList.Count == OldNodeCount); Debug.Assert(FirstNodeIndex < BlockState.StateList.Count); NotifyBlocksMerged(operation); }
/// <summary> /// Checks whether a block can be moved in a block list. /// </summary> /// <param name="inner">The inner where the block is.</param> /// <param name="blockIndex">Index of the block that would be moved.</param> /// <param name="direction">Direction of the move, relative to the current position of the item.</param> public virtual bool IsBlockMoveable(IWriteableBlockListInner inner, int blockIndex, int direction) { Contract.RequireNotNull(inner, out IWriteableBlockListInner Inner); Debug.Assert(blockIndex >= 0 && blockIndex < Inner.BlockStateList.Count); return(blockIndex + direction >= 0 && blockIndex + direction < Inner.BlockStateList.Count); }
/// <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 ExecuteSplitBlock(WriteableSplitBlockOperation operation) { Node ParentNode = operation.ParentNode; string PropertyName = operation.PropertyName; IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex> Inner = GetInner(ParentNode, PropertyName) as IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex>; IWriteableBlockState OldBlockState = (IWriteableBlockState)Inner.BlockStateList[operation.BlockIndex]; Debug.Assert(operation.Index < OldBlockState.StateList.Count); int OldNodeCount = OldBlockState.StateList.Count; Inner.SplitBlock(operation); Stats.BlockCount++; IWriteableBlockState NewBlockState = operation.BlockState; Debug.Assert(OldBlockState.StateList.Count + NewBlockState.StateList.Count == OldNodeCount); Debug.Assert(NewBlockState.StateList.Count > 0); IReadOnlyBrowsingPatternIndex PatternIndex = NewBlockState.PatternIndex; IReadOnlyPatternState PatternState = NewBlockState.PatternState; AddState(PatternIndex, PatternState); Stats.PlaceholderNodeCount++; IReadOnlyBrowsingSourceIndex SourceIndex = NewBlockState.SourceIndex; IReadOnlySourceState SourceState = NewBlockState.SourceState; AddState(SourceIndex, SourceState); Stats.PlaceholderNodeCount++; NotifyBlockSplit(operation); }
/// <summary> /// Expands the block list. /// * Only expand block list of arguments /// * Only expand if the list is empty. In that case, add a single default argument. /// </summary> private protected virtual void ExpandBlockList(IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex> blockListInner, WriteableOperationList operationList) { if (!blockListInner.IsEmpty) { return; } if (!NodeHelper.IsCollectionWithExpand(blockListInner.Owner.Node, blockListInner.PropertyName)) { return; } Node NewItem = NodeHelper.CreateDefaultFromType(blockListInner.InterfaceType); Pattern NewPattern = NodeHelper.CreateEmptyPattern(); Identifier NewSource = NodeHelper.CreateEmptyIdentifier(); IBlock NewBlock = NodeTreeHelperBlockList.CreateBlock(blockListInner.Owner.Node, blockListInner.PropertyName, ReplicationStatus.Normal, NewPattern, NewSource); Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoExpandBlockList(operation); Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => UndoExpandBlockList(operation); WriteableExpandArgumentOperation Operation = CreateExpandArgumentOperation(blockListInner.Owner.Node, blockListInner.PropertyName, NewBlock, NewItem, HandlerRedo, HandlerUndo, isNested: false); Operation.Redo(); operationList.Add(Operation); }
/// <summary> /// Checks whether a block can be split at the given index. /// </summary> /// <param name="inner">The inner where the block would be split.</param> /// <param name="nodeIndex">Index of the last node to stay in the old block.</param> public virtual bool IsSplittable(IWriteableBlockListInner inner, IWriteableBrowsingExistingBlockNodeIndex nodeIndex) { Contract.RequireNotNull(inner, out IWriteableBlockListInner Inner); Contract.RequireNotNull(nodeIndex, out IWriteableBrowsingExistingBlockNodeIndex NodeIndex); return(Inner.IsSplittable(NodeIndex)); }
/// <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 ExecuteChangeReplication(WriteableChangeBlockOperation operation) { Node ParentNode = operation.ParentNode; string PropertyName = operation.PropertyName; IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex> Inner = GetInner(ParentNode, PropertyName) as IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex>; Inner.ChangeReplication(operation); NotifyBlockStateChanged(operation); }
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> /// Moves a block around in a block list. /// </summary> /// <param name="inner">The inner where the block is moved.</param> /// <param name="blockIndex">Index of the block to move.</param> /// <param name="direction">The change in position, relative to the current block position.</param> public virtual void MoveBlock(IWriteableBlockListInner inner, int blockIndex, int direction) { Contract.RequireNotNull(inner, out IWriteableBlockListInner Inner); Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoMoveBlock(operation); Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => UndoMoveBlock(operation); WriteableMoveBlockOperation Operation = CreateMoveBlockOperation(Inner.Owner.Node, Inner.PropertyName, blockIndex, direction, HandlerRedo, HandlerUndo, isNested: false); Operation.Redo(); SetLastOperation(Operation); CheckInvariant(); }
private protected virtual void PruneBlockListInner(IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex> inner) { for (int BlockIndex = inner.BlockStateList.Count; BlockIndex > 0; BlockIndex--) { Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoRemoveBlockView(operation); Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => throw new NotImplementedException(); // Undo is not possible. WriteableRemoveBlockViewOperation Operation = CreateRemoveBlockViewOperation(inner.Owner.Node, inner.PropertyName, BlockIndex - 1, HandlerRedo, HandlerUndo, isNested: true); Operation.Redo(); } Stats.BlockListCount--; }
/// <summary> /// Changes the replication state of a block. /// </summary> /// <param name="inner">The inner where the blok is changed.</param> /// <param name="blockIndex">Position of the block in the block list.</param> /// <param name="replication">New replication value.</param> public virtual void ChangeReplication(IWriteableBlockListInner inner, int blockIndex, ReplicationStatus replication) { Contract.RequireNotNull(inner, out IWriteableBlockListInner Inner); Debug.Assert(blockIndex >= 0 && blockIndex < Inner.BlockStateList.Count); System.Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoChangeReplication(operation); System.Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => UndoChangeReplication(operation); WriteableChangeBlockOperation Operation = CreateChangeBlockOperation(Inner.Owner.Node, Inner.PropertyName, blockIndex, replication, HandlerRedo, HandlerUndo, isNested: false); Operation.Redo(); SetLastOperation(Operation); CheckInvariant(); }
private protected virtual void InsertNewBlock(IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex> blockListInner, IWriteableInsertionNewBlockNodeIndex newBlockIndex, out IWriteableBrowsingCollectionNodeIndex nodeIndex) { IBlock NewBlock = NodeTreeHelperBlockList.CreateBlock(blockListInner.Owner.Node, blockListInner.PropertyName, ReplicationStatus.Normal, newBlockIndex.PatternNode, newBlockIndex.SourceNode); Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoInsertNewBlock(operation); Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => UndoInsertNewBlock(operation); IWriteableInsertBlockOperation Operation = CreateInsertBlockOperation(blockListInner.Owner.Node, blockListInner.PropertyName, newBlockIndex.BlockIndex, NewBlock, newBlockIndex.Node, HandlerRedo, HandlerUndo, isNested: false); Operation.Redo(); SetLastOperation(Operation); CheckInvariant(); nodeIndex = Operation.BrowsingIndex; }
/// <summary> /// Merges two blocks at the given index. /// </summary> /// <param name="inner">The inner where blocks are merged.</param> /// <param name="nodeIndex">Index of the first node in the block to merge.</param> public virtual void MergeBlocks(IWriteableBlockListInner inner, IWriteableBrowsingExistingBlockNodeIndex nodeIndex) { Contract.RequireNotNull(inner, out IWriteableBlockListInner Inner); Contract.RequireNotNull(nodeIndex, out IWriteableBrowsingExistingBlockNodeIndex NodeIndex); Debug.Assert(Inner.IsMergeable(NodeIndex)); Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoMergeBlocks(operation); Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => UndoMergeBlocks(operation); WriteableMergeBlocksOperation Operation = CreateMergeBlocksOperation(Inner.Owner.Node, Inner.PropertyName, NodeIndex.BlockIndex, HandlerRedo, HandlerUndo, isNested: false); Operation.Redo(); SetLastOperation(Operation); CheckInvariant(); }
/// <summary></summary> public virtual void RemoveNodeRange(IWriteableBlockListInner inner, int blockIndex, int firstNodeIndex, int lastNodeIndex) { Contract.RequireNotNull(inner, out IWriteableBlockListInner Inner); Debug.Assert(blockIndex >= 0 && blockIndex < Inner.BlockStateList.Count); IWriteableBlockState BlockState = (IWriteableBlockState)Inner.BlockStateList[blockIndex]; Debug.Assert(firstNodeIndex >= 0 && firstNodeIndex < BlockState.StateList.Count); Debug.Assert(lastNodeIndex >= 0 && lastNodeIndex <= BlockState.StateList.Count); Debug.Assert(firstNodeIndex <= lastNodeIndex); int DeletedCount = lastNodeIndex - firstNodeIndex; System.Action <IWriteableOperation> HandlerRedoRemoveNode = (IWriteableOperation operation) => RedoRemoveNode(operation); System.Action <IWriteableOperation> HandlerUndoRemoveNode = (IWriteableOperation operation) => UndoRemoveNode(operation); System.Action <IWriteableOperation> HandlerRedoRemoveBlock = (IWriteableOperation operation) => RedoRemoveBlock(operation); System.Action <IWriteableOperation> HandlerUndoRemoveBlock = (IWriteableOperation operation) => UndoRemoveBlock(operation); WriteableOperationList OperationList = CreateOperationList(); for (int i = firstNodeIndex; i < lastNodeIndex; i++) { IWriteableRemoveOperation Operation; if (DeletedCount < BlockState.StateList.Count || i + 1 < lastNodeIndex) { Operation = CreateRemoveNodeOperation(Inner.Owner.Node, Inner.PropertyName, blockIndex, firstNodeIndex, HandlerRedoRemoveNode, HandlerUndoRemoveNode, isNested: true); } else { Operation = CreateRemoveBlockOperation(Inner.Owner.Node, Inner.PropertyName, blockIndex, HandlerRedoRemoveBlock, HandlerUndoRemoveBlock, isNested: true); } OperationList.Add(Operation); } 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 bool IsNodeRangeRemoveable(IWriteableBlockListInner inner, int blockIndex, int firstNodeIndex, int lastNodeIndex) { Contract.RequireNotNull(inner, out IWriteableBlockListInner Inner); Debug.Assert(blockIndex >= 0 && blockIndex < Inner.BlockStateList.Count); IWriteableBlockState BlockState = (IWriteableBlockState)Inner.BlockStateList[blockIndex]; Debug.Assert(firstNodeIndex >= 0 && firstNodeIndex < BlockState.StateList.Count); Debug.Assert(lastNodeIndex >= 0 && lastNodeIndex <= BlockState.StateList.Count); Debug.Assert(firstNodeIndex <= lastNodeIndex); int DeletedCount = lastNodeIndex - firstNodeIndex; return(Inner.BlockStateList.Count > 1 || BlockState.StateList.Count > DeletedCount); }
/// <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> /// Checks whether a range of blocks can be removed from a block list. /// </summary> /// <param name="inner">The inner with blocks to remove.</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 bool IsBlockRangeRemoveable(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); int DeletedCount = lastBlockIndex - firstBlockIndex; if (Inner.BlockStateList.Count > DeletedCount) { return(true); } Debug.Assert(Inner.BlockStateList.Count == DeletedCount); Debug.Assert(Inner.Owner != null); Node Node = Inner.Owner.Node; string PropertyName = Inner.PropertyName; Debug.Assert(Node != null); bool Result = true; //Type InterfaceType = NodeTreeHelper.NodeTypeToInterfaceType(inner.Owner.Node.GetType()); Type InterfaceType = Type.FromGetType(Inner.Owner.Node); IReadOnlyDictionary <Type, string[]> NeverEmptyCollectionTable = NodeHelper.NeverEmptyCollectionTable; if (NeverEmptyCollectionTable.ContainsKey(InterfaceType)) { foreach (string Item in NeverEmptyCollectionTable[InterfaceType]) { if (Item == PropertyName) { Result = false; } } } return(Result); }
/// <summary> /// Splits a block in two at the given index. /// </summary> /// <param name="inner">The inner where the block is split.</param> /// <param name="nodeIndex">Index of the last node to stay in the old block.</param> public virtual void SplitBlock(IWriteableBlockListInner inner, IWriteableBrowsingExistingBlockNodeIndex nodeIndex) { Contract.RequireNotNull(inner, out IWriteableBlockListInner Inner); Contract.RequireNotNull(nodeIndex, out IWriteableBrowsingExistingBlockNodeIndex NodeIndex); Debug.Assert(Inner.IsSplittable(NodeIndex)); IWriteableBlockState BlockState = (IWriteableBlockState)Inner.BlockStateList[NodeIndex.BlockIndex]; ReplicationStatus Replication = BlockState.ChildBlock.Replication; Pattern NewPatternNode = NodeHelper.CreateSimplePattern(BlockState.ChildBlock.ReplicationPattern.Text); Identifier NewSourceNode = NodeHelper.CreateSimpleIdentifier(BlockState.ChildBlock.SourceIdentifier.Text); IBlock NewBlock = NodeTreeHelperBlockList.CreateBlock(Inner.Owner.Node, Inner.PropertyName, Replication, NewPatternNode, NewSourceNode); Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoSplitBlock(operation); Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => UndoSplitBlock(operation); WriteableSplitBlockOperation Operation = CreateSplitBlockOperation(Inner.Owner.Node, Inner.PropertyName, NodeIndex.BlockIndex, NodeIndex.Index, NewBlock, HandlerRedo, HandlerUndo, isNested: false); Operation.Redo(); SetLastOperation(Operation); CheckInvariant(); }
private protected virtual void ExecuteMoveBlock(WriteableMoveBlockOperation operation) { Node ParentNode = operation.ParentNode; string PropertyName = operation.PropertyName; IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex> Inner = GetInner(ParentNode, PropertyName) as IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex>; IWriteableBlockState BlockState = (IWriteableBlockState)Inner.BlockStateList[operation.BlockIndex]; Debug.Assert(BlockState != null); Debug.Assert(BlockState.StateList.Count > 0); IWriteableNodeState State = (IWriteableNodeState)BlockState.StateList[0]; Debug.Assert(State != null); IWriteableBrowsingExistingBlockNodeIndex NodeIndex = State.ParentIndex as IWriteableBrowsingExistingBlockNodeIndex; Debug.Assert(NodeIndex != null); Inner.MoveBlock(operation); NotifyBlockStateMoved(operation); }
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); }
private protected virtual void ExecuteInsertNewBlock(IWriteableInsertBlockOperation operation) { Node ParentNode = operation.ParentNode; string PropertyName = operation.PropertyName; IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex> Inner = GetInner(ParentNode, PropertyName) as IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex>; Inner.InsertNewBlock(operation); IWriteableBrowsingExistingBlockNodeIndex BrowsingIndex = operation.BrowsingIndex; IWriteableBlockState BlockState = operation.BlockState; IWriteablePlaceholderNodeState ChildState = operation.ChildState; Debug.Assert(BlockState.StateList.Count == 1); Debug.Assert(BlockState.StateList[0] == ChildState); ((IWriteableBlockState <IWriteableInner <IWriteableBrowsingChildIndex> >)BlockState).InitBlockState(); Stats.BlockCount++; IWriteableBrowsingPatternIndex PatternIndex = BlockState.PatternIndex; IWriteablePatternState PatternState = BlockState.PatternState; AddState(PatternIndex, PatternState); Stats.PlaceholderNodeCount++; IWriteableBrowsingSourceIndex SourceIndex = BlockState.SourceIndex; IWriteableSourceState SourceState = BlockState.SourceState; AddState(SourceIndex, SourceState); Stats.PlaceholderNodeCount++; AddState(BrowsingIndex, ChildState); Stats.PlaceholderNodeCount++; BuildStateTable(Inner, null, BrowsingIndex, ChildState); Debug.Assert(Contains(BrowsingIndex)); NotifyBlockStateInserted(operation); }
private protected virtual void ExecuteRemoveBlockView(WriteableRemoveBlockViewOperation operation) { Node ParentNode = operation.ParentNode; string PropertyName = operation.PropertyName; IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex> Inner = GetInner(ParentNode, PropertyName) as IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex>; IWriteableBlockState RemovedBlockState = (IWriteableBlockState)Inner.BlockStateList[operation.BlockIndex]; for (int Index = 0; Index < RemovedBlockState.StateList.Count; Index++) { IWriteableNodeState State = (IWriteableNodeState)RemovedBlockState.StateList[Index]; PruneState(State); Stats.PlaceholderNodeCount--; } 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)); RemoveState(PatternIndex); Stats.PlaceholderNodeCount--; RemoveState(SourceIndex); Stats.PlaceholderNodeCount--; Inner.NotifyBlockStateRemoved(RemovedBlockState); Stats.BlockCount--; operation.Update(RemovedBlockState); NotifyBlockViewRemoved(operation); }
/// <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(); } }
/// <summary> /// Initializes a new instance of the <see cref="WriteableBlockState{IInner}"/> class. /// </summary> /// <param name="parentInner">Inner containing the block state.</param> /// <param name="newBlockIndex">Index that was used to create the block state.</param> /// <param name="childBlock">The block.</param> public WriteableBlockState(IWriteableBlockListInner parentInner, IWriteableBrowsingNewBlockNodeIndex newBlockIndex, IBlock childBlock) : base(parentInner, newBlockIndex, childBlock) { }
/// <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(); } }