1
0
forked from 0ad/0ad

Move static GUI<>::SetSetting operating on IGUIObject to a member IGUIObject::SetSetting.

Remove PSERROR codes from SetSetting (let std::map throw an out_of_range
if a caller wants to Set a setting that doesn't exist without having
checked with SettingExists, equal to GetSetting from 92b6cdfeab).
That also simplifies std::function SetSettingWrap construct from
0a7d0ecdde to void IGUIObject::SettingChanged.
Don't trigger debug_warn or exceptions in GUITooltip::ShowTooltip if the
XML author specified wrong tooltip input, and dodge another
dynamic_cast.

Rename existing IGUIObject::SetSetting to
IGUIObject::SetSettingFromString and comment that it is purposed for
parsing XML files.
Remove SetSetting default value, so that authors are made aware
explicitly of the need to decide the function broadcasting a message,
refs d87057b1c0, 719f2d7967, ...
Change const bool& SkipMessage to const bool SendMessage, so that a
positive value relates to a positive action.
Clean AddSettings whitespace and integer types.

Differential Revision: https://code.wildfiregames.com/D2231
Tested on: gcc 9.1.0, clang 8.0.1, Jenkins
Comments By: Philip on IRC on 2010-07-24 on GUIUtil being ugly, in case
that one counts

This was SVN commit r22796.
This commit is contained in:
elexis 2019-08-28 11:21:11 +00:00
parent 36e2c1caf8
commit 1a49ccb294
19 changed files with 203 additions and 231 deletions

View File

@ -27,7 +27,7 @@ CButton::CButton(CGUI& pGUI)
{
AddSetting<float>("buffer_zone");
AddSetting<CGUIString>("caption");
AddSetting<int>("cell_id");
AddSetting<i32>("cell_id");
AddSetting<CStrW>("font");
AddSetting<CStrW>("sound_disabled");
AddSetting<CStrW>("sound_enter");

View File

@ -33,7 +33,7 @@ CCheckBox::CCheckBox(CGUI& pGUI)
{
AddSetting<float>("buffer_zone");
AddSetting<CGUIString>("caption");
AddSetting<int>("cell_id");
AddSetting<i32>("cell_id");
AddSetting<bool>("checked");
AddSetting<CStrW>("font");
AddSetting<CStrW>("sound_disabled");
@ -88,7 +88,7 @@ void CCheckBox::HandleMessage(SGUIMessage& Message)
case GUIM_PRESSED:
{
// Switch to opposite.
GUI<bool>::SetSetting(this, "checked", !GetSetting<bool>("checked"));
SetSetting<bool>("checked", !GetSetting<bool>("checked"), true);
break;
}

View File

@ -32,7 +32,7 @@ CDropDown::CDropDown(CGUI& pGUI)
AddSetting<float>("button_width");
AddSetting<float>("dropdown_size");
AddSetting<float>("dropdown_buffer");
AddSetting<uint>("minimum_visible_items");
AddSetting<u32>("minimum_visible_items");
// AddSetting<CStrW, "font");
AddSetting<CStrW>("sound_closed");
AddSetting<CStrW>("sound_disabled");
@ -55,7 +55,7 @@ CDropDown::CDropDown(CGUI& pGUI)
AddSetting<CGUIColor>("textcolor_disabled");
// Scrollbar is forced to be true.
GUI<bool>::SetSetting(this, "scrollbar", true);
SetSetting<bool>("scrollbar", true, true);
}
CDropDown::~CDropDown()
@ -215,7 +215,7 @@ void CDropDown::HandleMessage(SGUIMessage& Message)
break;
++m_ElementHighlight;
GUI<int>::SetSetting(this, "selected", m_ElementHighlight);
SetSetting<i32>("selected", m_ElementHighlight, true);
break;
}
@ -229,8 +229,8 @@ void CDropDown::HandleMessage(SGUIMessage& Message)
if (m_ElementHighlight - 1 < 0)
break;
m_ElementHighlight--;
GUI<int>::SetSetting(this, "selected", m_ElementHighlight);
--m_ElementHighlight;
SetSetting<i32>("selected", m_ElementHighlight, true);
break;
}
@ -286,7 +286,7 @@ InReaction CDropDown::ManuallyHandleEvent(const SDL_Event_* ev)
return IN_PASS;
// Set current selected item to highlighted, before
// then really processing these in CList::ManuallyHandleEvent()
GUI<int>::SetSetting(this, "selected", m_ElementHighlight);
SetSetting<i32>("selected", m_ElementHighlight, true);
update_highlight = true;
break;
@ -334,7 +334,7 @@ InReaction CDropDown::ManuallyHandleEvent(const SDL_Event_* ev)
// let's select the closest element. There should basically always be one.
if (closest != -1)
{
GUI<int>::SetSetting(this, "selected", closest);
SetSetting<i32>("selected", closest, true);
update_highlight = true;
GetScrollBar(0).SetPos(m_ItemsYPositions[closest] - 60);
}

