Esempio n. 1
0
        public static void Serialize_OptionsPage(dynamic menu, OptionsPage op, Point cursorPosition)
        {
            menu.menuType = "optionsPage";
            var       optionSlots    = new List <dynamic>();
            Rectangle?activeDDBounds = null;

            for (int i = 0; i < op.optionSlots.Count; i++)
            {
                ClickableComponent cmp     = op.optionSlots[i];
                OptionsElement     element = op.options[op.currentItemIndex + i];
                if (element.greyedOut || (activeDDBounds.HasValue && cmp.bounds.Intersects((Rectangle)activeDDBounds)))
                {
                    continue;
                }
                if (element is OptionsPlusMinus)
                {
                    OptionsPlusMinus pm = element as OptionsPlusMinus;
                    var minusRect       = new Rectangle(cmp.bounds.X + pm.minusButton.X, cmp.bounds.Y + pm.minusButton.Y, pm.minusButton.Width, pm.minusButton.Height);
                    var minusCmp        = Utils.Merge(Utils.RectangleToClickableComponent(minusRect, cursorPosition), new { label = pm.label + " minus" });
                    var plusRect        = new Rectangle(cmp.bounds.X + pm.plusButton.X, cmp.bounds.Y + pm.plusButton.Y, pm.plusButton.Width, pm.plusButton.Height);
                    var plusCmp         = Utils.Merge(Utils.RectangleToClickableComponent(plusRect, cursorPosition), new { label = pm.label + " plus" });
                    optionSlots.Add(minusCmp);
                    optionSlots.Add(plusCmp);
                }
                else if (element is OptionsCheckbox)
                {
                    var rect = new Rectangle(cmp.bounds.X + element.bounds.X, cmp.bounds.Y + element.bounds.Y, element.bounds.Width, element.bounds.Height);
                    optionSlots.Add(Utils.Merge(Utils.RectangleToClickableComponent(rect, cursorPosition), new { element.label }));
                }
                else if (element is OptionsDropDown)
                {
                    OptionsDropDown odd = element as OptionsDropDown;
                    int             y   = cmp.bounds.Y + odd.bounds.Y;
                    if (!(System.Object.ReferenceEquals(OptionsDropDown.selected, odd)))
                    {
                        var rect        = new Rectangle(cmp.bounds.X + odd.bounds.X, y, element.bounds.Width, element.bounds.Height);
                        var focusTarget = new List <int> {
                            rect.X + 18, rect.Center.Y
                        };
                        optionSlots.Add(Utils.Merge(Utils.RectangleToClickableComponent(rect, cursorPosition), new { element.label, focusTarget }));
                    }
                    else
                    {
                        activeDDBounds = new Rectangle(cmp.bounds.X + odd.dropDownBounds.X, y, odd.dropDownBounds.Width, odd.dropDownBounds.Height);
                        int heightPerOption = odd.dropDownBounds.Height / odd.dropDownDisplayOptions.Count;
                        for (int j = 0; j < odd.dropDownDisplayOptions.Count; j++)
                        {
                            string option      = odd.dropDownDisplayOptions[j];
                            var    optY        = y + heightPerOption * j;
                            var    rect        = new Rectangle(cmp.bounds.X + odd.bounds.X, optY, element.bounds.Width, heightPerOption);
                            var    focusTarget = new List <int> {
                                rect.X + 18, rect.Center.Y
                            };
                            optionSlots.Add(Utils.Merge(Utils.RectangleToClickableComponent(rect, cursorPosition), new { label = option, focusTarget }));
                        }
                    }
                }
            }
            menu.optionSlots = optionSlots;
        }
