Index: ps/trunk/source/gui/CButton.cpp =================================================================== --- ps/trunk/source/gui/CButton.cpp +++ ps/trunk/source/gui/CButton.cpp @@ -27,7 +27,7 @@ { AddSetting("buffer_zone"); AddSetting("caption"); - AddSetting("cell_id"); + AddSetting("cell_id"); AddSetting("font"); AddSetting("sound_disabled"); AddSetting("sound_enter"); Index: ps/trunk/source/gui/CCheckBox.cpp =================================================================== --- ps/trunk/source/gui/CCheckBox.cpp +++ ps/trunk/source/gui/CCheckBox.cpp @@ -33,7 +33,7 @@ { AddSetting("buffer_zone"); AddSetting("caption"); - AddSetting("cell_id"); + AddSetting("cell_id"); AddSetting("checked"); AddSetting("font"); AddSetting("sound_disabled"); @@ -88,7 +88,7 @@ case GUIM_PRESSED: { // Switch to opposite. - GUI::SetSetting(this, "checked", !GetSetting("checked")); + SetSetting("checked", !GetSetting("checked"), true); break; } Index: ps/trunk/source/gui/CDropDown.cpp =================================================================== --- ps/trunk/source/gui/CDropDown.cpp +++ ps/trunk/source/gui/CDropDown.cpp @@ -32,7 +32,7 @@ AddSetting("button_width"); AddSetting("dropdown_size"); AddSetting("dropdown_buffer"); - AddSetting("minimum_visible_items"); + AddSetting("minimum_visible_items"); // AddSetting("sound_closed"); AddSetting("sound_disabled"); @@ -55,7 +55,7 @@ AddSetting("textcolor_disabled"); // Scrollbar is forced to be true. - GUI::SetSetting(this, "scrollbar", true); + SetSetting("scrollbar", true, true); } CDropDown::~CDropDown() @@ -215,7 +215,7 @@ break; ++m_ElementHighlight; - GUI::SetSetting(this, "selected", m_ElementHighlight); + SetSetting("selected", m_ElementHighlight, true); break; } @@ -229,8 +229,8 @@ if (m_ElementHighlight - 1 < 0) break; - m_ElementHighlight--; - GUI::SetSetting(this, "selected", m_ElementHighlight); + --m_ElementHighlight; + SetSetting("selected", m_ElementHighlight, true); break; } @@ -286,7 +286,7 @@ return IN_PASS; // Set current selected item to highlighted, before // then really processing these in CList::ManuallyHandleEvent() - GUI::SetSetting(this, "selected", m_ElementHighlight); + SetSetting("selected", m_ElementHighlight, true); update_highlight = true; break; @@ -334,7 +334,7 @@ // let's select the closest element. There should basically always be one. if (closest != -1) { - GUI::SetSetting(this, "selected", closest); + SetSetting("selected", closest, true); update_highlight = true; GetScrollBar(0).SetPos(m_ItemsYPositions[closest] - 60); } Index: ps/trunk/source/gui/CGUI.cpp =================================================================== --- ps/trunk/source/gui/CGUI.cpp +++ ps/trunk/source/gui/CGUI.cpp @@ -665,8 +665,11 @@ 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 @@ 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 @@ 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 @@ 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 @@ if (object->GetSetting("absolute")) // If the object is absolute, we'll have to get the parent's Z buffered, // and add to that! - GUI::SetSetting(object, "z", pParent->GetBufferedZ() + 10.f, true); + object->SetSetting("z", pParent->GetBufferedZ() + 10.f, false); else // If the object is relative, then we'll just store Z as "10" - GUI::SetSetting(object, "z", 10.f, true); + object->SetSetting("z", 10.f, false); } try @@ -1314,7 +1313,7 @@ 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); Index: ps/trunk/source/gui/CImage.cpp =================================================================== --- ps/trunk/source/gui/CImage.cpp +++ ps/trunk/source/gui/CImage.cpp @@ -27,7 +27,7 @@ : IGUIObject(pGUI) { AddSetting("sprite"); - AddSetting("cell_id"); + AddSetting("cell_id"); AddSetting("tooltip"); AddSetting("tooltip_style"); } Index: ps/trunk/source/gui/CInput.cpp =================================================================== --- ps/trunk/source/gui/CInput.cpp +++ ps/trunk/source/gui/CInput.cpp @@ -77,7 +77,7 @@ void CInput::UpdateBufferPositionSetting() { - GUI::SetSetting(this, "buffer_position", m_iBufferPos, true); + SetSetting("buffer_position", m_iBufferPos, false); } void CInput::ClearComposedText() Index: ps/trunk/source/gui/CList.cpp =================================================================== --- ps/trunk/source/gui/CList.cpp +++ ps/trunk/source/gui/CList.cpp @@ -38,13 +38,13 @@ AddSetting("sound_selected"); AddSetting("sprite"); AddSetting("sprite_selectarea"); - AddSetting( "cell_id"); + AddSetting("cell_id"); AddSetting("text_align"); AddSetting("textcolor"); AddSetting("textcolor_selected"); - AddSetting( "selected"); // Index selected. -1 is none. + AddSetting("selected"); // Index selected. -1 is none. AddSetting("auto_scroll"); - AddSetting( "hovered"); + AddSetting("hovered"); AddSetting("tooltip"); AddSetting("tooltip_style"); @@ -52,10 +52,10 @@ AddSetting("list"); AddSetting("list_data"); - GUI::SetSetting(this, "scrollbar", false); - GUI::SetSetting(this, "selected", -1); - GUI::SetSetting(this, "hovered", -1); - GUI::SetSetting(this, "auto_scroll", false); + SetSetting("scrollbar", false, true); + SetSetting("selected", -1, true); + SetSetting("hovered", -1, true); + SetSetting("auto_scroll", false, true); // Add scroll-bar CGUIScrollBarVertical* bar = new CGUIScrollBarVertical(pGUI); @@ -176,7 +176,7 @@ int hovered = GetHoveredItem(); if (hovered == -1) break; - GUI::SetSetting(this, "selected", hovered); + SetSetting("selected", hovered, true); UpdateAutoScroll(); PlaySound("sound_selected"); @@ -195,7 +195,7 @@ if (GetSetting("hovered") == -1) break; - GUI::SetSetting(this, "hovered", -1); + SetSetting("hovered", -1, true); ScriptEvent("hoverchange"); break; } @@ -206,7 +206,7 @@ if (hovered == GetSetting("hovered")) break; - GUI::SetSetting(this, "hovered", hovered); + SetSetting("hovered", hovered, true); ScriptEvent("hoverchange"); break; } @@ -402,7 +402,7 @@ if (selected != static_cast(pList.m_Items.size()) - 1) { ++selected; - GUI::SetSetting(this, "selected", selected); + SetSetting("selected", selected, true); PlaySound("sound_selected"); } } @@ -414,7 +414,7 @@ if (selected > 0) { --selected; - GUI::SetSetting(this, "selected", selected); + SetSetting("selected", selected, true); PlaySound("sound_selected"); } } @@ -422,7 +422,7 @@ void CList::SelectFirstElement() { if (GetSetting("selected") >= 0) - GUI::SetSetting(this, "selected", 0); + SetSetting("selected", 0, true); } void CList::SelectLastElement() @@ -430,8 +430,8 @@ const CGUIList& pList = GetSetting("list"); const int index = static_cast(pList.m_Items.size()) - 1; - if (GetSetting("selected") != index) - GUI::SetSetting(this, "selected", index); + if (GetSetting("selected") != index) + SetSetting("selected", index, true); } void CList::UpdateAutoScroll() Index: ps/trunk/source/gui/COList.cpp =================================================================== --- ps/trunk/source/gui/COList.cpp +++ ps/trunk/source/gui/COList.cpp @@ -32,7 +32,7 @@ AddSetting("sprite_heading"); AddSetting("sortable"); // The actual sorting is done in JS for more versatility AddSetting("selected_column"); - AddSetting("selected_column_order"); + AddSetting("selected_column_order"); AddSetting("sprite_asc"); // Show the order of sorting AddSetting("sprite_desc"); AddSetting("sprite_not_sorted"); @@ -165,8 +165,8 @@ else selectedColumnOrder = -selectedColumnOrder; - GUI::SetSetting(this, "selected_column", selectedColumn); - GUI::SetSetting(this, "selected_column_order", selectedColumnOrder); + SetSetting("selected_column", selectedColumn, true); + SetSetting("selected_column_order", selectedColumnOrder, true); ScriptEvent("selectioncolumnchange"); PlaySound("sound_selected"); @@ -271,7 +271,7 @@ AddSetting("list_" + column.m_Id); AddSetting("hidden_" + column.m_Id); - GUI::SetSetting(this, "hidden_" + column.m_Id, hidden); + SetSetting("hidden_" + column.m_Id, hidden, true); m_Columns.emplace_back(std::move(column)); Index: ps/trunk/source/gui/CProgressBar.cpp =================================================================== --- ps/trunk/source/gui/CProgressBar.cpp +++ ps/trunk/source/gui/CProgressBar.cpp @@ -50,9 +50,9 @@ { const float value = GetSetting("caption"); if (value > 100.f) - GUI::SetSetting(this, "caption", 100.f); + SetSetting("caption", 100.f, true); else if (value < 0.f) - GUI::SetSetting(this, "caption", 0.f); + SetSetting("caption", 0.f, true); } break; default: Index: ps/trunk/source/gui/CRadioButton.cpp =================================================================== --- ps/trunk/source/gui/CRadioButton.cpp +++ ps/trunk/source/gui/CRadioButton.cpp @@ -40,10 +40,10 @@ // 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::SetSetting(obj, "checked", false); + obj->SetSetting("checked", false, true); } - GUI::SetSetting(this, "checked", true); + SetSetting("checked", true, true); break; default: Index: ps/trunk/source/gui/CSlider.cpp =================================================================== --- ps/trunk/source/gui/CSlider.cpp +++ ps/trunk/source/gui/CSlider.cpp @@ -27,7 +27,7 @@ AddSetting("value"); AddSetting("min_value"); AddSetting("max_value"); - AddSetting("cell_id"); + AddSetting("cell_id"); AddSetting("sprite"); AddSetting("sprite_bar"); AddSetting("button_width"); @@ -129,7 +129,7 @@ void CSlider::UpdateValue() { - GUI::SetSetting(this, "value", m_Value); + SetSetting("value", m_Value, true); ScriptEvent("valuechange"); } Index: ps/trunk/source/gui/CText.cpp =================================================================== --- ps/trunk/source/gui/CText.cpp +++ ps/trunk/source/gui/CText.cpp @@ -28,7 +28,7 @@ { AddSetting("buffer_zone"); AddSetting("caption"); - AddSetting("cell_id"); + AddSetting("cell_id"); AddSetting("clip"); AddSetting("font"); AddSetting("scrollbar"); @@ -47,9 +47,9 @@ AddSetting("_icon_tooltip"); AddSetting("_icon_tooltip_style"); - //GUI::SetSetting(this, "ghost", true); - GUI::SetSetting(this, "scrollbar", false); - GUI::SetSetting(this, "clip", true); + //SetSetting("ghost", true, true); + SetSetting("scrollbar", false, true); + SetSetting("clip", true, true); // Add scroll-bar CGUIScrollBarVertical* bar = new CGUIScrollBarVertical(pGUI); @@ -228,8 +228,8 @@ // 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; Index: ps/trunk/source/gui/CTooltip.cpp =================================================================== --- ps/trunk/source/gui/CTooltip.cpp +++ ps/trunk/source/gui/CTooltip.cpp @@ -30,7 +30,7 @@ AddSetting("caption"); AddSetting("font"); AddSetting("sprite"); - AddSetting("delay"); + AddSetting("delay"); // in milliseconds AddSetting("textcolor"); AddSetting("maxwidth"); AddSetting("offset"); @@ -48,9 +48,9 @@ AddSetting("_mousepos"); // Defaults - GUI::SetSetting(this, "delay", 500); - GUI::SetSetting(this, "anchor", EVAlign_Bottom); - GUI::SetSetting(this, "text_align", EAlign_Left); + SetSetting("delay", 500, true); + SetSetting("anchor", EVAlign_Bottom, true); + SetSetting("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 @@ else if (size.pixel.right > screenw) size.pixel.left -= (size.pixel.right-screenw), size.pixel.right = screenw; - GUI::SetSetting(this, "size", size); + SetSetting("size", size, true); } void CTooltip::HandleMessage(SGUIMessage& Message) Index: ps/trunk/source/gui/GUITooltip.cpp =================================================================== --- ps/trunk/source/gui/GUITooltip.cpp +++ ps/trunk/source/gui/GUITooltip.cpp @@ -20,7 +20,6 @@ #include "GUITooltip.h" #include "CGUI.h" -#include "GUIutil.h" #include "IGUIObject.h" #include "lib/timer.h" @@ -119,17 +118,32 @@ 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("use_object"); - if (!usedObjectName.empty()) + if (usedObjectName.empty()) + { + usedobj = tooltipobj; + + if (usedobj->SettingExists("_mousepos")) + { + usedobj->SetSetting("_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 @@ return; } } - else if (GUI::SetSetting(usedobj, "_mousepos", pos) != PSRETURN_OK) - debug_warn(L"Failed to set tooltip mouse position"); - - GUI::SetSetting(usedobj, "hidden", false); - const CStrW& text = obj->GetSetting(m_IsIconTooltip ? "_icon_tooltip" : "tooltip"); + if (usedobj->SettingExists("caption")) + { + const CStrW& text = obj->GetSetting(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; + } - if (usedobj->SetSetting("caption", text) != PSRETURN_OK) - debug_warn(L"Failed to set tooltip caption"); + // Every IGUIObject has a "hidden" setting + usedobj->SetSetting("hidden", false, true); } void GUITooltip::HideTooltip(const CStr& style, CGUI& pGUI) @@ -154,10 +173,11 @@ 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 @@ 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("hide_object")) - GUI::SetSetting(usedobj, "hidden", true); + // Every IGUIObject has a "hidden" setting + usedobj->SetSetting("hidden", true, true); } else - GUI::SetSetting(tooltipobj, "hidden", true); + tooltipobj->SetSetting("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) Index: ps/trunk/source/gui/GUIutil.h =================================================================== --- ps/trunk/source/gui/GUIutil.h +++ ps/trunk/source/gui/GUIutil.h @@ -15,18 +15,11 @@ * along with 0 A.D. If not, see . */ -/* - 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 - class CGUI; template class GUI; @@ -41,12 +34,12 @@ /** * 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 @@ /** * 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 @@ /** * 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 @@ T m_pSetting; }; -/** - * Includes static functions that needs one template - * argument. - */ template 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 @@ * @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& valueSet); }; #endif // INCLUDED_GUIUTIL Index: ps/trunk/source/gui/GUIutil.cpp =================================================================== --- ps/trunk/source/gui/GUIutil.cpp +++ ps/trunk/source/gui/GUIutil.cpp @@ -20,7 +20,6 @@ #include "GUIutil.h" #include "gui/GUI.h" -#include "ps/CLogger.h" template CGUISetting::CGUISetting(IGUIObject& pObject, const CStr& Name) @@ -29,19 +28,19 @@ } template -bool CGUISetting::FromString(const CStrW& Value, const bool& SkipMessage) +bool CGUISetting::FromString(const CStrW& Value, const bool SendMessage) { T settingValue; if (!GUI::ParseString(&m_pObject.GetGUI(), Value, settingValue)) return false; - GUI::SetSetting(&m_pObject, m_Name, settingValue, SkipMessage); + m_pObject.SetSetting(m_Name, settingValue, SendMessage); return true; }; template<> -bool CGUISetting::FromJSVal(JSContext* cx, JS::HandleValue Value) +bool CGUISetting::FromJSVal(JSContext* cx, JS::HandleValue Value, const bool SendMessage) { CGUIColor settingValue; if (Value.isString()) @@ -59,18 +58,18 @@ else if (!ScriptInterface::FromJSVal(cx, Value, settingValue)) return false; - GUI::SetSetting(&m_pObject, m_Name, settingValue); + m_pObject.SetSetting(m_Name, settingValue, SendMessage); return true; }; template -bool CGUISetting::FromJSVal(JSContext* cx, JS::HandleValue Value) +bool CGUISetting::FromJSVal(JSContext* cx, JS::HandleValue Value, const bool SendMessage) { T settingValue; if (!ScriptInterface::FromJSVal(cx, Value, settingValue)) return false; - GUI::SetSetting(&m_pObject, m_Name, settingValue); + m_pObject.SetSetting(m_Name, settingValue, SendMessage); return true; }; @@ -80,76 +79,8 @@ ScriptInterface::ToJSVal(cx, Value, m_pSetting); }; -template -PSRETURN GUI::SetSetting(IGUIObject* pObject, const CStr& Setting, T& Value, const bool& SkipMessage) -{ - return SetSettingWrap(pObject, Setting, SkipMessage, - [&pObject, &Setting, &Value]() { - static_cast* >(pObject->m_Settings[Setting])->m_pSetting = std::move(Value); - }); -} - -template -PSRETURN GUI::SetSetting(IGUIObject* pObject, const CStr& Setting, const T& Value, const bool& SkipMessage) -{ - return SetSettingWrap(pObject, Setting, SkipMessage, - [&pObject, &Setting, &Value]() { - static_cast* >(pObject->m_Settings[Setting])->m_pSetting = Value; - }); -} - -template -PSRETURN GUI::SetSettingWrap(IGUIObject* pObject, const CStr& Setting, const bool& SkipMessage, const std::function& 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(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::SetSetting(IGUIObject* pObject, const CStr& Setting, T& Value, const bool& SkipMessage); \ template class CGUISetting; \ #include "GUItypes.h" #undef TYPE - -// Copying functions - discouraged except for primitives. -#define TYPE(T) \ - template PSRETURN GUI::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 Index: ps/trunk/source/gui/IGUIObject.h =================================================================== --- ps/trunk/source/gui/IGUIObject.h +++ ps/trunk/source/gui/IGUIObject.h @@ -33,7 +33,6 @@ #include "lib/input.h" // just for IN_PASS #include "ps/XML/Xeromyces.h" -#include #include #include @@ -160,6 +159,29 @@ 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 + void SetSetting(const CStr& Setting, T& Value, const bool SendMessage); + + /** + * This variant will copy the value. + */ + template + void SetSetting(const CStr& Setting, const T& Value, const bool SendMessage); + + /** * Returns whether this is object is set to be hidden. */ bool IsHidden() const; @@ -182,19 +204,6 @@ 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 * * @param Action Name of action @@ -417,6 +426,11 @@ //@{ /** + * 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 * than the inputted object... If so then the object is closer Index: ps/trunk/source/gui/IGUIObject.cpp =================================================================== --- ps/trunk/source/gui/IGUIObject.cpp +++ ps/trunk/source/gui/IGUIObject.cpp @@ -43,10 +43,10 @@ AddSetting("tooltip_style"); // Setup important defaults - GUI::SetSetting(this, "hidden", false); - GUI::SetSetting(this, "ghost", false); - GUI::SetSetting(this, "enabled", true); - GUI::SetSetting(this, "absolute", true); + SetSetting("hidden", false, true); + SetSetting("ghost", false, true); + SetSetting("enabled", true, true); + SetSetting("absolute", true, true); } IGUIObject::~IGUIObject() @@ -145,6 +145,46 @@ return static_cast* >(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 +void IGUIObject::SetSetting(const CStr& Setting, T& Value, const bool SendMessage) +{ + static_cast* >(m_Settings[Setting])->m_pSetting = std::move(Value); + SettingChanged(Setting, SendMessage); +} + +template +void IGUIObject::SetSetting(const CStr& Setting, const T& Value, const bool SendMessage) +{ + static_cast* >(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(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 @@ } } -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 @@ for (const std::pair& 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 @@ } // Instantiate templated functions: +// These functions avoid copies by working with a reference and move semantics. #define TYPE(T) \ template void IGUIObject::AddSetting(const CStr& Name); \ template T& IGUIObject::GetSetting(const CStr& Setting); \ template const T& IGUIObject::GetSetting(const CStr& Setting) const; \ + template void IGUIObject::SetSetting(const CStr& Setting, T& Value, const bool SendMessage); \ #include "gui/GUItypes.h" +#undef TYPE +// Copying functions - discouraged except for primitives. +#define TYPE(T) \ + template void IGUIObject::SetSetting(const CStr& Setting, const T& Value, const bool SendMessage); \ + +#define GUITYPE_IGNORE_NONCOPYABLE +#include "gui/GUItypes.h" +#undef GUITYPE_IGNORE_NONCOPYABLE #undef TYPE Index: ps/trunk/source/gui/scripting/JSInterface_IGUIObject.cpp =================================================================== --- ps/trunk/source/gui/scripting/JSInterface_IGUIObject.cpp +++ ps/trunk/source/gui/scripting/JSInterface_IGUIObject.cpp @@ -168,7 +168,7 @@ } 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);