From a33fd55e81c86c9e0a2f2fdcf793fd615b8ce25d Mon Sep 17 00:00:00 2001 From: elexis Date: Fri, 27 Sep 2019 12:49:59 +0000 Subject: [PATCH] Change GUI Object Setting values to be members of the IGUIObject inheriting class, rename AddSetting to RegisterSetting. Improves performance for Draw calls by 3-5% according to a shady benchmark. Improves memory layout, since the values are not on the heap anymore but in the using class. Reduces complexity of the implementation and increases type safety. Allows specifying default values at setting value construction time, refs D2242. Inspired by Vladislav introducing members that cached GetSetting values in c016a74309/D325, refs #4039, ee38f0db37/D763, refs 4225, a1c4c23ce4/D474, D406, which were formerly proposed to be removed in D2241. Differential Revision: https://code.wildfiregames.com/D2313 Tested on: clang 8.0.1, gcc 9.1.0, Jenkins vs2015 Comments By: Vladislav This was SVN commit r23005. --- source/gui/CButton.cpp | 86 +++--- source/gui/CButton.h | 18 ++ source/gui/CChart.cpp | 67 ++--- source/gui/CChart.h | 17 +- source/gui/CCheckBox.cpp | 62 ++-- source/gui/CCheckBox.h | 14 + source/gui/CDropDown.cpp | 190 ++++++------- source/gui/CDropDown.h | 18 ++ source/gui/CGUI.cpp | 4 +- source/gui/CGUISetting.cpp | 5 +- source/gui/CGUISetting.h | 7 +- source/gui/CImage.cpp | 14 +- source/gui/CImage.h | 5 + source/gui/CInput.cpp | 457 ++++++++++++++---------------- source/gui/CInput.h | 22 +- source/gui/CList.cpp | 185 ++++++------ source/gui/CList.h | 23 +- source/gui/COList.cpp | 174 ++++++------ source/gui/COList.h | 19 +- source/gui/CProgressBar.cpp | 28 +- source/gui/CProgressBar.h | 6 + source/gui/CSlider.cpp | 42 ++- source/gui/CSlider.h | 13 +- source/gui/CText.cpp | 100 +++---- source/gui/CText.h | 20 ++ source/gui/CTooltip.cpp | 80 +++--- source/gui/CTooltip.h | 20 +- source/gui/IGUIButtonBehavior.cpp | 57 ++-- source/gui/IGUIButtonBehavior.h | 9 +- source/gui/IGUIObject.cpp | 107 ++++--- source/gui/IGUIObject.h | 27 +- 31 files changed, 1019 insertions(+), 877 deletions(-) diff --git a/source/gui/CButton.cpp b/source/gui/CButton.cpp index af68f05f19..551fed34b5 100644 --- a/source/gui/CButton.cpp +++ b/source/gui/CButton.cpp @@ -23,22 +23,38 @@ #include "gui/CGUIText.h" CButton::CButton(CGUI& pGUI) - : IGUIObject(pGUI), IGUIButtonBehavior(pGUI), IGUITextOwner(pGUI) + : IGUIObject(pGUI), + IGUIButtonBehavior(pGUI), + IGUITextOwner(pGUI), + m_BufferZone(), + m_CellID(), + m_Caption(), + m_Font(), + m_Sprite(), + m_SpriteOver(), + m_SpritePressed(), + m_SpriteDisabled(), + m_TextAlign(), + m_TextVAlign(), + m_TextColor(), + m_TextColorOver(), + m_TextColorPressed(), + m_TextColorDisabled() { - AddSetting("buffer_zone"); - AddSetting("caption"); - AddSetting("cell_id"); - AddSetting("font"); - AddSetting("sprite"); - AddSetting("sprite_over"); - AddSetting("sprite_pressed"); - AddSetting("sprite_disabled"); - AddSetting("text_align"); - AddSetting("text_valign"); - AddSetting("textcolor"); - AddSetting("textcolor_over"); - AddSetting("textcolor_pressed"); - AddSetting("textcolor_disabled"); + RegisterSetting("buffer_zone", m_BufferZone); + RegisterSetting("cell_id", m_CellID); + RegisterSetting("caption", m_Caption); + RegisterSetting("font", m_Font); + RegisterSetting("sprite", m_Sprite); + RegisterSetting("sprite_over", m_SpriteOver); + RegisterSetting("sprite_pressed", m_SpritePressed); + RegisterSetting("sprite_disabled", m_SpriteDisabled); + RegisterSetting("text_align", m_TextAlign); + RegisterSetting("text_valign", m_TextVAlign); + RegisterSetting("textcolor", m_TextColor); + RegisterSetting("textcolor_over", m_TextColorOver); + RegisterSetting("textcolor_pressed", m_TextColorPressed); + RegisterSetting("textcolor_disabled", m_TextColorDisabled); AddText(); } @@ -51,14 +67,7 @@ void CButton::SetupText() { ENSURE(m_GeneratedTexts.size() == 1); - m_GeneratedTexts[0] = CGUIText( - m_pGUI, - GetSetting("caption"), - GetSetting("font"), - m_CachedActualSize.GetWidth(), - GetSetting("buffer_zone"), - this); - + m_GeneratedTexts[0] = CGUIText(m_pGUI, m_Caption, m_Font, m_CachedActualSize.GetWidth(), m_BufferZone, this); CalculateTextPosition(m_CachedActualSize, m_TextPos, m_GeneratedTexts[0]); } @@ -72,39 +81,20 @@ void CButton::HandleMessage(SGUIMessage& Message) void CButton::Draw() { const float bz = GetBufferedZ(); - - // Statically initialise some strings, so we don't have to do - // lots of allocation every time this function is called - static const CStr strSprite("sprite"); - static const CStr strSpriteOver("sprite_over"); - static const CStr strSpritePressed("sprite_pressed"); - static const CStr strSpriteDisabled("sprite_disabled"); - static const CStr strCellId("cell_id"); - - CGUISpriteInstance& sprite = GetSetting(strSprite); - CGUISpriteInstance& sprite_over = GetSetting(strSpriteOver); - CGUISpriteInstance& sprite_pressed = GetSetting(strSpritePressed); - CGUISpriteInstance& sprite_disabled = GetSetting(strSpriteDisabled); - - const i32 cell_id = GetSetting(strCellId); - - DrawButton(m_CachedActualSize, bz, sprite, sprite_over, sprite_pressed, sprite_disabled, cell_id); - + DrawButton(m_CachedActualSize, bz, m_Sprite, m_SpriteOver, m_SpritePressed, m_SpriteDisabled, m_CellID); DrawText(0, ChooseColor(), m_TextPos, bz + 0.1f); } const CGUIColor& CButton::ChooseColor() { - const CGUIColor& color = GetSetting("textcolor"); - - if (!GetSetting("enabled")) - return GetSetting("textcolor_disabled") || color; + if (!m_Enabled) + return m_TextColorDisabled || m_TextColor; if (!m_MouseHovering) - return color; + return m_TextColor; if (m_Pressed) - return GetSetting("textcolor_pressed") || color; + return m_TextColorPressed || m_TextColor; - return GetSetting("textcolor_over") || color; + return m_TextColorOver || m_TextColor; } diff --git a/source/gui/CButton.h b/source/gui/CButton.h index 80d6e8a5c4..7b485badf3 100644 --- a/source/gui/CButton.h +++ b/source/gui/CButton.h @@ -21,6 +21,8 @@ #include "gui/IGUIButtonBehavior.h" #include "gui/IGUIObject.h" #include "gui/IGUITextOwner.h" +#include "gui/CGUISprite.h" +#include "gui/CGUIString.h" class CButton : public IGUIButtonBehavior, public IGUITextOwner { @@ -61,6 +63,22 @@ protected: * Placement of text. */ CPos m_TextPos; + + // Settings + float m_BufferZone; + i32 m_CellID; + CGUIString m_Caption; + CStrW m_Font; + CGUISpriteInstance m_Sprite; + CGUISpriteInstance m_SpriteOver; + CGUISpriteInstance m_SpritePressed; + CGUISpriteInstance m_SpriteDisabled; + EAlign m_TextAlign; + EVAlign m_TextVAlign; + CGUIColor m_TextColor; + CGUIColor m_TextColorOver; + CGUIColor m_TextColorPressed; + CGUIColor m_TextColorDisabled; }; #endif // INCLUDED_CBUTTON diff --git a/source/gui/CChart.cpp b/source/gui/CChart.cpp index 42742f2700..1d6b91a08d 100644 --- a/source/gui/CChart.cpp +++ b/source/gui/CChart.cpp @@ -31,21 +31,27 @@ #include CChart::CChart(CGUI& pGUI) - : IGUIObject(pGUI), IGUITextOwner(pGUI) + : IGUIObject(pGUI), + IGUITextOwner(pGUI), + m_AxisColor(), + m_AxisWidth(), + m_BufferZone(), + m_Font(), + m_FormatX(), + m_FormatY(), + m_SeriesColor(), + m_SeriesSetting(), + m_TextAlign() { - AddSetting("axis_color"); - AddSetting("axis_width"); - AddSetting("buffer_zone"); - AddSetting("font"); - AddSetting("format_x"); - AddSetting("format_y"); - AddSetting("series_color"); - AddSetting("series"); - AddSetting("text_align"); - - m_AxisWidth = GetSetting("axis_width"); - m_FormatX = GetSetting("format_x"); - m_FormatY = GetSetting("format_y"); + RegisterSetting("axis_color", m_AxisColor); + RegisterSetting("axis_width", m_AxisWidth); + RegisterSetting("buffer_zone", m_BufferZone); + RegisterSetting("font", m_Font); + RegisterSetting("format_x", m_FormatX); + RegisterSetting("format_y", m_FormatY); + RegisterSetting("series_color", m_SeriesColor); + RegisterSetting("series", m_SeriesSetting); + RegisterSetting("text_align", m_TextAlign); } CChart::~CChart() @@ -59,10 +65,6 @@ void CChart::HandleMessage(SGUIMessage& Message) { case GUIM_SETTINGS_UPDATED: { - m_AxisWidth = GetSetting("axis_width"); - m_FormatX = GetSetting("format_x"); - m_FormatY = GetSetting("format_y"); - UpdateSeries(); break; } @@ -107,7 +109,7 @@ void CChart::DrawAxes(const CShaderProgramPtr& shader) const ADD(m_CachedActualSize.left, m_CachedActualSize.top); ADD(rect.left, rect.top - m_AxisWidth); #undef ADD - DrawTriangleStrip(shader, GetSetting("axis_color"), vertices); + DrawTriangleStrip(shader, m_AxisColor, vertices); } void CChart::Draw() @@ -181,19 +183,17 @@ CRect CChart::GetChartRect() const void CChart::UpdateSeries() { - const CGUISeries& pSeries = GetSetting("series"); - const CGUIList& pSeriesColor = GetSetting("series_color"); - m_Series.clear(); - m_Series.resize(pSeries.m_Series.size()); - for (size_t i = 0; i < pSeries.m_Series.size(); ++i) + m_Series.resize(m_SeriesSetting.m_Series.size()); + + for (size_t i = 0; i < m_SeriesSetting.m_Series.size(); ++i) { CChartData& data = m_Series[i]; - if (i < pSeriesColor.m_Items.size() && !data.m_Color.ParseString(m_pGUI, pSeriesColor.m_Items[i].GetOriginalString().ToUTF8(), 0)) - LOGWARNING("GUI: Error parsing 'series_color' (\"%s\")", utf8_from_wstring(pSeriesColor.m_Items[i].GetOriginalString())); + if (i < m_SeriesColor.m_Items.size() && !data.m_Color.ParseString(m_pGUI, m_SeriesColor.m_Items[i].GetOriginalString().ToUTF8(), 0)) + LOGWARNING("GUI: Error parsing 'series_color' (\"%s\")", utf8_from_wstring(m_SeriesColor.m_Items[i].GetOriginalString())); - data.m_Points = pSeries.m_Series[i]; + data.m_Points = m_SeriesSetting.m_Series[i]; } UpdateBounds(); @@ -208,38 +208,33 @@ void CChart::SetupText() if (m_Series.empty()) return; - const CStrW& font = GetSetting("font"); - const float buffer_zone = GetSetting("buffer_zone"); - // Add Y-axis - m_FormatY = GetSetting("format_y"); const float height = GetChartRect().GetHeight(); // TODO: split values depend on the format; if (m_EqualY) { // We don't need to generate many items for equal values - AddFormattedValue(m_FormatY, m_RightTop.Y, font, buffer_zone); + AddFormattedValue(m_FormatY, m_RightTop.Y, m_Font, m_BufferZone); m_TextPositions.emplace_back(GetChartRect().TopLeft()); } else for (int i = 0; i < 3; ++i) { - AddFormattedValue(m_FormatY, m_RightTop.Y - (m_RightTop.Y - m_LeftBottom.Y) / 3.f * i, font, buffer_zone); + AddFormattedValue(m_FormatY, m_RightTop.Y - (m_RightTop.Y - m_LeftBottom.Y) / 3.f * i, m_Font, m_BufferZone); m_TextPositions.emplace_back(GetChartRect().TopLeft() + CPos(0.f, height / 3.f * i)); } // Add X-axis - m_FormatX = GetSetting("format_x"); const float width = GetChartRect().GetWidth(); if (m_EqualX) { - CSize text_size = AddFormattedValue(m_FormatX, m_RightTop.X, font, buffer_zone); + CSize text_size = AddFormattedValue(m_FormatX, m_RightTop.X, m_Font, m_BufferZone); m_TextPositions.emplace_back(GetChartRect().BottomRight() - text_size); } else for (int i = 0; i < 3; ++i) { - CSize text_size = AddFormattedValue(m_FormatX, m_RightTop.X - (m_RightTop.X - m_LeftBottom.X) / 3 * i, font, buffer_zone); + CSize text_size = AddFormattedValue(m_FormatX, m_RightTop.X - (m_RightTop.X - m_LeftBottom.X) / 3 * i, m_Font, m_BufferZone); m_TextPositions.emplace_back(GetChartRect().BottomRight() - text_size - CPos(width / 3 * i, 0.f)); } } diff --git a/source/gui/CChart.h b/source/gui/CChart.h index 8ec20861aa..da87ed49c6 100644 --- a/source/gui/CChart.h +++ b/source/gui/CChart.h @@ -20,6 +20,8 @@ #include "graphics/ShaderProgramPtr.h" #include "gui/CGUIColor.h" +#include "gui/CGUIList.h" +#include "gui/CGUISeries.h" #include "gui/IGUITextOwner.h" #include "maths/Vector2D.h" @@ -68,14 +70,21 @@ protected: CVector2D m_LeftBottom, m_RightTop; - CStrW m_FormatX, m_FormatY; - std::vector m_TextPositions; - float m_AxisWidth; - bool m_EqualX, m_EqualY; + // Settings + CGUIColor m_AxisColor; + float m_AxisWidth; + float m_BufferZone; + CStrW m_Font; + CStrW m_FormatX; + CStrW m_FormatY; + CGUIList m_SeriesColor; + CGUISeries m_SeriesSetting; + EAlign m_TextAlign; + private: /** * Helper functions diff --git a/source/gui/CCheckBox.cpp b/source/gui/CCheckBox.cpp index 1970a304fa..55c43b5415 100644 --- a/source/gui/CCheckBox.cpp +++ b/source/gui/CCheckBox.cpp @@ -20,18 +20,29 @@ #include "CCheckBox.h" CCheckBox::CCheckBox(CGUI& pGUI) - : IGUIObject(pGUI), IGUIButtonBehavior(pGUI) + : IGUIObject(pGUI), + IGUIButtonBehavior(pGUI), + m_CellID(), + m_Checked(), + m_SpriteUnchecked(), + m_SpriteUncheckedOver(), + m_SpriteUncheckedPressed(), + m_SpriteUncheckedDisabled(), + m_SpriteChecked(), + m_SpriteCheckedOver(), + m_SpriteCheckedPressed(), + m_SpriteCheckedDisabled() { - AddSetting("cell_id"); - AddSetting("checked"); - AddSetting("sprite"); - AddSetting("sprite_over"); - AddSetting("sprite_pressed"); - AddSetting("sprite_disabled"); - AddSetting("sprite2"); - AddSetting("sprite2_over"); - AddSetting("sprite2_pressed"); - AddSetting("sprite2_disabled"); + RegisterSetting("cell_id", m_CellID); + RegisterSetting("checked", m_Checked), + RegisterSetting("sprite", m_SpriteUnchecked); + RegisterSetting("sprite_over", m_SpriteUncheckedOver); + RegisterSetting("sprite_pressed", m_SpriteUncheckedPressed); + RegisterSetting("sprite_disabled", m_SpriteUncheckedDisabled); + RegisterSetting("sprite2", m_SpriteChecked); + RegisterSetting("sprite2_over", m_SpriteCheckedOver); + RegisterSetting("sprite2_pressed", m_SpriteCheckedPressed); + RegisterSetting("sprite2_disabled", m_SpriteCheckedDisabled); } CCheckBox::~CCheckBox() @@ -48,7 +59,7 @@ void CCheckBox::HandleMessage(SGUIMessage& Message) case GUIM_PRESSED: { // Switch to opposite. - SetSetting("checked", !GetSetting("checked"), true); + SetSetting("checked", !m_Checked, true); break; } @@ -59,22 +70,21 @@ void CCheckBox::HandleMessage(SGUIMessage& Message) void CCheckBox::Draw() { - if (GetSetting("checked")) + if (m_Checked) DrawButton( m_CachedActualSize, GetBufferedZ(), - GetSetting("sprite2"), - GetSetting("sprite2_over"), - GetSetting("sprite2_pressed"), - GetSetting("sprite2_disabled"), - GetSetting("cell_id")); + m_SpriteChecked, + m_SpriteCheckedOver, + m_SpriteCheckedPressed, + m_SpriteCheckedDisabled, + m_CellID); else - DrawButton( - m_CachedActualSize, - GetBufferedZ(), - GetSetting("sprite"), - GetSetting("sprite_over"), - GetSetting("sprite_pressed"), - GetSetting("sprite_disabled"), - GetSetting("cell_id")); + DrawButton(m_CachedActualSize, + GetBufferedZ(), + m_SpriteUnchecked, + m_SpriteUncheckedOver, + m_SpriteUncheckedPressed, + m_SpriteUncheckedDisabled, + m_CellID); } diff --git a/source/gui/CCheckBox.h b/source/gui/CCheckBox.h index c4961adc9f..83bb5028d5 100644 --- a/source/gui/CCheckBox.h +++ b/source/gui/CCheckBox.h @@ -18,6 +18,7 @@ #ifndef INCLUDED_CCHECKBOX #define INCLUDED_CCHECKBOX +#include "gui/CGUISprite.h" #include "gui/IGUIButtonBehavior.h" class CCheckBox : public IGUIButtonBehavior @@ -42,6 +43,19 @@ public: * Draws the control */ virtual void Draw(); + +protected: + // Settings + i32 m_CellID; + bool m_Checked; + CGUISpriteInstance m_SpriteUnchecked; + CGUISpriteInstance m_SpriteUncheckedOver; + CGUISpriteInstance m_SpriteUncheckedPressed; + CGUISpriteInstance m_SpriteUncheckedDisabled; + CGUISpriteInstance m_SpriteChecked; + CGUISpriteInstance m_SpriteCheckedOver; + CGUISpriteInstance m_SpriteCheckedPressed; + CGUISpriteInstance m_SpriteCheckedDisabled; }; #endif // INCLUDED_CCHECKBOX diff --git a/source/gui/CDropDown.cpp b/source/gui/CDropDown.cpp index 7ec3513db1..4463574fd9 100644 --- a/source/gui/CDropDown.cpp +++ b/source/gui/CDropDown.cpp @@ -28,30 +28,48 @@ #include "ps/Profile.h" CDropDown::CDropDown(CGUI& pGUI) - : CList(pGUI), IGUIObject(pGUI), - m_Open(false), m_HideScrollBar(false), m_ElementHighlight(-1) + : CList(pGUI), + IGUIObject(pGUI), + m_Open(), + m_HideScrollBar(), + m_ElementHighlight(-1), + m_ButtonWidth(), + m_DropDownSize(), + m_DropDownBuffer(), + m_MinimumVisibleItems(), + m_SoundClosed(), + m_SoundEnter(), + m_SoundLeave(), + m_SoundOpened(), + m_SpriteDisabled(), + m_SpriteList(), + m_Sprite2(), + m_Sprite2Over(), + m_Sprite2Pressed(), + m_Sprite2Disabled(), + m_TextColorDisabled(), + m_TextVAlign() { - AddSetting("button_width"); - AddSetting("dropdown_size"); - AddSetting("dropdown_buffer"); - AddSetting("minimum_visible_items"); - AddSetting("sound_closed"); - AddSetting("sound_enter"); - AddSetting("sound_leave"); - AddSetting("sound_opened"); + RegisterSetting("button_width", m_ButtonWidth); + RegisterSetting("dropdown_size", m_DropDownSize); + RegisterSetting("dropdown_buffer", m_DropDownBuffer); + RegisterSetting("minimum_visible_items", m_MinimumVisibleItems); + RegisterSetting("sound_closed", m_SoundClosed); + RegisterSetting("sound_enter", m_SoundEnter); + RegisterSetting("sound_leave", m_SoundLeave); + RegisterSetting("sound_opened", m_SoundOpened); // Setting "sprite" is registered by CList and used as the background - AddSetting("sprite_disabled"); - AddSetting("sprite_list"); // Background of the drop down list - AddSetting("sprite2"); // Button that sits to the right - AddSetting("sprite2_over"); - AddSetting("sprite2_pressed"); - AddSetting("sprite2_disabled"); - AddSetting("text_valign"); - + RegisterSetting("sprite_disabled", m_SpriteDisabled); + RegisterSetting("sprite_list", m_SpriteList); // Background of the drop down list + RegisterSetting("sprite2", m_Sprite2); // Button that sits to the right + RegisterSetting("sprite2_over", m_Sprite2Over); + RegisterSetting("sprite2_pressed", m_Sprite2Pressed); + RegisterSetting("sprite2_disabled", m_Sprite2Disabled); + RegisterSetting("textcolor_disabled", m_TextColorDisabled); + RegisterSetting("text_valign", m_TextVAlign); // Add these in CList! And implement TODO - //AddSetting("textcolor_over"); - //AddSetting("textcolor_pressed"); - AddSetting("textcolor_disabled"); + //RegisterSetting("textcolor_over"); + //RegisterSetting("textcolor_pressed"); // Scrollbar is forced to be true. SetSetting("scrollbar", true, true); @@ -106,14 +124,12 @@ void CDropDown::HandleMessage(SGUIMessage& Message) if (!GetListRect().PointInside(mouse)) break; - const CGUIList& pList = GetSetting("list"); - const bool scrollbar = GetSetting("scrollbar"); - const float scroll = scrollbar ? GetScrollBar(0).GetPos() : 0.f; + const float scroll = m_ScrollBar ? GetScrollBar(0).GetPos() : 0.f; CRect rect = GetListRect(); mouse.y += scroll; int set = -1; - for (int i = 0; i < static_cast(pList.m_Items.size()); ++i) + for (int i = 0; i < static_cast(m_List.m_Items.size()); ++i) { if (mouse.y >= rect.top + m_ItemsYPositions[i] && mouse.y < rect.top + m_ItemsYPositions[i+1] && @@ -137,17 +153,17 @@ void CDropDown::HandleMessage(SGUIMessage& Message) case GUIM_MOUSE_ENTER: { - if (GetSetting("enabled")) - PlaySound("sound_enter"); + if (m_Enabled) + PlaySound(m_SoundEnter); break; } case GUIM_MOUSE_LEAVE: { - m_ElementHighlight = GetSetting("selected"); + m_ElementHighlight = m_Selected; - if (GetSetting("enabled")) - PlaySound("sound_leave"); + if (m_Enabled) + PlaySound(m_SoundLeave); break; } @@ -155,26 +171,25 @@ void CDropDown::HandleMessage(SGUIMessage& Message) // a mouse click to open the dropdown, also the coordinates are changed. case GUIM_MOUSE_PRESS_LEFT: { - if (!GetSetting("enabled")) + if (!m_Enabled) { - PlaySound("sound_disabled"); + PlaySound(m_SoundDisabled); break; } if (!m_Open) { - const CGUIList& pList = GetSetting("list"); - if (pList.m_Items.empty()) + if (m_List.m_Items.empty()) return; m_Open = true; GetScrollBar(0).SetZ(GetBufferedZ()); - m_ElementHighlight = GetSetting("selected"); + m_ElementHighlight = m_Selected; // Start at the position of the selected item, if possible. GetScrollBar(0).SetPos(m_ItemsYPositions.empty() ? 0 : m_ItemsYPositions[m_ElementHighlight] - 60); - PlaySound("sound_opened"); + PlaySound(m_SoundOpened); return; // overshadow } else @@ -186,7 +201,7 @@ void CDropDown::HandleMessage(SGUIMessage& Message) { m_Open = false; GetScrollBar(0).SetZ(GetBufferedZ()); - PlaySound("sound_closed"); + PlaySound(m_SoundClosed); return; // overshadow } @@ -205,10 +220,10 @@ void CDropDown::HandleMessage(SGUIMessage& Message) case GUIM_MOUSE_WHEEL_DOWN: { // Don't switch elements by scrolling when open, causes a confusing interaction between this and the scrollbar. - if (m_Open || !GetSetting("enabled")) + if (m_Open || !m_Enabled) break; - m_ElementHighlight = GetSetting("selected"); + m_ElementHighlight = m_Selected; if (m_ElementHighlight + 1 >= (int)m_ItemsYPositions.size() - 1) break; @@ -221,10 +236,10 @@ void CDropDown::HandleMessage(SGUIMessage& Message) case GUIM_MOUSE_WHEEL_UP: { // Don't switch elements by scrolling when open, causes a confusing interaction between this and the scrollbar. - if (m_Open || !GetSetting("enabled")) + if (m_Open || !m_Enabled) break; - m_ElementHighlight = GetSetting("selected"); + m_ElementHighlight = m_Selected; if (m_ElementHighlight - 1 < 0) break; @@ -236,7 +251,7 @@ void CDropDown::HandleMessage(SGUIMessage& Message) case GUIM_LOST_FOCUS: { if (m_Open) - PlaySound("sound_closed"); + PlaySound(m_SoundClosed); m_Open = false; break; @@ -305,19 +320,18 @@ InReaction CDropDown::ManuallyHandleEvent(const SDL_Event_* ev) m_TimeOfLastInput = timer_Time(); - const CGUIList& pList = GetSetting("list"); // let's look for the closest element // basically it's alphabetic order and "as many letters as we can get". int closest = -1; int bestIndex = -1; int difference = 1250; - for (int i = 0; i < static_cast(pList.m_Items.size()); ++i) + for (int i = 0; i < static_cast(m_List.m_Items.size()); ++i) { int indexOfDifference = 0; int diff = 0; for (size_t j = 0; j < m_InputBuffer.length(); ++j) { - diff = std::abs(static_cast(pList.m_Items[i].GetRawString().LowerCase()[j]) - static_cast(m_InputBuffer[j])); + diff = std::abs(static_cast(m_List.m_Items[i].GetRawString().LowerCase()[j]) - static_cast(m_InputBuffer[j])); if (diff == 0) indexOfDifference = j+1; else @@ -347,7 +361,7 @@ InReaction CDropDown::ManuallyHandleEvent(const SDL_Event_* ev) result = IN_HANDLED; if (update_highlight) - m_ElementHighlight = GetSetting("selected"); + m_ElementHighlight = m_Selected; return result; } @@ -358,57 +372,53 @@ void CDropDown::SetupListRect() extern float g_GuiScale; const float yres = g_yres / g_GuiScale; - const float size = GetSetting("dropdown_size"); - const float buffer = GetSetting("dropdown_buffer"); - const u32 minimumVisibleItems = GetSetting("minimum_visible_items"); - if (m_ItemsYPositions.empty()) { - m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom + buffer, - m_CachedActualSize.right, m_CachedActualSize.bottom + buffer + size); + m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom + m_DropDownBuffer, + m_CachedActualSize.right, m_CachedActualSize.bottom + m_DropDownBuffer + m_DropDownSize); m_HideScrollBar = false; } // Too many items so use a scrollbar - else if (m_ItemsYPositions.back() > size) + else if (m_ItemsYPositions.back() > m_DropDownSize) { // Place items below if at least some items can be placed below - if (m_CachedActualSize.bottom + buffer + size <= yres) - m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom + buffer, - m_CachedActualSize.right, m_CachedActualSize.bottom + buffer + size); - else if ((m_ItemsYPositions.size() > minimumVisibleItems && yres - m_CachedActualSize.bottom - buffer >= m_ItemsYPositions[minimumVisibleItems]) || + if (m_CachedActualSize.bottom + m_DropDownBuffer + m_DropDownSize <= yres) + m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom + m_DropDownBuffer, + m_CachedActualSize.right, m_CachedActualSize.bottom + m_DropDownBuffer + m_DropDownSize); + else if ((m_ItemsYPositions.size() > m_MinimumVisibleItems && yres - m_CachedActualSize.bottom - m_DropDownBuffer >= m_ItemsYPositions[m_MinimumVisibleItems]) || m_CachedActualSize.top < yres - m_CachedActualSize.bottom) - m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom + buffer, + m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom + m_DropDownBuffer, m_CachedActualSize.right, yres); // Not enough space below, thus place items above else - m_CachedListRect = CRect(m_CachedActualSize.left, std::max(0.f, m_CachedActualSize.top - buffer - size), - m_CachedActualSize.right, m_CachedActualSize.top - buffer); + m_CachedListRect = CRect(m_CachedActualSize.left, std::max(0.f, m_CachedActualSize.top - m_DropDownBuffer - m_DropDownSize), + m_CachedActualSize.right, m_CachedActualSize.top - m_DropDownBuffer); m_HideScrollBar = false; } else { // Enough space below, no scrollbar needed - if (m_CachedActualSize.bottom + buffer + m_ItemsYPositions.back() <= yres) + if (m_CachedActualSize.bottom + m_DropDownBuffer + m_ItemsYPositions.back() <= yres) { - m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom + buffer, - m_CachedActualSize.right, m_CachedActualSize.bottom + buffer + m_ItemsYPositions.back()); + m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom + m_DropDownBuffer, + m_CachedActualSize.right, m_CachedActualSize.bottom + m_DropDownBuffer + m_ItemsYPositions.back()); m_HideScrollBar = true; } // Enough space below for some items, but not all, so place items below and use a scrollbar - else if ((m_ItemsYPositions.size() > minimumVisibleItems && yres - m_CachedActualSize.bottom - buffer >= m_ItemsYPositions[minimumVisibleItems]) || + else if ((m_ItemsYPositions.size() > m_MinimumVisibleItems && yres - m_CachedActualSize.bottom - m_DropDownBuffer >= m_ItemsYPositions[m_MinimumVisibleItems]) || m_CachedActualSize.top < yres - m_CachedActualSize.bottom) { - m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom + buffer, + m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom + m_DropDownBuffer, m_CachedActualSize.right, yres); m_HideScrollBar = false; } // Not enough space below, thus place items above. Hide the scrollbar accordingly else { - m_CachedListRect = CRect(m_CachedActualSize.left, std::max(0.f, m_CachedActualSize.top - buffer - m_ItemsYPositions.back()), - m_CachedActualSize.right, m_CachedActualSize.top - buffer); - m_HideScrollBar = m_CachedActualSize.top > m_ItemsYPositions.back() + buffer; + m_CachedListRect = CRect(m_CachedActualSize.left, std::max(0.f, m_CachedActualSize.top - m_DropDownBuffer - m_ItemsYPositions.back()), + m_CachedActualSize.right, m_CachedActualSize.top - m_DropDownBuffer); + m_HideScrollBar = m_CachedActualSize.top > m_ItemsYPositions.back() + m_DropDownBuffer; } } } @@ -433,63 +443,53 @@ bool CDropDown::IsMouseOver() const void CDropDown::Draw() { const float bz = GetBufferedZ(); - const float button_width = GetSetting("button_width"); - const bool enabled = GetSetting("enabled"); - const int cell_id = GetSetting("cell_id"); - const int selected = GetSetting("selected"); - CGUISpriteInstance& sprite = GetSetting(enabled ? "sprite" : "sprite_disabled"); - CGUISpriteInstance& sprite2 = GetSetting("sprite2"); + const CGUISpriteInstance& sprite = m_Enabled ? m_Sprite : m_SpriteDisabled; - m_pGUI.DrawSprite(sprite, cell_id, bz, m_CachedActualSize); + m_pGUI.DrawSprite(sprite, m_CellID, bz, m_CachedActualSize); - if (button_width > 0.f) + if (m_ButtonWidth > 0.f) { - CRect rect(m_CachedActualSize.right-button_width, m_CachedActualSize.top, + CRect rect(m_CachedActualSize.right - m_ButtonWidth, m_CachedActualSize.top, m_CachedActualSize.right, m_CachedActualSize.bottom); - if (!enabled) + if (!m_Enabled) { - CGUISpriteInstance& sprite2_second = GetSetting("sprite2_disabled"); - m_pGUI.DrawSprite(sprite2_second || sprite2, cell_id, bz + 0.05f, rect); + m_pGUI.DrawSprite(m_Sprite2Disabled || m_Sprite2, m_CellID, bz + 0.05f, rect); } else if (m_Open) { - CGUISpriteInstance& sprite2_second = GetSetting("sprite2_pressed"); - m_pGUI.DrawSprite(sprite2_second || sprite2, cell_id, bz + 0.05f, rect); + m_pGUI.DrawSprite(m_Sprite2Pressed || m_Sprite2, m_CellID, bz + 0.05f, rect); } else if (m_MouseHovering) { - CGUISpriteInstance& sprite2_second = GetSetting("sprite2_over"); - m_pGUI.DrawSprite(sprite2_second || sprite2, cell_id, bz + 0.05f, rect); + m_pGUI.DrawSprite(m_Sprite2Over || m_Sprite2, m_CellID, bz + 0.05f, rect); } else - m_pGUI.DrawSprite(sprite2, cell_id, bz + 0.05f, rect); + m_pGUI.DrawSprite(m_Sprite2, m_CellID, bz + 0.05f, rect); } - if (selected != -1) // TODO: Maybe check validity completely? + if (m_Selected != -1) // TODO: Maybe check validity completely? { CRect cliparea(m_CachedActualSize.left, m_CachedActualSize.top, - m_CachedActualSize.right-button_width, m_CachedActualSize.bottom); - - const CGUIColor& color = GetSetting(enabled ? "textcolor_selected" : "textcolor_disabled"); + m_CachedActualSize.right - m_ButtonWidth, m_CachedActualSize.bottom); CPos pos(m_CachedActualSize.left, m_CachedActualSize.top); - DrawText(selected, color, pos, bz+0.1f, cliparea); + DrawText(m_Selected, m_Enabled ? m_TextColorSelected : m_TextColorDisabled, pos, bz + 0.1f, cliparea); } // Disable scrollbar during drawing without sending a setting-changed message - bool& scrollbar = GetSetting("scrollbar"); - bool old = scrollbar; + bool old = m_ScrollBar; if (m_Open) { + // TODO: drawScrollbar as an argument of DrawList? if (m_HideScrollBar) - scrollbar = false; + m_ScrollBar = false; - DrawList(m_ElementHighlight, "sprite_list", "sprite_selectarea", "textcolor"); + DrawList(m_ElementHighlight, m_SpriteList, m_SpriteSelectArea, m_TextColor); if (m_HideScrollBar) - scrollbar = old; + m_ScrollBar = old; } } diff --git a/source/gui/CDropDown.h b/source/gui/CDropDown.h index 67ffc6cca0..67798841fe 100644 --- a/source/gui/CDropDown.h +++ b/source/gui/CDropDown.h @@ -28,6 +28,7 @@ GUI Object - Drop Down (list) #ifndef INCLUDED_CDROPDOWN #define INCLUDED_CDROPDOWN +#include "gui/CGUISprite.h" #include "gui/CList.h" #include @@ -119,6 +120,23 @@ protected: // used to know if we want to restart anew or add to m_inputbuffer. double m_TimeOfLastInput; + // Settings + float m_ButtonWidth; + float m_DropDownSize; + float m_DropDownBuffer; + u32 m_MinimumVisibleItems; + CStrW m_SoundClosed; + CStrW m_SoundEnter; + CStrW m_SoundLeave; + CStrW m_SoundOpened; + CGUISpriteInstance m_SpriteDisabled; + CGUISpriteInstance m_SpriteList; + CGUISpriteInstance m_Sprite2; + CGUISpriteInstance m_Sprite2Over; + CGUISpriteInstance m_Sprite2Pressed; + CGUISpriteInstance m_Sprite2Disabled; + CGUIColor m_TextColorDisabled; + EVAlign m_TextVAlign; }; #endif // INCLUDED_CDROPDOWN diff --git a/source/gui/CGUI.cpp b/source/gui/CGUI.cpp index ed81e398b7..d66e091c3d 100644 --- a/source/gui/CGUI.cpp +++ b/source/gui/CGUI.cpp @@ -874,10 +874,12 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec } } + object->AdditionalChildrenHandled(); + if (!ManuallySetZ) { // Set it automatically to 10 plus its parents - if (object->GetSetting("absolute")) + if (object->m_Absolute) // If the object is absolute, we'll have to get the parent's Z buffered, // and add to that! object->SetSetting("z", pParent->GetBufferedZ() + 10.f, false); diff --git a/source/gui/CGUISetting.cpp b/source/gui/CGUISetting.cpp index a06513419d..afbeccf0b3 100644 --- a/source/gui/CGUISetting.cpp +++ b/source/gui/CGUISetting.cpp @@ -22,8 +22,9 @@ #include "gui/CGUI.h" template -CGUISetting::CGUISetting(IGUIObject& pObject, const CStr& Name) - : m_pSetting(T()), m_Name(Name), m_pObject(pObject) + +CGUISetting::CGUISetting(IGUIObject& pObject, const CStr& Name, T& Value) + : m_pSetting(Value), m_Name(Name), m_pObject(pObject) { } diff --git a/source/gui/CGUISetting.h b/source/gui/CGUISetting.h index a51bece058..68e2014c64 100644 --- a/source/gui/CGUISetting.h +++ b/source/gui/CGUISetting.h @@ -55,7 +55,7 @@ class CGUISetting : public IGUISetting public: NONCOPYABLE(CGUISetting); - CGUISetting(IGUIObject& pObject, const CStr& Name); + CGUISetting(IGUIObject& pObject, const CStr& Name, T& Value); /** * Parses the given string and assigns to the setting value. Used for parsing XML attributes. @@ -88,9 +88,10 @@ public: const CStr m_Name; /** - * Holds the value of the setting. + * Holds a reference to the value of the setting. + * The setting value is stored in the member class to optimize for draw calls of that class. */ - T m_pSetting; + T& m_pSetting; }; #endif // INCLUDED_CGUISETTINGS diff --git a/source/gui/CImage.cpp b/source/gui/CImage.cpp index ec0ec115bd..1dc4e25c5b 100644 --- a/source/gui/CImage.cpp +++ b/source/gui/CImage.cpp @@ -22,10 +22,12 @@ #include "gui/CGUI.h" CImage::CImage(CGUI& pGUI) - : IGUIObject(pGUI) + : IGUIObject(pGUI), + m_Sprite(), + m_CellID() { - AddSetting("sprite"); - AddSetting("cell_id"); + RegisterSetting("sprite", m_Sprite); + RegisterSetting("cell_id", m_CellID); } CImage::~CImage() @@ -34,9 +36,5 @@ CImage::~CImage() void CImage::Draw() { - m_pGUI.DrawSprite( - GetSetting("sprite"), - GetSetting("cell_id"), - GetBufferedZ(), - m_CachedActualSize); + m_pGUI.DrawSprite(m_Sprite, m_CellID, GetBufferedZ(), m_CachedActualSize); } diff --git a/source/gui/CImage.h b/source/gui/CImage.h index 2b47a5f742..a47b26234c 100644 --- a/source/gui/CImage.h +++ b/source/gui/CImage.h @@ -18,6 +18,7 @@ #ifndef INCLUDED_CIMAGE #define INCLUDED_CIMAGE +#include "gui/CGUISprite.h" #include "gui/IGUIObject.h" /** @@ -43,6 +44,10 @@ protected: * Draws the Image */ virtual void Draw(); + + // Settings + CGUISpriteInstance m_Sprite; + i32 m_CellID; }; #endif // INCLUDED_CIMAGE diff --git a/source/gui/CInput.cpp b/source/gui/CInput.cpp index ec30af0cca..5118551cb8 100644 --- a/source/gui/CInput.cpp +++ b/source/gui/CInput.cpp @@ -38,27 +38,53 @@ extern int g_yres; CInput::CInput(CGUI& pGUI) - : IGUIObject(pGUI), IGUIScrollBarOwner(pGUI), - m_iBufferPos(-1), m_iBufferPos_Tail(-1), m_SelectingText(false), m_HorizontalScroll(0.f), - m_PrevTime(0.0), m_CursorVisState(true), m_CursorBlinkRate(0.5), m_ComposingText(false), - m_iComposedLength(0), m_iComposedPos(0), m_iInsertPos(0), m_Readonly(false) + : + IGUIObject(pGUI), + IGUIScrollBarOwner(pGUI), + m_iBufferPos(-1), + m_iBufferPos_Tail(-1), + m_SelectingText(), + m_HorizontalScroll(), + m_PrevTime(), + m_CursorVisState(true), + m_CursorBlinkRate(0.5), + m_ComposingText(), + m_iComposedLength(), + m_iComposedPos(), + m_iInsertPos(), + m_BufferPosition(), + m_BufferZone(), + m_Caption(), + m_CellID(), + m_Font(), + m_MaskChar(), + m_Mask(), + m_MaxLength(), + m_MultiLine(), + m_Readonly(), + m_ScrollBar(), + m_ScrollBarStyle(), + m_Sprite(), + m_SpriteSelectArea(), + m_TextColor(), + m_TextColorSelected() { - AddSetting("buffer_position"); - AddSetting("buffer_zone"); - AddSetting("caption"); - AddSetting("cell_id"); - AddSetting("font"); - AddSetting("mask_char"); - AddSetting("mask"); - AddSetting("max_length"); - AddSetting("multiline"); - AddSetting("readonly"); - AddSetting("scrollbar"); - AddSetting("scrollbar_style"); - AddSetting("sprite"); - AddSetting("sprite_selectarea"); - AddSetting("textcolor"); - AddSetting("textcolor_selected"); + RegisterSetting("buffer_position", m_BufferPosition); + RegisterSetting("buffer_zone", m_BufferZone); + RegisterSetting("caption", m_Caption); + RegisterSetting("cell_id", m_CellID); + RegisterSetting("font", m_Font); + RegisterSetting("mask_char", m_MaskChar); + RegisterSetting("mask", m_Mask); + RegisterSetting("max_length", m_MaxLength); + RegisterSetting("multiline", m_MultiLine); + RegisterSetting("readonly", m_Readonly); + RegisterSetting("scrollbar", m_ScrollBar); + RegisterSetting("scrollbar_style", m_ScrollBarStyle); + RegisterSetting("sprite", m_Sprite); + RegisterSetting("sprite_selectarea", m_SpriteSelectArea); + RegisterSetting("textcolor", m_TextColor); + RegisterSetting("textcolor_selected", m_TextColorSelected); CFG_GET_VAL("gui.cursorblinkrate", m_CursorBlinkRate); @@ -78,8 +104,7 @@ void CInput::UpdateBufferPositionSetting() void CInput::ClearComposedText() { - CStrW& pCaption = GetSetting("caption"); - pCaption.erase(m_iInsertPos, m_iComposedLength); + m_Caption.erase(m_iInsertPos, m_iComposedLength); m_iBufferPos = m_iInsertPos; UpdateBufferPositionSetting(); m_iComposedLength = 0; @@ -107,7 +132,6 @@ InReaction CInput::ManuallyHandleEvent(const SDL_Event_* ev) return IN_PASS; // Text has been committed, either single key presses or through an IME - CStrW& pCaption = GetSetting("caption"); std::wstring text = wstring_from_utf8(ev->ev.text.text); m_WantedX = 0.0f; @@ -121,10 +145,10 @@ InReaction CInput::ManuallyHandleEvent(const SDL_Event_* ev) m_ComposingText = false; } - if (m_iBufferPos == static_cast(pCaption.length())) - pCaption.append(text); + if (m_iBufferPos == static_cast(m_Caption.length())) + m_Caption.append(text); else - pCaption.insert(m_iBufferPos, text); + m_Caption.insert(m_iBufferPos, text); UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos+1); @@ -144,7 +168,6 @@ InReaction CInput::ManuallyHandleEvent(const SDL_Event_* ev) // Text is being composed with an IME // TODO: indicate this by e.g. underlining the uncommitted text - CStrW& pCaption = GetSetting("caption"); const char* rawText = ev->ev.edit.text; int rawLength = strlen(rawText); std::wstring wtext = wstring_from_utf8(rawText); @@ -167,7 +190,7 @@ InReaction CInput::ManuallyHandleEvent(const SDL_Event_* ev) m_ComposingText = ev->ev.edit.start != 0 || rawLength != 0; if (m_ComposingText) { - pCaption.insert(m_iInsertPos, wtext); + m_Caption.insert(m_iInsertPos, wtext); // The text buffer is limited to SDL_TEXTEDITINGEVENT_TEXT_SIZE bytes, yet start // increases without limit, so don't let it advance beyond the composed text length @@ -195,11 +218,10 @@ InReaction CInput::ManuallyHandleEvent(const SDL_Event_* ev) // Since the GUI framework doesn't handle to set settings // in Unicode (CStrW), we'll simply retrieve the actual // pointer and edit that. - CStrW& pCaption = GetSetting("caption"); SDL_Keycode keyCode = ev->ev.key.keysym.sym; - ManuallyImmutableHandleKeyDownEvent(keyCode, pCaption); - ManuallyMutableHandleKeyDownEvent(keyCode, pCaption); + ManuallyImmutableHandleKeyDownEvent(keyCode); + ManuallyMutableHandleKeyDownEvent(keyCode); UpdateBufferPositionSetting(); return IN_HANDLED; @@ -211,7 +233,7 @@ InReaction CInput::ManuallyHandleEvent(const SDL_Event_* ev) } } -void CInput::ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode, CStrW& pCaption) +void CInput::ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode) { if (m_Readonly) return; @@ -237,15 +259,15 @@ void CInput::ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode, CStrW& { m_iBufferPos_Tail = -1; - if (pCaption.empty() || m_iBufferPos == 0) + if (m_Caption.empty() || m_iBufferPos == 0) break; - if (m_iBufferPos == static_cast(pCaption.length())) - pCaption = pCaption.Left(static_cast(pCaption.length()) - 1); + if (m_iBufferPos == static_cast(m_Caption.length())) + m_Caption = m_Caption.Left(static_cast(m_Caption.length()) - 1); else - pCaption = - pCaption.Left(m_iBufferPos - 1) + - pCaption.Right(static_cast(pCaption.length()) - m_iBufferPos); + m_Caption = + m_Caption.Left(m_iBufferPos - 1) + + m_Caption.Right(static_cast(m_Caption.length()) - m_iBufferPos); --m_iBufferPos; @@ -264,12 +286,12 @@ void CInput::ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode, CStrW& DeleteCurSelection(); else { - if (pCaption.empty() || m_iBufferPos == static_cast(pCaption.length())) + if (m_Caption.empty() || m_iBufferPos == static_cast(m_Caption.length())) break; - pCaption = - pCaption.Left(m_iBufferPos) + - pCaption.Right(static_cast(pCaption.length()) - (m_iBufferPos + 1)); + m_Caption = + m_Caption.Left(m_iBufferPos) + + m_Caption.Right(static_cast(m_Caption.length()) - (m_iBufferPos + 1)); UpdateText(m_iBufferPos, m_iBufferPos + 1, m_iBufferPos); } @@ -283,7 +305,7 @@ void CInput::ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode, CStrW& { // 'Return' should do a Press event for single liners (e.g. submitting forms) // otherwise a '\n' character will be added. - if (!GetSetting("multiline")) + if (!m_MultiLine) { SendEvent(GUIM_PRESSED, "press"); break; @@ -300,8 +322,7 @@ void CInput::ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode, CStrW& return; // check max length - const int max_length = GetSetting("max_length"); - if (max_length != 0 && static_cast(pCaption.length()) >= max_length) + if (m_MaxLength != 0 && static_cast(m_Caption.length()) >= m_MaxLength) break; m_WantedX = 0.0f; @@ -310,12 +331,12 @@ void CInput::ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode, CStrW& DeleteCurSelection(); m_iBufferPos_Tail = -1; - if (m_iBufferPos == static_cast(pCaption.length())) - pCaption += cooked; + if (m_iBufferPos == static_cast(m_Caption.length())) + m_Caption += cooked; else - pCaption = - pCaption.Left(m_iBufferPos) + cooked + - pCaption.Right(static_cast(pCaption.length()) - m_iBufferPos); + m_Caption = + m_Caption.Left(m_iBufferPos) + cooked + + m_Caption.Right(static_cast(m_Caption.length()) - m_iBufferPos); UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos + 1); @@ -328,7 +349,7 @@ void CInput::ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode, CStrW& } } -void CInput::ManuallyImmutableHandleKeyDownEvent(const SDL_Keycode keyCode, CStrW& pCaption) +void CInput::ManuallyImmutableHandleKeyDownEvent(const SDL_Keycode keyCode) { bool shiftKeyPressed = g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT]; @@ -368,7 +389,7 @@ void CInput::ManuallyImmutableHandleKeyDownEvent(const SDL_Keycode keyCode, CStr m_iBufferPos_Tail = m_iBufferPos; } - m_iBufferPos = static_cast(pCaption.length()); + m_iBufferPos = static_cast(m_Caption.length()); m_WantedX = 0.0f; UpdateAutoScroll(); @@ -431,7 +452,7 @@ void CInput::ManuallyImmutableHandleKeyDownEvent(const SDL_Keycode keyCode, CStr else if (!SelectingText()) m_iBufferPos_Tail = m_iBufferPos; - if (m_iBufferPos < static_cast(pCaption.length())) + if (m_iBufferPos < static_cast(m_Caption.length())) ++m_iBufferPos; } else @@ -564,8 +585,6 @@ void CInput::ManuallyImmutableHandleKeyDownEvent(const SDL_Keycode keyCode, CStr InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev) { - CStrW& pCaption = GetSetting("caption"); - bool shiftKeyPressed = g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT]; std::string hotkey = static_cast(ev->ev.user.data1); @@ -583,12 +602,12 @@ InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev) if (SelectingText()) DeleteCurSelection(); - if (m_iBufferPos == static_cast(pCaption.length())) - pCaption += text; + if (m_iBufferPos == static_cast(m_Caption.length())) + m_Caption += text; else - pCaption = - pCaption.Left(m_iBufferPos) + text + - pCaption.Right(static_cast(pCaption.length()) - m_iBufferPos); + m_Caption = + m_Caption.Left(m_iBufferPos) + text + + m_Caption.Right(static_cast(m_Caption.length()) - m_iBufferPos); UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos+1); @@ -626,7 +645,7 @@ InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev) virtualTo = m_iBufferPos; } - CStrW text = (pCaption.Left(virtualTo)).Right(virtualTo - virtualFrom); + CStrW text = m_Caption.Left(virtualTo).Right(virtualTo - virtualFrom); sys_clipboard_set(&text[0]); @@ -650,10 +669,10 @@ InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev) if (SelectingText()) DeleteCurSelection(); - if (!pCaption.empty() && m_iBufferPos != 0) + if (!m_Caption.empty() && m_iBufferPos != 0) { m_iBufferPos_Tail = m_iBufferPos; - CStrW searchString = pCaption.Left(m_iBufferPos); + CStrW searchString = m_Caption.Left(m_iBufferPos); // If we are starting in whitespace, adjust position until we get a non whitespace while (m_iBufferPos > 0) @@ -696,22 +715,22 @@ InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev) if (SelectingText()) DeleteCurSelection(); - if (!pCaption.empty() && m_iBufferPos < static_cast(pCaption.length())) + if (!m_Caption.empty() && m_iBufferPos < static_cast(m_Caption.length())) { // Delete the word to the right of the cursor m_iBufferPos_Tail = m_iBufferPos; // Delete chars to the right unit we hit whitespace - while (++m_iBufferPos < static_cast(pCaption.length())) + while (++m_iBufferPos < static_cast(m_Caption.length())) { - if (iswspace(pCaption[m_iBufferPos]) || iswpunct(pCaption[m_iBufferPos])) + if (iswspace(m_Caption[m_iBufferPos]) || iswpunct(m_Caption[m_iBufferPos])) break; } // Eliminate any whitespace behind the word we just deleted - while (m_iBufferPos < static_cast(pCaption.length())) + while (m_iBufferPos < static_cast(m_Caption.length())) { - if (!iswspace(pCaption[m_iBufferPos])) + if (!iswspace(m_Caption[m_iBufferPos])) break; ++m_iBufferPos; @@ -734,9 +753,9 @@ InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev) else if (!SelectingText()) m_iBufferPos_Tail = m_iBufferPos; - if (!pCaption.empty() && m_iBufferPos != 0) + if (!m_Caption.empty() && m_iBufferPos != 0) { - CStrW searchString = pCaption.Left(m_iBufferPos); + CStrW searchString = m_Caption.Left(m_iBufferPos); // If we are starting in whitespace, adjust position until we get a non whitespace while (m_iBufferPos > 0) @@ -787,19 +806,19 @@ InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev) else if (!SelectingText()) m_iBufferPos_Tail = m_iBufferPos; - if (!pCaption.empty() && m_iBufferPos < static_cast(pCaption.length())) + if (!m_Caption.empty() && m_iBufferPos < static_cast(m_Caption.length())) { // Select chars to the right until we hit whitespace - while (++m_iBufferPos < static_cast(pCaption.length())) + while (++m_iBufferPos < static_cast(m_Caption.length())) { - if (iswspace(pCaption[m_iBufferPos]) || iswpunct(pCaption[m_iBufferPos])) + if (iswspace(m_Caption[m_iBufferPos]) || iswpunct(m_Caption[m_iBufferPos])) break; } // Also select any whitespace following the word we just selected - while (m_iBufferPos < static_cast(pCaption.length())) + while (m_iBufferPos < static_cast(m_Caption.length())) { - if (!iswspace(pCaption[m_iBufferPos])) + if (!iswspace(m_Caption[m_iBufferPos])) break; ++m_iBufferPos; @@ -834,10 +853,10 @@ void CInput::HandleMessage(SGUIMessage& Message) { // Update scroll-bar // TODO Gee: (2004-09-01) Is this really updated each time it should? - if (GetSetting("scrollbar") && - (Message.value == CStr("size") || - Message.value == CStr("z") || - Message.value == CStr("absolute"))) + if (m_ScrollBar && + (Message.value == "size" || + Message.value == "z" || + Message.value == "absolute")) { GetScrollBar(0).SetX(m_CachedActualSize.right); GetScrollBar(0).SetY(m_CachedActualSize.top); @@ -846,31 +865,29 @@ void CInput::HandleMessage(SGUIMessage& Message) } // Update scrollbar - if (Message.value == CStr("scrollbar_style")) - { - GetScrollBar(0).SetScrollBarStyle(GetSetting(Message.value)); - } + if (Message.value == "scrollbar_style") + GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle); - if (Message.value == CStr("buffer_position")) + if (Message.value == "buffer_position") { - m_iBufferPos = GetSetting(Message.value); + m_iBufferPos = m_BufferPosition; m_iBufferPos_Tail = -1; // position change resets selection } - if (Message.value == CStr("size") || - Message.value == CStr("z") || - Message.value == CStr("font") || - Message.value == CStr("absolute") || - Message.value == CStr("caption") || - Message.value == CStr("scrollbar") || - Message.value == CStr("scrollbar_style")) + if (Message.value == "size" || + Message.value == "z" || + Message.value == "font" || + Message.value == "absolute" || + Message.value == "caption" || + Message.value == "scrollbar" || + Message.value == "scrollbar_style") { UpdateText(); } - if (Message.value == CStr("multiline")) + if (Message.value == "multiline") { - if (!GetSetting("multiline")) + if (!m_MultiLine) GetScrollBar(0).SetLength(0.f); else GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top); @@ -880,16 +897,13 @@ void CInput::HandleMessage(SGUIMessage& Message) UpdateAutoScroll(); - if (Message.value == CStr("readonly")) - m_Readonly = GetSetting("readonly"); - break; } case GUIM_MOUSE_PRESS_LEFT: { // Check if we're selecting the scrollbar - if (GetSetting("scrollbar") && - GetSetting("multiline") && + if (m_ScrollBar && + m_MultiLine && GetScrollBar(0).GetStyle()) { if (m_pGUI.GetMousePos().x > m_CachedActualSize.right - GetScrollBar(0).GetStyle()->m_Width) @@ -922,22 +936,20 @@ void CInput::HandleMessage(SGUIMessage& Message) if (m_ComposingText) break; - const CStrW& pCaption = GetSetting("caption"); - - if (pCaption.empty()) + if (m_Caption.empty()) break; m_iBufferPos = m_iBufferPos_Tail = GetMouseHoveringTextPosition(); - if (m_iBufferPos >= (int)pCaption.length()) - m_iBufferPos = m_iBufferPos_Tail = pCaption.length() - 1; + if (m_iBufferPos >= (int)m_Caption.length()) + m_iBufferPos = m_iBufferPos_Tail = m_Caption.length() - 1; // See if we are clicking over whitespace - if (iswspace(pCaption[m_iBufferPos])) + if (iswspace(m_Caption[m_iBufferPos])) { // see if we are in a section of whitespace greater than one character - if ((m_iBufferPos + 1 < (int) pCaption.length() && iswspace(pCaption[m_iBufferPos + 1])) || - (m_iBufferPos - 1 > 0 && iswspace(pCaption[m_iBufferPos - 1]))) + if ((m_iBufferPos + 1 < (int) m_Caption.length() && iswspace(m_Caption[m_iBufferPos + 1])) || + (m_iBufferPos - 1 > 0 && iswspace(m_Caption[m_iBufferPos - 1]))) { // // We are clicking in an area with more than one whitespace character @@ -947,7 +959,7 @@ void CInput::HandleMessage(SGUIMessage& Message) // skip the whitespace while (m_iBufferPos > 0) { - if (!iswspace(pCaption[m_iBufferPos - 1])) + if (!iswspace(m_Caption[m_iBufferPos - 1])) break; m_iBufferPos--; @@ -955,52 +967,52 @@ void CInput::HandleMessage(SGUIMessage& Message) // now go until we hit white space or punctuation while (m_iBufferPos > 0) { - if (iswspace(pCaption[m_iBufferPos - 1])) + if (iswspace(m_Caption[m_iBufferPos - 1])) break; m_iBufferPos--; - if (iswpunct(pCaption[m_iBufferPos])) + if (iswpunct(m_Caption[m_iBufferPos])) break; } // [2] Then the right // go right until we are not in whitespace - while (++m_iBufferPos_Tail < static_cast(pCaption.length())) + while (++m_iBufferPos_Tail < static_cast(m_Caption.length())) { - if (!iswspace(pCaption[m_iBufferPos_Tail])) + if (!iswspace(m_Caption[m_iBufferPos_Tail])) break; } - if (m_iBufferPos_Tail == static_cast(pCaption.length())) + if (m_iBufferPos_Tail == static_cast(m_Caption.length())) break; // now go to the right until we hit whitespace or punctuation - while (++m_iBufferPos_Tail < static_cast(pCaption.length())) + while (++m_iBufferPos_Tail < static_cast(m_Caption.length())) { - if (iswspace(pCaption[m_iBufferPos_Tail]) || iswpunct(pCaption[m_iBufferPos_Tail])) + if (iswspace(m_Caption[m_iBufferPos_Tail]) || iswpunct(m_Caption[m_iBufferPos_Tail])) break; } } else { // single whitespace so select word to the right - while (++m_iBufferPos_Tail < static_cast(pCaption.length())) + while (++m_iBufferPos_Tail < static_cast(m_Caption.length())) { - if (!iswspace(pCaption[m_iBufferPos_Tail])) + if (!iswspace(m_Caption[m_iBufferPos_Tail])) break; } - if (m_iBufferPos_Tail == static_cast(pCaption.length())) + if (m_iBufferPos_Tail == static_cast(m_Caption.length())) break; // Don't include the leading whitespace m_iBufferPos = m_iBufferPos_Tail; // now go to the right until we hit whitespace or punctuation - while (++m_iBufferPos_Tail < static_cast(pCaption.length())) + while (++m_iBufferPos_Tail < static_cast(m_Caption.length())) { - if (iswspace(pCaption[m_iBufferPos_Tail]) || iswpunct(pCaption[m_iBufferPos_Tail])) + if (iswspace(m_Caption[m_iBufferPos_Tail]) || iswpunct(m_Caption[m_iBufferPos_Tail])) break; } } @@ -1011,17 +1023,17 @@ void CInput::HandleMessage(SGUIMessage& Message) // go until we hit white space or punctuation while (m_iBufferPos > 0) { - if (iswspace(pCaption[m_iBufferPos - 1])) + if (iswspace(m_Caption[m_iBufferPos - 1])) break; m_iBufferPos--; - if (iswpunct(pCaption[m_iBufferPos])) + if (iswpunct(m_Caption[m_iBufferPos])) break; } // go to the right until we hit whitespace or punctuation - while (++m_iBufferPos_Tail < static_cast(pCaption.length())) - if (iswspace(pCaption[m_iBufferPos_Tail]) || iswpunct(pCaption[m_iBufferPos_Tail])) + while (++m_iBufferPos_Tail < static_cast(m_Caption.length())) + if (iswspace(m_Caption[m_iBufferPos_Tail]) || iswpunct(m_Caption[m_iBufferPos_Tail])) break; } UpdateAutoScroll(); @@ -1055,12 +1067,11 @@ void CInput::HandleMessage(SGUIMessage& Message) GetScrollBar(0).SetY(m_CachedActualSize.top); GetScrollBar(0).SetZ(GetBufferedZ()); GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top); - GetScrollBar(0).SetScrollBarStyle(GetSetting("scrollbar_style")); + GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle); UpdateText(); UpdateAutoScroll(); - m_Readonly = GetSetting("readonly"); break; } case GUIM_GOT_FOCUS: @@ -1112,7 +1123,7 @@ void CInput::UpdateCachedSize() IGUIObject::UpdateCachedSize(); - if (GetSetting("scrollbar")) + if (m_ScrollBar) { GetScrollBar(0).SetX(m_CachedActualSize.right); GetScrollBar(0).SetY(m_CachedActualSize.top); @@ -1140,38 +1151,19 @@ void CInput::Draw() m_CursorVisState = true; // First call draw on ScrollBarOwner - const bool scrollbar = GetSetting("scrollbar"); - const float buffer_zone = GetSetting("buffer_zone"); - const bool multiline = GetSetting("multiline"); - const bool mask = GetSetting("mask"); - - if (scrollbar && multiline) + if (m_ScrollBar && m_MultiLine) IGUIScrollBarOwner::Draw(); - const CGUIColor& color = GetSetting("textcolor"); - const CGUIColor& color_selected = GetSetting("textcolor_selected"); + CStrIntern font_name(m_Font.ToUTF8()); - CStrIntern font_name(GetSetting("font").ToUTF8()); - - const CStrW& pCaption = GetSetting("caption"); wchar_t mask_char = L'*'; - if (mask) - { - const CStrW& maskStr = GetSetting("mask_char"); + if (m_Mask && m_MaskChar.length() > 0) + mask_char = m_MaskChar[0]; - if (maskStr.length() > 0) - mask_char = maskStr[0]; - } - - CGUISpriteInstance& sprite = GetSetting("sprite"); - CGUISpriteInstance& sprite_selectarea = GetSetting("sprite_selectarea"); - - const int cell_id = GetSetting("cell_id"); - - m_pGUI.DrawSprite(sprite, cell_id, bz, m_CachedActualSize); + m_pGUI.DrawSprite(m_Sprite, m_CellID, bz, m_CachedActualSize); float scroll = 0.f; - if (scrollbar && multiline) + if (m_ScrollBar && m_MultiLine) scroll = GetScrollBar(0).GetPos(); CFontMetrics font(font_name); @@ -1181,7 +1173,7 @@ void CInput::Draw() // First we'll figure out the clipping area, which is the cached actual size // substracted by an optional scrollbar - if (scrollbar) + if (m_ScrollBar) { scroll = GetScrollBar(0).GetPos(); @@ -1231,14 +1223,14 @@ void CInput::Draw() // Set the Z to somewhat more, so we can draw a selected area between the // the control and the text. textRenderer.Translate( - (float)(int)(m_CachedActualSize.left) + buffer_zone, - (float)(int)(m_CachedActualSize.top+h) + buffer_zone, + (float)(int)(m_CachedActualSize.left) + m_BufferZone, + (float)(int)(m_CachedActualSize.top+h) + m_BufferZone, bz+0.1f); // U+FE33: PRESENTATION FORM FOR VERTICAL LOW LINE // (sort of like a | which is aligned to the left of most characters) - float buffered_y = -scroll+buffer_zone; + float buffered_y = -scroll + m_BufferZone; // When selecting larger areas, we need to draw a rectangle box // around it, and this is to keep track of where the box @@ -1286,7 +1278,7 @@ void CInput::Draw() it != m_CharacterPositions.end(); ++it, buffered_y += ls, x_pointer = 0.f) { - if (multiline && buffered_y > m_CachedActualSize.GetHeight()) + if (m_MultiLine && buffered_y > m_CachedActualSize.GetHeight()) break; // We might as well use 'i' here to iterate, because we need it @@ -1315,7 +1307,7 @@ void CInput::Draw() { if (it->m_ListStart + i != VirtualFrom) // and actually add a white space! yes, this is done in any common input - x_pointer += (float)font.GetCharacterWidth(L' '); + x_pointer += font.GetCharacterWidth(L' '); } else { @@ -1325,12 +1317,12 @@ void CInput::Draw() CRect rect; // Set 'rect' depending on if it's a multiline control, or a one-line control - if (multiline) + if (m_MultiLine) { rect = CRect( - m_CachedActualSize.left + box_x + buffer_zone, + m_CachedActualSize.left + box_x + m_BufferZone, m_CachedActualSize.top + buffered_y + (h - ls) / 2, - m_CachedActualSize.left + x_pointer + buffer_zone, + m_CachedActualSize.left + x_pointer + m_BufferZone, m_CachedActualSize.top + buffered_y + (h + ls) / 2); if (rect.bottom < m_CachedActualSize.top) @@ -1345,9 +1337,9 @@ void CInput::Draw() else // if one-line { rect = CRect( - m_CachedActualSize.left + box_x + buffer_zone - m_HorizontalScroll, + m_CachedActualSize.left + box_x + m_BufferZone - m_HorizontalScroll, m_CachedActualSize.top + buffered_y + (h - ls) / 2, - m_CachedActualSize.left + x_pointer + buffer_zone - m_HorizontalScroll, + m_CachedActualSize.left + x_pointer + m_BufferZone - m_HorizontalScroll, m_CachedActualSize.top + buffered_y + (h + ls) / 2); if (rect.left < m_CachedActualSize.left) @@ -1357,15 +1349,15 @@ void CInput::Draw() rect.right = m_CachedActualSize.right; } - m_pGUI.DrawSprite(sprite_selectarea, cell_id, bz + 0.05f, rect); + m_pGUI.DrawSprite(m_SpriteSelectArea, m_CellID, bz + 0.05f, rect); } if (i < (int)it->m_ListOfX.size()) { - if (!mask) - x_pointer += (float)font.GetCharacterWidth(pCaption[it->m_ListStart + i]); + if (!m_Mask) + x_pointer += font.GetCharacterWidth(m_Caption[it->m_ListStart + i]); else - x_pointer += (float)font.GetCharacterWidth(mask_char); + x_pointer += font.GetCharacterWidth(mask_char); } } @@ -1384,7 +1376,7 @@ void CInput::Draw() buffered_y = -scroll; // Setup initial color (then it might change and change back, when drawing selected area) - textRenderer.Color(color); + textRenderer.Color(m_TextColor); tech->BeginPass(); @@ -1394,15 +1386,15 @@ void CInput::Draw() it != m_CharacterPositions.end(); ++it, buffered_y += ls) { - if (buffered_y + buffer_zone >= -ls || !multiline) + if (buffered_y + m_BufferZone >= -ls || !m_MultiLine) { - if (multiline && buffered_y + buffer_zone > m_CachedActualSize.GetHeight()) + if (m_MultiLine && buffered_y + m_BufferZone > m_CachedActualSize.GetHeight()) break; CMatrix3D savedTransform = textRenderer.GetTransform(); // Text must always be drawn in integer values. So we have to convert scroll - if (multiline) + if (m_MultiLine) textRenderer.Translate(0.f, -(float)(int)scroll, 0.f); else textRenderer.Translate(-(float)(int)m_HorizontalScroll, 0.f, 0.f); @@ -1411,9 +1403,9 @@ void CInput::Draw() // (often compared against ints, so don't make it size_t) for (int i = 0; i < (int)it->m_ListOfX.size()+1; ++i) { - if (!multiline && i < (int)it->m_ListOfX.size()) + if (!m_MultiLine && i < (int)it->m_ListOfX.size()) { - if (it->m_ListOfX[i] - m_HorizontalScroll < -buffer_zone) + if (it->m_ListOfX[i] - m_HorizontalScroll < -m_BufferZone) { // We still need to translate the OpenGL matrix if (i == 0) @@ -1429,7 +1421,7 @@ void CInput::Draw() if (SelectingText() && it->m_ListStart + i == VirtualTo) { using_selected_color = false; - textRenderer.Color(color); + textRenderer.Color(m_TextColor); } // selecting only one, then we need only to draw a cursor. @@ -1443,31 +1435,31 @@ void CInput::Draw() !using_selected_color) { using_selected_color = true; - textRenderer.Color(color_selected); + textRenderer.Color(m_TextColorSelected); } if (i != (int)it->m_ListOfX.size()) { - if (!mask) - textRenderer.PrintfAdvance(L"%lc", pCaption[it->m_ListStart + i]); + if (!m_Mask) + textRenderer.PrintfAdvance(L"%lc", m_Caption[it->m_ListStart + i]); else textRenderer.PrintfAdvance(L"%lc", mask_char); } // check it's now outside a one-liner, then we'll break - if (!multiline && i < (int)it->m_ListOfX.size() && - it->m_ListOfX[i] - m_HorizontalScroll > m_CachedActualSize.GetWidth() - buffer_zone) + if (!m_MultiLine && i < (int)it->m_ListOfX.size() && + it->m_ListOfX[i] - m_HorizontalScroll > m_CachedActualSize.GetWidth() - m_BufferZone) break; } if (it->m_ListStart + (int)it->m_ListOfX.size() == m_iBufferPos) { - textRenderer.Color(color); + textRenderer.Color(m_TextColor); if (m_CursorVisState) textRenderer.PutAdvance(L"_"); if (using_selected_color) - textRenderer.Color(color_selected); + textRenderer.Color(m_TextColorSelected); } textRenderer.SetTransform(savedTransform); @@ -1486,23 +1478,15 @@ void CInput::Draw() void CInput::UpdateText(int from, int to_before, int to_after) { - const CStrW& caption = GetSetting("caption"); - const float buffer_zone = GetSetting("buffer_zone"); - const bool multiline = GetSetting("multiline"); - const bool mask = GetSetting("mask"); - CStrIntern font_name(GetSetting("font").ToUTF8()); + CStrIntern font_name(m_Font.ToUTF8()); wchar_t mask_char = L'*'; - if (mask) - { - const CStrW& maskStr = GetSetting("mask_char"); - if (maskStr.length() > 0) - mask_char = maskStr[0]; - } + if (m_Mask && m_MaskChar.length() > 0) + mask_char = m_MaskChar[0]; // Ensure positions are valid after caption changes - m_iBufferPos = std::min(m_iBufferPos, (int)caption.size()); - m_iBufferPos_Tail = std::min(m_iBufferPos_Tail, (int)caption.size()); + m_iBufferPos = std::min(m_iBufferPos, static_cast(m_Caption.size())); + m_iBufferPos_Tail = std::min(m_iBufferPos_Tail, static_cast(m_Caption.size())); UpdateBufferPositionSetting(); if (font_name.empty()) @@ -1518,7 +1502,7 @@ void CInput::UpdateText(int from, int to_before, int to_after) int to = 0; // make sure it's initialized if (to_before == -1) - to = (int)caption.length(); + to = static_cast(m_Caption.length()); CFontMetrics font(font_name); @@ -1621,7 +1605,7 @@ void CInput::UpdateText(int from, int to_before, int to_after) if (destroy_row_to != m_CharacterPositions.end()) to = destroy_row_to->m_ListStart; // notice it will iterate [from, to), so it will never reach to. else - to = (int)caption.length(); + to = static_cast(m_Caption.length()); // Setup the first row @@ -1648,7 +1632,7 @@ void CInput::UpdateText(int from, int to_before, int to_after) check_point_row_start += delta; check_point_row_end += delta; - if (to != (int)caption.length()) + if (to != static_cast(m_Caption.length())) to += delta; } } @@ -1661,9 +1645,9 @@ void CInput::UpdateText(int from, int to_before, int to_after) for (int i = from; i < to; ++i) { - if (caption[i] == L'\n' && multiline) + if (m_Caption[i] == L'\n' && m_MultiLine) { - if (i == to-1 && to != (int)caption.length()) + if (i == to-1 && to != static_cast(m_Caption.length())) break; // it will be added outside current_line = m_CharacterPositions.insert(current_line, row); @@ -1676,16 +1660,16 @@ void CInput::UpdateText(int from, int to_before, int to_after) } else { - if (caption[i] == L' '/* || TODO Gee (2004-10-13): the '-' disappears, fix. - caption[i] == L'-'*/) + if (m_Caption[i] == L' '/* || TODO Gee (2004-10-13): the '-' disappears, fix. + m_Caption[i] == L'-'*/) last_word_started = i+1; - if (!mask) - x_pos += (float)font.GetCharacterWidth(caption[i]); + if (!m_Mask) + x_pos += font.GetCharacterWidth(m_Caption[i]); else - x_pos += (float)font.GetCharacterWidth(mask_char); + x_pos += font.GetCharacterWidth(mask_char); - if (x_pos >= GetTextAreaWidth() && multiline) + if (x_pos >= GetTextAreaWidth() && m_MultiLine) { // The following decides whether it will word-wrap a word, // or if it's only one word on the line, where it has to @@ -1806,7 +1790,7 @@ void CInput::UpdateText(int from, int to_before, int to_after) if (destroy_row_to != m_CharacterPositions.end()) to = destroy_row_to->m_ListStart; // notice it will iterate [from, to[, so it will never reach to. else - to = (int)caption.length(); + to = static_cast(m_Caption.length()); // Set current line, new rows will be added before current_line, so @@ -1832,9 +1816,9 @@ void CInput::UpdateText(int from, int to_before, int to_after) // add the final row (even if empty) m_CharacterPositions.insert(current_line, row); - if (GetSetting("scrollbar")) + if (m_ScrollBar) { - GetScrollBar(0).SetScrollRange(m_CharacterPositions.size() * font.GetLineSpacing() + buffer_zone*2.f); + GetScrollBar(0).SetScrollRange(m_CharacterPositions.size() * font.GetLineSpacing() + m_BufferZone * 2.f); GetScrollBar(0).SetScrollSpace(m_CachedActualSize.GetHeight()); } } @@ -1844,9 +1828,6 @@ int CInput::GetMouseHoveringTextPosition() const if (m_CharacterPositions.empty()) return 0; - const float buffer_zone = GetSetting("buffer_zone"); - const bool multiline = GetSetting("multiline"); - // Return position int retPosition; @@ -1854,21 +1835,21 @@ int CInput::GetMouseHoveringTextPosition() const CPos mouse = m_pGUI.GetMousePos(); - if (multiline) + if (m_MultiLine) { float scroll = 0.f; - if (GetSetting("scrollbar")) + if (m_ScrollBar) scroll = GetScrollBarPos(0); // Now get the height of the font. // TODO: Get the real font - CFontMetrics font(CStrIntern(GetSetting("font").ToUTF8())); + CFontMetrics font(CStrIntern(m_Font.ToUTF8())); float spacing = (float)font.GetLineSpacing(); // Change mouse position relative to text. mouse -= m_CachedActualSize.TopLeft(); - mouse.x -= buffer_zone; - mouse.y += scroll - buffer_zone; + mouse.x -= m_BufferZone; + mouse.y += scroll - m_BufferZone; int row = (int)((mouse.y) / spacing); @@ -1889,7 +1870,7 @@ int CInput::GetMouseHoveringTextPosition() const // current is already set to begin, // but we'll change the mouse.x to fit our horizontal scrolling mouse -= m_CachedActualSize.TopLeft(); - mouse.x -= buffer_zone - m_HorizontalScroll; + mouse.x -= m_BufferZone - m_HorizontalScroll; // mouse.y is moot } @@ -1939,8 +1920,6 @@ int CInput::GetXTextPosition(const std::list::const_iterator& current, con void CInput::DeleteCurSelection() { - CStrW& pCaption = GetSetting("caption"); - int virtualFrom; int virtualTo; @@ -1955,9 +1934,9 @@ void CInput::DeleteCurSelection() virtualTo = m_iBufferPos; } - pCaption = - pCaption.Left(virtualFrom) + - pCaption.Right(static_cast(pCaption.length()) - virtualTo); + m_Caption = + m_Caption.Left(virtualFrom) + + m_Caption.Right(static_cast(m_Caption.length()) - virtualTo); UpdateText(virtualFrom, virtualTo, virtualFrom); @@ -1975,29 +1954,25 @@ bool CInput::SelectingText() const float CInput::GetTextAreaWidth() { - const float buffer_zone = GetSetting("buffer_zone"); + if (m_ScrollBar && GetScrollBar(0).GetStyle()) + return m_CachedActualSize.GetWidth() - m_BufferZone * 2.f - GetScrollBar(0).GetStyle()->m_Width; - if (GetSetting("scrollbar") && GetScrollBar(0).GetStyle()) - return m_CachedActualSize.GetWidth() - buffer_zone*2.f - GetScrollBar(0).GetStyle()->m_Width; - else - return m_CachedActualSize.GetWidth() - buffer_zone*2.f; + return m_CachedActualSize.GetWidth() - m_BufferZone * 2.f; } void CInput::UpdateAutoScroll() { - const float buffer_zone = GetSetting("buffer_zone"); - // Autoscrolling up and down - if (GetSetting("multiline")) + if (m_MultiLine) { - if (!GetSetting("scrollbar")) + if (!m_ScrollBar) return; const float scroll = GetScrollBar(0).GetPos(); // Now get the height of the font. // TODO: Get the real font - CFontMetrics font(CStrIntern(GetSetting("font").ToUTF8())); + CFontMetrics font(CStrIntern(m_Font.ToUTF8())); float spacing = (float)font.GetLineSpacing(); //float height = font.GetHeight(); @@ -2017,15 +1992,15 @@ void CInput::UpdateAutoScroll() } // If scrolling down - if (-scroll + (float)(row+1) * spacing + buffer_zone*2.f > m_CachedActualSize.GetHeight()) + if (-scroll + static_cast(row + 1) * spacing + m_BufferZone * 2.f > m_CachedActualSize.GetHeight()) { - // Scroll so the selected row is shown completely, also with buffer_zone length to the edge. - GetScrollBar(0).SetPos((float)(row+1) * spacing - m_CachedActualSize.GetHeight() + buffer_zone*2.f); + // Scroll so the selected row is shown completely, also with m_BufferZone length to the edge. + GetScrollBar(0).SetPos(static_cast(row + 1) * spacing - m_CachedActualSize.GetHeight() + m_BufferZone * 2.f); } // If scrolling up else if (-scroll + (float)row * spacing < 0.f) { - // Scroll so the selected row is shown completely, also with buffer_zone length to the edge. + // Scroll so the selected row is shown completely, also with m_BufferZone length to the edge. GetScrollBar(0).SetPos((float)row * spacing); } } @@ -2050,8 +2025,8 @@ void CInput::UpdateAutoScroll() } // Check if outside to the right - if (x_position - m_HorizontalScroll + buffer_zone*2.f > m_CachedActualSize.GetWidth()) - m_HorizontalScroll = x_position - m_CachedActualSize.GetWidth() + buffer_zone*2.f; + if (x_position - m_HorizontalScroll + m_BufferZone * 2.f > m_CachedActualSize.GetWidth()) + m_HorizontalScroll = x_position - m_CachedActualSize.GetWidth() + m_BufferZone * 2.f; // Check if outside to the left if (x_position - m_HorizontalScroll < 0.f) @@ -2059,12 +2034,12 @@ void CInput::UpdateAutoScroll() // Check if the text doesn't even fill up to the right edge even though scrolling is done. if (m_HorizontalScroll != 0.f && - x_total - m_HorizontalScroll + buffer_zone*2.f < m_CachedActualSize.GetWidth()) - m_HorizontalScroll = x_total - m_CachedActualSize.GetWidth() + buffer_zone*2.f; + x_total - m_HorizontalScroll + m_BufferZone * 2.f < m_CachedActualSize.GetWidth()) + m_HorizontalScroll = x_total - m_CachedActualSize.GetWidth() + m_BufferZone * 2.f; // Now this is the fail-safe, if x_total isn't even the length of the control, // remove all scrolling - if (x_total + buffer_zone*2.f < m_CachedActualSize.GetWidth()) + if (x_total + m_BufferZone * 2.f < m_CachedActualSize.GetWidth()) m_HorizontalScroll = 0.f; } } diff --git a/source/gui/CInput.h b/source/gui/CInput.h index ae1894009c..6ad32b8966 100644 --- a/source/gui/CInput.h +++ b/source/gui/CInput.h @@ -19,6 +19,7 @@ #define INCLUDED_CINPUT #include "gui/IGUIScrollBarOwner.h" +#include "gui/CGUISprite.h" #include "lib/external_libraries/libsdl.h" #include @@ -68,12 +69,12 @@ protected: /** * Handle events manually to catch keys which change the text. */ - virtual void ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode, CStrW& pCaption); + virtual void ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode); /** * Handle events manually to catch keys which don't change the text. */ - virtual void ManuallyImmutableHandleKeyDownEvent(const SDL_Keycode keyCode, CStrW& pCaption); + virtual void ManuallyImmutableHandleKeyDownEvent(const SDL_Keycode keyCode); /** * Handle hotkey events (called by ManuallyHandleEvent) @@ -189,8 +190,23 @@ protected: /// If the cursor should be drawn or not. bool m_CursorVisState; - /// If enabled, it is only allowed to select and copy text. + // Settings + i32 m_BufferPosition; + float m_BufferZone; + CStrW m_Caption; + i32 m_CellID; + CStrW m_Font; + CStrW m_MaskChar; + bool m_Mask; + i32 m_MaxLength; + bool m_MultiLine; bool m_Readonly; + bool m_ScrollBar; + CStr m_ScrollBarStyle; + CGUISpriteInstance m_Sprite; + CGUISpriteInstance m_SpriteSelectArea; + CGUIColor m_TextColor; + CGUIColor m_TextColorSelected; }; #endif // INCLUDED_CINPUT diff --git a/source/gui/CList.cpp b/source/gui/CList.cpp index 79c4195df4..a46e87b954 100644 --- a/source/gui/CList.cpp +++ b/source/gui/CList.cpp @@ -27,29 +27,49 @@ #include "lib/timer.h" CList::CList(CGUI& pGUI) - : IGUIObject(pGUI), IGUITextOwner(pGUI), IGUIScrollBarOwner(pGUI), - m_Modified(false), m_PrevSelectedItem(-1), m_LastItemClickTime(0) + : IGUIObject(pGUI), + IGUITextOwner(pGUI), + IGUIScrollBarOwner(pGUI), + m_Modified(false), + m_PrevSelectedItem(-1), + m_LastItemClickTime(0), + m_BufferZone(), + m_Font(), + m_ScrollBar(), + m_ScrollBarStyle(), + m_SoundDisabled(), + m_SoundSelected(), + m_Sprite(), + m_SpriteSelectArea(), + m_CellID(), + m_TextAlign(), + m_TextColor(), + m_TextColorSelected(), + m_Selected(), + m_AutoScroll(), + m_Hovered(), + m_List(), + m_ListData() { + RegisterSetting("buffer_zone", m_BufferZone); + RegisterSetting("font", m_Font); + RegisterSetting("scrollbar", m_ScrollBar); + RegisterSetting("scrollbar_style", m_ScrollBarStyle); + RegisterSetting("sound_disabled", m_SoundDisabled); + RegisterSetting("sound_selected", m_SoundSelected); + RegisterSetting("sprite", m_Sprite); // Add sprite_disabled! TODO - AddSetting("buffer_zone"); - AddSetting("font"); - AddSetting("scrollbar"); - AddSetting("scrollbar_style"); - AddSetting("sound_disabled"); - AddSetting("sound_selected"); - AddSetting("sprite"); - AddSetting("sprite_selectarea"); - AddSetting("cell_id"); - AddSetting("text_align"); - AddSetting("textcolor"); - AddSetting("textcolor_selected"); - AddSetting("selected"); // Index selected. -1 is none. - AddSetting("auto_scroll"); - AddSetting("hovered"); - + RegisterSetting("sprite_selectarea", m_SpriteSelectArea); + RegisterSetting("cell_id", m_CellID); + RegisterSetting("text_align", m_TextAlign); + RegisterSetting("textcolor", m_TextColor); + RegisterSetting("textcolor_selected", m_TextColorSelected); + RegisterSetting("selected", m_Selected); // Index selected. -1 is none. + RegisterSetting("auto_scroll", m_AutoScroll); + RegisterSetting("hovered", m_Hovered); // Each list item has both a name (in 'list') and an associated data string (in 'list_data') - AddSetting("list"); - AddSetting("list_data"); + RegisterSetting("list", m_List); + RegisterSetting("list_data", m_ListData); SetSetting("scrollbar", false, true); SetSetting("selected", -1, true); @@ -69,53 +89,44 @@ CList::~CList() void CList::SetupText() { m_Modified = true; - const CGUIList& pList = GetSetting("list"); - //ENSURE(m_GeneratedTexts.size()>=1); - - m_ItemsYPositions.resize(pList.m_Items.size() + 1); + m_ItemsYPositions.resize(m_List.m_Items.size() + 1); // Delete all generated texts. Some could probably be saved, // but this is easier, and this function will never be called // continuously, or even often, so it'll probably be okay. m_GeneratedTexts.clear(); - const CStrW& font = GetSetting("font"); - - const bool scrollbar = GetSetting("scrollbar"); - float width = GetListRect().GetWidth(); // remove scrollbar if applicable - if (scrollbar && GetScrollBar(0).GetStyle()) + if (m_ScrollBar && GetScrollBar(0).GetStyle()) width -= GetScrollBar(0).GetStyle()->m_Width; - const float buffer_zone = GetSetting("buffer_zone"); - // Generate texts float buffered_y = 0.f; - for (size_t i = 0; i < pList.m_Items.size(); ++i) + for (size_t i = 0; i < m_List.m_Items.size(); ++i) { CGUIText* text; - if (!pList.m_Items[i].GetOriginalString().empty()) - text = &AddText(pList.m_Items[i], font, width, buffer_zone, this); + if (!m_List.m_Items[i].GetOriginalString().empty()) + text = &AddText(m_List.m_Items[i], m_Font, width, m_BufferZone, this); else { // Minimum height of a space character of the current font size CGUIString align_string; align_string.SetValue(L" "); - text = &AddText(align_string, font, width, buffer_zone, this); + text = &AddText(align_string, m_Font, width, m_BufferZone, this); } m_ItemsYPositions[i] = buffered_y; buffered_y += text->GetSize().cy; } - m_ItemsYPositions[pList.m_Items.size()] = buffered_y; + m_ItemsYPositions[m_List.m_Items.size()] = buffered_y; // Setup scrollbar - if (scrollbar) + if (m_ScrollBar) { GetScrollBar(0).SetScrollRange(m_ItemsYPositions.back()); GetScrollBar(0).SetScrollSpace(GetListRect().GetHeight()); @@ -145,7 +156,7 @@ void CList::HandleMessage(SGUIMessage& Message) { // TODO: Check range - if (GetSetting("auto_scroll")) + if (m_AutoScroll) UpdateAutoScroll(); // TODO only works if lower-case, shouldn't it be made case sensitive instead? @@ -158,7 +169,7 @@ void CList::HandleMessage(SGUIMessage& Message) // Update scrollbar if (Message.value == "scrollbar_style") { - GetScrollBar(0).SetScrollBarStyle(GetSetting(Message.value)); + GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle); SetupText(); } @@ -166,9 +177,9 @@ void CList::HandleMessage(SGUIMessage& Message) case GUIM_MOUSE_PRESS_LEFT: { - if (!GetSetting("enabled")) + if (!m_Enabled) { - PlaySound("sound_disabled"); + PlaySound(m_SoundDisabled); break; } @@ -177,7 +188,7 @@ void CList::HandleMessage(SGUIMessage& Message) break; SetSetting("selected", hovered, true); UpdateAutoScroll(); - PlaySound("sound_selected"); + PlaySound(m_SoundSelected); if (timer_Time() - m_LastItemClickTime < SELECT_DBLCLICK_RATE && hovered == m_PrevSelectedItem) this->SendEvent(GUIM_MOUSE_DBLCLICK_LEFT_ITEM, "mouseleftdoubleclickitem"); @@ -191,7 +202,7 @@ void CList::HandleMessage(SGUIMessage& Message) case GUIM_MOUSE_LEAVE: { - if (GetSetting("hovered") == -1) + if (m_Hovered == -1) break; SetSetting("hovered", -1, true); @@ -202,7 +213,7 @@ void CList::HandleMessage(SGUIMessage& Message) case GUIM_MOUSE_OVER: { int hovered = GetHoveredItem(); - if (hovered == GetSetting("hovered")) + if (hovered == m_Hovered) break; SetSetting("hovered", hovered, true); @@ -212,7 +223,7 @@ void CList::HandleMessage(SGUIMessage& Message) case GUIM_LOAD: { - GetScrollBar(0).SetScrollBarStyle(GetSetting("scrollbar_style")); + GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle); break; } @@ -277,30 +288,24 @@ InReaction CList::ManuallyHandleEvent(const SDL_Event_* ev) void CList::Draw() { - DrawList(GetSetting("selected"), "sprite", "sprite_selectarea", "textcolor"); + DrawList(m_Selected, m_Sprite, m_SpriteSelectArea, m_TextColor); } -void CList::DrawList(const int& selected, const CStr& _sprite, const CStr& _sprite_selected, const CStr& _textcolor) +void CList::DrawList(const int& selected, const CGUISpriteInstance& sprite, const CGUISpriteInstance& sprite_selectarea, const CGUIColor& textcolor) { float bz = GetBufferedZ(); // First call draw on ScrollBarOwner - const bool scrollbar = GetSetting("scrollbar"); - - if (scrollbar) + if (m_ScrollBar) IGUIScrollBarOwner::Draw(); { CRect rect = GetListRect(); - CGUISpriteInstance& sprite = GetSetting(_sprite); - CGUISpriteInstance& sprite_selectarea = GetSetting(_sprite_selected); - - const int cell_id = GetSetting("cell_id"); - m_pGUI.DrawSprite(sprite, cell_id, bz, rect); + m_pGUI.DrawSprite(sprite, m_CellID, bz, rect); float scroll = 0.f; - if (scrollbar) + if (m_ScrollBar) scroll = GetScrollBar(0).GetPos(); if (selected >= 0 && selected+1 < (int)m_ItemsYPositions.size()) @@ -317,7 +322,7 @@ void CList::DrawList(const int& selected, const CStr& _sprite, const CStr& _spri if (rect_sel.top < rect.top) rect_sel.top = rect.top; - if (scrollbar) + if (m_ScrollBar) { // Remove any overlapping area of the scrollbar. if (rect_sel.right > GetScrollBar(0).GetOuterRect().left && @@ -329,14 +334,11 @@ void CList::DrawList(const int& selected, const CStr& _sprite, const CStr& _spri rect_sel.left = GetScrollBar(0).GetOuterRect().right; } - m_pGUI.DrawSprite(sprite_selectarea, cell_id, bz+0.05f, rect_sel); + m_pGUI.DrawSprite(sprite_selectarea, m_CellID, bz + 0.05f, rect_sel); } } - const CGUIList& pList = GetSetting("list"); - const CGUIColor& color = GetSetting(_textcolor); - - for (size_t i = 0; i < pList.m_Items.size(); ++i) + for (size_t i = 0; i < m_List.m_Items.size(); ++i) { if (m_ItemsYPositions[i+1] - scroll < 0 || m_ItemsYPositions[i] - scroll > rect.GetHeight()) @@ -345,7 +347,7 @@ void CList::DrawList(const int& selected, const CStr& _sprite, const CStr& _spri // Clipping area (we'll have to substract the scrollbar) CRect cliparea = GetListRect(); - if (scrollbar) + if (m_ScrollBar) { if (cliparea.right > GetScrollBar(0).GetOuterRect().left && cliparea.right <= GetScrollBar(0).GetOuterRect().right) @@ -356,7 +358,7 @@ void CList::DrawList(const int& selected, const CStr& _sprite, const CStr& _spri cliparea.left = GetScrollBar(0).GetOuterRect().right; } - DrawText(i, color, rect.TopLeft() - CPos(0.f, scroll - m_ItemsYPositions[i]), bz + 0.1f, cliparea); + DrawText(i, textcolor, rect.TopLeft() - CPos(0.f, scroll - m_ItemsYPositions[i]), bz + 0.1f, cliparea); } } } @@ -367,13 +369,12 @@ void CList::AddItem(const CStrW& str, const CStrW& data) gui_string.SetValue(str); // Do not send a settings-changed message - CGUIList& pList = GetSetting("list"); - pList.m_Items.push_back(gui_string); + m_List.m_Items.push_back(gui_string); CGUIString data_string; data_string.SetValue(data); - CGUIList& pListData = GetSetting("list_data"); - pListData.m_Items.push_back(data_string); + + m_ListData.m_Items.push_back(data_string); // TODO Temp SetupText(); @@ -394,87 +395,73 @@ bool CList::HandleAdditionalChildren(const XMBElement& child, CXeromyces* pFile) void CList::SelectNextElement() { - int selected = GetSetting("selected"); - - const CGUIList& pList = GetSetting("list"); - - if (selected != static_cast(pList.m_Items.size()) - 1) + if (m_Selected != static_cast(m_List.m_Items.size()) - 1) { - ++selected; - SetSetting("selected", selected, true); - PlaySound("sound_selected"); + SetSetting("selected", m_Selected + 1, true); + PlaySound(m_SoundSelected); } } void CList::SelectPrevElement() { - int selected = GetSetting("selected"); - - if (selected > 0) + if (m_Selected > 0) { - --selected; - SetSetting("selected", selected, true); - PlaySound("sound_selected"); + SetSetting("selected", m_Selected - 1, true); + PlaySound(m_SoundSelected); } } void CList::SelectFirstElement() { - if (GetSetting("selected") >= 0) + if (m_Selected >= 0) SetSetting("selected", 0, true); } void CList::SelectLastElement() { - const CGUIList& pList = GetSetting("list"); - const int index = static_cast(pList.m_Items.size()) - 1; + const int index = static_cast(m_List.m_Items.size()) - 1; - if (GetSetting("selected") != index) + if (m_Selected != index) SetSetting("selected", index, true); } void CList::UpdateAutoScroll() { - const int selected = GetSetting("selected"); - const bool scrollbar = GetSetting("scrollbar"); - // No scrollbar, no scrolling (at least it's not made to work properly). - if (!scrollbar || selected < 0 || static_cast(selected) >= m_ItemsYPositions.size()) + if (!m_ScrollBar || m_Selected < 0 || static_cast(m_Selected) >= m_ItemsYPositions.size()) return; float scroll = GetScrollBar(0).GetPos(); // Check upper boundary - if (m_ItemsYPositions[selected] < scroll) + if (m_ItemsYPositions[m_Selected] < scroll) { - GetScrollBar(0).SetPos(m_ItemsYPositions[selected]); + GetScrollBar(0).SetPos(m_ItemsYPositions[m_Selected]); return; // this means, if it wants to align both up and down at the same time // this will have precedence. } // Check lower boundary CRect rect = GetListRect(); - if (m_ItemsYPositions[selected+1]-rect.GetHeight() > scroll) - GetScrollBar(0).SetPos(m_ItemsYPositions[selected+1]-rect.GetHeight()); + if (m_ItemsYPositions[m_Selected+1]-rect.GetHeight() > scroll) + GetScrollBar(0).SetPos(m_ItemsYPositions[m_Selected+1]-rect.GetHeight()); } int CList::GetHoveredItem() { - const bool scrollbar = GetSetting("scrollbar"); - const float scroll = scrollbar ? GetScrollBar(0).GetPos() : 0.f; + const float scroll = m_ScrollBar ? GetScrollBar(0).GetPos() : 0.f; const CRect& rect = GetListRect(); CPos mouse = m_pGUI.GetMousePos(); mouse.y += scroll; // Mouse is over scrollbar - if (scrollbar && GetScrollBar(0).IsVisible() && + if (m_ScrollBar && GetScrollBar(0).IsVisible() && mouse.x >= GetScrollBar(0).GetOuterRect().left && mouse.x <= GetScrollBar(0).GetOuterRect().right) return -1; - const CGUIList& pList = GetSetting("list"); - for (size_t i = 0; i < pList.m_Items.size(); ++i) + for (size_t i = 0; i < m_List.m_Items.size(); ++i) if (mouse.y >= rect.top + m_ItemsYPositions[i] && mouse.y < rect.top + m_ItemsYPositions[i + 1]) return i; diff --git a/source/gui/CList.h b/source/gui/CList.h index a3d3f7283d..395a7e3734 100644 --- a/source/gui/CList.h +++ b/source/gui/CList.h @@ -18,6 +18,8 @@ #ifndef INCLUDED_CLIST #define INCLUDED_CLIST +#include "gui/CGUIList.h" +#include "gui/CGUISprite.h" #include "gui/IGUIScrollBarOwner.h" #include "gui/IGUITextOwner.h" @@ -90,7 +92,7 @@ protected: // Extended drawing interface, this is so that classes built on the this one // can use other sprite names. - virtual void DrawList(const int& selected, const CStr& _sprite, const CStr& _sprite_selected, const CStr& _textcolor); + virtual void DrawList(const int& selected, const CGUISpriteInstance& sprite, const CGUISpriteInstance& sprite_selected, const CGUIColor& textcolor); // Get the area of the list. This is so that it can easily be changed, like in CDropDown // where the area is not equal to m_CachedActualSize. @@ -110,6 +112,25 @@ protected: virtual int GetHoveredItem(); + // Settings + float m_BufferZone; + CStrW m_Font; + bool m_ScrollBar; + CStr m_ScrollBarStyle; + CStrW m_SoundDisabled; + CStrW m_SoundSelected; + CGUISpriteInstance m_Sprite; + CGUISpriteInstance m_SpriteSelectArea; + i32 m_CellID; + EAlign m_TextAlign; + CGUIColor m_TextColor; + CGUIColor m_TextColorSelected; + i32 m_Selected; + bool m_AutoScroll; + i32 m_Hovered; + CGUIList m_List; + CGUIList m_ListData; + private: // Whether the list's items have been modified since last handling a message. bool m_Modified; diff --git a/source/gui/COList.cpp b/source/gui/COList.cpp index 9b617ed109..f4efd36b22 100644 --- a/source/gui/COList.cpp +++ b/source/gui/COList.cpp @@ -30,37 +30,39 @@ const float SORT_SPRITE_DIM = 16.0f; const CPos COLUMN_SHIFT = CPos(0, 4); COList::COList(CGUI& pGUI) - : CList(pGUI), IGUIObject(pGUI) + : CList(pGUI), + IGUIObject(pGUI), + m_SpriteHeading(), + m_Sortable(), + m_SelectedColumn(), + m_SelectedColumnOrder(), + m_SpriteAsc(), + m_SpriteDesc(), + m_SpriteNotSorted() { - AddSetting("sprite_heading"); - AddSetting("sortable"); // The actual sorting is done in JS for more versatility - AddSetting("selected_column"); - AddSetting("selected_column_order"); - AddSetting("sprite_asc"); // Show the order of sorting - AddSetting("sprite_desc"); - AddSetting("sprite_not_sorted"); + RegisterSetting("sprite_heading", m_SpriteHeading); + RegisterSetting("sortable", m_Sortable); // The actual sorting is done in JS for more versatility + RegisterSetting("selected_column", m_SelectedColumn); + RegisterSetting("selected_column_order", m_SelectedColumnOrder); + RegisterSetting("sprite_asc", m_SpriteAsc); // Show the order of sorting + RegisterSetting("sprite_desc", m_SpriteDesc); + RegisterSetting("sprite_not_sorted", m_SpriteNotSorted); } void COList::SetupText() { - const CGUIList& pList = GetSetting("list"); - m_ItemsYPositions.resize(pList.m_Items.size() + 1); + m_ItemsYPositions.resize(m_List.m_Items.size() + 1); // Delete all generated texts. Some could probably be saved, // but this is easier, and this function will never be called // continuously, or even often, so it'll probably be okay. m_GeneratedTexts.clear(); - const CStrW& font = GetSetting("font"); - const bool scrollbar = GetSetting("scrollbar"); - m_TotalAvailableColumnWidth = GetListRect().GetWidth(); // remove scrollbar if applicable - if (scrollbar && GetScrollBar(0).GetStyle()) + if (m_ScrollBar && GetScrollBar(0).GetStyle()) m_TotalAvailableColumnWidth -= GetScrollBar(0).GetStyle()->m_Width; - const float buffer_zone = GetSetting("buffer_zone"); - m_HeadingHeight = SORT_SPRITE_DIM; // At least the size of the sorting sprite for (const COListColumn& column : m_Columns) @@ -72,14 +74,14 @@ void COList::SetupText() CGUIString gui_string; gui_string.SetValue(column.m_Heading); - const CGUIText& text = AddText(gui_string, font, width, buffer_zone, this); + const CGUIText& text = AddText(gui_string, m_Font, width, m_BufferZone, this); m_HeadingHeight = std::max(m_HeadingHeight, text.GetSize().cy + COLUMN_SHIFT.y); } // Generate texts float buffered_y = 0.f; - for (size_t i = 0; i < pList.m_Items.size(); ++i) + for (size_t i = 0; i < m_List.m_Items.size(); ++i) { m_ItemsYPositions[i] = buffered_y; float shift = 0.0f; @@ -89,25 +91,24 @@ void COList::SetupText() if (column.m_Width > 0 && column.m_Width < 1) width *= m_TotalAvailableColumnWidth; - CGUIList& pList_c = GetSetting("list_" + column.m_Id); CGUIText* text; - if (!pList_c.m_Items[i].GetOriginalString().empty()) - text = &AddText(pList_c.m_Items[i], font, width, buffer_zone, this); + if (!column.m_List.m_Items[i].GetOriginalString().empty()) + text = &AddText(column.m_List.m_Items[i], m_Font, width, m_BufferZone, this); else { // Minimum height of a space character of the current font size CGUIString align_string; align_string.SetValue(L" "); - text = &AddText(align_string, font, width, buffer_zone, this); + text = &AddText(align_string, m_Font, width, m_BufferZone, this); } shift = std::max(shift, text->GetSize().cy); } buffered_y += shift; } - m_ItemsYPositions[pList.m_Items.size()] = buffered_y; + m_ItemsYPositions[m_List.m_Items.size()] = buffered_y; - if (scrollbar) + if (m_ScrollBar) { CRect rect = GetListRect(); GetScrollBar(0).SetScrollRange(m_ItemsYPositions.back()); @@ -134,21 +135,17 @@ void COList::HandleMessage(SGUIMessage& Message) // If somebody clicks on the column heading case GUIM_MOUSE_PRESS_LEFT: { - if (!GetSetting("sortable")) + if (!m_Sortable) return; const CPos& mouse = m_pGUI.GetMousePos(); if (!m_CachedActualSize.PointInside(mouse)) return; - // Copies, so that these settings are only modfied via SetSettings later. - CStr selectedColumn = GetSetting("selected_column"); - int selectedColumnOrder = GetSetting("selected_column_order"); - float xpos = 0; for (const COListColumn& column : m_Columns) { - if (GetSetting("hidden_" + column.m_Id)) + if (column.m_Hidden) continue; float width = column.m_Width; @@ -160,19 +157,17 @@ void COList::HandleMessage(SGUIMessage& Message) mouse.x < leftTopCorner.x + width && mouse.y < leftTopCorner.y + m_HeadingHeight) { - if (column.m_Id != selectedColumn) + if (column.m_Id != m_SelectedColumn) { - selectedColumnOrder = 1; - selectedColumn = column.m_Id; + SetSetting("selected_column_order", -1, true); + CStr selected_column = column.m_Id; + SetSetting("selected_column", selected_column, true); } else - selectedColumnOrder = -selectedColumnOrder; - - SetSetting("selected_column", selectedColumn, true); - SetSetting("selected_column_order", selectedColumnOrder, true); + SetSetting("selected_column_order", -m_SelectedColumnOrder, true); ScriptEvent("selectioncolumnchange"); - PlaySound("sound_selected"); + PlaySound(m_SoundSelected); return; } xpos += width; @@ -202,7 +197,6 @@ bool COList::HandleAdditionalChildren(const XMBElement& child, CXeromyces* pFile else if (child.GetNodeName() == elmt_column) { COListColumn column; - bool hidden = false; for (XMBAttribute attr : child.GetAttributes()) { @@ -220,8 +214,11 @@ bool COList::HandleAdditionalChildren(const XMBElement& child, CXeromyces* pFile } else if (attr_name == "hidden") { + bool hidden = false; if (!CGUI::ParseString(&m_pGUI, attr_value.FromUTF8(), hidden)) LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name.c_str(), attr_value.c_str()); + else + column.m_Hidden = hidden; } else if (attr_name == "width") { @@ -272,39 +269,38 @@ bool COList::HandleAdditionalChildren(const XMBElement& child, CXeromyces* pFile } } - AddSetting("list_" + column.m_Id); - AddSetting("hidden_" + column.m_Id); - SetSetting("hidden_" + column.m_Id, hidden, true); - m_Columns.emplace_back(std::move(column)); - - SetupText(); - return true; } return false; } -void COList::DrawList(const int& selected, const CStr& _sprite, const CStr& _sprite_selected, const CStr& _textcolor) +void COList::AdditionalChildrenHandled() +{ + SetupText(); + + // Do this after the last push_back call to avoid iterator invalidation + for (COListColumn& column : m_Columns) + { + RegisterSetting("list_" + column.m_Id, column.m_List); + RegisterSetting("hidden_" + column.m_Id, column.m_Hidden); + } +} + +void COList::DrawList(const int& selected, const CGUISpriteInstance& sprite, const CGUISpriteInstance& sprite_selected, const CGUIColor& textcolor) { const float bz = GetBufferedZ(); - const bool scrollbar = GetSetting("scrollbar"); - if (scrollbar) + if (m_ScrollBar) IGUIScrollBarOwner::Draw(); CRect rect = GetListRect(); - CGUISpriteInstance& sprite = GetSetting(_sprite); - CGUISpriteInstance& sprite_selectarea = GetSetting(_sprite_selected); - - const int cell_id = GetSetting("cell_id"); - - m_pGUI.DrawSprite(sprite, cell_id, bz, rect); + m_pGUI.DrawSprite(sprite, m_CellID, bz, rect); float scroll = 0.f; - if (scrollbar) + if (m_ScrollBar) scroll = GetScrollBar(0).GetPos(); // Draw item selection @@ -324,7 +320,7 @@ void COList::DrawList(const int& selected, const CStr& _sprite, const CStr& _spr if (rect_sel.top < rect.top) rect_sel.top = rect.top; - if (scrollbar) + if (m_ScrollBar) { // Remove any overlapping area of the scrollbar. if (rect_sel.right > GetScrollBar(0).GetOuterRect().left && @@ -337,65 +333,62 @@ void COList::DrawList(const int& selected, const CStr& _sprite, const CStr& _spr } // Draw item selection - m_pGUI.DrawSprite(sprite_selectarea, cell_id, bz+0.05f, rect_sel); + m_pGUI.DrawSprite(sprite_selected, m_CellID, bz + 0.05f, rect_sel); } } // Draw line above column header - CGUISpriteInstance& sprite_heading = GetSetting("sprite_heading"); CRect rect_head(m_CachedActualSize.left, m_CachedActualSize.top, m_CachedActualSize.right, m_CachedActualSize.top + m_HeadingHeight); - m_pGUI.DrawSprite(sprite_heading, cell_id, bz, rect_head); + m_pGUI.DrawSprite(m_SpriteHeading, m_CellID, bz, rect_head); // Draw column headers - const bool sortable = GetSetting("sortable"); - const CStr& selectedColumn = GetSetting("selected_column"); - const int selectedColumnOrder = GetSetting("selected_column_order"); - const CGUIColor& color = GetSetting(_textcolor); - float xpos = 0; - for (size_t col = 0; col < m_Columns.size(); ++col) + size_t col = 0; + for (const COListColumn& column : m_Columns) { - if (GetSetting("hidden_" + m_Columns[col].m_Id)) + if (column.m_Hidden) + { + ++col; continue; + } // Check if it's a decimal value, and if so, assume relative positioning. - float width = m_Columns[col].m_Width; - if (m_Columns[col].m_Width < 1 && m_Columns[col].m_Width > 0) + float width = column.m_Width; + if (column.m_Width < 1 && column.m_Width > 0) width *= m_TotalAvailableColumnWidth; CPos leftTopCorner = m_CachedActualSize.TopLeft() + CPos(xpos, 0); // Draw sort arrows in colum header - if (sortable) + if (m_Sortable) { - CStr spriteName; - if (selectedColumn == m_Columns[col].m_Id) + const CGUISpriteInstance* sprite; + if (m_SelectedColumn == column.m_Id) { - if (selectedColumnOrder == 0) + if (m_SelectedColumnOrder == 0) LOGERROR("selected_column_order must not be 0"); - if (selectedColumnOrder != -1) - spriteName = "sprite_asc"; + if (m_SelectedColumnOrder != -1) + sprite = &m_SpriteAsc; else - spriteName = "sprite_desc"; + sprite = &m_SpriteDesc; } else - spriteName = "sprite_not_sorted"; + sprite = &m_SpriteNotSorted; - CGUISpriteInstance& sprite = GetSetting(spriteName); - m_pGUI.DrawSprite(sprite, cell_id, bz + 0.1f, CRect(leftTopCorner + CPos(width - SORT_SPRITE_DIM, 0), leftTopCorner + CPos(width, SORT_SPRITE_DIM))); + m_pGUI.DrawSprite(*sprite, m_CellID, bz + 0.1f, CRect(leftTopCorner + CPos(width - SORT_SPRITE_DIM, 0), leftTopCorner + CPos(width, SORT_SPRITE_DIM))); } // Draw column header text - DrawText(col, color, leftTopCorner + COLUMN_SHIFT, bz + 0.1f, rect_head); + DrawText(col, textcolor, leftTopCorner + COLUMN_SHIFT, bz + 0.1f, rect_head); xpos += width; + ++col; } // Draw list items for each column - const CGUIList& pList = GetSetting("list"); const size_t objectsCount = m_Columns.size(); - for (size_t i = 0; i < pList.m_Items.size(); ++i) + for (size_t i = 0; i < m_List.m_Items.size(); ++i) { if (m_ItemsYPositions[i+1] - scroll < 0 || m_ItemsYPositions[i] - scroll > rect.GetHeight()) @@ -406,7 +399,7 @@ void COList::DrawList(const int& selected, const CStr& _sprite, const CStr& _spr // Clipping area (we'll have to substract the scrollbar) CRect cliparea = GetListRect(); - if (scrollbar) + if (m_ScrollBar) { if (cliparea.right > GetScrollBar(0).GetOuterRect().left && cliparea.right <= GetScrollBar(0).GetOuterRect().right) @@ -419,17 +412,21 @@ void COList::DrawList(const int& selected, const CStr& _sprite, const CStr& _spr // Draw all items for that column xpos = 0; - for (size_t col = 0; col < objectsCount; ++col) + size_t col = 0; + for (const COListColumn& column : m_Columns) { - if (GetSetting("hidden_" + m_Columns[col].m_Id)) + if (column.m_Hidden) + { + ++col; continue; + } // Determine text position and width const CPos textPos = rect.TopLeft() + CPos(xpos, -scroll + m_ItemsYPositions[i]); - float width = m_Columns[col].m_Width; + float width = column.m_Width; // Check if it's a decimal value, and if so, assume relative positioning. - if (m_Columns[col].m_Width < 1 && m_Columns[col].m_Width > 0) + if (column.m_Width < 1 && column.m_Width > 0) width *= m_TotalAvailableColumnWidth; // Clip text to the column (to prevent drawing text into the neighboring column) @@ -438,8 +435,9 @@ void COList::DrawList(const int& selected, const CStr& _sprite, const CStr& _spr cliparea2.bottom = std::min(cliparea2.bottom, textPos.y + rowHeight); // Draw list item - DrawText(objectsCount * (i +/*Heading*/1) + col, m_Columns[col].m_TextColor, textPos, bz + 0.1f, cliparea2); + DrawText(objectsCount * (i +/*Heading*/1) + col, column.m_TextColor, textPos, bz + 0.1f, cliparea2); xpos += width; + ++col; } } } diff --git a/source/gui/COList.h b/source/gui/COList.h index 87fd3038e1..b10c10d859 100644 --- a/source/gui/COList.h +++ b/source/gui/COList.h @@ -30,12 +30,13 @@ struct COListColumn // Avoid copying the strings. NONCOPYABLE(COListColumn); MOVABLE(COListColumn); - COListColumn() = default; - + COListColumn() : m_Width(0), m_Hidden(false) {} CGUIColor m_TextColor; CStr m_Id; float m_Width; - CStrW m_Heading; + CStrW m_Heading; // CGUIString?? + CGUIList m_List; + bool m_Hidden; }; /** @@ -61,8 +62,9 @@ protected: * Handle the \ tag. */ virtual bool HandleAdditionalChildren(const XMBElement& child, CXeromyces* pFile); + virtual void AdditionalChildrenHandled(); - void DrawList(const int& selected, const CStr& _sprite, const CStr& _sprite_selected, const CStr& _textcolor); + void DrawList(const int& selected, const CGUISpriteInstance& sprite, const CGUISpriteInstance& sprite_selected, const CGUIColor& textcolor); virtual CRect GetListRect() const; @@ -71,6 +73,15 @@ protected: */ std::vector m_Columns; + // Settings + CGUISpriteInstance m_SpriteHeading; + bool m_Sortable; + CStr m_SelectedColumn; + i32 m_SelectedColumnOrder; + CGUISpriteInstance m_SpriteAsc; + CGUISpriteInstance m_SpriteDesc; + CGUISpriteInstance m_SpriteNotSorted; + private: // Width of space available for columns float m_TotalAvailableColumnWidth; diff --git a/source/gui/CProgressBar.cpp b/source/gui/CProgressBar.cpp index 0cbf88d9d0..1a8bce1b71 100644 --- a/source/gui/CProgressBar.cpp +++ b/source/gui/CProgressBar.cpp @@ -22,11 +22,14 @@ #include "gui/CGUI.h" CProgressBar::CProgressBar(CGUI& pGUI) - : IGUIObject(pGUI) + : IGUIObject(pGUI), + m_SpriteBackground(), + m_SpriteBar(), + m_Caption() { - AddSetting("sprite_background"); - AddSetting("sprite_bar"); - AddSetting("caption"); // aka value from 0 to 100 + RegisterSetting("sprite_background", m_SpriteBackground); + RegisterSetting("sprite_bar", m_SpriteBar); + RegisterSetting("caption", m_Caption); // aka value from 0 to 100 } CProgressBar::~CProgressBar() @@ -43,12 +46,11 @@ void CProgressBar::HandleMessage(SGUIMessage& Message) case GUIM_SETTINGS_UPDATED: // Update scroll-bar // TODO Gee: (2004-09-01) Is this really updated each time it should? - if (Message.value == CStr("caption")) + if (Message.value == "caption") { - const float value = GetSetting("caption"); - if (value > 100.f) + if (m_Caption > 100.f) SetSetting("caption", 100.f, true); - else if (value < 0.f) + else if (m_Caption < 0.f) SetSetting("caption", 0.f, true); } break; @@ -59,18 +61,14 @@ void CProgressBar::HandleMessage(SGUIMessage& Message) void CProgressBar::Draw() { - CGUISpriteInstance& sprite_bar = GetSetting("sprite_bar"); - CGUISpriteInstance& sprite_background = GetSetting("sprite_background"); - float bz = GetBufferedZ(); int cell_id = 0; - const float value = GetSetting("caption"); - m_pGUI.DrawSprite(sprite_background, cell_id, bz, m_CachedActualSize); + m_pGUI.DrawSprite(m_SpriteBackground, cell_id, bz, m_CachedActualSize); // Get size of bar (notice it is drawn slightly closer, to appear above the background) CRect bar_size(m_CachedActualSize.left, m_CachedActualSize.top, - m_CachedActualSize.left+m_CachedActualSize.GetWidth()*(value/100.f), m_CachedActualSize.bottom); - m_pGUI.DrawSprite(sprite_bar, cell_id, bz+0.01f, bar_size); + m_CachedActualSize.left+m_CachedActualSize.GetWidth()*(m_Caption/100.f), m_CachedActualSize.bottom); + m_pGUI.DrawSprite(m_SpriteBar, cell_id, bz+0.01f, bar_size); } diff --git a/source/gui/CProgressBar.h b/source/gui/CProgressBar.h index 490d879a81..83faab19ec 100644 --- a/source/gui/CProgressBar.h +++ b/source/gui/CProgressBar.h @@ -19,6 +19,7 @@ #define INCLUDED_CPROGRESSBAR #include "gui/IGUIObject.h" +#include "gui/CGUISprite.h" /** * Object used to draw a value (e.g. progress) from 0 to 100 visually. @@ -42,6 +43,11 @@ protected: * @see IGUIObject#HandleMessage() */ void HandleMessage(SGUIMessage& Message); + + // Settings + CGUISpriteInstance m_SpriteBackground; + CGUISpriteInstance m_SpriteBar; + float m_Caption; }; #endif // INCLUDED_CPROGRESSBAR diff --git a/source/gui/CSlider.cpp b/source/gui/CSlider.cpp index cf38e26a6f..8a9c07d8fd 100644 --- a/source/gui/CSlider.cpp +++ b/source/gui/CSlider.cpp @@ -23,20 +23,23 @@ #include "maths/MathUtil.h" CSlider::CSlider(CGUI& pGUI) - : IGUIObject(pGUI), m_IsPressed(false), m_ButtonSide(0) + : IGUIObject(pGUI), + m_IsPressed(), + m_ButtonSide() + m_CellID(), + m_MaxValue(), + m_MinValue(), + m_Sprite(), + m_SpriteBar(), + m_Value(), { - AddSetting("value"); - AddSetting("min_value"); - AddSetting("max_value"); - AddSetting("cell_id"); - AddSetting("sprite"); - AddSetting("sprite_bar"); - AddSetting("button_width"); - - m_Value = GetSetting("value"); - m_MinValue = GetSetting("min_value"); - m_MaxValue = GetSetting("max_value"); - m_ButtonSide = GetSetting("button_width"); + RegisterSetting("button_width", m_ButtonSide); + RegisterSetting("cell_id", m_CellID); + RegisterSetting("max_value", m_MaxValue); + RegisterSetting("min_value", m_MinValue); + RegisterSetting("sprite", m_Sprite); + RegisterSetting("sprite_bar", m_SpriteBar); + RegisterSetting("value", m_Value); m_Value = Clamp(m_Value, m_MinValue, m_MaxValue); } @@ -62,11 +65,6 @@ void CSlider::HandleMessage(SGUIMessage& Message) { case GUIM_SETTINGS_UPDATED: { - m_Value = GetSetting("value"); - m_MinValue = GetSetting("min_value"); - m_MaxValue = GetSetting("max_value"); - m_ButtonSide = GetSetting("button_width"); - m_Value = Clamp(m_Value, m_MinValue, m_MaxValue); break; } @@ -116,16 +114,12 @@ void CSlider::HandleMessage(SGUIMessage& Message) void CSlider::Draw() { - CGUISpriteInstance& sprite = GetSetting("sprite_bar"); - CGUISpriteInstance& sprite_button = GetSetting("sprite"); - const int cell_id = GetSetting("cell_id"); - CRect slider_line(m_CachedActualSize); slider_line.left += m_ButtonSide / 2.0f; slider_line.right -= m_ButtonSide / 2.0f; float bz = GetBufferedZ(); - m_pGUI.DrawSprite(sprite, cell_id, bz, slider_line); - m_pGUI.DrawSprite(sprite_button, cell_id, bz, GetButtonRect()); + m_pGUI.DrawSprite(m_SpriteBar, m_CellID, bz, slider_line); + m_pGUI.DrawSprite(m_Sprite, m_CellID, bz, GetButtonRect()); } void CSlider::UpdateValue() diff --git a/source/gui/CSlider.h b/source/gui/CSlider.h index be9e63114e..c647ba11cf 100644 --- a/source/gui/CSlider.h +++ b/source/gui/CSlider.h @@ -19,6 +19,7 @@ #define INCLUDED_CSLIDER #include "gui/IGUIObject.h" +#include "gui/CGUISprite.h" class CSlider : public IGUIObject { @@ -51,14 +52,18 @@ protected: void IncrementallyChangeValue(const float value); - float m_MinValue, m_MaxValue, m_Value; + // Settings + float m_ButtonSide; + i32 m_CellID; + float m_MinValue; + float m_MaxValue; + CGUISpriteInstance m_Sprite; + CGUISpriteInstance m_SpriteBar; + float m_Value; private: bool m_IsPressed; - CPos m_Mouse; - - float m_ButtonSide; }; #endif // INCLUDED_CSLIDER diff --git a/source/gui/CText.cpp b/source/gui/CText.cpp index 8364ac921a..8af2a1e80d 100644 --- a/source/gui/CText.cpp +++ b/source/gui/CText.cpp @@ -24,26 +24,43 @@ #include "gui/CGUIText.h" CText::CText(CGUI& pGUI) - : IGUIObject(pGUI), IGUIScrollBarOwner(pGUI), IGUITextOwner(pGUI) + : IGUIObject(pGUI), + IGUIScrollBarOwner(pGUI), + IGUITextOwner(pGUI), + m_BufferZone(), + m_Caption(), + m_CellID(), + m_Clip(), + m_Font(), + m_ScrollBar(), + m_ScrollBarStyle(), + m_ScrollBottom(), + m_ScrollTop(), + m_Sprite(), + m_TextAlign(), + m_TextVAlign(), + m_TextColor(), + m_TextColorDisabled(), + m_IconTooltip(), + m_IconTooltipStyle() { - AddSetting("buffer_zone"); - AddSetting("caption"); - AddSetting("cell_id"); - AddSetting("clip"); - AddSetting("font"); - AddSetting("scrollbar"); - AddSetting("scrollbar_style"); - AddSetting("scroll_bottom"); - AddSetting("scroll_top"); - AddSetting("sprite"); - AddSetting("text_align"); - AddSetting("text_valign"); - AddSetting("textcolor"); - AddSetting("textcolor_disabled"); - + RegisterSetting("buffer_zone", m_BufferZone); + RegisterSetting("caption", m_Caption); + RegisterSetting("cell_id", m_CellID); + RegisterSetting("clip", m_Clip); + RegisterSetting("font", m_Font); + RegisterSetting("scrollbar", m_ScrollBar); + RegisterSetting("scrollbar_style", m_ScrollBarStyle); + RegisterSetting("scroll_bottom", m_ScrollBottom); + RegisterSetting("scroll_top", m_ScrollTop); + RegisterSetting("sprite", m_Sprite); + RegisterSetting("text_align", m_TextAlign); + RegisterSetting("text_valign", m_TextVAlign); + RegisterSetting("textcolor", m_TextColor); + RegisterSetting("textcolor_disabled", m_TextColorDisabled); // Private settings - AddSetting("_icon_tooltip"); - AddSetting("_icon_tooltip_style"); + RegisterSetting("_icon_tooltip", m_IconTooltip); + RegisterSetting("_icon_tooltip_style", m_IconTooltipStyle); //SetSetting("ghost", true, true); SetSetting("scrollbar", false, true); @@ -67,34 +84,25 @@ void CText::SetupText() if (m_GeneratedTexts.empty()) return; - const bool scrollbar = GetSetting("scrollbar"); - float width = m_CachedActualSize.GetWidth(); // remove scrollbar if applicable - if (scrollbar && GetScrollBar(0).GetStyle()) + if (m_ScrollBar && GetScrollBar(0).GetStyle()) width -= GetScrollBar(0).GetStyle()->m_Width; - const CGUIString& caption = GetSetting("caption"); - const CStrW& font = GetSetting("font"); - const float buffer_zone = GetSetting("buffer_zone"); + m_GeneratedTexts[0] = CGUIText(m_pGUI, m_Caption, m_Font, width, m_BufferZone, this); - m_GeneratedTexts[0] = CGUIText(m_pGUI, caption, font, width, buffer_zone, this); - - if (!scrollbar) + if (!m_ScrollBar) CalculateTextPosition(m_CachedActualSize, m_TextPos, m_GeneratedTexts[0]); // Setup scrollbar - if (scrollbar) + if (m_ScrollBar) { - const bool scroll_bottom = GetSetting("scroll_bottom"); - const bool scroll_top = GetSetting("scroll_top"); - // If we are currently scrolled to the bottom of the text, // then add more lines of text, update the scrollbar so we // stick to the bottom. // (Use 1.5px delta so this triggers the first time caption is set) bool bottom = false; - if (scroll_bottom && GetScrollBar(0).GetPos() > GetScrollBar(0).GetMaxPos() - 1.5f) + if (m_ScrollBottom && GetScrollBar(0).GetPos() > GetScrollBar(0).GetMaxPos() - 1.5f) bottom = true; GetScrollBar(0).SetScrollRange(m_GeneratedTexts[0].GetSize().cy); @@ -107,7 +115,8 @@ void CText::SetupText() if (bottom) GetScrollBar(0).SetPos(GetScrollBar(0).GetMaxPos()); - if (scroll_top) + + if (m_ScrollTop) GetScrollBar(0).SetPos(0.0f); } } @@ -126,7 +135,7 @@ void CText::HandleMessage(SGUIMessage& Message) // Update scrollbar if (Message.value == "scrollbar_style") { - GetScrollBar(0).SetScrollBarStyle(GetSetting(Message.value)); + GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle); SetupText(); } @@ -156,7 +165,7 @@ void CText::HandleMessage(SGUIMessage& Message) GetScrollBar(0).SetY(m_CachedActualSize.top); GetScrollBar(0).SetZ(GetBufferedZ()); GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top); - GetScrollBar(0).SetScrollBarStyle(GetSetting("scrollbar_style")); + GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle); break; } @@ -171,28 +180,22 @@ void CText::Draw() { float bz = GetBufferedZ(); - const bool scrollbar = GetSetting("scrollbar"); - - if (scrollbar) + if (m_ScrollBar) IGUIScrollBarOwner::Draw(); - CGUISpriteInstance& sprite = GetSetting("sprite"); - const int cell_id = GetSetting("cell_id"); - const bool clip = GetSetting("clip"); - - m_pGUI.DrawSprite(sprite, cell_id, bz, m_CachedActualSize); + m_pGUI.DrawSprite(m_Sprite, m_CellID, bz, m_CachedActualSize); float scroll = 0.f; - if (scrollbar) + if (m_ScrollBar) scroll = GetScrollBar(0).GetPos(); // Clipping area (we'll have to subtract the scrollbar) CRect cliparea; - if (clip) + if (m_Clip) { cliparea = m_CachedActualSize; - if (scrollbar) + if (m_ScrollBar) { // subtract scrollbar from cliparea if (cliparea.right > GetScrollBar(0).GetOuterRect().left && @@ -205,10 +208,9 @@ void CText::Draw() } } - const bool enabled = GetSetting("enabled"); - const CGUIColor& color = GetSetting(enabled ? "textcolor" : "textcolor_disabled"); + const CGUIColor& color = m_Enabled ? m_TextColor : m_TextColorDisabled; - if (scrollbar) + if (m_ScrollBar) DrawText(0, color, m_CachedActualSize.TopLeft() - CPos(0.f, scroll), bz + 0.1f, cliparea); else DrawText(0, color, m_TextPos, bz + 0.1f, cliparea); diff --git a/source/gui/CText.h b/source/gui/CText.h index d3330602de..91316d1e26 100644 --- a/source/gui/CText.h +++ b/source/gui/CText.h @@ -18,6 +18,8 @@ #ifndef INCLUDED_CTEXT #define INCLUDED_CTEXT +#include "gui/CGUISprite.h" +#include "gui/CGUIString.h" #include "gui/IGUIScrollBarOwner.h" #include "gui/IGUITextOwner.h" @@ -63,6 +65,24 @@ protected: * Placement of text. Ignored when scrollbars are active. */ CPos m_TextPos; + + // Settings + float m_BufferZone; + CGUIString m_Caption; + i32 m_CellID; + bool m_Clip; + CStrW m_Font; + bool m_ScrollBar; + CStr m_ScrollBarStyle; + bool m_ScrollBottom; + bool m_ScrollTop; + CGUISpriteInstance m_Sprite; + EAlign m_TextAlign; + EVAlign m_TextVAlign; + CGUIColor m_TextColor; + CGUIColor m_TextColorDisabled; + CStrW m_IconTooltip; + CStr m_IconTooltipStyle; }; #endif // INCLUDED_CTEXT diff --git a/source/gui/CTooltip.cpp b/source/gui/CTooltip.cpp index 94bea66769..8bfae59d2f 100644 --- a/source/gui/CTooltip.cpp +++ b/source/gui/CTooltip.cpp @@ -20,34 +20,48 @@ #include "CTooltip.h" #include "gui/CGUI.h" +#include "gui/CGUIString.h" #include "gui/CGUIText.h" #include CTooltip::CTooltip(CGUI& pGUI) - : IGUIObject(pGUI), IGUITextOwner(pGUI) + : IGUIObject(pGUI), + IGUITextOwner(pGUI), + m_BufferZone(), + m_Caption(), + m_Font(), + m_Sprite(), + m_Delay(), + m_TextColor(), + m_MaxWidth(), + m_Offset(), + m_Anchor(), + m_TextAlign(), + m_Independent(), + m_MousePos(), + m_UseObject(), + m_HideObject() { // If the tooltip is an object by itself: - AddSetting("buffer_zone"); - AddSetting("caption"); - AddSetting("font"); - AddSetting("sprite"); - AddSetting("delay"); // in milliseconds - AddSetting("textcolor"); - AddSetting("maxwidth"); - AddSetting("offset"); - AddSetting("anchor"); - AddSetting("text_align"); + RegisterSetting("buffer_zone", m_BufferZone); + RegisterSetting("caption", m_Caption); + RegisterSetting("font", m_Font); + RegisterSetting("sprite", m_Sprite); + RegisterSetting("delay", m_Delay); // in milliseconds + RegisterSetting("textcolor", m_TextColor); + RegisterSetting("maxwidth", m_MaxWidth); + RegisterSetting("offset", m_Offset); + RegisterSetting("anchor", m_Anchor); + RegisterSetting("text_align", m_TextAlign); // This is used for tooltips that are hidden/revealed manually by scripts, rather than through the standard tooltip display mechanism - AddSetting("independent"); - - // If the tooltip is just a reference to another object: - AddSetting("use_object"); - AddSetting("hide_object"); - + RegisterSetting("independent", m_Independent); // Private settings: // This is set by GUITooltip - AddSetting("_mousepos"); + RegisterSetting("_mousepos", m_MousePos); + // If the tooltip is just a reference to another object: + RegisterSetting("use_object", m_UseObject); + RegisterSetting("hide_object", m_HideObject); // Defaults SetSetting("delay", 500, true); @@ -67,40 +81,31 @@ void CTooltip::SetupText() { ENSURE(m_GeneratedTexts.size() == 1); - const CGUIString& caption = GetSetting("caption"); - const CStrW& font = GetSetting("font"); - const float max_width = GetSetting("maxwidth"); - const float buffer_zone = GetSetting("buffer_zone"); - - m_GeneratedTexts[0] = CGUIText(m_pGUI, caption, font, max_width, buffer_zone, this); + m_GeneratedTexts[0] = CGUIText(m_pGUI, m_Caption, m_Font, m_MaxWidth, m_BufferZone, this); // Position the tooltip relative to the mouse: - const CPos& mousepos = GetSetting("independent") ? - m_pGUI.GetMousePos() : - GetSetting("_mousepos"); - - const CPos& offset = GetSetting("offset"); + const CPos& mousepos = m_Independent ? m_pGUI.GetMousePos() : m_MousePos; float textwidth = m_GeneratedTexts[0].GetSize().cx; float textheight = m_GeneratedTexts[0].GetSize().cy; CClientArea size; - size.pixel.left = mousepos.x + offset.x; + size.pixel.left = mousepos.x + m_Offset.x; size.pixel.right = size.pixel.left + textwidth; - switch (GetSetting("anchor")) + switch (m_Anchor) { case EVAlign_Top: - size.pixel.top = mousepos.y + offset.y; + size.pixel.top = mousepos.y + m_Offset.y; size.pixel.bottom = size.pixel.top + textheight; break; case EVAlign_Bottom: - size.pixel.bottom = mousepos.y + offset.y; + size.pixel.bottom = mousepos.y + m_Offset.y; size.pixel.top = size.pixel.bottom - textheight; break; case EVAlign_Center: - size.pixel.top = mousepos.y + offset.y - textheight/2.f; + size.pixel.top = mousepos.y + m_Offset.y - textheight/2.f; size.pixel.bottom = size.pixel.top + textwidth; break; default: @@ -137,8 +142,6 @@ void CTooltip::Draw() { float z = 900.f; // TODO: Find a nicer way of putting the tooltip on top of everything else - CGUISpriteInstance& sprite = GetSetting("sprite"); - // Normally IGUITextOwner will handle this updating but since SetupText can modify the position // we need to call it now *before* we do the rest of the drawing if (!m_GeneratedTextsValid) @@ -147,8 +150,7 @@ void CTooltip::Draw() m_GeneratedTextsValid = true; } - m_pGUI.DrawSprite(sprite, 0, z, m_CachedActualSize); + m_pGUI.DrawSprite(m_Sprite, 0, z, m_CachedActualSize); - const CGUIColor& color = GetSetting("textcolor"); - DrawText(0, color, m_CachedActualSize.TopLeft(), z+0.1f); + DrawText(0, m_TextColor, m_CachedActualSize.TopLeft(), z + 0.1f); } diff --git a/source/gui/CTooltip.h b/source/gui/CTooltip.h index 8697aaae01..a635ef4a62 100644 --- a/source/gui/CTooltip.h +++ b/source/gui/CTooltip.h @@ -18,7 +18,9 @@ #ifndef INCLUDED_CTOOLTIP #define INCLUDED_CTOOLTIP -#include "IGUITextOwner.h" +#include "gui/IGUITextOwner.h" +#include "gui/CGUISprite.h" +#include "gui/CGUIString.h" /** * Dynamic tooltips. Similar to CText. @@ -40,6 +42,22 @@ protected: virtual void HandleMessage(SGUIMessage& Message); virtual void Draw(); + + // Settings + float m_BufferZone; + CGUIString m_Caption; + CStrW m_Font; + CGUISpriteInstance m_Sprite; + i32 m_Delay; + CGUIColor m_TextColor; + float m_MaxWidth; + CPos m_Offset; + EVAlign m_Anchor; + EAlign m_TextAlign; + bool m_Independent; + CPos m_MousePos; + CStr m_UseObject; + bool m_HideObject; }; #endif // INCLUDED_CTOOLTIP diff --git a/source/gui/IGUIButtonBehavior.cpp b/source/gui/IGUIButtonBehavior.cpp index 2a2e94eacc..952694a3f1 100644 --- a/source/gui/IGUIButtonBehavior.cpp +++ b/source/gui/IGUIButtonBehavior.cpp @@ -24,14 +24,19 @@ IGUIButtonBehavior::IGUIButtonBehavior(CGUI& pGUI) : IGUIObject(pGUI), - m_Pressed(false), - m_PressedRight(false) + m_Pressed(), + m_PressedRight(), + m_SoundDisabled(), + m_SoundEnter(), + m_SoundLeave(), + m_SoundPressed(), + m_SoundReleased() { - AddSetting("sound_disabled"); - AddSetting("sound_enter"); - AddSetting("sound_leave"); - AddSetting("sound_pressed"); - AddSetting("sound_released"); + RegisterSetting("sound_disabled", m_SoundDisabled); + RegisterSetting("sound_enter", m_SoundEnter); + RegisterSetting("sound_leave", m_SoundLeave); + RegisterSetting("sound_pressed", m_SoundPressed); + RegisterSetting("sound_released", m_SoundReleased); } IGUIButtonBehavior::~IGUIButtonBehavior() @@ -40,23 +45,21 @@ IGUIButtonBehavior::~IGUIButtonBehavior() void IGUIButtonBehavior::HandleMessage(SGUIMessage& Message) { - const bool enabled = GetSetting("enabled"); - // TODO Gee: easier access functions switch (Message.type) { case GUIM_MOUSE_ENTER: - if (enabled) - PlaySound("sound_enter"); + if (m_Enabled) + PlaySound(m_SoundEnter); break; case GUIM_MOUSE_LEAVE: - if (enabled) - PlaySound("sound_leave"); + if (m_Enabled) + PlaySound(m_SoundLeave); break; case GUIM_MOUSE_DBLCLICK_LEFT: - if (!enabled) + if (!m_Enabled) break; // Since GUIM_MOUSE_PRESS_LEFT also gets called twice in a @@ -65,19 +68,19 @@ void IGUIButtonBehavior::HandleMessage(SGUIMessage& Message) break; case GUIM_MOUSE_PRESS_LEFT: - if (!enabled) + if (!m_Enabled) { - PlaySound("sound_disabled"); + PlaySound(m_SoundDisabled); break; } - PlaySound("sound_pressed"); + PlaySound(m_SoundPressed); SendEvent(GUIM_PRESSED, "press"); m_Pressed = true; break; case GUIM_MOUSE_DBLCLICK_RIGHT: - if (!enabled) + if (!m_Enabled) break; // Since GUIM_MOUSE_PRESS_RIGHT also gets called twice in a @@ -86,37 +89,37 @@ void IGUIButtonBehavior::HandleMessage(SGUIMessage& Message) break; case GUIM_MOUSE_PRESS_RIGHT: - if (!enabled) + if (!m_Enabled) { - PlaySound("sound_disabled"); + PlaySound(m_SoundDisabled); break; } // Button was right-clicked - PlaySound("sound_pressed"); + PlaySound(m_SoundPressed); SendEvent(GUIM_PRESSED_MOUSE_RIGHT, "pressright"); m_PressedRight = true; break; case GUIM_MOUSE_RELEASE_RIGHT: - if (!enabled) + if (!m_Enabled) break; if (m_PressedRight) { m_PressedRight = false; - PlaySound("sound_released"); + PlaySound(m_SoundReleased); } break; case GUIM_MOUSE_RELEASE_LEFT: - if (!enabled) + if (!m_Enabled) break; if (m_Pressed) { m_Pressed = false; - PlaySound("sound_released"); + PlaySound(m_SoundReleased); } break; @@ -125,9 +128,9 @@ void IGUIButtonBehavior::HandleMessage(SGUIMessage& Message) } } -void IGUIButtonBehavior::DrawButton(const CRect& rect, const float& z, CGUISpriteInstance& sprite, CGUISpriteInstance& sprite_over, CGUISpriteInstance& sprite_pressed, CGUISpriteInstance& sprite_disabled, int cell_id) +void IGUIButtonBehavior::DrawButton(const CRect& rect, const float& z, const CGUISpriteInstance& sprite, const CGUISpriteInstance& sprite_over, const CGUISpriteInstance& sprite_pressed, const CGUISpriteInstance& sprite_disabled, int cell_id) { - if (!GetSetting("enabled")) + if (!m_Enabled) m_pGUI.DrawSprite(sprite_disabled || sprite, cell_id, z, rect); else if (m_MouseHovering) { diff --git a/source/gui/IGUIButtonBehavior.h b/source/gui/IGUIButtonBehavior.h index cbe9c5c149..7ef3c0bc15 100644 --- a/source/gui/IGUIButtonBehavior.h +++ b/source/gui/IGUIButtonBehavior.h @@ -63,7 +63,7 @@ public: * @param cell_id Identifies the icon to be used (if the sprite contains * cell-using images) */ - void DrawButton(const CRect& rect, const float& z, CGUISpriteInstance& sprite, CGUISpriteInstance& sprite_over, CGUISpriteInstance& sprite_pressed, CGUISpriteInstance& sprite_disabled, int cell_id); + void DrawButton(const CRect& rect, const float& z, const CGUISpriteInstance& sprite, const CGUISpriteInstance& sprite_over, const CGUISpriteInstance& sprite_pressed, const CGUISpriteInstance& sprite_disabled, int cell_id); protected: /** @@ -86,6 +86,13 @@ protected: */ bool m_Pressed; bool m_PressedRight; + + // Settings + CStrW m_SoundDisabled; + CStrW m_SoundEnter; + CStrW m_SoundLeave; + CStrW m_SoundPressed; + CStrW m_SoundReleased; }; #endif // INCLUDED_IGUIBUTTONBEHAVIOR diff --git a/source/gui/IGUIObject.cpp b/source/gui/IGUIObject.cpp index 2d99639507..75b85c8585 100644 --- a/source/gui/IGUIObject.cpp +++ b/source/gui/IGUIObject.cpp @@ -30,21 +30,36 @@ #include "soundmanager/ISoundManager.h" IGUIObject::IGUIObject(CGUI& pGUI) - : m_pGUI(pGUI), m_pParent(nullptr), m_MouseHovering(false), m_LastClickTime() + : m_pGUI(pGUI), + m_pParent(), + m_MouseHovering(), + m_LastClickTime(), + m_Enabled(), + m_Hidden(), + m_Size(), + m_Style(), + m_Hotkey(), + m_Z(), + m_Absolute(), + m_Ghost(), + m_AspectRatio(), + m_Tooltip(), + m_TooltipStyle() { - AddSetting("enabled"); - AddSetting("hidden"); - AddSetting("size"); - AddSetting("style"); - AddSetting("hotkey"); - AddSetting("z"); - AddSetting("absolute"); - AddSetting("ghost"); - AddSetting("aspectratio"); - AddSetting("tooltip"); - AddSetting("tooltip_style"); + RegisterSetting("enabled", m_Enabled); + RegisterSetting("hidden", m_Hidden); + RegisterSetting("size", m_Size); + RegisterSetting("style", m_Style); + RegisterSetting("hotkey", m_Hotkey); + RegisterSetting("z", m_Z); + RegisterSetting("absolute", m_Absolute); + RegisterSetting("ghost", m_Ghost); + RegisterSetting("aspectratio", m_AspectRatio); + RegisterSetting("tooltip", m_Tooltip); + RegisterSetting("tooltip_style", m_TooltipStyle); // Setup important defaults + // TODO: Should be in the default style? SetSetting("hidden", false, true); SetSetting("ghost", false, true); SetSetting("enabled", true, true); @@ -117,12 +132,12 @@ void IGUIObject::AddToPointersMap(map_pObjects& ObjectMap) } template -void IGUIObject::AddSetting(const CStr& Name) +void IGUIObject::RegisterSetting(const CStr& Name, T& Value) { if (SettingExists(Name)) LOGERROR("The setting '%s' already exists on the object '%s'!", Name.c_str(), GetPresentableName().c_str()); else - m_Settings.emplace(Name, new CGUISetting(*this, Name)); + m_Settings.emplace(Name, new CGUISetting(*this, Name, Value)); } bool IGUIObject::SettingExists(const CStr& Setting) const @@ -157,7 +172,7 @@ template void IGUIObject::SetSetting(const CStr& Setting, T& Value, const bool SendMessage) { PreSettingChange(Setting); - static_cast* >(m_Settings[Setting])->m_pSetting = std::move(Value); + static_cast* >(m_Settings.at(Setting))->m_pSetting = std::move(Value); SettingChanged(Setting, SendMessage); } @@ -165,7 +180,7 @@ template void IGUIObject::SetSetting(const CStr& Setting, const T& Value, const bool SendMessage) { PreSettingChange(Setting); - static_cast* >(m_Settings[Setting])->m_pSetting = Value; + static_cast* >(m_Settings.at(Setting))->m_pSetting = Value; SettingChanged(Setting, SendMessage); } @@ -185,7 +200,7 @@ void IGUIObject::SettingChanged(const CStr& Setting, const bool SendMessage) else if (Setting == "hidden") { // Hiding an object requires us to reset it and all children - if (GetSetting(Setting)) + if (m_Hidden) RecurseObject(nullptr, &IGUIObject::ResetStates); } else if (Setting == "hotkey") @@ -267,31 +282,28 @@ void IGUIObject::ResetStates() void IGUIObject::UpdateCachedSize() { - const CClientArea& ca = GetSetting("size"); - const float aspectratio = GetSetting("aspectratio"); - // If absolute="false" and the object has got a parent, // use its cached size instead of the screen. Notice // it must have just been cached for it to work. - if (!GetSetting("absolute") && m_pParent && !IsRootObject()) - m_CachedActualSize = ca.GetClientArea(m_pParent->m_CachedActualSize); + if (!m_Absolute && m_pParent && !IsRootObject()) + m_CachedActualSize = m_Size.GetClientArea(m_pParent->m_CachedActualSize); else - m_CachedActualSize = ca.GetClientArea(CRect(0.f, 0.f, g_xres / g_GuiScale, g_yres / g_GuiScale)); + m_CachedActualSize = m_Size.GetClientArea(CRect(0.f, 0.f, g_xres / g_GuiScale, g_yres / g_GuiScale)); // In a few cases, GUI objects have to resize to fill the screen // but maintain a constant aspect ratio. // Adjust the size to be the max possible, centered in the original size: - if (aspectratio) + if (m_AspectRatio) { - if (m_CachedActualSize.GetWidth() > m_CachedActualSize.GetHeight()*aspectratio) + if (m_CachedActualSize.GetWidth() > m_CachedActualSize.GetHeight() * m_AspectRatio) { - float delta = m_CachedActualSize.GetWidth() - m_CachedActualSize.GetHeight()*aspectratio; + float delta = m_CachedActualSize.GetWidth() - m_CachedActualSize.GetHeight() * m_AspectRatio; m_CachedActualSize.left += delta/2.f; m_CachedActualSize.right -= delta/2.f; } else { - float delta = m_CachedActualSize.GetHeight() - m_CachedActualSize.GetWidth()/aspectratio; + float delta = m_CachedActualSize.GetHeight() - m_CachedActualSize.GetWidth() / m_AspectRatio; m_CachedActualSize.bottom -= delta/2.f; m_CachedActualSize.top += delta/2.f; } @@ -318,22 +330,16 @@ void IGUIObject::LoadStyle(const CStr& StyleName) float IGUIObject::GetBufferedZ() const { - const float Z = GetSetting("z"); + if (m_Absolute) + return m_Z; - if (GetSetting("absolute")) - return Z; + if (GetParent()) + return GetParent()->GetBufferedZ() + m_Z; - { - if (GetParent()) - return GetParent()->GetBufferedZ() + Z; - else - { - // In philosophy, a parentless object shouldn't be able to have a relative sizing, - // but we'll accept it so that absolute can be used as default without a complaint. - // Also, you could consider those objects children to the screen resolution. - return Z; - } - } + // In philosophy, a parentless object shouldn't be able to have a relative sizing, + // but we'll accept it so that absolute can be used as default without a complaint. + // Also, you could consider those objects children to the screen resolution. + return m_Z; } void IGUIObject::RegisterScriptHandler(const CStr& Action, const CStr& Code, CGUI& pGUI) @@ -463,26 +469,17 @@ JSObject* IGUIObject::GetJSObject() bool IGUIObject::IsHidden() const { - // Statically initialise some strings, so we don't have to do - // lots of allocation every time this function is called - static const CStr strHidden("hidden"); - return GetSetting(strHidden); + return m_Hidden; } bool IGUIObject::IsHiddenOrGhost() const { - static const CStr strGhost("ghost"); - return IsHidden() || GetSetting(strGhost); + return m_Hidden || m_Ghost; } -void IGUIObject::PlaySound(const CStr& settingName) const +void IGUIObject::PlaySound(const CStrW& soundPath) const { - if (!g_SoundManager) - return; - - const CStrW& soundPath = GetSetting(settingName); - - if (!soundPath.empty()) + if (g_SoundManager && !soundPath.empty()) g_SoundManager->PlayAsUI(soundPath.c_str(), false); } @@ -530,7 +527,7 @@ void IGUIObject::TraceMember(JSTracer* trc) // Instantiate templated functions: // These functions avoid copies by working with a reference and move semantics. #define TYPE(T) \ - template void IGUIObject::AddSetting(const CStr& Name); \ + template void IGUIObject::RegisterSetting(const CStr& Name, T& Value); \ template T& IGUIObject::GetSetting(const CStr& Setting); \ template const T& IGUIObject::GetSetting(const CStr& Setting) const; \ template void IGUIObject::SetSetting(const CStr& Setting, T& Value, const bool SendMessage); \ diff --git a/source/gui/IGUIObject.h b/source/gui/IGUIObject.h index 85141320c0..9fd4b02c44 100644 --- a/source/gui/IGUIObject.h +++ b/source/gui/IGUIObject.h @@ -228,12 +228,14 @@ protected: //@{ /** - * Add a setting to m_Settings + * Registers the given setting variables with the GUI object. + * Enable XML and JS to modify the given variable. * * @param Type Setting type * @param Name Setting reference name */ - template void AddSetting(const CStr& Name); + template + void RegisterSetting(const CStr& Name, T& Value); public: /** @@ -351,6 +353,12 @@ protected: return false; } + /** + * Allow the GUI object to process after all child items were handled. + * Useful to avoid iterator invalidation with push_back calls. + */ + virtual void AdditionalChildrenHandled() {} + /** * Cached size, real size m_Size is actually dependent on resolution * and can have different *real* outcomes, this is the real outcome @@ -399,7 +407,7 @@ protected: /** * Retrieves the configured sound filename from the given setting name and plays that once. */ - void PlaySound(const CStr& settingName) const; + void PlaySound(const CStrW& soundPath) const; //@} private: @@ -496,6 +504,19 @@ protected: // Cached JSObject representing this GUI object JS::PersistentRootedObject m_JSObject; + + // Cache references to settings for performance + bool m_Enabled; + bool m_Hidden; + CClientArea m_Size; + CStr m_Style; + CStr m_Hotkey; + float m_Z; + bool m_Absolute; + bool m_Ghost; + float m_AspectRatio; + CStrW m_Tooltip; + CStr m_TooltipStyle; }; #endif // INCLUDED_IGUIOBJECT