Esempio n. 2
0
        /// <summary>
        /// Constructs an instance.
        /// </summary>
        /// <param name="mod">Mod to use to create search results</param>
        /// <param name="config">Mod config</param>
        /// <param name="x">X position of tab</param>
        /// <param name="y">Y position of tab</param>
        /// <param name="width">Tab width</param>
        /// <param name="height">Tab height</param>
        public SearchTab(GeodeInfoMenuMod mod, GeodeInfoMenuConfig config, int x, int y, int width, int height) : base(x, y, width, height, false)
        {
            this.config          = config;
            this.mod             = mod;
            searchResults        = new List <OptionsElement>();
            visibleSearchResults = new List <ClickableComponent>();
            headerText           = new OptionsElement("Search for a drop: ");
            this.headerBounds    = new Point(this.xPositionOnScreen + Game1.tileSize / 4, this.yPositionOnScreen + Game1.tileSize * 5 / 4 + Game1.pixelZoom);
            searchBox            = new UpdatingTextBox(new TextChangedDelegate(SearchBoxTextChanged), Game1.content.Load <Texture2D>("LooseSprites\\textBox"), (Texture2D)null, Game1.smallFont, Game1.textColor)
            {
                X    = this.xPositionOnScreen + Game1.tileSize / 4 + Game1.tileSize * 8,
                Y    = this.yPositionOnScreen + Game1.tileSize * 5 / 4 + Game1.pixelZoom + Game1.tileSize / 2,
                Text = ""
            };

            this.upArrow         = new ClickableTextureComponent(new Rectangle(this.xPositionOnScreen + width + Game1.tileSize / 4, this.yPositionOnScreen + Game1.tileSize, 11 * Game1.pixelZoom, 12 * Game1.pixelZoom), Game1.mouseCursors, new Rectangle(421, 459, 11, 12), (float)Game1.pixelZoom, false);
            this.downArrow       = new ClickableTextureComponent(new Rectangle(this.xPositionOnScreen + width + Game1.tileSize / 4, this.yPositionOnScreen + height - Game1.tileSize, 11 * Game1.pixelZoom, 12 * Game1.pixelZoom), Game1.mouseCursors, new Rectangle(421, 472, 11, 12), (float)Game1.pixelZoom, false);
            this.scrollBar       = new ClickableTextureComponent(new Rectangle(this.upArrow.bounds.X + Game1.pixelZoom * 3, this.upArrow.bounds.Y + this.upArrow.bounds.Height + Game1.pixelZoom, 6 * Game1.pixelZoom, 10 * Game1.pixelZoom), Game1.mouseCursors, new Rectangle(435, 463, 6, 10), (float)Game1.pixelZoom, false);
            this.scrollBarRunner = new Rectangle(this.scrollBar.bounds.X, this.upArrow.bounds.Y + this.upArrow.bounds.Height + Game1.pixelZoom, this.scrollBar.bounds.Width, height - Game1.tileSize * 2 - this.upArrow.bounds.Height - Game1.pixelZoom * 2);
            //height -= searchBox.Height + 20;
            for (int index = 0; index < SearchTab.NUM_ITEMS; ++index)
            {
                List <ClickableComponent> optionSlots        = this.visibleSearchResults;
                ClickableComponent        clickableComponent = new ClickableComponent(new Rectangle(this.xPositionOnScreen + Game1.tileSize / 4, this.yPositionOnScreen + Game1.tileSize * 5 / 4 + Game1.pixelZoom + (index + 1) * ((height - Game1.tileSize * 2) / (NUM_ITEMS + 1)), width - Game1.tileSize / 2, (height - Game1.tileSize * 2) / (NUM_ITEMS + 1) + Game1.pixelZoom), string.Concat((object)index));
                clickableComponent.myID = index;
                int num1 = index < SearchTab.NUM_ITEMS - 1 ? index + 1 : -7777;
                clickableComponent.downNeighborID = num1;
                int num2 = index > 0 ? index - 1 : -7777;
                clickableComponent.upNeighborID = num2;
                int num3 = 1;
                clickableComponent.fullyImmutable = num3 != 0;
                optionSlots.Add(clickableComponent);
            }
        }
