void LoadLayout()

in CreatorsSDK/Social/UWP/Cpp/SampleGUI.cpp [466:1220]


    void LoadLayout(const wchar_t* layoutFile, const wchar_t* imageDir, unsigned offset)
    {
        static const wchar_t* s_seps = L" ,;|";
        static wchar_t s_text[4096] = {};

        DX::CSVReader reader(layoutFile, DX::CSVReader::Encoding::ANSI, true);

        IPanel* currentPanel = nullptr;

        if (imageDir)
            m_layoutImageDir = imageDir;
        else
            m_layoutImageDir.clear();

        while (!reader.EndOfFile())
        {
            // Each record starts with ITEM,ID,RECTX,RECTY,DX,DY
            wchar_t item[1024] = {};
            if (!reader.NextItem(item))
            {
                reader.NextRecord();
                continue;
            }

            TrimTrailingWhitespace(item);

            unsigned id;
            {
                // IPanel object ids need to be globally unique
                wchar_t tmp[16] = {};
                if (!reader.NextItem(tmp))
                {
                    DebugTrace("ERROR: Expected an id for record %zu\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }
                id = _wtoi(tmp);
            }

            RECT rct = { 0, 0, 0, 0 };
            {
                wchar_t tmp[16] = {};
                if (!reader.NextItem(tmp))
                {
                    DebugTrace("ERROR: Expected an rectx for record %zu\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                rct.left = _wtoi(tmp);

                if (!reader.NextItem(tmp))
                {
                    DebugTrace("ERROR: Expected an recty for record %zu\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                rct.top = _wtoi(tmp);

                if (!reader.NextItem(tmp))
                {
                    DebugTrace("ERROR: Expected an dx for record %zu\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                rct.right = rct.left + _wtoi(tmp);

                if (!reader.NextItem(tmp))
                {
                    DebugTrace("ERROR: Expected an dy for record %zu\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                rct.bottom = rct.top + _wtoi(tmp);
            }

            // Create item
            if (_wcsicmp(item, L"POPUP") == 0)
            {
                id += offset;

                auto it = m_panels.find(id);
                if (it != m_panels.end())
                {
                    DebugTrace("ERROR: Duplicate panel id found [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                currentPanel = new Popup(rct);

                m_panels[id] = currentPanel;
            }
            else if (_wcsicmp(item, L"HUD") == 0)
            {
                id += offset;

                auto it = m_panels.find(id);
                if (it != m_panels.end())
                {
                    DebugTrace("ERROR: Duplicate panel id found [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                currentPanel = new HUD(rct);

                m_panels[id] = currentPanel;

                if (!m_hudPanel)
                {
                    currentPanel->Show();
                }
            }
            else if (_wcsicmp(item, L"OVERLAY") == 0)
            {
                id += offset;

                auto it = m_panels.find(id);
                if (it != m_panels.end())
                {
                    DebugTrace("ERROR: Duplicate panel id found [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                currentPanel = new Overlay(rct);

                m_panels[id] = currentPanel;
            }
            else if (_wcsicmp(item, L"LABEL") == 0)
            {
                if (!currentPanel)
                {
                    DebugTrace("ERROR: LABEL found outside of panel [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                if (!reader.NextItem(s_text))
                {
                    DebugTrace("ERROR: LABEL missing text string [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                HandleEscapeCharacters(s_text);

                unsigned style = 0;
                XMVECTOR color = Colors::White;
                {
                    wchar_t styleStr[128] = {};
                    if (reader.NextItem(styleStr))
                    {
                        _wcsupr_s(styleStr);

                        wchar_t* context = nullptr;
                        const wchar_t* tok = wcstok_s(styleStr, s_seps, &context);
                        while (tok)
                        {
                            if (wcscmp(tok, L"LEFT") == 0)
                            {
                                style |= TextLabel::c_StyleAlignLeft | TextLabel::c_StyleAlignMiddle;
                            }
                            else if (wcscmp(tok, L"CENTER") == 0)
                            {
                                style |= TextLabel::c_StyleAlignCenter | TextLabel::c_StyleAlignMiddle;
                            }
                            else if (wcscmp(tok, L"RIGHT") == 0)
                            {
                                style |= TextLabel::c_StyleAlignRight | TextLabel::c_StyleAlignMiddle;
                            }
                            else if (wcscmp(tok, L"LARGE") == 0)
                            {
                                style |= TextLabel::c_StyleFontLarge;
                            }
                            else if (wcscmp(tok, L"SMALL") == 0)
                            {
                                style |= TextLabel::c_StyleFontSmall;
                            }
                            else if (wcscmp(tok, L"BOLD") == 0)
                            {
                                style |= TextLabel::c_StyleFontBold;
                            }
                            else if (wcscmp(tok, L"ITALIC") == 0)
                            {
                                style |= TextLabel::c_StyleFontItalic;
                            }
                            else if (wcscmp(tok, L"TRANSPARENT") == 0)
                            {
                                style |= TextLabel::c_StyleTransparent;
                            }
                            else if (wcscmp(tok, L"WORDWRAP") == 0)
                            {
                                style |= TextLabel::c_StyleWordWrap;
                            }

                            tok = wcstok_s(nullptr, s_seps, &context);
                        }

                        wchar_t colorStr[32] = {};
                        if (reader.NextItem(colorStr))
                        {
                            _wcsupr_s(colorStr);
                            color = LoadColorItem(colorStr, reader.RecordIndex());
                        }
                    }
                }

                if (id)
                {
                    // check for duplicates if nonzero ids used
                    if (currentPanel->Find(id))
                    {
                        DebugTrace("ERROR: Duplicate control id found [record %zu]\n", reader.RecordIndex() + 1);
                        throw std::exception("LoadLayout");
                    }
                }

                auto label = new TextLabel(id, s_text, rct, style);
                label->SetForegroundColor(color);
                currentPanel->Add(label);
            }
            else if (_wcsicmp(item, L"LEGEND") == 0)
            {
                if (!currentPanel)
                {
                    DebugTrace("ERROR: LEGEND found outside of panel [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                if (!reader.NextItem(s_text))
                {
                    DebugTrace("ERROR: LEGEND missing text string [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                HandleEscapeCharacters(s_text);

                unsigned style = 0;
                XMVECTOR color = Colors::White;
                {
                    wchar_t styleStr[128] = {};
                    if (reader.NextItem(styleStr))
                    {
                        _wcsupr_s(styleStr);

                        wchar_t* context = nullptr;
                        const wchar_t* tok = wcstok_s(styleStr, s_seps, &context);
                        while (tok)
                        {
                            if (wcscmp(tok, L"LEFT") == 0)
                            {
                                style |= Legend::c_StyleAlignLeft | Legend::c_StyleAlignMiddle;
                            }
                            else if (wcscmp(tok, L"CENTER") == 0)
                            {
                                style |= Legend::c_StyleAlignCenter | Legend::c_StyleAlignMiddle;
                            }
                            else if (wcscmp(tok, L"RIGHT") == 0)
                            {
                                style |= Legend::c_StyleAlignRight | Legend::c_StyleAlignMiddle;
                            }
                            else if (wcscmp(tok, L"LARGE") == 0)
                            {
                                style |= Legend::c_StyleFontLarge;
                            }
                            else if (wcscmp(tok, L"SMALL") == 0)
                            {
                                style |= Legend::c_StyleFontSmall;
                            }
                            else if (wcscmp(tok, L"BOLD") == 0)
                            {
                                style |= Legend::c_StyleFontBold;
                            }
                            else if (wcscmp(tok, L"ITALIC") == 0)
                            {
                                style |= Legend::c_StyleFontItalic;
                            }
                            else if (wcscmp(tok, L"TRANSPARENT") == 0)
                            {
                                style |= Legend::c_StyleTransparent;
                            }

                            tok = wcstok_s(nullptr, s_seps, &context);
                        }

                        wchar_t colorStr[32] = {};
                        if (reader.NextItem(colorStr))
                        {
                            _wcsupr_s(colorStr);
                            color = LoadColorItem(colorStr, reader.RecordIndex());
                        }
                    }
                }

                if (id)
                {
                    // check for duplicates if nonzero ids used
                    if (currentPanel->Find(id))
                    {
                        DebugTrace("ERROR: Duplicate control id found [record %zu]\n", reader.RecordIndex() + 1);
                        throw std::exception("LoadLayout");
                    }
                }

                auto legend = new Legend(id, s_text, rct, style);
                legend->SetForegroundColor(color);
                currentPanel->Add(legend);
            }
            else if (_wcsicmp(item, L"IMAGE") == 0)
            {
                if (!currentPanel)
                {
                    DebugTrace("ERROR: IMAGE found outside of panel [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                unsigned imageId = 0;
                wchar_t imageFile[MAX_PATH] = {};
                if (reader.NextItem(imageFile))
                {
                    TrimTrailingWhitespace(imageFile);
                    imageId = LoadImageItem(imageFile);
                }
                else
                {
                    DebugTrace("ERROR: IMAGE missing image file name [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                if (id)
                {
                    // check for duplicates if nonzero ids used
                    if (currentPanel->Find(id))
                    {
                        DebugTrace("ERROR: Duplicate control id found [record %zu]\n", reader.RecordIndex() + 1);
                        throw std::exception("LoadLayout");
                    }
                }

                currentPanel->Add(new Image(id, imageId, rct));
            }
            else if (_wcsicmp(item, L"BUTTON") == 0 || _wcsicmp(item, L"EXITBUTTON") == 0 || _wcsicmp(item, L"DEFBUTTON") == 0)
            {
                if (!currentPanel)
                {
                    DebugTrace("ERROR: BUTTON found outside of panel [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                if (!reader.NextItem(s_text))
                {
                    DebugTrace("ERROR: BUTTON missing text string [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                unsigned hotkey = 0;
                wchar_t hotkeyStr[64] = {};
                unsigned style = 0;
                if (reader.NextItem(hotkeyStr))
                {
                    TrimTrailingWhitespace(hotkeyStr);

                    hotkey = HandleVirtualKeys(hotkeyStr);

                    // Optional style
                    wchar_t styleStr[128] = {};
                    if (reader.NextItem(styleStr))
                    {
                        _wcsupr_s(styleStr);

                        wchar_t* context = nullptr;
                        const wchar_t* tok = wcstok_s(styleStr, s_seps, &context);
                        while (tok)
                        {
                            if (wcscmp(tok, L"LARGE") == 0)
                            {
                                style |= Button::c_StyleFontLarge;
                            }
                            else if (wcscmp(tok, L"SMALL") == 0)
                            {
                                style |= Button::c_StyleFontSmall;
                            }
                            else if (wcscmp(tok, L"BOLD") == 0)
                            {
                                style |= Button::c_StyleFontBold;
                            }
                            else if (wcscmp(tok, L"ITALIC") == 0)
                            {
                                style |= Button::c_StyleFontItalic;
                            }
                            else if (wcscmp(tok, L"TRANSPARENT") == 0)
                            {
                                style |= Button::c_StyleTransparent;
                            }

                            tok = wcstok_s(nullptr, s_seps, &context);
                        }
                    }
                }

                if (_wcsicmp(item, L"EXITBUTTON") == 0)
                {
                    style |= Button::c_StyleExit;
                }
                else if (_wcsicmp(item, L"DEFBUTTON") == 0)
                {
                    style |= Button::c_StyleExit | Button::c_StyleDefault;
                }

                // check for duplicate id
                if (currentPanel->Find(id))
                {
                    DebugTrace("ERROR: Duplicate control found [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                auto *butn = new Button(id, s_text, rct);
                butn->SetStyle(style);
                butn->SetHotKey(hotkey);
                currentPanel->Add(butn);
            }
            else if (_wcsicmp(item, L"IMAGEBUTTON") == 0 || _wcsicmp(item, L"EXITIMAGEBUTTON") == 0 || _wcsicmp(item, L"DEFIMAGEBUTTON") == 0)
            {
                if (!currentPanel)
                {
                    DebugTrace("ERROR: IMAGEBUTTON found outside of panel [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                unsigned imageId = 0;
                wchar_t imageFile[MAX_PATH] = {};
                if (reader.NextItem(imageFile))
                {
                    TrimTrailingWhitespace(imageFile);
                    imageId = LoadImageItem(imageFile);
                }
                else
                {
                    DebugTrace("ERROR: IMAGEBUTTON missing image file name [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                unsigned hotkey = 0;
                wchar_t hotkeyStr[64] = {};
                unsigned style = 0;
                if (reader.NextItem(hotkeyStr))
                {
                    TrimTrailingWhitespace(hotkeyStr);

                    hotkey = HandleVirtualKeys(hotkeyStr);

                    // Optional style
                    wchar_t styleStr[128] = {};
                    if (reader.NextItem(styleStr))
                    {
                        _wcsupr_s(styleStr);

                        wchar_t* context = nullptr;
                        const wchar_t* tok = wcstok_s(styleStr, s_seps, &context);
                        while (tok)
                        {
                            if (wcscmp(tok, L"BACKGROUND") == 0)
                            {
                                style |= ImageButton::c_StyleBackground;
                            }
                            else if (wcscmp(tok, L"TRANSPARENT") == 0)
                            {
                                style |= ImageButton::c_StyleTransparent | ImageButton::c_StyleBackground;
                            }

                            tok = wcstok_s(nullptr, s_seps, &context);
                        }
                    }
                }

                if (_wcsicmp(item, L"EXITIMAGEBUTTON") == 0)
                {
                    style |= ImageButton::c_StyleExit;
                }
                else if (_wcsicmp(item, L"DEFIMAGEBUTTON") == 0)
                {
                    style |= ImageButton::c_StyleExit | ImageButton::c_StyleDefault;
                }

                // check for duplicate id
                if (currentPanel->Find(id))
                {
                    DebugTrace("ERROR: Duplicate control found [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                auto *butn = new ImageButton(id, imageId, rct);
                butn->SetStyle(style);
                butn->SetHotKey(hotkey);
                currentPanel->Add(butn);
            }
            else if (_wcsicmp(item, L"CHECKBOX") == 0)
            {
                if (!currentPanel)
                {
                    DebugTrace("ERROR: CHECKBOX found outside of panel [record %zu]", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                if (!reader.NextItem(s_text))
                {
                    DebugTrace("ERROR: CHECKBOX missing text string [record %zu]", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                unsigned style = 0;
                bool checked = false;
                {
                    wchar_t styleStr[128] = {};
                    if (reader.NextItem(styleStr))
                    {
                        _wcsupr_s(styleStr);

                        wchar_t* context = nullptr;
                        const wchar_t* tok = wcstok_s(styleStr, s_seps, &context);
                        while (tok)
                        {
                            if (wcscmp(tok, L"LARGE") == 0)
                            {
                                style |= CheckBox::c_StyleFontLarge;
                            }
                            else if (wcscmp(tok, L"SMALL") == 0)
                            {
                                style |= CheckBox::c_StyleFontSmall;
                            }
                            else if (wcscmp(tok, L"BOLD") == 0)
                            {
                                style |= CheckBox::c_StyleFontBold;
                            }
                            else if (wcscmp(tok, L"ITALIC") == 0)
                            {
                                style |= CheckBox::c_StyleFontItalic;
                            }
                            else if (wcscmp(tok, L"CHECKED") == 0)
                            {
                                checked = true;
                            }
                            else if (wcscmp(tok, L"TRANSPARENT") == 0)
                            {
                                style |= CheckBox::c_StyleTransparent;
                            }

                            tok = wcstok_s(nullptr, s_seps, &context);
                        }
                    }
                }

                // check for duplicate id
                if (currentPanel->Find(id))
                {
                    DebugTrace("ERROR: Duplicate control id found [record %zu]", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                auto *box = new CheckBox(id, s_text, rct, checked);
                box->SetStyle(style);
                currentPanel->Add(box);
            }
            else if (_wcsicmp(item, L"SLIDER") == 0)
            {
                if (!currentPanel)
                {
                    DebugTrace("ERROR: SLIDER found outside of panel [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                // check for duplicate id
                if (currentPanel->Find(id))
                {
                    DebugTrace("ERROR: Duplicate control id found [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                unsigned style = 0;
                {
                    wchar_t styleStr[128] = {};
                    if (reader.NextItem(styleStr))
                    {
                        _wcsupr_s(styleStr);

                        wchar_t* context = nullptr;
                        const wchar_t* tok = wcstok_s(styleStr, s_seps, &context);
                        while (tok)
                        {
                            if (wcscmp(tok, L"TRANSPARENT") == 0)
                            {
                                style |= Slider::c_StyleTransparent;
                            }

                            tok = wcstok_s(nullptr, s_seps, &context);
                        }
                    }
                }

                auto slider = new Slider(id, rct);
                slider->SetStyle(style);
                currentPanel->Add(slider);
            }
            else if (_wcsicmp(item, L"PROGRESSBAR") == 0)
            {
                if (!currentPanel)
                {
                    DebugTrace("ERROR: PROGRESSBAR found outside of panel [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                // check for duplicate id
                if (currentPanel->Find(id))
                {
                    DebugTrace("ERROR: Duplicate control id found [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                currentPanel->Add(new ProgressBar(id, rct));
            }
            else if (_wcsicmp(item, L"LISTBOX") == 0)
            {
                if (!currentPanel)
                {
                    DebugTrace("ERROR: LISTBOX found outside of panel [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                // check for duplicate id
                if (currentPanel->Find(id))
                {
                    DebugTrace("ERROR: Duplicate control id found [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                int itemHeight = 0;
                wchar_t itemHeightStr[64] = {};
                unsigned style = 0;
                if (reader.NextItem(itemHeightStr))
                {
                    itemHeight = _wtoi(itemHeightStr);

                    wchar_t styleStr[128] = {};
                    if (reader.NextItem(styleStr))
                    {
                        _wcsupr_s(styleStr);

                        wchar_t* context = nullptr;
                        const wchar_t* tok = wcstok_s(styleStr, s_seps, &context);
                        while (tok)
                        {
                            if (wcscmp(tok, L"MULTISELECT") == 0)
                            {
                                style |= ListBox::c_StyleMultiSelection;
                            }
                            else if (wcscmp(tok, L"LARGE") == 0)
                            {
                                style |= ListBox::c_StyleFontLarge;
                            }
                            else if (wcscmp(tok, L"SMALL") == 0)
                            {
                                style |= ListBox::c_StyleFontSmall;
                            }
                            else if (wcscmp(tok, L"BOLD") == 0)
                            {
                                style |= ListBox::c_StyleFontBold;
                            }
                            else if (wcscmp(tok, L"ITALIC") == 0)
                            {
                                style |= ListBox::c_StyleFontItalic;
                            }
                            else if (wcscmp(tok, L"TRANSPARENT") == 0)
                            {
                                style |= ListBox::c_StyleTransparent;
                            }
                            else if (wcscmp(tok, L"SCROLLBAR") == 0)
                            {
                                style |= ListBox::c_StyleScrollBar;
                            }

                            tok = wcstok_s(nullptr, s_seps, &context);
                        }
                    }
                }

                currentPanel->Add(new ListBox(id, rct, style, itemHeight));
            }
            else if (_wcsicmp(item, L"TEXTBOX") == 0)
            {
                if (!currentPanel)
                {
                    DebugTrace("ERROR: TEXTBOX found outside of panel [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                if (id)
                {
                    // check for duplicates if nonzero ids used
                    if (currentPanel->Find(id))
                    {
                        DebugTrace("ERROR: Duplicate control id found [record %zu]\n", reader.RecordIndex() + 1);
                        throw std::exception("LoadLayout");
                    }
                }

                if (!reader.NextItem(s_text))
                {
                    DebugTrace("ERROR: TEXTBOX missing text string [record %zu]\n", reader.RecordIndex() + 1);
                    throw std::exception("LoadLayout");
                }

                HandleEscapeCharacters(s_text);

                unsigned style = 0;
                {
                    wchar_t styleStr[128] = {};
                    if (reader.NextItem(styleStr))
                    {
                        _wcsupr_s(styleStr);

                        wchar_t* context = nullptr;
                        const wchar_t* tok = wcstok_s(styleStr, s_seps, &context);
                        while (tok)
                        {
                            if (wcscmp(tok, L"LARGE") == 0)
                            {
                                style |= TextBox::c_StyleFontLarge;
                            }
                            else if (wcscmp(tok, L"SMALL") == 0)
                            {
                                style |= TextBox::c_StyleFontSmall;
                            }
                            else if (wcscmp(tok, L"BOLD") == 0)
                            {
                                style |= TextBox::c_StyleFontBold;
                            }
                            else if (wcscmp(tok, L"ITALIC") == 0)
                            {
                                style |= TextBox::c_StyleFontItalic;
                            }
                            else if (wcscmp(tok, L"TRANSPARENT") == 0)
                            {
                                style |= TextBox::c_StyleTransparent;
                            }
                            else if (wcscmp(tok, L"SCROLLBAR") == 0)
                            {
                                style |= TextBox::c_StyleScrollBar;
                            }

                            tok = wcstok_s(nullptr, s_seps, &context);
                        }
                    }
                }

                currentPanel->Add(new TextBox(id, s_text, rct, style));
            }

            reader.NextRecord();
        }
    }