/// <summary> /// Initializes a new instance of the <see cref="ReadOnlyBlockListInner{IIndex}"/> class. /// </summary> /// <param name="owner">Parent containing the inner.</param> /// <param name="propertyName">Property name of the inner in <paramref name="owner"/>.</param> public ReadOnlyBlockListInner(IReadOnlyNodeState owner, string propertyName) : base(owner, propertyName) { BlockType = NodeTreeHelperBlockList.BlockListBlockType(Owner.Node, PropertyName); _BlockStateList = CreateBlockStateList(); BlockStateList = _BlockStateList.ToReadOnly(); }
/// <summary> /// Gets the frame that creates cells associated to states in the inner. /// </summary> /// <param name="inner">The inner.</param> public virtual IFrameFrame InnerToFrame(IFrameInner <IFrameBrowsingChildIndex> inner) { // Call overloads of this method if they exist. ControllerTools.AssertNoOverride(this, Type.FromTypeof <FrameTemplateSet>()); IFrameNodeState Owner = inner.Owner; Type OwnerType = Type.FromGetType(Owner.Node); //Type InterfaceType = NodeTreeHelper.NodeTypeToInterfaceType(OwnerType); //IFrameNodeTemplate Template = NodeTypeToTemplate(InterfaceType); IFrameNodeTemplate Template = NodeTypeToTemplate(OwnerType); IFrameFrame Frame = Template.PropertyToFrame(inner.PropertyName); if (Frame is IFrameBlockListFrame AsBlockListFrame) { IFrameBlockListInner <IFrameBrowsingBlockNodeIndex> BlockListInner = inner as IFrameBlockListInner <IFrameBrowsingBlockNodeIndex>; Debug.Assert(BlockListInner != null); Type BlockType = NodeTreeHelperBlockList.BlockListBlockType(Owner.Node, BlockListInner.PropertyName); IFrameBlockTemplate BlockTemplate = BlockTypeToTemplate(BlockType); Frame = BlockTemplate.GetPlaceholderFrame(); } return(Frame); }
private protected virtual bool IsNodeTreeValid(Node node) { Type ChildNodeType; IList <string> PropertyNames = NodeTreeHelper.EnumChildNodeProperties(node); bool IsValid = true; foreach (string PropertyName in PropertyNames) { if (NodeTreeHelperChild.IsChildNodeProperty(node, PropertyName, out ChildNodeType)) { IsValid &= InvariantFailed(IsNodeTreeChildNodeValid(node, PropertyName)); } else if (NodeTreeHelperOptional.IsOptionalChildNodeProperty(node, PropertyName, out ChildNodeType)) { IsValid &= InvariantFailed(IsNodeTreeOptionalNodeValid(node, PropertyName)); } else if (NodeTreeHelperList.IsNodeListProperty(node, PropertyName, out ChildNodeType)) { IsValid &= InvariantFailed(IsNodeTreeListValid(node, PropertyName)); } else if (NodeTreeHelperBlockList.IsBlockListProperty(node, PropertyName, /*out Type ChildInterfaceType,*/ out ChildNodeType)) { IsValid &= InvariantFailed(IsNodeTreeBlockListValid(node, PropertyName)); } } return(IsValid); }
/// <summary> /// Replaces a node. /// </summary> /// <param name="operation">Details of the operation performed.</param> public virtual void Replace(IWriteableReplaceOperation operation) { int BlockIndex = operation.BlockIndex; Debug.Assert(BlockIndex >= 0 && BlockIndex < BlockStateList.Count); IWriteableBlockState BlockState = (IWriteableBlockState)BlockStateList[BlockIndex]; int Index = operation.Index; Debug.Assert(Index >= 0 && Index < BlockState.StateList.Count); IBlock ChildBlock = BlockState.ChildBlock; Node ParentNode = Owner.Node; IWriteableNodeState OldChildState = (IWriteableNodeState)BlockState.StateList[Index]; Node OldNode = OldChildState.Node; IWriteableBrowsingBlockNodeIndex OldBrowsingIndex = (IWriteableBrowsingBlockNodeIndex)OldChildState.ParentIndex; BlockState.Remove(OldBrowsingIndex, Index); NodeTreeHelperBlockList.ReplaceInBlock(ChildBlock, Index, operation.NewNode); IWriteableBrowsingExistingBlockNodeIndex NewBrowsingIndex = CreateBrowsingNodeIndex(operation.NewNode, BlockIndex, Index); IWriteablePlaceholderNodeState NewChildState = (IWriteablePlaceholderNodeState)CreateNodeState(NewBrowsingIndex); BlockState.Insert(NewBrowsingIndex, Index, NewChildState); operation.Update(OldBrowsingIndex, NewBrowsingIndex, OldNode, NewChildState); }
private protected virtual bool IsNodeTreeBlockListValid(Node node, string propertyName) { NodeTreeHelperBlockList.GetChildBlockList(node, propertyName, out IList <NodeTreeBlock> ChildBlockList); Debug.Assert(ChildBlockList != null); bool IsValid = true; if (ChildBlockList.Count == 0) { IsValid &= InvariantFailed(IsEmptyBlockListValid(node, propertyName)); } for (int BlockIndex = 0; BlockIndex < ChildBlockList.Count; BlockIndex++) { NodeTreeBlock Block = ChildBlockList[BlockIndex]; Debug.Assert(Block.NodeList.Count > 0); for (int Index = 0; Index < Block.NodeList.Count; Index++) { Node ChildNode = Block.NodeList[Index]; Debug.Assert(ChildNode != null); IsValid &= InvariantFailed(IsNodeTreeValid(ChildNode)); } } return(IsValid); }
private protected virtual void UpdateInterfaceType(Type nodeType) { if (InterfaceType == Type.Missing) { string[] Split = CollectionName.Split('.'); Type BaseType = nodeType; for (int i = 0; i < Split.Length; i++) { string PropertyName = Split[i]; Type ChildNodeType; if (i + 1 < Split.Length) { bool IsValidProperty = NodeTreeHelperChild.IsChildNodeProperty(BaseType, PropertyName, out ChildNodeType) || NodeTreeHelperOptional.IsOptionalChildNodeProperty(BaseType, PropertyName, out ChildNodeType); Debug.Assert(IsValidProperty); BaseType = ChildNodeType; } else { Type ChildInterfaceType; bool IsValidProperty = NodeTreeHelperBlockList.IsBlockListProperty(BaseType, PropertyName, /*out ChildInterfaceType,*/ out /*ChildNodeType*/ ChildInterfaceType) || NodeTreeHelperList.IsNodeListProperty(BaseType, PropertyName, out ChildInterfaceType); Debug.Assert(IsValidProperty); BaseType = ChildInterfaceType; } } InterfaceType = BaseType; } }
/// <summary> /// Modifies the index to address the next position in a block list. /// </summary> public virtual void MoveBlockUp() { NodeTreeHelperBlockList.GetLastBlockIndex(ParentNode, PropertyName, out int LastBlockIndex); Debug.Assert(BlockIndex + 1 < LastBlockIndex); BlockIndex++; }
/// <summary> /// Modifies the index to address the next position in a list. /// </summary> public virtual void MoveUp() { NodeTreeHelperBlockList.GetLastBlockChildIndex(ParentNode, PropertyName, BlockIndex, out int LastIndex); Debug.Assert(Index + 1 < LastIndex); Index++; }
/// <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> /// Moves a block around in a block list. /// </summary> /// <param name="operation">Details of the operation performed.</param> public virtual void MoveBlock(WriteableMoveBlockOperation operation) { int BlockIndex = operation.BlockIndex; int Direction = operation.Direction; Debug.Assert(BlockIndex >= 0 && BlockIndex < BlockStateList.Count); Debug.Assert(BlockIndex + Direction >= 0 && BlockIndex + Direction < BlockStateList.Count); int MoveIndex = BlockIndex; IWriteableBlockState BlockState = (IWriteableBlockState)BlockStateList[MoveIndex]; MoveInBlockStateList(MoveIndex, Direction); NodeTreeHelperBlockList.MoveBlock(Owner.Node, PropertyName, MoveIndex, Direction); if (Direction > 0) { for (int i = MoveIndex; i < MoveIndex + Direction; i++) { for (int j = 0; j < BlockStateList[i].StateList.Count; j++) { IWriteableBrowsingExistingBlockNodeIndex ChildNodeIndex = BlockStateList[i].StateList[j].ParentIndex as IWriteableBrowsingExistingBlockNodeIndex; Debug.Assert(ChildNodeIndex != null); ChildNodeIndex.MoveBlockDown(); } for (int j = 0; j < BlockState.StateList.Count; j++) { IWriteableBrowsingExistingBlockNodeIndex ChildNodeIndex = BlockState.StateList[j].ParentIndex as IWriteableBrowsingExistingBlockNodeIndex; Debug.Assert(ChildNodeIndex != null); ChildNodeIndex.MoveBlockUp(); } } } else if (Direction < 0) { for (int i = MoveIndex; i > MoveIndex + Direction; i--) { for (int j = 0; j < BlockStateList[i].StateList.Count; j++) { IWriteableBrowsingExistingBlockNodeIndex ChildNodeIndex = BlockStateList[i].StateList[j].ParentIndex as IWriteableBrowsingExistingBlockNodeIndex; Debug.Assert(ChildNodeIndex != null); ChildNodeIndex.MoveBlockUp(); } for (int j = 0; j < BlockState.StateList.Count; j++) { IWriteableBrowsingExistingBlockNodeIndex ChildNodeIndex = BlockState.StateList[j].ParentIndex as IWriteableBrowsingExistingBlockNodeIndex; Debug.Assert(ChildNodeIndex != null); ChildNodeIndex.MoveBlockDown(); } } } operation.Update(BlockState); }
/// <summary> /// Merges two blocks at the given index. /// </summary> /// <param name="operation">Details of the operation performed.</param> public virtual void MergeBlocks(IWriteableMergeBlocksOperation operation) { Debug.Assert(operation != null); int MergeBlockIndex = operation.BlockIndex; Debug.Assert(MergeBlockIndex > 0 && MergeBlockIndex < BlockStateList.Count); IWriteableBlockState FirstBlockState = BlockStateList[MergeBlockIndex - 1]; IWriteableBlockState SecondBlockState = BlockStateList[MergeBlockIndex]; int MergeIndex = FirstBlockState.StateList.Count; Debug.Assert(MergeIndex > 0); NodeTreeHelperBlockList.MergeBlocks(Owner.Node, PropertyName, MergeBlockIndex, out IBlock mergedBlock); Debug.Assert(FirstBlockState.ChildBlock == mergedBlock); RemoveFromBlockStateList(MergeBlockIndex - 1); operation.Update(FirstBlockState, MergeIndex); int i; for (i = 0; i < MergeIndex; i++) { IWriteablePlaceholderNodeState State = FirstBlockState.StateList[0]; IWriteableBrowsingExistingBlockNodeIndex ChildNodeIndex = State.ParentIndex as IWriteableBrowsingExistingBlockNodeIndex; Debug.Assert(ChildNodeIndex != null); FirstBlockState.Remove(ChildNodeIndex, 0); SecondBlockState.Insert(ChildNodeIndex, i, State); } for (; i < SecondBlockState.StateList.Count; i++) { IWriteablePlaceholderNodeState State = SecondBlockState.StateList[i]; IWriteableBrowsingExistingBlockNodeIndex ChildNodeIndex = State.ParentIndex as IWriteableBrowsingExistingBlockNodeIndex; Debug.Assert(ChildNodeIndex != null); ChildNodeIndex.MoveBlockDown(); for (int j = 0; j < MergeIndex; j++) { ChildNodeIndex.MoveUp(); } } for (i = MergeBlockIndex; i < BlockStateList.Count; i++) { foreach (IWriteablePlaceholderNodeState State in BlockStateList[i].StateList) { IWriteableBrowsingExistingBlockNodeIndex ChildNodeIndex = State.ParentIndex as IWriteableBrowsingExistingBlockNodeIndex; Debug.Assert(ChildNodeIndex != null); ChildNodeIndex.MoveBlockDown(); } } }
/// <summary> /// Initializes a new instance of the <see cref="ReadOnlyBrowsingNewBlockNodeIndex"/> class. /// </summary> /// <param name="parentNode">Node containing the block list.</param> /// <param name="node">First node in the block.</param> /// <param name="propertyName">Property in <paramref name="parentNode"/> corresponding to the block list.</param> /// <param name="blockIndex">Position of the block in the block list.</param> public ReadOnlyBrowsingNewBlockNodeIndex(Node parentNode, Node node, string propertyName, int blockIndex) : base(node, propertyName, blockIndex) { Debug.Assert(!string.IsNullOrEmpty(propertyName)); Debug.Assert(blockIndex >= 0); Debug.Assert(NodeTreeHelperBlockList.IsBlockChildNode(parentNode, propertyName, blockIndex, 0, node)); ParentNode = parentNode; }
/// <summary> /// Checks that a frame is correctly constructed. /// </summary> /// <param name="nodeType">Type of the node this frame can describe.</param> /// <param name="nodeTemplateTable">Table of templates with all frames.</param> /// <param name="commentFrameCount">Number of comment frames found so far.</param> public override bool IsValid(Type nodeType, FrameTemplateReadOnlyDictionary nodeTemplateTable, ref int commentFrameCount) { bool IsValid = true; IsValid &= base.IsValid(nodeType, nodeTemplateTable, ref commentFrameCount); IsValid &= NodeTreeHelperBlockList.IsBlockListProperty(nodeType, PropertyName, /*out Type ChildInterfaceType,*/ out Type ChildNodeType); Debug.Assert(IsValid); return(IsValid); }
/// <summary> /// Initializes a new instance of the <see cref="WriteableInsertionExistingBlockNodeIndex"/> class. /// </summary> /// <param name="parentNode">Node containing the block list.</param> /// <param name="propertyName">Property in <paramref name="parentNode"/> corresponding to the block list..</param> /// <param name="node">Inserted node.</param> /// <param name="blockIndex">Position of the block in the block list.</param> /// <param name="index">Position where to insert <paramref name="node"/> in the block.</param> public WriteableInsertionExistingBlockNodeIndex(INode parentNode, string propertyName, INode node, int blockIndex, int index) : base(parentNode, propertyName, node) { Debug.Assert(blockIndex >= 0); Debug.Assert(index >= 0); // You can insert at position 0, contrary to a browsing index that only supports positions other than 0. Debug.Assert(NodeTreeHelperBlockList.GetLastBlockChildIndex(parentNode, propertyName, blockIndex, out int LastIndex) && index <= LastIndex); BlockIndex = blockIndex; Index = index; }
private protected virtual void CloneChildren(INode parentNode, IBlock parentBlock) { for (int i = 0; i < StateList.Count; i++) { IReadOnlyPlaceholderNodeState ChildState = StateList[i]; INode ChildNodeClone = ChildState.CloneNode(); Debug.Assert(ChildNodeClone != null); NodeTreeHelperBlockList.InsertIntoBlock(parentBlock, i, ChildNodeClone); } }
/// <summary> /// Initializes a new instance of the <see cref="WriteableInsertionNewBlockNodeIndex"/> class. /// </summary> /// <param name="parentNode">Node containing the block list.</param> /// <param name="propertyName">Property in <paramref name="parentNode"/> corresponding to the block list.</param> /// <param name="node">First node in the block.</param> /// <param name="blockIndex">Position of the block in the block list.</param> /// <param name="patternNode">Replication pattern in the block.</param> /// <param name="sourceNode">Source identifier in the block.</param> public WriteableInsertionNewBlockNodeIndex(INode parentNode, string propertyName, INode node, int blockIndex, IPattern patternNode, IIdentifier sourceNode) : base(parentNode, propertyName, node) { Debug.Assert(blockIndex >= 0); Debug.Assert(NodeTreeHelperBlockList.GetLastBlockIndex(parentNode, propertyName, out int LastBlockIndex) && blockIndex <= LastBlockIndex); Debug.Assert(patternNode != null); Debug.Assert(sourceNode != null); BlockIndex = blockIndex; PatternNode = patternNode; SourceNode = sourceNode; }
/// <summary> /// Moves a node around in a list or block list. In a block list, the node stays in same block. /// </summary> /// <param name="operation">Details of the operation performed.</param> public virtual void Move(IWriteableMoveNodeOperation operation) { Debug.Assert(operation != null); int BlockIndex = operation.BlockIndex; Debug.Assert(BlockIndex >= 0 && BlockIndex < BlockStateList.Count); IWriteableBlockState BlockState = BlockStateList[BlockIndex]; IWriteablePlaceholderNodeStateReadOnlyList StateList = BlockState.StateList; int MoveIndex = operation.Index; int Direction = operation.Direction; Debug.Assert(MoveIndex >= 0 && MoveIndex < StateList.Count); Debug.Assert(MoveIndex + Direction >= 0 && MoveIndex + Direction < StateList.Count); IWriteableBrowsingExistingBlockNodeIndex ExistingBlockNodeIndex = StateList[MoveIndex].ParentIndex as IWriteableBrowsingExistingBlockNodeIndex; Debug.Assert(ExistingBlockNodeIndex != null); BlockState.Move(ExistingBlockNodeIndex, MoveIndex, Direction); IBlock ChildBlock = BlockState.ChildBlock; NodeTreeHelperBlockList.MoveNode(ChildBlock, MoveIndex, Direction); operation.Update(StateList[MoveIndex + Direction]); if (Direction > 0) { for (int i = MoveIndex; i < MoveIndex + Direction; i++) { IWriteableBrowsingExistingBlockNodeIndex ChildNodeIndex = StateList[i].ParentIndex as IWriteableBrowsingExistingBlockNodeIndex; Debug.Assert(ChildNodeIndex != null); ChildNodeIndex.MoveDown(); ExistingBlockNodeIndex.MoveUp(); } } else if (Direction < 0) { for (int i = MoveIndex; i > MoveIndex + Direction; i--) { IWriteableBrowsingExistingBlockNodeIndex ChildNodeIndex = StateList[i].ParentIndex as IWriteableBrowsingExistingBlockNodeIndex; Debug.Assert(ChildNodeIndex != null); ChildNodeIndex.MoveUp(); ExistingBlockNodeIndex.MoveDown(); } } }
/// <summary> /// Changes the replication state of a block. /// </summary> /// <param name="operation">Details of the operation performed.</param> public virtual void ChangeReplication(WriteableChangeBlockOperation operation) { ReplicationStatus Replication = operation.Replication; int BlockIndex = operation.BlockIndex; Debug.Assert(BlockIndex >= 0 && BlockIndex < BlockStateList.Count); IWriteableBlockState BlockState = (IWriteableBlockState)BlockStateList[BlockIndex]; NodeTreeHelperBlockList.SetReplication(BlockState.ChildBlock, Replication); operation.Update(BlockState); }
/// <summary> /// Initializes a new instance of the <see cref="ReadOnlyBrowsingExistingBlockNodeIndex"/> class. /// </summary> /// <param name="parentNode">Node containing the block list.</param> /// <param name="node">Indexed node in the block.</param> /// <param name="propertyName">Property in <paramref name="parentNode"/> corresponding to the block list.</param> /// <param name="blockIndex">Position of the block in the block list.</param> /// <param name="index">Position of the node in the block.</param> public ReadOnlyBrowsingExistingBlockNodeIndex(INode parentNode, INode node, string propertyName, int blockIndex, int index) : base(node, propertyName, blockIndex) { Debug.Assert(parentNode != null); Debug.Assert(node != null); Debug.Assert(!string.IsNullOrEmpty(propertyName)); Debug.Assert(blockIndex >= 0); Debug.Assert(index >= 0); Debug.Assert(NodeTreeHelperBlockList.IsBlockChildNode(parentNode, propertyName, blockIndex, index, node)); ParentNode = parentNode; Index = index; }
private protected virtual void SetNodeTypeToDefault(IFrameTemplateDictionary dictionary, Type nodeType) { Debug.Assert(dictionary.ContainsKey(nodeType)); Debug.Assert(dictionary[nodeType] == null); FrameHorizontalPanelFrame RootFrame = (FrameHorizontalPanelFrame)CreateHorizontalPanelFrame(); FrameNodeTemplate RootTemplate = (FrameNodeTemplate)CreateNodeTemplate(); RootTemplate.NodeType = nodeType; RootTemplate.Root = RootFrame; // Set the template, even if empty, in case the node recursively refers to itself (ex: expressions). dictionary[nodeType] = RootTemplate; RootFrame.Items.Add(CreateCommentFrame()); Type ChildNodeType; IList <string> Properties = NodeTreeHelper.EnumChildNodeProperties(nodeType); foreach (string PropertyName in Properties) { bool IsHandled = false; if (NodeTreeHelperChild.IsChildNodeProperty(nodeType, PropertyName, out ChildNodeType)) { FramePlaceholderFrame NewFrame = (FramePlaceholderFrame)CreatePlaceholderFrame(); NewFrame.PropertyName = PropertyName; RootFrame.Items.Add(NewFrame); IsHandled = true; } else if (NodeTreeHelperOptional.IsOptionalChildNodeProperty(nodeType, PropertyName, out ChildNodeType)) { FrameOptionalFrame NewFrame = (FrameOptionalFrame)CreateOptionalFrame(); NewFrame.PropertyName = PropertyName; RootFrame.Items.Add(NewFrame); IsHandled = true; } else if (NodeTreeHelperList.IsNodeListProperty(nodeType, PropertyName, out Type ListNodeType)) { FrameHorizontalListFrame NewFrame = (FrameHorizontalListFrame)CreateHorizontalListFrame(); NewFrame.PropertyName = PropertyName; RootFrame.Items.Add(NewFrame); IsHandled = true; } else if (NodeTreeHelperBlockList.IsBlockListProperty(nodeType, PropertyName, out Type ChildInterfaceType, out Type ChildItemType)) { FrameHorizontalBlockListFrame NewFrame = (FrameHorizontalBlockListFrame)CreateHorizontalBlockListFrame(); NewFrame.PropertyName = PropertyName; RootFrame.Items.Add(NewFrame); IsHandled = true; }
/// <summary> /// Initializes a new instance of the <see cref="ReadOnlyBrowsingExistingBlockNodeIndex"/> class. /// </summary> /// <param name="parentNode">Node containing the block list.</param> /// <param name="node">Indexed node in the block.</param> /// <param name="propertyName">Property in <paramref name="parentNode"/> corresponding to the block list.</param> /// <param name="blockIndex">Position of the block in the block list.</param> /// <param name="index">Position of the node in the block.</param> public ReadOnlyBrowsingExistingBlockNodeIndex(Node parentNode, Node node, string propertyName, int blockIndex, int index) : base(node, propertyName, blockIndex) { Contract.RequireNotNull(parentNode, out Node ParentNode); Contract.RequireNotNull(node, out Node Node); Contract.RequireNotNull(propertyName, out string PropertyName); Debug.Assert(PropertyName.Length > 0); Debug.Assert(blockIndex >= 0); Debug.Assert(index >= 0); Debug.Assert(NodeTreeHelperBlockList.IsBlockChildNode(ParentNode, PropertyName, blockIndex, index, Node)); this.ParentNode = ParentNode; Index = index; }
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> /// Inserts a new block with one node in a block list. /// </summary> /// <param name="operation">Details of the operation performed.</param> public virtual void InsertNewBlock(IWriteableInsertBlockOperation operation) { Debug.Assert(operation != null); int BlockIndex = operation.BlockIndex; Debug.Assert(BlockIndex >= 0 && BlockIndex <= BlockStateList.Count); IBlock NewBlock = operation.Block; Debug.Assert(NewBlock != null); INode NewNode = operation.Node; Debug.Assert(NewBlock != null); INode ParentNode = Owner.Node; NodeTreeHelperBlockList.InsertIntoBlockList(ParentNode, PropertyName, BlockIndex, NewBlock); NodeTreeHelperBlockList.InsertIntoBlock(NewBlock, 0, NewNode); IWriteableBrowsingNewBlockNodeIndex BrowsingNewBlockIndex = CreateNewBlockNodeIndex(NewNode, BlockIndex); IWriteableBrowsingExistingBlockNodeIndex BrowsingExistingBlockIndex = (IWriteableBrowsingExistingBlockNodeIndex)BrowsingNewBlockIndex.ToExistingBlockIndex(); IWriteableBlockState BlockState = (IWriteableBlockState)CreateBlockState(BrowsingNewBlockIndex, NewBlock); InsertInBlockStateList(BlockIndex, BlockState); IWriteablePlaceholderNodeState ChildState = (IWriteablePlaceholderNodeState)CreateNodeState(BrowsingExistingBlockIndex); BlockState.Insert(BrowsingExistingBlockIndex, 0, ChildState); operation.Update(BrowsingExistingBlockIndex, BlockState, ChildState); while (++BlockIndex < BlockStateList.Count) { IWriteableBlockState NextBlockState = BlockStateList[BlockIndex]; foreach (IWriteablePlaceholderNodeState State in NextBlockState.StateList) { IWriteableBrowsingExistingBlockNodeIndex NodeIndex = State.ParentIndex as IWriteableBrowsingExistingBlockNodeIndex; Debug.Assert(NodeIndex != null); Debug.Assert(NodeIndex.BlockIndex == BlockIndex - 1); NodeIndex.MoveBlockUp(); } } }
/// <summary> /// Creates and initializes a new block state in the inner. /// </summary> /// <param name="newBlockIndex">Index of the new block state to create.</param> /// <returns>The created block state.</returns> public virtual IReadOnlyBlockState InitNewBlock(IReadOnlyBrowsingNewBlockNodeIndex newBlockIndex) { Debug.Assert(newBlockIndex.PropertyName == PropertyName); int BlockIndex = newBlockIndex.BlockIndex; Debug.Assert(BlockIndex == BlockStateList.Count); NodeTreeHelperBlockList.GetChildBlock(Owner.Node, PropertyName, BlockIndex, out IBlock ChildBlock); IReadOnlyBlockState BlockState = CreateBlockState(newBlockIndex, ChildBlock); InsertInBlockStateList(BlockIndex, BlockState); return(BlockState); }
/// <inheritdoc/> public override void CloneChildren(Node parentNode) { NodeTreeHelperBlockList.ClearChildBlockList(parentNode, PropertyName); // Clone and insert all blocks. This will clone all children recursively. for (int BlockIndex = 0; BlockIndex < BlockStateList.Count; BlockIndex++) { IReadOnlyBlockState BlockState = BlockStateList[BlockIndex]; ((IReadOnlyBlockState <IReadOnlyInner <IReadOnlyBrowsingChildIndex> >)BlockState).CloneBlock(parentNode, BlockIndex); } // Copy comments. IBlockList BlockList = NodeTreeHelperBlockList.GetBlockList(Owner.Node, PropertyName); IBlockList NewBlockList = NodeTreeHelperBlockList.GetBlockList(parentNode, PropertyName); NodeTreeHelper.CopyDocumentation(BlockList, NewBlockList, cloneCommentGuid: true); }
private protected virtual void AddBlockNodeTypes(FrameTemplateDictionary dictionary, Type nodeType) { IList <string> Properties = NodeTreeHelper.EnumChildNodeProperties(nodeType); foreach (string PropertyName in Properties) { if (NodeTreeHelperBlockList.IsBlockListProperty(nodeType, PropertyName, /*out Type ChildInterfaceType,*/ out Type ChildItemType)) { Type BlockListType = NodeTreeHelperBlockList.BlockListBlockType(nodeType, PropertyName); if (!dictionary.ContainsKey(BlockListType)) { dictionary.Add(BlockListType, null); } } } }
/// <summary> /// Creates a clone of the block and assigns it in the provided parent. /// </summary> /// <param name="parentNode">The node that will contains a reference to the cloned block upon return.</param> /// <param name="blockIndex">Position where to insert the block in <paramref name="parentNode"/>.</param> public virtual void CloneBlock(Node parentNode, int blockIndex) { Pattern PatternClone = ClonePattern(); Debug.Assert(PatternClone != null); Identifier SourceClone = CloneSource(); Debug.Assert(SourceClone != null); IBlock NewBlock = NodeTreeHelperBlockList.CreateBlock(parentNode, ParentInner.PropertyName, ChildBlock.Replication, PatternClone, SourceClone); NodeTreeHelperBlockList.InsertIntoBlockList(parentNode, ParentInner.PropertyName, blockIndex, NewBlock); NodeTreeHelper.CopyDocumentation(ChildBlock, NewBlock, cloneCommentGuid: true); // Clone children recursively. CloneChildren(parentNode, NewBlock); }
/// <summary> /// Checks that a frame selector is correctly constructed. /// </summary> /// <param name="nodeType">Type of the node this frame selector can describe.</param> /// <param name="nodeTemplateTable">Table of templates with all frames.</param> /// <param name="propertyName">The property for which frames can be selected.</param> public virtual bool IsValid(Type nodeType, IFocusTemplateReadOnlyDictionary nodeTemplateTable, string propertyName) { bool IsValid = true; IsValid &= SelectorType != null; IsValid &= !string.IsNullOrEmpty(SelectorName); Type ChildInterfaceType, ChildNodeType; IsValid &= NodeTreeHelperChild.IsChildNodeProperty(nodeType, propertyName, out ChildInterfaceType) || NodeTreeHelperOptional.IsOptionalChildNodeProperty(nodeType, propertyName, out ChildInterfaceType) || NodeTreeHelperList.IsNodeListProperty(nodeType, propertyName, out ChildInterfaceType) || NodeTreeHelperBlockList.IsBlockListProperty(nodeType, propertyName, out ChildInterfaceType, out ChildNodeType) || (NodeTreeHelper.IsBlockType(nodeType) && propertyName == nameof(BaseNode.IBlock.NodeList)); IsValid &= nodeTemplateTable.ContainsKey(SelectorType); IFocusNodeTemplate Template = nodeTemplateTable[SelectorType] as IFocusNodeTemplate; Debug.Assert(Template != null); IFocusSelectionFrame AsSelectionFrame = Template.Root as IFocusSelectionFrame; IsValid &= AsSelectionFrame != null; if (IsValid) { IFocusSelectableFrame SelectedItem = null; foreach (IFocusSelectableFrame Item in AsSelectionFrame.Items) { if (Item.Name == SelectorName) { SelectedItem = Item; break; } } IsValid &= SelectedItem != null; } Debug.Assert(IsValid); return(IsValid); }
/// <summary> /// Initializes a new instance of the <see cref="FocusBlockListSelection"/> class. /// </summary> /// <param name="stateView">The state view that encompasses the selection.</param> /// <param name="propertyName">The property name.</param> /// <param name="startIndex">Index of the first selected block.</param> /// <param name="endIndex">Index following the last selected block.</param> public FocusBlockListSelection(IFocusNodeStateView stateView, string propertyName, int startIndex, int endIndex) : base(stateView) { Node Node = stateView.State.Node; Debug.Assert(NodeTreeHelperBlockList.IsBlockListProperty(Node, propertyName, /*out Type childInterfaceType,*/ out Type childNodeType)); PropertyName = propertyName; if (startIndex <= endIndex) { StartIndex = startIndex; EndIndex = endIndex; } else { StartIndex = endIndex; EndIndex = startIndex; } }
/// <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(); }