Esempio n. 3
0
 /// <summary>
 /// Constructs an instance.
 /// </summary>
 /// <param name="name">The name of this tab</param>
 /// <param name="items">The items this tab should show</param>
 /// <param name="x">X position of the tab</param>
 /// <param name="y">Y position of the tab</param>
 /// <param name="width">Tab width</param>
 /// <param name="height">Tab height</param>
 public GeodeTab(string name, Tuple <int[], bool[]> items, int x, int y, int width, int height)
     : base(x, y, width, height, true)
 {
     this.name            = name;
     this.upArrow         = new ClickableTextureComponent(new Rectangle(this.xPositionOnScreen + width + Game1.tileSize / 4, this.yPositionOnScreen + Game1.tileSize, 11 * Game1.pixelZoom, 12 * Game1.pixelZoom), Game1.mouseCursors, new Rectangle(421, 459, 11, 12), (float)Game1.pixelZoom, false);
     this.downArrow       = new ClickableTextureComponent(new Rectangle(this.xPositionOnScreen + width + Game1.tileSize / 4, this.yPositionOnScreen + height - Game1.tileSize, 11 * Game1.pixelZoom, 12 * Game1.pixelZoom), Game1.mouseCursors, new Rectangle(421, 472, 11, 12), (float)Game1.pixelZoom, false);
     this.scrollBar       = new ClickableTextureComponent(new Rectangle(this.upArrow.bounds.X + Game1.pixelZoom * 3, this.upArrow.bounds.Y + this.upArrow.bounds.Height + Game1.pixelZoom, 6 * Game1.pixelZoom, 10 * Game1.pixelZoom), Game1.mouseCursors, new Rectangle(435, 463, 6, 10), (float)Game1.pixelZoom, false);
     this.scrollBarRunner = new Rectangle(this.scrollBar.bounds.X, this.upArrow.bounds.Y + this.upArrow.bounds.Height + Game1.pixelZoom, this.scrollBar.bounds.Width, height - Game1.tileSize * 2 - this.upArrow.bounds.Height - Game1.pixelZoom * 2);
     this.headerBounds    = new Point(this.xPositionOnScreen + Game1.tileSize / 4, this.yPositionOnScreen + Game1.tileSize * 5 / 4 + Game1.pixelZoom);
     for (int index = 0; index < GeodeTab.NUM_ITEMS; ++index)
     {
         List <ClickableComponent> optionSlots        = this.optionSlots;
         ClickableComponent        clickableComponent = new ClickableComponent(new Rectangle(this.xPositionOnScreen + Game1.tileSize / 4, this.yPositionOnScreen + Game1.tileSize * 5 / 4 + Game1.pixelZoom + (index + 1) * ((height - Game1.tileSize * 2) / (NUM_ITEMS + 1)), width - Game1.tileSize / 2, (height - Game1.tileSize * 2) / (NUM_ITEMS + 1) + Game1.pixelZoom), string.Concat((object)index));
         clickableComponent.myID = index;
         int num1 = index < GeodeTab.NUM_ITEMS - 1 ? index + 1 : -7777;
         clickableComponent.downNeighborID = num1;
         int num2 = index > 0 ? index - 1 : -7777;
         clickableComponent.upNeighborID = num2;
         int num3 = 1;
         clickableComponent.fullyImmutable = num3 != 0;
         optionSlots.Add(clickableComponent);
     }
     this.header = new OptionsElement("Next " + items.Item1.Length + " " + name + " drops: ");
     if (items != null)
     {
         for (int i = 0; i < items.Item1.Length; i++)
         {
             this.options.Add(new GeodeTabItem(items.Item1[i], i + 1, items.Item2[i]));
         }
     }
 }
        public PylonsElement(IMonitor monitor, PylonData pylon)
        {
            bounds = new Rectangle(0, 15, 800, 50);

            _monitor = monitor;
            _pylon   = pylon;

            _label  = new OptionsElement($"{pylon.Name}", 32, 16, 36, 50);
            _rename = new OptionsPylonRenameButton(_monitor, "Rename", pylon);
            _warp   = new OptionsPylonWarpButton(_monitor, "Warp", pylon);
        }