View File

@ -665,8 +665,11 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
if (attr.Name == attr_z)
ManuallySetZ = true;
if (object->SetSetting(pFile->GetAttributeString(attr.Name), attr.Value.FromUTF8(), true) != PSRETURN_OK)
LOGERROR("GUI: (object: %s) Can't set \"%s\" to \"%s\"", object->GetPresentableName(), pFile->GetAttributeString(attr.Name), attr.Value);
const CStr settingName = pFile->GetAttributeString(attr.Name);
if (object->SettingExists(settingName))
object->SetSettingFromString(settingName, attr.Value.FromUTF8(), false);
else
LOGERROR("GUI: (object: %s) Can't set \"%s\" to \"%s\"", object->GetPresentableName(), settingName, attr.Value);
}
// Check if name isn't set, generate an internal name in that case.
@ -681,7 +684,7 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
CStrW caption(Element.GetText().FromUTF8());
if (!caption.empty())
object->SetSetting("caption", caption, true);
object->SetSettingFromString("caption", caption, false);
for (XMBElement child : Element.GetChildNodes())
{
@ -752,16 +755,12 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
continue;
CStr context(child.GetAttributes().GetNamedItem(attr_context)); // Read the context if any.
if (!context.empty())
{
CStr translatedValue(g_L10n.TranslateWithContext(context, value));
object->SetSetting(attributeName, translatedValue.FromUTF8(), true);
}
else
{
CStr translatedValue(g_L10n.Translate(value));
object->SetSetting(attributeName, translatedValue.FromUTF8(), true);
}
CStr translatedValue = context.empty() ?
g_L10n.Translate(value) :
g_L10n.TranslateWithContext(context, value);
object->SetSettingFromString(attributeName, translatedValue.FromUTF8(), false);
}
else if (element_name == elmt_attribute)
{
@ -783,7 +782,7 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
else if (grandchild.GetNodeName() == elmt_keep)
translatedValue += grandchild.GetText();
}
object->SetSetting(attributeName, translatedValue.FromUTF8(), true);
object->SetSettingFromString(attributeName, translatedValue.FromUTF8(), false);
}
else if (element_name == elmt_include)
{
@ -867,10 +866,10 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
if (object->GetSetting<bool>("absolute"))
// If the object is absolute, we'll have to get the parent's Z buffered,
// and add to that!
GUI<float>::SetSetting(object, "z", pParent->GetBufferedZ() + 10.f, true);
object->SetSetting<float>("z", pParent->GetBufferedZ() + 10.f, false);
else
// If the object is relative, then we'll just store Z as "10"
GUI<float>::SetSetting(object, "z", 10.f, true);
object->SetSetting<float>("z", 10.f, false);
}
try
@ -1314,7 +1313,7 @@ void CGUI::Xeromyces_ReadTooltip(XMBElement Element, CXeromyces* pFile)
if (attr_name == "name")
object->SetName("__tooltip_" + attr_value);
else
object->SetSetting(attr_name, attr_value.FromUTF8());
object->SetSettingFromString(attr_name, attr_value.FromUTF8(), true);
}
AddObject(object);

View File

@ -27,7 +27,7 @@ CImage::CImage(CGUI& pGUI)
: IGUIObject(pGUI)
{
AddSetting<CGUISpriteInstance>("sprite");
AddSetting<int>("cell_id");
AddSetting<i32>("cell_id");
AddSetting<CStrW>("tooltip");
AddSetting<CStr>("tooltip_style");
}

View File

@ -77,7 +77,7 @@ CInput::~CInput()
void CInput::UpdateBufferPositionSetting()
{
GUI<i32>::SetSetting(this, "buffer_position", m_iBufferPos, true);
SetSetting<i32>("buffer_position", m_iBufferPos, false);
}
void CInput::ClearComposedText()

View File

