/// <summary> /// Builds a BlockContainer control, populating it with the appropriate controls /// based on the supplied XML TDF data. /// </summary> /// <returns>The BlockContainer that was created.</returns> protected BlockContainer BuildStruct(XmlNode node, bool mainBlock) { int depth = 0; // Setup the block container. BlockContainer container = new BlockContainer(); container.LinkedUndoManager = this.undoManager; containers.Push(container); XmlNodeList valueNodes = node.SelectNodes("*"); foreach (XmlNode valueNode in valueNodes) { if (valueNode.Name.ToLower() == "group") { // Make sure that this node is a direct child of the Main Struct. // That's the only place that groups are allowed to exist. bool allowGroup = false; if (valueNode.ParentNode.Name.ToLower() == "struct") { if (valueNode.ParentNode.Attributes["name"] != null) { if (valueNode.ParentNode.Attributes["name"].InnerText == mainStructName) { allowGroup = true; } } } if (!allowGroup) { throw new Exception("Unable to create group: Not a direct member of the main struct."); } buildDepth.Push(0); CreateTab(valueNode.Attributes["caption"].InnerText); BlockContainer newContainer = BuildStruct(valueNode, mainBlock); newContainer.DatabindChildrenToBlock(this.tagData); containers.Peek().AddFieldContainer(newContainer); containers.Pop(); buildDepth.Pop(); } else if (valueNode.Name.ToLower() == "section") { // NOTE: This code is duplicated from the block creation. // A seperate method for building sections would really be ideal, but I don't feel // like going into that right now. IFieldContainer fieldContainer; if (((int)buildDepth.Peek()) < 1) { fieldContainer = new SectionContainer(); (fieldContainer as SectionContainer).Title = valueNode.Attributes["caption"].InnerText; if (valueNode.Attributes["description"] != null) { (fieldContainer as SectionContainer).Description = valueNode.Attributes["description"].InnerText; } } else { fieldContainer = new RegionContainer(); (fieldContainer as RegionContainer).Caption = valueNode.Attributes["caption"].InnerText; } depth = (int)(buildDepth.Pop()); buildDepth.Push(depth + 1); BlockContainer newContainer = BuildStruct(valueNode, mainBlock); newContainer.DatabindChildrenToBlock(this.tagData); fieldContainer.AddFieldContainer(newContainer); containers.Peek().AddFieldContainer(fieldContainer); } else if (valueNode.Name.ToLower() == "value") { string valueName = valueNode.Attributes["name"].InnerText; Field fieldControl = new Field(); string valueText = valueNode.Attributes["type"].InnerText; string fullPropertyName = (mainBlock ? className + "Values." : "") + Types.GlobalMethods.MakePublicName(valueName); if (standardControls.ContainsKey(valueText)) { //TODO: Look into adding the types into the hashtable, rather than using reflection. string controlTypeName = "TagEditor.Controls." + valueText; Type fieldControlType = Type.GetType(controlTypeName); Assembly targetAssembly = Assembly.GetAssembly(fieldControlType); fieldControl = (targetAssembly.CreateInstance(controlTypeName) as Field); fieldControl.Configure(valueNode); if (valueText != "Block") { containers.Peek().AddField(fieldControl); } else { fieldControl = new Block(); fieldControl.Configure(valueNode); (fieldControl as Block).Caption = "Select Block:"; // At this point, we need to recurse and create the sub control for this block. // Step 1: Locate the proper struct in the document. string structName = valueNode.Attributes["struct"].InnerText; XmlNode structNode = tagDefinition.SelectSingleNode("//struct[@name='" + structName + "']"); IFieldContainer fieldContainer; if (((int)buildDepth.Peek()) < 1) { fieldContainer = new SectionContainer(); (fieldContainer as SectionContainer).Title = Utility.CapitalizeWords(fieldControl.Caption); XmlNode descriptionNode = structNode.SelectSingleNode("description"); if (descriptionNode != null) { (fieldContainer as SectionContainer).Description = descriptionNode.InnerText; } } else { fieldContainer = new RegionContainer(); (fieldContainer as RegionContainer).Caption = Utility.CapitalizeWords(fieldControl.Caption); } depth = (int)(buildDepth.Pop()); buildDepth.Push(depth + 1); // Step 2: Build the BlockContainer and dock it. BlockContainer subBlockContainer = BuildStruct(structNode, false); fieldContainer.AddField(fieldControl); fieldContainer.AddFieldContainer(subBlockContainer); containers.Peek().AddFieldContainer(fieldContainer); subBlockContainer.Refresh(); // Step 3: Wire up the BlockChanged event for databinding. (fieldControl as Block).BlockChanged += new Block.BlockChangedHandler(subBlockContainer.DatabindChildrenToBlock); (fieldControl as Block).Initialize(); } } else { continue; } fieldControl.BoundPropertyName = fullPropertyName; } } depth = (int)(buildDepth.Pop()); buildDepth.Push(depth - 1); containers.Pop(); return(container); }