Esempio n. 5
0
        /// <summary>
        ///  Returns which elements should be drawn.
        /// </summary>
        /// <returns>The elements that can be drawn</returns>
        public List <OptionsElement> GetElementsToShow()
        {
            List <OptionsElement> menuElements = _tabs[_tabIndex].GetElements();
            List <OptionsElement> elements     = new List <OptionsElement>();
            int y = 16;

            for (int i = _firstIndex; i < menuElements.Count; i++)
            {
                OptionsElement element = menuElements[i];
                int            hElem   = element is ModifiedSlider ? element.bounds.Height + 4 : element.bounds.Height;
                if (y + hElem + 16 < height)
                {
                    y += hElem + 16;
                    elements.Add(element);
                }
                else
                {
                    break;
                }
            }
            return(elements);
        }
Esempio n. 6
0
        public MenuTab(int x, int y, int width, int height, TabName name, List <SObject> items) : base(x, y, width, height, true)
        {
            Name             = name;
            HoverText        = "";
            currentItemIndex = 0;
            Items            = new List <MenuTabItem>();
            foreach (SObject obj in items)
            {
                Items.Add(new MenuTabItem(obj));
            }

            ViewableItems = new List <ClickableComponent>();

            Initialize();

            upArrow         = new ClickableTextureComponent(new Rectangle(xPositionOnScreen + width + Game1.tileSize / 4, yPositionOnScreen + Game1.tileSize, 11 * Game1.pixelZoom, 12 * Game1.pixelZoom), Game1.mouseCursors, new Rectangle(421, 459, 11, 12), Game1.pixelZoom, false);
            downArrow       = new ClickableTextureComponent(new Rectangle(xPositionOnScreen + width + Game1.tileSize / 4, yPositionOnScreen + height - Game1.tileSize, 11 * Game1.pixelZoom, 12 * Game1.pixelZoom), Game1.mouseCursors, new Rectangle(421, 472, 11, 12), Game1.pixelZoom, false);
            scrollBar       = new ClickableTextureComponent(new Rectangle(upArrow.bounds.X + Game1.pixelZoom * 3, upArrow.bounds.Y + upArrow.bounds.Height + Game1.pixelZoom, 6 * Game1.pixelZoom, 10 * Game1.pixelZoom), Game1.mouseCursors, new Rectangle(435, 463, 6, 10), Game1.pixelZoom, false);
            scrollBarRunner = new Rectangle(scrollBar.bounds.X, upArrow.bounds.Y + upArrow.bounds.Height + Game1.pixelZoom, scrollBar.bounds.Width, height - Game1.tileSize * 2 - upArrow.bounds.Height - Game1.pixelZoom * 2);
            headerBounds    = new Point(xPositionOnScreen + Game1.tileSize / 4, yPositionOnScreen + Game1.tileSize * 5 / 4 + Game1.pixelZoom);

            header = new OptionsElement(TabNameToString());
        }