@ -38,13 +38,13 @@ CList::CList(CGUI& pGUI)
AddSetting<CStrW>("sound_selected");
AddSetting<CGUISpriteInstance>("sprite");
AddSetting<CGUISpriteInstance>("sprite_selectarea");
AddSetting<int>( "cell_id");
AddSetting<i32>("cell_id");
AddSetting<EAlign>("text_align");
AddSetting<CGUIColor>("textcolor");
AddSetting<CGUIColor>("textcolor_selected");
AddSetting<int>( "selected"); // Index selected. -1 is none.
AddSetting<i32>("selected"); // Index selected. -1 is none.
AddSetting<bool>("auto_scroll");
AddSetting<int>( "hovered");
AddSetting<i32>("hovered");
AddSetting<CStrW>("tooltip");
AddSetting<CStr>("tooltip_style");
@ -52,10 +52,10 @@ CList::CList(CGUI& pGUI)
AddSetting<CGUIList>("list");
AddSetting<CGUIList>("list_data");
GUI<bool>::SetSetting(this, "scrollbar", false);
GUI<int>::SetSetting(this, "selected", -1);
GUI<int>::SetSetting(this, "hovered", -1);
GUI<bool>::SetSetting(this, "auto_scroll", false);
SetSetting<bool>("scrollbar", false, true);
SetSetting<i32>("selected", -1, true);
SetSetting<i32>("hovered", -1, true);
SetSetting<bool>("auto_scroll", false, true);
// Add scroll-bar
CGUIScrollBarVertical* bar = new CGUIScrollBarVertical(pGUI);
@ -176,7 +176,7 @@ void CList::HandleMessage(SGUIMessage& Message)
int hovered = GetHoveredItem();
if (hovered == -1)
break;
GUI<int>::SetSetting(this, "selected", hovered);
SetSetting<i32>("selected", hovered, true);
UpdateAutoScroll();
PlaySound("sound_selected");
@ -195,7 +195,7 @@ void CList::HandleMessage(SGUIMessage& Message)
if (GetSetting<i32>("hovered") == -1)
break;
GUI<int>::SetSetting(this, "hovered", -1);
SetSetting<i32>("hovered", -1, true);
ScriptEvent("hoverchange");
break;
}
@ -206,7 +206,7 @@ void CList::HandleMessage(SGUIMessage& Message)
if (hovered == GetSetting<i32>("hovered"))
break;
GUI<int>::SetSetting(this, "hovered", hovered);
SetSetting<i32>("hovered", hovered, true);
ScriptEvent("hoverchange");
break;
}
@ -402,7 +402,7 @@ void CList::SelectNextElement()
if (selected != static_cast<int>(pList.m_Items.size()) - 1)
{
++selected;
GUI<int>::SetSetting(this, "selected", selected);
SetSetting<i32>("selected", selected, true);
PlaySound("sound_selected");
}
}
@ -414,7 +414,7 @@ void CList::SelectPrevElement()
if (selected > 0)
{
--selected;
GUI<int>::SetSetting(this, "selected", selected);
SetSetting<i32>("selected", selected, true);
PlaySound("sound_selected");
}
}
@ -422,7 +422,7 @@ void CList::SelectPrevElement()
void CList::SelectFirstElement()
{
if (GetSetting<i32>("selected") >= 0)
GUI<int>::SetSetting(this, "selected", 0);
SetSetting<i32>("selected", 0, true);
}
void CList::SelectLastElement()
@ -430,8 +430,8 @@ void CList::SelectLastElement()
const CGUIList& pList = GetSetting<CGUIList>("list");
const int index = static_cast<int>(pList.m_Items.size()) - 1;
if (GetSetting<i32>("selected") != index)
GUI<int>::SetSetting(this, "selected", index);
if (GetSetting<i32>("selected") != index)
SetSetting<i32>("selected", index, true);
}
void CList::UpdateAutoScroll()

View File

@ -32,7 +32,7 @@ COList::COList(CGUI& pGUI)
AddSetting<CGUISpriteInstance>("sprite_heading");
AddSetting<bool>("sortable"); // The actual sorting is done in JS for more versatility
AddSetting<CStr>("selected_column");
AddSetting<int>("selected_column_order");
AddSetting<i32>("selected_column_order");
AddSetting<CGUISpriteInstance>("sprite_asc"); // Show the order of sorting
AddSetting<CGUISpriteInstance>("sprite_desc");
AddSetting<CGUISpriteInstance>("sprite_not_sorted");
@ -165,8 +165,8 @@ void COList::HandleMessage(SGUIMessage& Message)
else
selectedColumnOrder = -selectedColumnOrder;
GUI<CStr>::SetSetting(this, "selected_column", selectedColumn);
GUI<int>::SetSetting(this, "selected_column_order", selectedColumnOrder);
SetSetting<CStr>("selected_column", selectedColumn, true);
SetSetting<i32>("selected_column_order", selectedColumnOrder, true);
ScriptEvent("selectioncolumnchange");
PlaySound("sound_selected");
@ -271,7 +271,7 @@ bool COList::HandleAdditionalChildren(const XMBElement& child, CXeromyces* pFile
AddSetting<CGUIList>("list_" + column.m_Id);
AddSetting<bool>("hidden_" + column.m_Id);
GUI<bool>::SetSetting(this, "hidden_" + column.m_Id, hidden);
SetSetting<bool>("hidden_" + column.m_Id, hidden, true);
m_Columns.emplace_back(std::move(column));

View File

@ -50,9 +50,9 @@ void CProgressBar::HandleMessage(SGUIMessage& Message)
{
const float value = GetSetting<float>("caption");
if (value > 100.f)
GUI<float>::SetSetting(this, "caption", 100.f);
SetSetting<float>("caption", 100.f, true);
else if (value < 0.f)
GUI<float>::SetSetting(this, "caption", 0.f);
SetSetting<float>("caption", 0.f, true);
}
break;
default:

View File

@ -40,10 +40,10 @@ void CRadioButton::HandleMessage(SGUIMessage& Message)
// Notice, if you use other objects within the parent object that has got
// the setting "checked", it too will change. Hence NO OTHER OBJECTS THAN
// RADIO BUTTONS SHOULD BE WITHIN IT!
GUI<bool>::SetSetting(obj, "checked", false);
obj->SetSetting<bool>("checked", false, true);
}
GUI<bool>::SetSetting(this, "checked", true);
SetSetting<bool>("checked", true, true);
break;
default:

