1
0
forked from 0ad/0ad

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.
This commit is contained in:
elexis 2019-09-27 12:49:59 +00:00
parent 7790fd7d29
commit a33fd55e81
31 changed files with 1019 additions and 877 deletions

View File

@ -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<float>("buffer_zone");
AddSetting<CGUIString>("caption");
AddSetting<i32>("cell_id");
AddSetting<CStrW>("font");
AddSetting<CGUISpriteInstance>("sprite");
AddSetting<CGUISpriteInstance>("sprite_over");
AddSetting<CGUISpriteInstance>("sprite_pressed");
AddSetting<CGUISpriteInstance>("sprite_disabled");
AddSetting<EAlign>("text_align");
AddSetting<EVAlign>("text_valign");
AddSetting<CGUIColor>("textcolor");
AddSetting<CGUIColor>("textcolor_over");
AddSetting<CGUIColor>("textcolor_pressed");
AddSetting<CGUIColor>("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<CGUIString>("caption"),
GetSetting<CStrW>("font"),
m_CachedActualSize.GetWidth(),
GetSetting<float>("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<CGUISpriteInstance>(strSprite);
CGUISpriteInstance& sprite_over = GetSetting<CGUISpriteInstance>(strSpriteOver);
CGUISpriteInstance& sprite_pressed = GetSetting<CGUISpriteInstance>(strSpritePressed);
CGUISpriteInstance& sprite_disabled = GetSetting<CGUISpriteInstance>(strSpriteDisabled);
const i32 cell_id = GetSetting<i32>(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<CGUIColor>("textcolor");
if (!GetSetting<bool>("enabled"))
return GetSetting<CGUIColor>("textcolor_disabled") || color;
if (!m_Enabled)
return m_TextColorDisabled || m_TextColor;
if (!m_MouseHovering)
return color;
return m_TextColor;
if (m_Pressed)
return GetSetting<CGUIColor>("textcolor_pressed") || color;
return m_TextColorPressed || m_TextColor;
return GetSetting<CGUIColor>("textcolor_over") || color;
return m_TextColorOver || m_TextColor;
}

View File

@ -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

View File

@ -31,21 +31,27 @@
#include <cmath>
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<CGUIColor>("axis_color");
AddSetting<float>("axis_width");
AddSetting<float>("buffer_zone");
AddSetting<CStrW>("font");
AddSetting<CStrW>("format_x");
AddSetting<CStrW>("format_y");
AddSetting<CGUIList>("series_color");
AddSetting<CGUISeries>("series");
AddSetting<EAlign>("text_align");
m_AxisWidth = GetSetting<float>("axis_width");
m_FormatX = GetSetting<CStrW>("format_x");
m_FormatY = GetSetting<CStrW>("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<float>("axis_width");
m_FormatX = GetSetting<CStrW>("format_x");
m_FormatY = GetSetting<CStrW>("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<CGUIColor>("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<CGUISeries>("series");
const CGUIList& pSeriesColor = GetSetting<CGUIList>("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<CStrW>("font");
const float buffer_zone = GetSetting<float>("buffer_zone");
// Add Y-axis
m_FormatY = GetSetting<CStrW>("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<CStrW>("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));
}
}

View File

@ -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<CPos> 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

View File

@ -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<i32>("cell_id");
AddSetting<bool>("checked");
AddSetting<CGUISpriteInstance>("sprite");
AddSetting<CGUISpriteInstance>("sprite_over");
AddSetting<CGUISpriteInstance>("sprite_pressed");
AddSetting<CGUISpriteInstance>("sprite_disabled");
AddSetting<CGUISpriteInstance>("sprite2");
AddSetting<CGUISpriteInstance>("sprite2_over");
AddSetting<CGUISpriteInstance>("sprite2_pressed");
AddSetting<CGUISpriteInstance>("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<bool>("checked", !GetSetting<bool>("checked"), true);
SetSetting<bool>("checked", !m_Checked, true);
break;
}
@ -59,22 +70,21 @@ void CCheckBox::HandleMessage(SGUIMessage& Message)
void CCheckBox::Draw()
{
if (GetSetting<bool>("checked"))
if (m_Checked)
DrawButton(
m_CachedActualSize,
GetBufferedZ(),
GetSetting<CGUISpriteInstance>("sprite2"),
GetSetting<CGUISpriteInstance>("sprite2_over"),
GetSetting<CGUISpriteInstance>("sprite2_pressed"),
GetSetting<CGUISpriteInstance>("sprite2_disabled"),
GetSetting<i32>("cell_id"));
m_SpriteChecked,
m_SpriteCheckedOver,
m_SpriteCheckedPressed,
m_SpriteCheckedDisabled,
m_CellID);
else
DrawButton(
m_CachedActualSize,
GetBufferedZ(),
GetSetting<CGUISpriteInstance>("sprite"),
GetSetting<CGUISpriteInstance>("sprite_over"),
GetSetting<CGUISpriteInstance>("sprite_pressed"),
GetSetting<CGUISpriteInstance>("sprite_disabled"),
GetSetting<i32>("cell_id"));
DrawButton(m_CachedActualSize,
GetBufferedZ(),
m_SpriteUnchecked,
m_SpriteUncheckedOver,
m_SpriteUncheckedPressed,
m_SpriteUncheckedDisabled,
m_CellID);
}

View File

@ -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

View File

@ -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<float>("button_width");
AddSetting<float>("dropdown_size");
AddSetting<float>("dropdown_buffer");
AddSetting<u32>("minimum_visible_items");
AddSetting<CStrW>("sound_closed");
AddSetting<CStrW>("sound_enter");
AddSetting<CStrW>("sound_leave");
AddSetting<CStrW>("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<CGUISpriteInstance>("sprite_disabled");
AddSetting<CGUISpriteInstance>("sprite_list"); // Background of the drop down list
AddSetting<CGUISpriteInstance>("sprite2"); // Button that sits to the right
AddSetting<CGUISpriteInstance>("sprite2_over");
AddSetting<CGUISpriteInstance>("sprite2_pressed");
AddSetting<CGUISpriteInstance>("sprite2_disabled");
AddSetting<EVAlign>("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<CGUIColor>("textcolor_over");
//AddSetting<CGUIColor>("textcolor_pressed");
AddSetting<CGUIColor>("textcolor_disabled");
//RegisterSetting("textcolor_over");
//RegisterSetting("textcolor_pressed");
// Scrollbar is forced to be true.
SetSetting<bool>("scrollbar", true, true);
@ -106,14 +124,12 @@ void CDropDown::HandleMessage(SGUIMessage& Message)
if (!GetListRect().PointInside(mouse))
break;
const CGUIList& pList = GetSetting<CGUIList>("list");
const bool scrollbar = GetSetting<bool>("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<int>(pList.m_Items.size()); ++i)
for (int i = 0; i < static_cast<int>(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<bool>("enabled"))
PlaySound("sound_enter");
if (m_Enabled)
PlaySound(m_SoundEnter);
break;
}
case GUIM_MOUSE_LEAVE:
{
m_ElementHighlight = GetSetting<i32>("selected");
m_ElementHighlight = m_Selected;
if (GetSetting<bool>("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<bool>("enabled"))
if (!m_Enabled)
{
PlaySound("sound_disabled");
PlaySound(m_SoundDisabled);
break;
}
if (!m_Open)
{
const CGUIList& pList = GetSetting<CGUIList>("list");
if (pList.m_Items.empty())
if (m_List.m_Items.empty())
return;
m_Open = true;
GetScrollBar(0).SetZ(GetBufferedZ());
m_ElementHighlight = GetSetting<i32>("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<bool>("enabled"))
if (m_Open || !m_Enabled)
break;
m_ElementHighlight = GetSetting<i32>("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<bool>("enabled"))
if (m_Open || !m_Enabled)
break;
m_ElementHighlight = GetSetting<i32>("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<CGUIList>("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<int>(pList.m_Items.size()); ++i)
for (int i = 0; i < static_cast<int>(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<int>(pList.m_Items[i].GetRawString().LowerCase()[j]) - static_cast<int>(m_InputBuffer[j]));
diff = std::abs(static_cast<int>(m_List.m_Items[i].GetRawString().LowerCase()[j]) - static_cast<int>(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<i32>("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<float>("dropdown_size");
const float buffer = GetSetting<float>("dropdown_buffer");
const u32 minimumVisibleItems = GetSetting<u32>("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<float>("button_width");
const bool enabled = GetSetting<bool>("enabled");
const int cell_id = GetSetting<i32>("cell_id");
const int selected = GetSetting<i32>("selected");
CGUISpriteInstance& sprite = GetSetting<CGUISpriteInstance>(enabled ? "sprite" : "sprite_disabled");
CGUISpriteInstance& sprite2 = GetSetting<CGUISpriteInstance>("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<CGUISpriteInstance>("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<CGUISpriteInstance>("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<CGUISpriteInstance>("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<CGUIColor>(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<bool>("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;
}
}

View File

@ -28,6 +28,7 @@ GUI Object - Drop Down (list)
#ifndef INCLUDED_CDROPDOWN
#define INCLUDED_CDROPDOWN
#include "gui/CGUISprite.h"
#include "gui/CList.h"
#include <string>
@ -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

View File

@ -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<bool>("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<float>("z", pParent->GetBufferedZ() + 10.f, false);

View File

@ -22,8 +22,9 @@
#include "gui/CGUI.h"
template<typename T>
CGUISetting<T>::CGUISetting(IGUIObject& pObject, const CStr& Name)
: m_pSetting(T()), m_Name(Name), m_pObject(pObject)
CGUISetting<T>::CGUISetting(IGUIObject& pObject, const CStr& Name, T& Value)
: m_pSetting(Value), m_Name(Name), m_pObject(pObject)
{
}

View File

@ -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

View File

@ -22,10 +22,12 @@
#include "gui/CGUI.h"
CImage::CImage(CGUI& pGUI)
: IGUIObject(pGUI)
: IGUIObject(pGUI),
m_Sprite(),
m_CellID()
{
AddSetting<CGUISpriteInstance>("sprite");
AddSetting<i32>("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<CGUISpriteInstance>("sprite"),
GetSetting<i32>("cell_id"),
GetBufferedZ(),
m_CachedActualSize);
m_pGUI.DrawSprite(m_Sprite, m_CellID, GetBufferedZ(), m_CachedActualSize);
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,7 @@
#define INCLUDED_CINPUT
#include "gui/IGUIScrollBarOwner.h"
#include "gui/CGUISprite.h"
#include "lib/external_libraries/libsdl.h"
#include <vector>
@ -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

View File

@ -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<float>("buffer_zone");
AddSetting<CStrW>("font");
AddSetting<bool>("scrollbar");
AddSetting<CStr>("scrollbar_style");
AddSetting<CStrW>("sound_disabled");
AddSetting<CStrW>("sound_selected");
AddSetting<CGUISpriteInstance>("sprite");
AddSetting<CGUISpriteInstance>("sprite_selectarea");
AddSetting<i32>("cell_id");
AddSetting<EAlign>("text_align");
AddSetting<CGUIColor>("textcolor");
AddSetting<CGUIColor>("textcolor_selected");
AddSetting<i32>("selected"); // Index selected. -1 is none.
AddSetting<bool>("auto_scroll");
AddSetting<i32>("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<CGUIList>("list");
AddSetting<CGUIList>("list_data");
RegisterSetting("list", m_List);
RegisterSetting("list_data", m_ListData);
SetSetting<bool>("scrollbar", false, true);
SetSetting<i32>("selected", -1, true);
@ -69,53 +89,44 @@ CList::~CList()
void CList::SetupText()
{
m_Modified = true;
const CGUIList& pList = GetSetting<CGUIList>("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<CStrW>("font");
const bool scrollbar = GetSetting<bool>("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<float>("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<bool>("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<CStr>(Message.value));
GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle);
SetupText();
}
@ -166,9 +177,9 @@ void CList::HandleMessage(SGUIMessage& Message)
case GUIM_MOUSE_PRESS_LEFT:
{
if (!GetSetting<bool>("enabled"))
if (!m_Enabled)
{
PlaySound("sound_disabled");
PlaySound(m_SoundDisabled);
break;
}
@ -177,7 +188,7 @@ void CList::HandleMessage(SGUIMessage& Message)
break;
SetSetting<i32>("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<i32>("hovered") == -1)
if (m_Hovered == -1)
break;
SetSetting<i32>("hovered", -1, true);
@ -202,7 +213,7 @@ void CList::HandleMessage(SGUIMessage& Message)
case GUIM_MOUSE_OVER:
{
int hovered = GetHoveredItem();
if (hovered == GetSetting<i32>("hovered"))
if (hovered == m_Hovered)
break;
SetSetting<i32>("hovered", hovered, true);
@ -212,7 +223,7 @@ void CList::HandleMessage(SGUIMessage& Message)
case GUIM_LOAD:
{
GetScrollBar(0).SetScrollBarStyle(GetSetting<CStr>("scrollbar_style"));
GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle);
break;
}
@ -277,30 +288,24 @@ InReaction CList::ManuallyHandleEvent(const SDL_Event_* ev)
void CList::Draw()
{
DrawList(GetSetting<i32>("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<bool>("scrollbar");
if (scrollbar)
if (m_ScrollBar)
IGUIScrollBarOwner::Draw();
{
CRect rect = GetListRect();
CGUISpriteInstance& sprite = GetSetting<CGUISpriteInstance>(_sprite);
CGUISpriteInstance& sprite_selectarea = GetSetting<CGUISpriteInstance>(_sprite_selected);
const int cell_id = GetSetting<i32>("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<CGUIList>("list");
const CGUIColor& color = GetSetting<CGUIColor>(_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<CGUIList>("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<CGUIList>("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<i32>("selected");
const CGUIList& pList = GetSetting<CGUIList>("list");
if (selected != static_cast<int>(pList.m_Items.size()) - 1)
if (m_Selected != static_cast<int>(m_List.m_Items.size()) - 1)
{
++selected;
SetSetting<i32>("selected", selected, true);
PlaySound("sound_selected");
SetSetting<i32>("selected", m_Selected + 1, true);
PlaySound(m_SoundSelected);
}
}
void CList::SelectPrevElement()
{
int selected = GetSetting<i32>("selected");
if (selected > 0)
if (m_Selected > 0)
{
--selected;
SetSetting<i32>("selected", selected, true);
PlaySound("sound_selected");
SetSetting<i32>("selected", m_Selected - 1, true);
PlaySound(m_SoundSelected);
}
}
void CList::SelectFirstElement()
{
if (GetSetting<i32>("selected") >= 0)
if (m_Selected >= 0)
SetSetting<i32>("selected", 0, true);
}
void CList::SelectLastElement()
{
const CGUIList& pList = GetSetting<CGUIList>("list");
const int index = static_cast<int>(pList.m_Items.size()) - 1;
const int index = static_cast<int>(m_List.m_Items.size()) - 1;
if (GetSetting<i32>("selected") != index)
if (m_Selected != index)
SetSetting<i32>("selected", index, true);
}
void CList::UpdateAutoScroll()
{
const int selected = GetSetting<i32>("selected");
const bool scrollbar = GetSetting<bool>("scrollbar");
// No scrollbar, no scrolling (at least it's not made to work properly).
if (!scrollbar || selected < 0 || static_cast<std::size_t>(selected) >= m_ItemsYPositions.size())
if (!m_ScrollBar || m_Selected < 0 || static_cast<std::size_t>(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<bool>("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<CGUIList>("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;

View File

@ -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;

View File

@ -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<CGUISpriteInstance>("sprite_heading");
AddSetting<bool>("sortable"); // The actual sorting is done in JS for more versatility
AddSetting<CStr>("selected_column");
AddSetting<i32>("selected_column_order");
AddSetting<CGUISpriteInstance>("sprite_asc"); // Show the order of sorting
AddSetting<CGUISpriteInstance>("sprite_desc");
AddSetting<CGUISpriteInstance>("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<CGUIList>("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<CStrW>("font");
const bool scrollbar = GetSetting<bool>("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<float>("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<CGUIList>("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<bool>("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<CStr>("selected_column");
int selectedColumnOrder = GetSetting<i32>("selected_column_order");
float xpos = 0;
for (const COListColumn& column : m_Columns)
{
if (GetSetting<bool>("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<i32>("selected_column_order", -1, true);
CStr selected_column = column.m_Id;
SetSetting<CStr>("selected_column", selected_column, true);
}
else
selectedColumnOrder = -selectedColumnOrder;
SetSetting<CStr>("selected_column", selectedColumn, true);
SetSetting<i32>("selected_column_order", selectedColumnOrder, true);
SetSetting<i32>("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<bool>(&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<CGUIList>("list_" + column.m_Id);
AddSetting<bool>("hidden_" + column.m_Id);
SetSetting<bool>("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<bool>("scrollbar");
if (scrollbar)
if (m_ScrollBar)
IGUIScrollBarOwner::Draw();
CRect rect = GetListRect();
CGUISpriteInstance& sprite = GetSetting<CGUISpriteInstance>(_sprite);
CGUISpriteInstance& sprite_selectarea = GetSetting<CGUISpriteInstance>(_sprite_selected);
const int cell_id = GetSetting<i32>("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<CGUISpriteInstance>("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<bool>("sortable");
const CStr& selectedColumn = GetSetting<CStr>("selected_column");
const int selectedColumnOrder = GetSetting<i32>("selected_column_order");
const CGUIColor& color = GetSetting<CGUIColor>(_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<bool>("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<CGUISpriteInstance>(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<CGUIList>("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<bool>("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;
}
}
}

View File

@ -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 \<item\> 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<COListColumn> 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;

View File

@ -22,11 +22,14 @@
#include "gui/CGUI.h"
CProgressBar::CProgressBar(CGUI& pGUI)
: IGUIObject(pGUI)
: IGUIObject(pGUI),
m_SpriteBackground(),
m_SpriteBar(),
m_Caption()
{
AddSetting<CGUISpriteInstance>("sprite_background");
AddSetting<CGUISpriteInstance>("sprite_bar");
AddSetting<float>("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<float>("caption");
if (value > 100.f)
if (m_Caption > 100.f)
SetSetting<float>("caption", 100.f, true);
else if (value < 0.f)
else if (m_Caption < 0.f)
SetSetting<float>("caption", 0.f, true);
}
break;
@ -59,18 +61,14 @@ void CProgressBar::HandleMessage(SGUIMessage& Message)
void CProgressBar::Draw()
{
CGUISpriteInstance& sprite_bar = GetSetting<CGUISpriteInstance>("sprite_bar");
CGUISpriteInstance& sprite_background = GetSetting<CGUISpriteInstance>("sprite_background");
float bz = GetBufferedZ();
int cell_id = 0;
const float value = GetSetting<float>("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);
}

View File

@ -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

View File

@ -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<float>("value");
AddSetting<float>("min_value");
AddSetting<float>("max_value");
AddSetting<i32>("cell_id");
AddSetting<CGUISpriteInstance>("sprite");
AddSetting<CGUISpriteInstance>("sprite_bar");
AddSetting<float>("button_width");
m_Value = GetSetting<float>("value");
m_MinValue = GetSetting<float>("min_value");
m_MaxValue = GetSetting<float>("max_value");
m_ButtonSide = GetSetting<float>("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<float>("value");
m_MinValue = GetSetting<float>("min_value");
m_MaxValue = GetSetting<float>("max_value");
m_ButtonSide = GetSetting<float>("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<CGUISpriteInstance>("sprite_bar");
CGUISpriteInstance& sprite_button = GetSetting<CGUISpriteInstance>("sprite");
const int cell_id = GetSetting<i32>("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()

View File

@ -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

View File

@ -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<float>("buffer_zone");
AddSetting<CGUIString>("caption");
AddSetting<i32>("cell_id");
AddSetting<bool>("clip");
AddSetting<CStrW>("font");
AddSetting<bool>("scrollbar");
AddSetting<CStr>("scrollbar_style");
AddSetting<bool>("scroll_bottom");
AddSetting<bool>("scroll_top");
AddSetting<CGUISpriteInstance>("sprite");
AddSetting<EAlign>("text_align");
AddSetting<EVAlign>("text_valign");
AddSetting<CGUIColor>("textcolor");
AddSetting<CGUIColor>("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<CStrW>("_icon_tooltip");
AddSetting<CStr>("_icon_tooltip_style");
RegisterSetting("_icon_tooltip", m_IconTooltip);
RegisterSetting("_icon_tooltip_style", m_IconTooltipStyle);
//SetSetting<bool>("ghost", true, true);
SetSetting<bool>("scrollbar", false, true);
@ -67,34 +84,25 @@ void CText::SetupText()
if (m_GeneratedTexts.empty())
return;
const bool scrollbar = GetSetting<bool>("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<CGUIString>("caption");
const CStrW& font = GetSetting<CStrW>("font");
const float buffer_zone = GetSetting<float>("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<bool>("scroll_bottom");
const bool scroll_top = GetSetting<bool>("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<CStr>(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<CStr>("scrollbar_style"));
GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle);
break;
}
@ -171,28 +180,22 @@ void CText::Draw()
{
float bz = GetBufferedZ();
const bool scrollbar = GetSetting<bool>("scrollbar");
if (scrollbar)
if (m_ScrollBar)
IGUIScrollBarOwner::Draw();
CGUISpriteInstance& sprite = GetSetting<CGUISpriteInstance>("sprite");
const int cell_id = GetSetting<i32>("cell_id");
const bool clip = GetSetting<bool>("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<bool>("enabled");
const CGUIColor& color = GetSetting<CGUIColor>(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);

View File

@ -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

View File

@ -20,34 +20,48 @@
#include "CTooltip.h"
#include "gui/CGUI.h"
#include "gui/CGUIString.h"
#include "gui/CGUIText.h"
#include <algorithm>
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<float>("buffer_zone");
AddSetting<CGUIString>("caption");
AddSetting<CStrW>("font");
AddSetting<CGUISpriteInstance>("sprite");
AddSetting<i32>("delay"); // in milliseconds
AddSetting<CGUIColor>("textcolor");
AddSetting<float>("maxwidth");
AddSetting<CPos>("offset");
AddSetting<EVAlign>("anchor");
AddSetting<EAlign>("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<bool>("independent");
// If the tooltip is just a reference to another object:
AddSetting<CStr>("use_object");
AddSetting<bool>("hide_object");
RegisterSetting("independent", m_Independent);
// Private settings:
// This is set by GUITooltip
AddSetting<CPos>("_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<i32>("delay", 500, true);
@ -67,40 +81,31 @@ void CTooltip::SetupText()
{
ENSURE(m_GeneratedTexts.size() == 1);
const CGUIString& caption = GetSetting<CGUIString>("caption");
const CStrW& font = GetSetting<CStrW>("font");
const float max_width = GetSetting<float>("maxwidth");
const float buffer_zone = GetSetting<float>("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<bool>("independent") ?
m_pGUI.GetMousePos() :
GetSetting<CPos>("_mousepos");
const CPos& offset = GetSetting<CPos>("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<EVAlign>("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<CGUISpriteInstance>("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<CGUIColor>("textcolor");
DrawText(0, color, m_CachedActualSize.TopLeft(), z+0.1f);
DrawText(0, m_TextColor, m_CachedActualSize.TopLeft(), z + 0.1f);
}

View File

@ -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

View File

@ -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<CStrW>("sound_disabled");
AddSetting<CStrW>("sound_enter");
AddSetting<CStrW>("sound_leave");
AddSetting<CStrW>("sound_pressed");
AddSetting<CStrW>("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<bool>("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<bool>("enabled"))
if (!m_Enabled)
m_pGUI.DrawSprite(sprite_disabled || sprite, cell_id, z, rect);
else if (m_MouseHovering)
{

View File

@ -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

View File

@ -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<bool>("enabled");
AddSetting<bool>("hidden");
AddSetting<CClientArea>("size");
AddSetting<CStr>("style");
AddSetting<CStr>("hotkey");
AddSetting<float>("z");
AddSetting<bool>("absolute");
AddSetting<bool>("ghost");
AddSetting<float>("aspectratio");
AddSetting<CStrW>("tooltip");
AddSetting<CStr>("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<bool>("hidden", false, true);
SetSetting<bool>("ghost", false, true);
SetSetting<bool>("enabled", true, true);
@ -117,12 +132,12 @@ void IGUIObject::AddToPointersMap(map_pObjects& ObjectMap)
}
template<typename T>
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<T>(*this, Name));
m_Settings.emplace(Name, new CGUISetting<T>(*this, Name, Value));
}
bool IGUIObject::SettingExists(const CStr& Setting) const
@ -157,7 +172,7 @@ template <typename T>
void IGUIObject::SetSetting(const CStr& Setting, T& Value, const bool SendMessage)
{
PreSettingChange(Setting);
static_cast<CGUISetting<T>* >(m_Settings[Setting])->m_pSetting = std::move(Value);
static_cast<CGUISetting<T>* >(m_Settings.at(Setting))->m_pSetting = std::move(Value);
SettingChanged(Setting, SendMessage);
}
@ -165,7 +180,7 @@ template <typename T>
void IGUIObject::SetSetting(const CStr& Setting, const T& Value, const bool SendMessage)
{
PreSettingChange(Setting);
static_cast<CGUISetting<T>* >(m_Settings[Setting])->m_pSetting = Value;
static_cast<CGUISetting<T>* >(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<bool>(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<CClientArea>("size");
const float aspectratio = GetSetting<float>("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<bool>("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<float>("z");
if (m_Absolute)
return m_Z;
if (GetSetting<bool>("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<bool>(strHidden);
return m_Hidden;
}
bool IGUIObject::IsHiddenOrGhost() const
{
static const CStr strGhost("ghost");
return IsHidden() || GetSetting<bool>(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<CStrW>(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<T>(const CStr& Name); \
template void IGUIObject::RegisterSetting<T>(const CStr& Name, T& Value); \
template T& IGUIObject::GetSetting<T>(const CStr& Setting); \
template const T& IGUIObject::GetSetting<T>(const CStr& Setting) const; \
template void IGUIObject::SetSetting<T>(const CStr& Setting, T& Value, const bool SendMessage); \

View File

@ -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<typename T> void AddSetting(const CStr& Name);
template<typename T>
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