Esempio n. 7
0
        /// <summary>
        /// Can all elements from firstIndex be drawn?
        /// </summary>
        /// <param name="firstIndex">first index of element that be tested firstly.</param>
        /// <returns>If true, all elements can be drawn</returns>
        public bool CanDrawAll(int firstIndex = -1)
        {
            if (firstIndex < 0)
            {
                firstIndex = _firstIndex;
            }
            List <OptionsElement> menuElements = _tabs[_tabIndex].GetElements();
            int y = 16;

            for (int i = firstIndex; i < menuElements.Count; i++)
            {
                OptionsElement element = menuElements[i];
                int            hElem   = element is ModifiedSlider ? element.bounds.Height + 4 : element.bounds.Height;
                if (y + hElem + 16 < height)
                {
                    y += hElem + 16;
                }
                else
                {
                    return(false);
                }
            }
            return(true);
        }
        public NewMediumLevelRecordEditor(Plugin p, Record r, SubRecord sr, SubrecordStructure ss)
        {
            InitializeComponent();
            Icon = Resources.tesv_ico;
            SuspendLayout();
            this.sr = sr;
            this.ss = ss;
            this.p  = p;
            this.r  = r;

            // walk each element in standard fashion
            int panelOffset = 0;

            try
            {
                foreach (var elem in ss.elements)
                {
                    Control c = null;
                    if (elem.options != null && elem.options.Length > 1)
                    {
                        c = new OptionsElement();
                    }
                    else if (elem.flags != null && elem.flags.Length > 1)
                    {
                        c = new FlagsElement();
                    }
                    else
                    {
                        switch (elem.type)
                        {
                        case ElementValueType.LString:
                            c = new LStringElement();
                            break;

                        case ElementValueType.FormID:
                            c = new FormIDElement();
                            break;

                        case ElementValueType.Blob:
                            c = new HexElement();
                            break;

                        default:
                            c = new TextElement();
                            break;
                        }
                    }
                    if (c is IElementControl)
                    {
                        var ec = c as IElementControl;
                        ec.formIDLookup = p.GetRecordByID;
                        ec.formIDScan   = p.EnumerateRecords;
                        ec.strIDLookup  = p.LookupFormStrings;
                        ec.Element      = elem;

                        if (elem.repeat > 0)
                        {
                            var ge = new RepeatingElement();
                            c        = ge;
                            c.Left   = 8;
                            c.Width  = fpanel1.Width - 16;
                            c.Top    = panelOffset;
                            c.Anchor = c.Anchor | AnchorStyles.Left | AnchorStyles.Right;

                            ge.InnerControl = ec;
                            ge.Element      = elem;
                            ec = ge;
                        }
                        else if (elem.optional)
                        {
                            var re = new OptionalElement();
                            c        = re;
                            c.Left   = 8;
                            c.Width  = fpanel1.Width - 16;
                            c.Top    = panelOffset;
                            c.Anchor = c.Anchor | AnchorStyles.Left | AnchorStyles.Right;

                            re.InnerControl = ec;
                            re.Element      = elem;
                            ec = re;
                            c  = re;
                        }
                        else
                        {
                            c.Left   = 8;
                            c.Width  = fpanel1.Width - 16;
                            c.Top    = panelOffset;
                            c.Anchor = c.Anchor | AnchorStyles.Left | AnchorStyles.Right;
                        }
                        c.MinimumSize = c.Size;

                        controlMap.Add(elem, ec);
                        fpanel1.Controls.Add(c);
                        panelOffset = c.Bottom;
                    }
                }

                foreach (Element elem in r.EnumerateElements(sr, true))
                {
                    var es = elem.Structure;

                    IElementControl c;
                    if (controlMap.TryGetValue(es, out c))
                    {
                        if (c is IGroupedElementControl)
                        {
                            var gc = c as IGroupedElementControl;
                            gc.Elements.Add(elem.Data);
                        }
                        else
                        {
                            c.Data = elem.Data;
                        }
                    }
                }
            }
            catch
            {
                strWarnOnSave =
                    "The subrecord doesn't appear to conform to the expected structure.\nThe formatted information may be incorrect.";
                Error.SetError(bSave, strWarnOnSave);
                Error.SetIconAlignment(bSave, ErrorIconAlignment.MiddleLeft);
                AcceptButton = bCancel; // remove save as default button when exception occurs
                CancelButton = bCancel;
                UpdateDefaultButton();
            }
            ResumeLayout();
        }
Esempio n. 9
0
 public void AddOptionsElement(OptionsElement element)
 {
     _optionsElements.Add(element);
 }