View File

@ -27,7 +27,7 @@ CSlider::CSlider(CGUI& pGUI)
AddSetting<float>("value");
AddSetting<float>("min_value");
AddSetting<float>("max_value");
AddSetting<int>("cell_id");
AddSetting<i32>("cell_id");
AddSetting<CGUISpriteInstance>("sprite");
AddSetting<CGUISpriteInstance>("sprite_bar");
AddSetting<float>("button_width");
@ -129,7 +129,7 @@ void CSlider::Draw()
void CSlider::UpdateValue()
{
GUI<float>::SetSetting(this, "value", m_Value);
SetSetting<float>("value", m_Value, true);
ScriptEvent("valuechange");
}

View File

@ -28,7 +28,7 @@ CText::CText(CGUI& pGUI)
{
AddSetting<float>("buffer_zone");
AddSetting<CGUIString>("caption");
AddSetting<int>("cell_id");
AddSetting<i32>("cell_id");
AddSetting<bool>("clip");
AddSetting<CStrW>("font");
AddSetting<bool>("scrollbar");
@ -47,9 +47,9 @@ CText::CText(CGUI& pGUI)
AddSetting<CStrW>("_icon_tooltip");
AddSetting<CStr>("_icon_tooltip_style");
//GUI<bool>::SetSetting(this, "ghost", true);
GUI<bool>::SetSetting(this, "scrollbar", false);
GUI<bool>::SetSetting(this, "clip", true);
//SetSetting<bool>("ghost", true, true);
SetSetting<bool>("scrollbar", false, true);
SetSetting<bool>("clip", true, true);
// Add scroll-bar
CGUIScrollBarVertical* bar = new CGUIScrollBarVertical(pGUI);
@ -228,8 +228,8 @@ bool CText::MouseOverIcon()
// If tooltip exists, set the property
if (!spritecall.m_Tooltip.empty())
{
SetSetting("_icon_tooltip_style", spritecall.m_TooltipStyle);
SetSetting("_icon_tooltip", spritecall.m_Tooltip);
SetSettingFromString("_icon_tooltip_style", spritecall.m_TooltipStyle, true);
SetSettingFromString("_icon_tooltip", spritecall.m_Tooltip, true);
}
return true;

View File

@ -30,7 +30,7 @@ CTooltip::CTooltip(CGUI& pGUI)
AddSetting<CGUIString>("caption");
AddSetting<CStrW>("font");
AddSetting<CGUISpriteInstance>("sprite");
AddSetting<int>("delay");
AddSetting<i32>("delay"); // in milliseconds
AddSetting<CGUIColor>("textcolor");
AddSetting<float>("maxwidth");
AddSetting<CPos>("offset");
@ -48,9 +48,9 @@ CTooltip::CTooltip(CGUI& pGUI)
AddSetting<CPos>("_mousepos");
// Defaults
GUI<int>::SetSetting(this, "delay", 500);
GUI<EVAlign>::SetSetting(this, "anchor", EVAlign_Bottom);
GUI<EAlign>::SetSetting(this, "text_align", EAlign_Left);
SetSetting<i32>("delay", 500, true);
SetSetting<EVAlign>("anchor", EVAlign_Bottom, true);
SetSetting<EAlign>("text_align", EAlign_Left, true);
// Set up a blank piece of text, to be replaced with a more
// interesting message later
@ -123,7 +123,7 @@ void CTooltip::SetupText()
else if (size.pixel.right > screenw)
size.pixel.left -= (size.pixel.right-screenw), size.pixel.right = screenw;
GUI<CClientArea>::SetSetting(this, "size", size);
SetSetting<CClientArea>("size", size, true);
}
void CTooltip::HandleMessage(SGUIMessage& Message)

View File

