private static bool OnUpdate(Node node, WalkCallbacks <string> callback, string data) { IList <string> PropertyNames = NodeTreeHelper.EnumChildNodeProperties(node); foreach (string PropertyName in PropertyNames) { if (NodeTreeHelperOptional.IsOptionalChildNodeProperty(node, PropertyName, out Type ChildNodeType)) { NodeTreeHelperOptional.GetChildNode(node, PropertyName, out bool IsAssigned, out Node ChildNode); if (!IsAssigned) { if (ChildNode is null) { Node NewChildNode = NodeHelper.CreateDefaultFromType(ChildNodeType); NodeTreeHelperOptional.SetOptionalChildNode(node, PropertyName, NewChildNode); NodeTreeHelperOptional.UnassignChildNode(node, PropertyName); } } else if (ChildNode is null) { Node NewChildNode = NodeHelper.CreateDefaultFromType(ChildNodeType); NodeTreeHelperOptional.SetOptionalChildNode(node, PropertyName, NewChildNode); } else if (NodeHelper.IsDefaultNode(ChildNode)) { } } } return(true); }
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> /// Returns a clone of the node of this state. /// </summary> /// <returns>The cloned node.</returns> public override INode CloneNode() { INode NewNode = null; NodeTreeHelperOptional.GetChildNode(Optional, out bool IsAssigned, out INode ChildNode); if (ChildNode != null) { // Create a clone, initially empty and full of null references. NewNode = NodeHelper.CreateEmptyNode(ChildNode.GetType()); // Clone and assign reference to all nodes, optional or not, list and block lists. foreach (KeyValuePair <string, IReadOnlyInner> Entry in InnerTable) { string PropertyName = Entry.Key; IReadOnlyInner Inner = Entry.Value; ((IReadOnlyInner <IReadOnlyBrowsingChildIndex>)Inner).CloneChildren(NewNode); } // Copy other properties. foreach (KeyValuePair <string, ValuePropertyType> Entry in ValuePropertyTypeTable) { string PropertyName = Entry.Key; ValuePropertyType Type = Entry.Value; bool IsHandled = false; switch (Type) { case ValuePropertyType.Boolean: NodeTreeHelper.CopyBooleanProperty(Node, NewNode, Entry.Key); IsHandled = true; break; case ValuePropertyType.Enum: NodeTreeHelper.CopyEnumProperty(Node, NewNode, Entry.Key); IsHandled = true; break; case ValuePropertyType.String: NodeTreeHelper.CopyStringProperty(Node, NewNode, Entry.Key); IsHandled = true; break; case ValuePropertyType.Guid: NodeTreeHelper.CopyGuidProperty(Node, NewNode, Entry.Key); IsHandled = true; break; } Debug.Assert(IsHandled); } // Also copy comments. NodeTreeHelper.CopyDocumentation(Node, NewNode, cloneCommentGuid: true); } return(NewNode); }
/// <summary> /// Checks that a frame visibility is correctly constructed. /// </summary> /// <param name="nodeType">Type of the node this frame visibility can describe.</param> public override bool IsValid(Type nodeType) { bool IsValid = true; IsValid &= !string.IsNullOrEmpty(PropertyName); IsValid &= NodeTreeHelperOptional.IsOptionalChildNodeProperty(nodeType, PropertyName, out Type ChildNodeType); return(IsValid); }
/// <summary> /// Browse the optional node in the node tree. /// </summary> /// <param name="browseContext">The context used to browse the node tree.</param> /// <param name="parentInner">The inner containing this state as a child.</param> public override void BrowseChildren(ReadOnlyBrowseContext browseContext, IReadOnlyInner <IReadOnlyBrowsingChildIndex> parentInner) { NodeTreeHelperOptional.GetChildNode(Optional, out bool IsAssigned, out Node ChildNode); if (ChildNode != null) { BrowseChildrenOfNode(browseContext, ChildNode); } }
/// <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 &= NodeTreeHelperOptional.IsOptionalChildNodeProperty(nodeType, PropertyName, out Type ChildNodeType); Debug.Assert(IsValid); return(IsValid); }
/// <summary> /// Initializes a new instance of the <see cref="WriteableInsertionOptionalClearIndex"/> class. /// </summary> /// <param name="parentNode">Node containing the indexed optional node.</param> /// <param name="propertyName">Property in <paramref name="parentNode"/> corresponding to the indexed optional node.</param> public WriteableInsertionOptionalClearIndex(INode parentNode, string propertyName) { Debug.Assert(parentNode != null); Debug.Assert(!string.IsNullOrEmpty(propertyName)); ParentNode = parentNode; PropertyName = propertyName; Optional = NodeTreeHelperOptional.GetOptionalReference(parentNode, propertyName); Debug.Assert(Optional != null); }
/// <summary> /// Initializes a new instance of the <see cref="ReadOnlyBrowsingOptionalNodeIndex"/> class. /// </summary> /// <param name="parentNode">Node containing the indexed optional node.</param> /// <param name="propertyName">Property in <paramref name="parentNode"/> corresponding to the indexed optional node.</param> public ReadOnlyBrowsingOptionalNodeIndex(INode parentNode, string propertyName) { Debug.Assert(parentNode != null); Debug.Assert(!string.IsNullOrEmpty(propertyName)); Debug.Assert(NodeTreeHelperOptional.IsOptionalChildNodeProperty(parentNode, propertyName, out Type ChildNodeType)); Optional = NodeTreeHelperOptional.GetOptionalReference(parentNode, propertyName); Debug.Assert(Optional != null); PropertyName = propertyName; }
private protected virtual bool IsNodeTreeOptionalNodeValid(Node node, string propertyName) { bool IsValid = true; NodeTreeHelperOptional.GetChildNode(node, propertyName, out bool IsAssigned, out Node ChildNode); if (IsAssigned) { IsValid &= InvariantFailed(IsNodeTreeValid(ChildNode)); } return(IsValid); }
/// <summary> /// Initializes a new instance of the <see cref="ReadOnlyBrowsingOptionalNodeIndex"/> class. /// </summary> /// <param name="parentNode">Node containing the indexed optional node.</param> /// <param name="propertyName">Property in <paramref name="parentNode"/> corresponding to the indexed optional node.</param> public ReadOnlyBrowsingOptionalNodeIndex(Node parentNode, string propertyName) { Contract.RequireNotNull(parentNode, out Node ParentNode); Contract.RequireNotNull(propertyName, out string PropertyName); Debug.Assert(PropertyName.Length > 0); Debug.Assert(NodeTreeHelperOptional.IsOptionalChildNodeProperty(ParentNode, PropertyName, out _)); Optional = NodeTreeHelperOptional.GetOptionalReference(ParentNode, PropertyName); Debug.Assert(Optional != null); this.PropertyName = PropertyName; }
/// <summary> /// Initializes a new instance of the <see cref="WriteableInsertionOptionalClearIndex"/> class. /// </summary> /// <param name="parentNode">Node containing the indexed optional node.</param> /// <param name="propertyName">Property in <paramref name="parentNode"/> corresponding to the indexed optional node.</param> public WriteableInsertionOptionalClearIndex(Node parentNode, string propertyName) { Contract.RequireNotNull(parentNode, out Node ParentNode); Contract.RequireNotNull(propertyName, out string PropertyName); Debug.Assert(PropertyName.Length > 0); this.ParentNode = ParentNode; this.PropertyName = PropertyName; Optional = NodeTreeHelperOptional.GetOptionalReference(ParentNode, PropertyName); Debug.Assert(Optional != null); }
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; }
/// <inheritdoc/> public override void CloneChildren(Node parentNode) { // Clone the child recursively. Node ChildNodeClone = ChildState.CloneNode(); // If the original is set, set the clone too. if (ChildNodeClone != null) { NodeTreeHelperOptional.SetOptionalChildNode(parentNode, PropertyName, ChildNodeClone); if (!IsAssigned) { NodeTreeHelperOptional.UnassignChildNode(parentNode, PropertyName); } } }
private protected virtual void ClearOptional(IWriteableReplaceOperation operation) { INode ParentNode = Owner.Node; WriteableBrowsingOptionalNodeIndex OldBrowsingIndex = (WriteableBrowsingOptionalNodeIndex)ChildState.ParentIndex; INode OldNode = ChildState.Optional.HasItem ? ChildState.Node : null; NodeTreeHelperOptional.ClearOptionalChildNode(ParentNode, PropertyName); IWriteableBrowsingOptionalNodeIndex NewBrowsingIndex = CreateBrowsingNodeIndex(); IWriteableOptionalNodeState NewChildState = (IWriteableOptionalNodeState)CreateNodeState(NewBrowsingIndex); SetChildState(NewChildState); operation.Update(OldBrowsingIndex, NewBrowsingIndex, OldNode, NewChildState); }
/// <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); }
private protected virtual void ReplaceOptional(IWriteableReplaceOperation operation) { Node ParentNode = Owner.Node; IWriteableBrowsingOptionalNodeIndex OldBrowsingIndex = (IWriteableBrowsingOptionalNodeIndex)ChildState.ParentIndex; Node OldNode = ChildState.Node; if (operation.ClearNode) { NodeTreeHelperOptional.UnassignChildNode(ParentNode, PropertyName); } else { NodeTreeHelperOptional.SetOptionalChildNode(ParentNode, PropertyName, operation.NewNode); } IWriteableBrowsingOptionalNodeIndex NewBrowsingIndex = CreateBrowsingNodeIndex(); IWriteableOptionalNodeState NewChildState = (IWriteableOptionalNodeState)CreateNodeState(NewBrowsingIndex); SetChildState(NewChildState); operation.Update(OldBrowsingIndex, NewBrowsingIndex, OldNode, NewChildState); }
static void BrowseNode(ReadOnlyController controller, IReadOnlyIndex index, Stats stats) { Assert.That(index != null, "ReadOnly #0"); Assert.That(controller.Contains(index), "ReadOnly #1"); IReadOnlyNodeState State = controller.IndexToState(index); Assert.That(State != null, "ReadOnly #2"); Assert.That(State.ParentIndex == index, "ReadOnly #4"); Node Node; if (State is IReadOnlyPlaceholderNodeState AsPlaceholderState) { Node = AsPlaceholderState.Node; } else if (State is IReadOnlyPatternState AsPatternState) { Node = AsPatternState.Node; } else if (State is IReadOnlySourceState AsSourceState) { Node = AsSourceState.Node; } else { Assert.That(State is IReadOnlyOptionalNodeState, "ReadOnly #5"); IReadOnlyOptionalNodeState AsOptionalState = (IReadOnlyOptionalNodeState)State; IReadOnlyOptionalInner ParentInner = AsOptionalState.ParentInner; //Assert.That(ParentInner.IsAssigned, "ReadOnly #6"); Node = AsOptionalState.Node; } stats.NodeCount++; Type ChildNodeType; IList <string> PropertyNames = NodeTreeHelper.EnumChildNodeProperties(Node); foreach (string PropertyName in PropertyNames) { if (NodeTreeHelperChild.IsChildNodeProperty(Node, PropertyName, out ChildNodeType)) { stats.PlaceholderNodeCount++; IReadOnlyPlaceholderInner Inner = (IReadOnlyPlaceholderInner)State.PropertyToInner(PropertyName); IReadOnlyNodeState ChildState = Inner.ChildState; IReadOnlyIndex ChildIndex = ChildState.ParentIndex; BrowseNode(controller, ChildIndex, stats); } else if (NodeTreeHelperOptional.IsOptionalChildNodeProperty(Node, PropertyName, out ChildNodeType)) { stats.OptionalNodeCount++; NodeTreeHelperOptional.GetChildNode(Node, PropertyName, out bool IsAssigned, out Node ChildNode); Debug.Assert(ChildNode is not null); //if (IsAssigned) { if (IsAssigned) { stats.AssignedOptionalNodeCount++; } IReadOnlyOptionalInner Inner = (IReadOnlyOptionalInner)State.PropertyToInner(PropertyName); IReadOnlyNodeState ChildState = Inner.ChildState; IReadOnlyIndex ChildIndex = ChildState.ParentIndex; BrowseNode(controller, ChildIndex, stats); } /*else * stats.NodeCount++;*/ } else if (NodeTreeHelperList.IsNodeListProperty(Node, PropertyName, out ChildNodeType)) { stats.ListCount++; IReadOnlyListInner Inner = (IReadOnlyListInner)State.PropertyToInner(PropertyName); for (int i = 0; i < Inner.StateList.Count; i++) { stats.PlaceholderNodeCount++; IReadOnlyPlaceholderNodeState ChildState = Inner.StateList[i]; IReadOnlyIndex ChildIndex = ChildState.ParentIndex; BrowseNode(controller, ChildIndex, stats); } } else if (NodeTreeHelperBlockList.IsBlockListProperty(Node, PropertyName, /*out Type ChildInterfaceType,*/ out ChildNodeType)) { stats.BlockListCount++; IReadOnlyBlockListInner Inner = (IReadOnlyBlockListInner)State.PropertyToInner(PropertyName); for (int BlockIndex = 0; BlockIndex < Inner.BlockStateList.Count; BlockIndex++) { IReadOnlyBlockState BlockState = Inner.BlockStateList[BlockIndex]; stats.PlaceholderNodeCount++; BrowseNode(controller, BlockState.PatternIndex, stats); stats.PlaceholderNodeCount++; BrowseNode(controller, BlockState.SourceIndex, stats); for (int i = 0; i < BlockState.StateList.Count; i++) { stats.PlaceholderNodeCount++; IReadOnlyPlaceholderNodeState ChildState = BlockState.StateList[i]; IReadOnlyIndex ChildIndex = ChildState.ParentIndex; BrowseNode(controller, ChildIndex, stats); } } } else { Type NodeType = Type.FromGetType(Node); PropertyInfo Info = NodeType.GetProperty(PropertyName); if (Info.PropertyType.IsTypeof <Document>()) { } else if (Info.PropertyType.IsTypeof <bool>()) { } else if (Info.PropertyType.IsEnum) { } else if (Info.PropertyType.IsTypeof <string>()) { } else if (Info.PropertyType.IsTypeof <Guid>()) { } else { Assert.That(false, $"State Tree unexpected property: {Info.PropertyType.Name}"); } } } }
/// <summary> /// Unassign the optional node. /// </summary> /// <param name="operation">Details of the operation performed.</param> public void Unassign(IWriteableAssignmentOperation operation) { NodeTreeHelperOptional.UnassignChildNode(Owner.Node, PropertyName); operation.Update(ChildState); }
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; } }
private protected virtual void BrowseChildrenOfNode(IReadOnlyBrowseContext browseNodeContext, INode node) { IList <string> PropertyNames = NodeTreeHelper.EnumChildNodeProperties(node); foreach (string PropertyName in PropertyNames) { INode ChildNode; Type ChildInterfaceType, ChildNodeType; IReadOnlyList <INode> ChildNodeList; IReadOnlyList <INodeTreeBlock> ChildBlockList; bool IsHandled = false; if (NodeTreeHelperChild.IsChildNodeProperty(node, PropertyName, out ChildNodeType)) { NodeTreeHelperChild.GetChildNode(node, PropertyName, out ChildNode); Debug.Assert(ChildNode != null); IReadOnlyBrowsingPlaceholderNodeIndex ChildNodeIndex = CreateChildNodeIndex(browseNodeContext, node, PropertyName, ChildNode); // Create a collection containing one index for this child node. IReadOnlyIndexCollection IndexCollection = CreatePlaceholderIndexCollection(browseNodeContext, PropertyName, ChildNodeIndex); browseNodeContext.AddIndexCollection(IndexCollection); IsHandled = true; } else if (NodeTreeHelperOptional.IsOptionalChildNodeProperty(node, PropertyName, out ChildNodeType)) { IReadOnlyBrowsingOptionalNodeIndex OptionalNodeIndex = CreateOptionalNodeIndex(browseNodeContext, node, PropertyName); // Create a collection containing one index for this optional node. IReadOnlyIndexCollection IndexCollection = CreateOptionalIndexCollection(browseNodeContext, PropertyName, OptionalNodeIndex); browseNodeContext.AddIndexCollection(IndexCollection); IsHandled = true; } else if (NodeTreeHelperList.IsNodeListProperty(node, PropertyName, out ChildNodeType)) { NodeTreeHelperList.GetChildNodeList(node, PropertyName, out ChildNodeList); Debug.Assert(ChildNodeList != null); // Create a collection containing indexes for each children. IReadOnlyIndexCollection IndexCollection = BrowseNodeList(browseNodeContext, node, PropertyName, ChildNodeList); browseNodeContext.AddIndexCollection(IndexCollection); IsHandled = true; } else if (NodeTreeHelperBlockList.IsBlockListProperty(node, PropertyName, out ChildInterfaceType, out ChildNodeType)) { NodeTreeHelperBlockList.GetChildBlockList(node, PropertyName, out ChildBlockList); Debug.Assert(ChildBlockList != null); // Create a collection containing indexes for each child blocks and their children. IReadOnlyIndexCollection IndexCollection = BrowseNodeBlockList(browseNodeContext, node, PropertyName, ChildBlockList); browseNodeContext.AddIndexCollection(IndexCollection); IsHandled = true; } else if (NodeTreeHelper.IsBooleanProperty(node, PropertyName)) { browseNodeContext.AddValueProperty(PropertyName, ValuePropertyType.Boolean); IsHandled = true; } else if (NodeTreeHelper.IsEnumProperty(node, PropertyName)) { browseNodeContext.AddValueProperty(PropertyName, ValuePropertyType.Enum); IsHandled = true; } else if (NodeTreeHelper.IsStringProperty(node, PropertyName)) { browseNodeContext.AddValueProperty(PropertyName, ValuePropertyType.String); IsHandled = true; } else if (NodeTreeHelper.IsGuidProperty(node, PropertyName)) { browseNodeContext.AddValueProperty(PropertyName, ValuePropertyType.Guid); IsHandled = true; } else if (NodeTreeHelper.IsDocumentProperty(node, PropertyName)) { IsHandled = true; // Ignore the doc node. } Debug.Assert(IsHandled); } }
private protected virtual void SetNodeTypeToDefault(FrameTemplateDictionary 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; } else if (NodeTreeHelper.IsBooleanProperty(nodeType, PropertyName)) { FrameDiscreteFrame NewDiscreteFrame = (FrameDiscreteFrame)CreateDiscreteFrame(); NewDiscreteFrame.PropertyName = PropertyName; FrameKeywordFrame KeywordFalseFrame = (FrameKeywordFrame)CreateKeywordFrame(); KeywordFalseFrame.Text = $"{PropertyName}=False"; NewDiscreteFrame.Items.Add(KeywordFalseFrame); FrameKeywordFrame KeywordTrueFrame = (FrameKeywordFrame)CreateKeywordFrame(); KeywordTrueFrame.Text = $"{PropertyName}=True"; NewDiscreteFrame.Items.Add(KeywordTrueFrame); RootFrame.Items.Add(NewDiscreteFrame); IsHandled = true; } else if (NodeTreeHelper.IsEnumProperty(nodeType, PropertyName)) { NodeTreeHelper.GetEnumRange(nodeType, PropertyName, out int Min, out int Max); FrameDiscreteFrame NewDiscreteFrame = (FrameDiscreteFrame)CreateDiscreteFrame(); NewDiscreteFrame.PropertyName = PropertyName; for (int i = Min; i <= Max; i++) { FrameKeywordFrame KeywordFrame = (FrameKeywordFrame)CreateKeywordFrame(); KeywordFrame.Text = $"{PropertyName}={i}"; NewDiscreteFrame.Items.Add(KeywordFrame); } RootFrame.Items.Add(NewDiscreteFrame); IsHandled = true; } else if (NodeTreeHelper.IsStringProperty(nodeType, PropertyName)) { FrameTextValueFrame NewDiscreteFrame = (FrameTextValueFrame)CreateTextValueFrame(); NewDiscreteFrame.PropertyName = PropertyName; RootFrame.Items.Add(NewDiscreteFrame); IsHandled = true; } else if (NodeTreeHelper.IsGuidProperty(nodeType, PropertyName)) { IsHandled = true; } else if (NodeTreeHelper.IsDocumentProperty(nodeType, PropertyName)) { IsHandled = true; } Debug.Assert(IsHandled); } RootFrame.UpdateParent(RootTemplate, GetRoot()); }