Esempio n. 10
0
        public NewMediumLevelRecordEditor(Plugin p, Record r, SubRecord sr, SubrecordStructure ss)
        {
            this.InitializeComponent();
            Icon = Resources.tesv_ico;
            SuspendLayout();
            this.sr = sr;
            this.ss = ss;
            this.p  = p;
            this.r  = r;

            // walk each element in standard fashion
            int panelOffset = 0;

            try
            {
                this.fpanel1.ColumnStyles[0] = new ColumnStyle(SizeType.Percent, 100.0f);
                int maxWidth   = this.fpanel1.Width - SystemInformation.VerticalScrollBarWidth - 8;
                int leftOffset = 0; // 8;
                foreach (var elem in ss.elements)
                {
                    Control c = null;
                    if (elem.options != null && elem.options.Length > 1)
                    {
                        c = new OptionsElement();
                    }
                    else if (elem.flags != null && elem.flags.Length > 1)
                    {
                        c = new FlagsElement();
                    }
                    else
                    {
                        switch (elem.type)
                        {
                        case ElementValueType.LString:
                            c = new LStringElement();
                            break;

                        case ElementValueType.FormID:
                            c = new FormIDElement();
                            break;

                        case ElementValueType.Blob:
                            c = new HexElement();
                            break;

                        default:
                            c = new TextElement();
                            break;
                        }
                    }

                    if (c is IElementControl)
                    {
                        var ec = c as IElementControl;
                        ec.formIDLookup = p.GetRecordByID;
                        ec.formIDScan   = p.EnumerateRecords;
                        ec.strIDLookup  = p.LookupFormStrings;
                        ec.Element      = elem;

                        if (elem.repeat > 0)
                        {
                            var ge = new RepeatingElement();
                            c        = ge;
                            c.Left   = leftOffset;
                            c.Width  = maxWidth;
                            c.Top    = panelOffset;
                            c.Anchor = c.Anchor | AnchorStyles.Left | AnchorStyles.Right;

                            ge.InnerControl = ec;
                            ge.Element      = elem;
                            ec = ge;
                        }
                        else if (elem.optional > 0)
                        {
                            var re = new OptionalElement();
                            c        = re;
                            c.Left   = leftOffset;
                            c.Width  = maxWidth;
                            c.Top    = panelOffset;
                            c.Anchor = c.Anchor | AnchorStyles.Left | AnchorStyles.Right;

                            re.InnerControl = ec;
                            re.Element      = elem;
                            ec = re;
                            c  = re;
                        }
                        else
                        {
                            c.Left   = leftOffset;
                            c.Width  = maxWidth;
                            c.Top    = panelOffset;
                            c.Anchor = c.Anchor | AnchorStyles.Left | AnchorStyles.Right;
                        }

                        this.controlMap.Add(elem, ec);
                        int idx = this.fpanel1.RowCount - 1;
                        this.fpanel1.Controls.Add(c, 0, idx);
                        var info = new RowStyle(SizeType.Absolute, c.Size.Height + 2);
                        if (idx == 0)
                        {
                            this.fpanel1.RowStyles[0] = info;
                        }
                        else
                        {
                            this.fpanel1.RowStyles.Add(info);
                        }
                        panelOffset = 0;
                        ++this.fpanel1.RowCount;
                    }
                }

                foreach (Element elem in r.EnumerateElements(sr, true))
                {
                    var es = elem.Structure;

                    IElementControl c;
                    if (this.controlMap.TryGetValue(es, out c))
                    {
                        if (c is IGroupedElementControl)
                        {
                            var gc = c as IGroupedElementControl;
                            gc.Elements.Add(elem.Data);
                        }
                        else
                        {
                            c.Data = elem.Data;
                        }
                    }
                }
            }
            catch
            {
                this.strWarnOnSave = "The subrecord doesn't appear to conform to the expected structure.\nThe formatted information may be incorrect.";
                this.Error.SetError(this.bSave, this.strWarnOnSave);
                this.Error.SetIconAlignment(this.bSave, ErrorIconAlignment.MiddleLeft);
                AcceptButton = this.bCancel; // remove save as default button when exception occurs
                CancelButton = this.bCancel;
                UpdateDefaultButton();
            }

            ResumeLayout();
        }