@ -20,7 +20,6 @@
#include "GUITooltip.h"
#include "CGUI.h"
#include "GUIutil.h"
#include "IGUIObject.h"
#include "lib/timer.h"
@ -119,17 +118,32 @@ void GUITooltip::ShowTooltip(IGUIObject* obj, const CPos& pos, const CStr& style
if (style.empty())
return;
// Must be a CTooltip*, but we avoid dynamic_cast
IGUIObject* tooltipobj = pGUI.FindObjectByName("__tooltip_" + style);
if (!tooltipobj)
if (!tooltipobj || !tooltipobj->SettingExists("use_object"))
{
LOGERROR("Cannot find tooltip named '%s'", style.c_str());
return;
}
IGUIObject* usedobj = tooltipobj; // object actually used to display the tooltip in
IGUIObject* usedobj; // object actually used to display the tooltip in
const CStr& usedObjectName = tooltipobj->GetSetting<CStr>("use_object");
if (!usedObjectName.empty())
if (usedObjectName.empty())
{
usedobj = tooltipobj;
if (usedobj->SettingExists("_mousepos"))
{
usedobj->SetSetting<CPos>("_mousepos", pos, true);
}
else
{
LOGERROR("Object '%s' used by tooltip '%s' isn't a tooltip object!", usedObjectName.c_str(), style.c_str());
return;
}
}
else
{
usedobj = pGUI.FindObjectByName(usedObjectName);
if (!usedobj)
@ -138,15 +152,20 @@ void GUITooltip::ShowTooltip(IGUIObject* obj, const CPos& pos, const CStr& style
return;
}
}
else if (GUI<CPos>::SetSetting(usedobj, "_mousepos", pos) != PSRETURN_OK)
debug_warn(L"Failed to set tooltip mouse position");
GUI<bool>::SetSetting(usedobj, "hidden", false);
if (usedobj->SettingExists("caption"))
{
const CStrW& text = obj->GetSetting<CStrW>(m_IsIconTooltip ? "_icon_tooltip" : "tooltip");
usedobj->SetSettingFromString("caption", text, true);
}
else
{
LOGERROR("Object '%s' used by tooltip '%s' must have a caption setting!", usedobj->GetPresentableName().c_str(), style.c_str());
return;
}
const CStrW& text = obj->GetSetting<CStrW>(m_IsIconTooltip ? "_icon_tooltip" : "tooltip");
if (usedobj->SetSetting("caption", text) != PSRETURN_OK)
debug_warn(L"Failed to set tooltip caption");
// Every IGUIObject has a "hidden" setting
usedobj->SetSetting<bool>("hidden", false, true);
}
void GUITooltip::HideTooltip(const CStr& style, CGUI& pGUI)
@ -154,10 +173,11 @@ void GUITooltip::HideTooltip(const CStr& style, CGUI& pGUI)
if (style.empty())
return;
// Must be a CTooltip*, but we avoid dynamic_cast
IGUIObject* tooltipobj = pGUI.FindObjectByName("__tooltip_" + style);
if (!tooltipobj)
if (!tooltipobj || !tooltipobj->SettingExists("use_object") || !tooltipobj->SettingExists("hide_object"))
{
LOGERROR("Cannot find tooltip named '%s'", style.c_str());
LOGERROR("Cannot find tooltip named '%s' or it is not a tooltip", style.c_str());
return;
}
@ -165,23 +185,27 @@ void GUITooltip::HideTooltip(const CStr& style, CGUI& pGUI)
if (!usedObjectName.empty())
{
IGUIObject* usedobj = pGUI.FindObjectByName(usedObjectName);
if (!usedobj)
if (usedobj && usedobj->SettingExists("caption"))
{
LOGERROR("Cannot find object named '%s' used by tooltip '%s'", usedObjectName.c_str(), style.c_str());
usedobj->SetSettingFromString("caption", L"", true);
}
else
{
LOGERROR("Object named '%s' used by tooltip '%s' does not exist or does not have a caption setting!", usedObjectName.c_str(), style.c_str());
return;
}
usedobj->SetSetting("caption", L"");
if (tooltipobj->GetSetting<bool>("hide_object"))
GUI<bool>::SetSetting(usedobj, "hidden", true);
// Every IGUIObject has a "hidden" setting
usedobj->SetSetting<bool>("hidden", true, true);
}
else
GUI<bool>::SetSetting(tooltipobj, "hidden", true);
tooltipobj->SetSetting<bool>("hidden", true, true);
}
static i32 GetTooltipDelay(const CStr& style, CGUI& pGUI)
{
// Must be a CTooltip*, but we avoid dynamic_cast
IGUIObject* tooltipobj = pGUI.FindObjectByName("__tooltip_" + style);
if (!tooltipobj)

View File

@ -20,7 +20,6 @@
#include "GUIutil.h"
#include "gui/GUI.h"
#include "ps/CLogger.h"
template<typename T>
CGUISetting<T>::CGUISetting(IGUIObject& pObject, const CStr& Name)
@ -29,19 +28,19 @@ CGUISetting<T>::CGUISetting(IGUIObject& pObject, const CStr& Name)
}
template<typename T>
bool CGUISetting<T>::FromString(const CStrW& Value, const bool& SkipMessage)
bool CGUISetting<T>::FromString(const CStrW& Value, const bool SendMessage)
{
T settingValue;
if (!GUI<T>::ParseString(&m_pObject.GetGUI(), Value, settingValue))
return false;
GUI<T>::SetSetting(&m_pObject, m_Name, settingValue, SkipMessage);
m_pObject.SetSetting<T>(m_Name, settingValue, SendMessage);
return true;
};
template<>
bool CGUISetting<CGUIColor>::FromJSVal(JSContext* cx, JS::HandleValue Value)
bool CGUISetting<CGUIColor>::FromJSVal(JSContext* cx, JS::HandleValue Value, const bool SendMessage)
{
CGUIColor settingValue;
if (Value.isString())
@ -59,18 +58,18 @@ bool CGUISetting<CGUIColor>::FromJSVal(JSContext* cx, JS::HandleValue Value)
else if (!ScriptInterface::FromJSVal<CColor>(cx, Value, settingValue))
return false;
GUI<CGUIColor>::SetSetting(&m_pObject, m_Name, settingValue);
m_pObject.SetSetting<CGUIColor>(m_Name, settingValue, SendMessage);
return true;
};
template<typename T>
bool CGUISetting<T>::FromJSVal(JSContext* cx, JS::HandleValue Value)
bool CGUISetting<T>::FromJSVal(JSContext* cx, JS::HandleValue Value, const bool SendMessage)
{
T settingValue;
if (!ScriptInterface::FromJSVal<T>(cx, Value, settingValue))
return false;
GUI<T>::SetSetting(&m_pObject, m_Name, settingValue);
m_pObject.SetSetting<T>(m_Name, settingValue, SendMessage);
return true;
};
@ -80,76 +79,8 @@ void CGUISetting<T>::ToJSVal(JSContext* cx, JS::MutableHandleValue Value)
ScriptInterface::ToJSVal<T>(cx, Value, m_pSetting);
};
template <typename T>
PSRETURN GUI<T>::SetSetting(IGUIObject* pObject, const CStr& Setting, T& Value, const bool& SkipMessage)
{
return SetSettingWrap(pObject, Setting, SkipMessage,
[&pObject, &Setting, &Value]() {
static_cast<CGUISetting<T>* >(pObject->m_Settings[Setting])->m_pSetting = std::move(Value);
});
}
template <typename T>
PSRETURN GUI<T>::SetSetting(IGUIObject* pObject, const CStr& Setting, const T& Value, const bool& SkipMessage)
{
return SetSettingWrap(pObject, Setting, SkipMessage,
[&pObject, &Setting, &Value]() {
static_cast<CGUISetting<T>* >(pObject->m_Settings[Setting])->m_pSetting = Value;
});
}
template <typename T>
PSRETURN GUI<T>::SetSettingWrap(IGUIObject* pObject, const CStr& Setting, const bool& SkipMessage, const std::function<void()>& valueSet)
{
ENSURE(pObject != NULL);
if (!pObject->SettingExists(Setting))
{
LOGWARNING("setting %s was not found on object %s",
Setting.c_str(),
pObject->GetPresentableName().c_str());
return PSRETURN_GUI_InvalidSetting;
}
valueSet();
// Some settings needs special attention at change
// If setting was "size", we need to re-cache itself and all children
if (Setting == "size")
{
pObject->RecurseObject(nullptr, &IGUIObject::UpdateCachedSize);
}
else if (Setting == "hidden")
{
// Hiding an object requires us to reset it and all children
if (pObject->GetSetting<bool>(Setting))
pObject->RecurseObject(nullptr, &IGUIObject::ResetStates);
}
if (!SkipMessage)
{
SGUIMessage msg(GUIM_SETTINGS_UPDATED, Setting);
pObject->HandleMessage(msg);
}
return PSRETURN_OK;
}
// Instantiate templated functions:
// These functions avoid copies by working with a reference and move semantics.
#define TYPE(T) \
template PSRETURN GUI<T>::SetSetting(IGUIObject* pObject, const CStr& Setting, T& Value, const bool& SkipMessage); \
template class CGUISetting<T>; \
#include "GUItypes.h"
#undef TYPE
// Copying functions - discouraged except for primitives.
#define TYPE(T) \
template PSRETURN GUI<T>::SetSetting(IGUIObject* pObject, const CStr& Setting, const T& Value, const bool& SkipMessage); \
#define GUITYPE_IGNORE_NONCOPYABLE
#include "GUItypes.h"
#undef GUITYPE_IGNORE_NONCOPYABLE
#undef TYPE