Esempio n. 11
0
        public void SetContext(Record r, SubRecord sr, bool hexView)
        {
            if (this.r == r && this.sr == sr && this.hexView == hexView)
            {
                return;
            }

            if (r == null || sr == null)
            {
                this.ClearControl();
                return;
            }

            // walk each element in standard fashion
            int panelOffset = 0;

            try
            {
                this.BeginUpdate();

                this.ClearControl();
                SuspendLayout();
                this.fpanel1.SuspendLayout();
                this.fpanel1.Width = Parent.Width;
                this.controlMap.Clear();

                this.hexView = hexView;
                this.r       = r;
                this.sr      = sr;
                var p = this.GetPluginFromNode(r);
                this.ss = sr.Structure;

                // default to blob if no elements
                if (this.ss == null || this.ss.elements == null || hexView)
                {
                    var c = new HexElement();
                    c.Left   = 8;
                    c.Width  = this.fpanel1.Width - 16;
                    c.Top    = panelOffset;
                    c.Anchor = c.Anchor | AnchorStyles.Left | AnchorStyles.Right;

                    var elem = r.EnumerateElements(sr, true).FirstOrDefault();
                    if (elem != null)
                    {
                        this.controlMap.Add(elem.Structure, c);
                        this.fpanel1.Controls.Add(c);
                        c.Data = elem.Data;
                    }
                }
                else
                {
                    foreach (var elem in this.ss.elements)
                    {
                        Control c = null;
                        if (elem.options != null && elem.options.Length > 1)
                        {
                            c = new OptionsElement();
                        }
                        else if (elem.flags != null && elem.flags.Length > 1)
                        {
                            c = new FlagsElement();
                        }
                        else
                        {
                            switch (elem.type)
                            {
                            case ElementValueType.LString:
                                c = new LStringElement();
                                break;

                            case ElementValueType.FormID:
                                c = new FormIDElement();
                                break;

                            case ElementValueType.Blob:
                                c = new HexElement();
                                break;

                            default:
                                c = new TextElement();
                                break;
                            }
                        }

                        if (c is IElementControl)
                        {
                            var ec = c as IElementControl;
                            ec.formIDLookup = p.GetRecordByID;
                            ec.formIDScan   = p.EnumerateRecords;
                            ec.strIDLookup  = p.LookupFormStrings;
                            ec.Element      = elem;

                            if (elem.repeat > 0)
                            {
                                var ge = new RepeatingElement();
                                c        = ge;
                                c.Left   = 8;
                                c.Width  = this.fpanel1.Width - 16;
                                c.Top    = panelOffset;
                                c.Anchor = c.Anchor | AnchorStyles.Left | AnchorStyles.Right;

                                ge.InnerControl = ec;
                                ge.Element      = elem;
                                ec = ge;
                            }
                            else if (elem.optional > 0)
                            {
                                var re = new OptionalElement();
                                c        = re;
                                c.Left   = 8;
                                c.Width  = this.fpanel1.Width - 16;
                                c.Top    = panelOffset;
                                c.Anchor = c.Anchor | AnchorStyles.Left | AnchorStyles.Right;

                                re.InnerControl = ec;
                                re.Element      = elem;
                                ec = re;
                                c  = re;
                            }
                            else
                            {
                                c.Left   = 8;
                                c.Width  = this.fpanel1.Width - 16;
                                c.Top    = panelOffset;
                                c.Anchor = c.Anchor | AnchorStyles.Left | AnchorStyles.Right;
                            }

                            c.MinimumSize = c.Size;

                            this.controlMap.Add(elem, ec);
                            this.fpanel1.Controls.Add(c);
                            panelOffset = c.Bottom;
                        }
                    }

                    foreach (Element elem in r.EnumerateElements(sr, true))
                    {
                        var es = elem.Structure;

                        IElementControl c;
                        if (this.controlMap.TryGetValue(es, out c))
                        {
                            if (c is IGroupedElementControl)
                            {
                                var gc = c as IGroupedElementControl;
                                gc.Elements.Add(elem.Data);
                            }
                            else
                            {
                                c.Data = elem.Data;
                            }
                        }
                    }
                }

                Enabled = true;
            }
            catch
            {
                this.strWarnOnSave = "The subrecord doesn't appear to conform to the expected structure.\nThe formatted information may be incorrect.";
            }
            finally
            {
                this.fpanel1.ResumeLayout();
                ResumeLayout();
                this.EndUpdate();
                Refresh();
            }
        }