View File

@ -15,18 +15,11 @@
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Contains help class GUI<>, which gives us templated
parameter to all functions within GUI.
*/
#ifndef INCLUDED_GUIUTIL
#define INCLUDED_GUIUTIL
#include "gui/IGUIObject.h"
#include <functional>
class CGUI;
template<typename T> class GUI;
@ -41,12 +34,12 @@ public:
/**
* Parses the given string and assigns to the setting value. Used for parsing XML attributes.
*/
virtual bool FromString(const CStrW& Value, const bool& SkipMessage) = 0;
virtual bool FromString(const CStrW& Value, const bool SendMessage) = 0;
/**
* Parses the given JS::Value using ScriptInterface::FromJSVal and assigns it to the setting data.
*/
virtual bool FromJSVal(JSContext* cx, JS::HandleValue Value) = 0;
virtual bool FromJSVal(JSContext* cx, JS::HandleValue Value, const bool SendMessage) = 0;
/**
* Converts the setting data to a JS::Value using ScriptInterface::ToJSVal.
@ -67,12 +60,12 @@ public:
/**
* Parses the given string and assigns to the setting value. Used for parsing XML attributes.
*/
bool FromString(const CStrW& Value, const bool& SkipMessage) override;
bool FromString(const CStrW& Value, const bool SendMessage) override;
/**
* Parses the given JS::Value using ScriptInterface::FromJSVal and assigns it to the setting data.
*/
bool FromJSVal(JSContext* cx, JS::HandleValue Value) override;
bool FromJSVal(JSContext* cx, JS::HandleValue Value, const bool SendMessage) override;
/**
* Converts the setting data to a JS::Value using ScriptInterface::ToJSVal.
@ -81,6 +74,7 @@ public:
/**
* These members are public because they are either unmodifiable or free to be modified.
* In particular it avoids the need for setter templates specialized depending on copiability.
*/
/**
@ -99,33 +93,12 @@ public:
T m_pSetting;
};
/**
* Includes static functions that needs one template
* argument.
*/
template <typename T>
class GUI
{
public:
NONCOPYABLE(GUI);
/**
* Sets a value by name using a real datatype as input.
* This variant will use the move-assignment.
*
* @param pObject Object pointer
* @param Setting Setting by name
* @param Value Sets value to this, note type T!
* @param SkipMessage Does not send a GUIM_SETTINGS_UPDATED if true
*/
static PSRETURN SetSetting(IGUIObject* pObject, const CStr& Setting, T& Value, const bool& SkipMessage = false);
/**
* This variant will copy the value.
*/
static PSRETURN SetSetting(IGUIObject* pObject, const CStr& Setting, const T& Value, const bool& SkipMessage = false);
/**
* Sets a value by setting and object name using a real
* datatype as input.
@ -135,14 +108,6 @@ public:
* @return True at success.
*/
static bool ParseString(const CGUI* pGUI, const CStrW& Value, T& tOutput);
private:
/**
* Changes the value of the setting by calling the valueSet functon that performs either a copy or move assignment.
* Updates some internal data depending on the setting changed.
*/
static PSRETURN SetSettingWrap(IGUIObject* pObject, const CStr& Setting, const bool& SkipMessage, const std::function<void()>& valueSet);
};
#endif // INCLUDED_GUIUTIL

View File

@ -43,10 +43,10 @@ IGUIObject::IGUIObject(CGUI& pGUI)
AddSetting<CStr>("tooltip_style");
// Setup important defaults
GUI<bool>::SetSetting(this, "hidden", false);
GUI<bool>::SetSetting(this, "ghost", false);
GUI<bool>::SetSetting(this, "enabled", true);
GUI<bool>::SetSetting(this, "absolute", true);
SetSetting<bool>("hidden", false, true);
SetSetting<bool>("ghost", false, true);
SetSetting<bool>("enabled", true, true);
SetSetting<bool>("absolute", true, true);
}
IGUIObject::~IGUIObject()
@ -145,6 +145,46 @@ const T& IGUIObject::GetSetting(const CStr& Setting) const
return static_cast<CGUISetting<T>* >(m_Settings.at(Setting))->m_pSetting;
}
bool IGUIObject::SetSettingFromString(const CStr& Setting, const CStrW& Value, const bool SendMessage)
{
return m_Settings[Setting]->FromString(Value, SendMessage);
}
template <typename T>
void IGUIObject::SetSetting(const CStr& Setting, T& Value, const bool SendMessage)
{
static_cast<CGUISetting<T>* >(m_Settings[Setting])->m_pSetting = std::move(Value);
SettingChanged(Setting, SendMessage);
}
template <typename T>
void IGUIObject::SetSetting(const CStr& Setting, const T& Value, const bool SendMessage)
{
static_cast<CGUISetting<T>* >(m_Settings[Setting])->m_pSetting = Value;
SettingChanged(Setting, SendMessage);
}
void IGUIObject::SettingChanged(const CStr& Setting, const bool SendMessage)
{
if (Setting == "size")
{
// If setting was "size", we need to re-cache itself and all children
RecurseObject(nullptr, &IGUIObject::UpdateCachedSize);
}
else if (Setting == "hidden")
{
// Hiding an object requires us to reset it and all children
if (GetSetting<bool>(Setting))
RecurseObject(nullptr, &IGUIObject::ResetStates);
}
if (SendMessage)
{
SGUIMessage msg(GUIM_SETTINGS_UPDATED, Setting);
HandleMessage(msg);
}
}
bool IGUIObject::IsMouseOver() const
{
return m_CachedActualSize.PointInside(m_pGUI.GetMousePos());
@ -176,17 +216,6 @@ void IGUIObject::UpdateMouseOver(IGUIObject* const& pMouseOver)
}
}
PSRETURN IGUIObject::SetSetting(const CStr& Setting, const CStrW& Value, const bool& SkipMessage)
{
if (!SettingExists(Setting))
return PSRETURN_GUI_InvalidSetting;
if (!m_Settings[Setting]->FromString(Value, SkipMessage))
return PSRETURN_GUI_UnableToParse;
return PSRETURN_OK;
}
void IGUIObject::ChooseMouseOverAndClosest(IGUIObject*& pObject)
{
if (!IsMouseOver())
@ -271,7 +300,7 @@ void IGUIObject::LoadStyle(const CStr& StyleName)
for (const std::pair<CStr, CStrW>& p : m_pGUI.GetStyle(StyleName).m_SettingsDefaults)
{
if (SettingExists(p.first))
SetSetting(p.first, p.second);
SetSettingFromString(p.first, p.second, true);
else if (StyleName != "default")
LOGWARNING("GUI object has no setting \"%s\", but the style \"%s\" defines it", p.first, StyleName.c_str());
}
@ -483,11 +512,21 @@ 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 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); \
#include "gui/GUItypes.h"
#undef TYPE
// Copying functions - discouraged except for primitives.
#define TYPE(T) \
template void IGUIObject::SetSetting<T>(const CStr& Setting, const T& Value, const bool SendMessage); \
#define GUITYPE_IGNORE_NONCOPYABLE
#include "gui/GUItypes.h"
#undef GUITYPE_IGNORE_NONCOPYABLE
#undef TYPE

View File

@ -33,7 +33,6 @@
#include "lib/input.h" // just for IN_PASS
#include "ps/XML/Xeromyces.h"
#include <functional>
#include <string>
#include <vector>
@ -159,6 +158,29 @@ public:
template <typename T>
const T& GetSetting(const CStr& Setting) const;
/**
* Set a setting by string, regardless of what type it is.
* Used to parse setting values from XML files.
* For example a CRect(10,10,20,20) is created from "10 10 20 20".
* Returns false if the conversion fails, otherwise true.
*/
bool SetSettingFromString(const CStr& Setting, const CStrW& Value, const bool SendMessage);
/**
* Assigns the given value to the setting identified by the given name.
* Uses move semantics, so do not read from Value after this call.
*
* @param SendMessage If true, a GUIM_SETTINGS_UPDATED message will be broadcasted to all GUI objects.
*/
template <typename T>
void SetSetting(const CStr& Setting, T& Value, const bool SendMessage);
/**
* This variant will copy the value.
*/
template <typename T>
void SetSetting(const CStr& Setting, const T& Value, const bool SendMessage);
/**
* Returns whether this is object is set to be hidden.
*/
@ -181,19 +203,6 @@ public:
*/
virtual void ResetStates();
/**
* Set a setting by string, regardless of what type it is.
*
* example a CRect(10,10,20,20) would be "10 10 20 20"
*
* @param Setting Setting by name
* @param Value Value to set to
* @param SkipMessage Does not send a GUIM_SETTINGS_UPDATED if true
*
* @return PSRETURN (PSRETURN_OK if successful)
*/
PSRETURN SetSetting(const CStr& Setting, const CStrW& Value, const bool& SkipMessage = false);
/**
* Set the script handler for a particular object-specific action
*
@ -416,6 +425,11 @@ private:
//--------------------------------------------------------
//@{
/**
* Updates some internal data depending on the setting changed.
*/
void SettingChanged(const CStr& Setting, const bool SendMessage);
/**
* Inputs a reference pointer, checks if the new inputted object
* if hovered, if so, then check if this's Z value is greater

View File

@ -168,7 +168,7 @@ bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Handle
}
if (e->SettingExists(propName))
return e->m_Settings[propName]->FromJSVal(cx, vp) ? result.succeed() : result.fail(JSMSG_TYPE_ERR_BAD_ARGS);
return e->m_Settings[propName]->FromJSVal(cx, vp, true) ? result.succeed() : result.fail(JSMSG_TYPE_ERR_BAD_ARGS);
JS_ReportError(cx, "Property '%s' does not exist!", propName.c_str());
return result.fail(JSMSG_UNDEFINED_PROP);