diff --git a/source/gui/IGUIObject.cpp b/source/gui/IGUIObject.cpp index 161dad7b8f..c98d1668c4 100644 --- a/source/gui/IGUIObject.cpp +++ b/source/gui/IGUIObject.cpp @@ -27,6 +27,24 @@ #include "ps/Profile.h" #include "scriptinterface/ScriptInterface.h" +template +void SGUISetting::Init(IGUIObject& pObject, const CStr& Name) +{ + m_pSetting = new T(); + + m_FromJSVal = [Name, &pObject](JSContext* cx, JS::HandleValue v) { + T value; + if (!ScriptInterface::FromJSVal(cx, v, value)) + return false; + + GUI::SetSetting(&pObject, Name, value); + return true; + }; + + m_ToJSVal = [Name, this](JSContext* cx, JS::MutableHandleValue v) { + ScriptInterface::ToJSVal(cx, v, *static_cast(m_pSetting)); + }; +} IGUIObject::IGUIObject() : m_pGUI(NULL), m_pParent(NULL), m_MouseHovering(false), m_LastClickTime() @@ -151,7 +169,7 @@ void IGUIObject::AddSetting(const EGUISettingType& Type, const CStr& Name) { #define TYPE(type) \ case GUIST_##type: \ - m_Settings[Name].m_pSetting = new type(); \ + m_Settings[Name].Init(*this, Name);\ break; // Construct the setting. diff --git a/source/gui/IGUIObject.h b/source/gui/IGUIObject.h index b411c29f96..dd4d8848e6 100644 --- a/source/gui/IGUIObject.h +++ b/source/gui/IGUIObject.h @@ -32,6 +32,7 @@ #include "lib/input.h" // just for IN_PASS #include "ps/XML/Xeromyces.h" +#include #include #include @@ -68,8 +69,25 @@ struct SGUISetting { SGUISetting() : m_pSetting(NULL) {} + /** + * Stores the instance of the setting type holding the setting data. Can be set from XML and JS. + */ void *m_pSetting; + EGUISettingType m_Type; + + template + void Init(IGUIObject& pObject, const CStr& Name); + + /** + * Parses the given JS::Value using ScriptInterface::FromJSVal and assigns it to the setting data. + */ + std::function m_FromJSVal; + + /** + * Converts the setting data to a JS::Value using ScriptInterface::ToJSVal. + */ + std::function m_ToJSVal; }; /** diff --git a/source/gui/scripting/JSInterface_IGUIObject.cpp b/source/gui/scripting/JSInterface_IGUIObject.cpp index 033018b467..0ee0b4a872 100644 --- a/source/gui/scripting/JSInterface_IGUIObject.cpp +++ b/source/gui/scripting/JSInterface_IGUIObject.cpp @@ -114,147 +114,14 @@ bool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Handle ScriptInterface::ToJSVal(cx, vp, e->GetName()); return true; } - else + else if (e->SettingExists(propName)) { - // Retrieve the setting's type (and make sure it actually exists) - EGUISettingType Type; - if (e->GetSettingType(propName, Type) != PSRETURN_OK) - { - JS_ReportError(cx, "Invalid GUIObject property '%s'", propName.c_str()); - return false; - } - - // (All the cases are in {...} to avoid scoping problems) - switch (Type) - { - case GUIST_bool: - { - bool value; - GUI::GetSetting(e, propName, value); - ScriptInterface::ToJSVal(cx, vp, value); - break; - } - - case GUIST_int: - { - i32 value; - GUI::GetSetting(e, propName, value); - ScriptInterface::ToJSVal(cx, vp, value); - break; - } - - case GUIST_uint: - { - u32 value; - GUI::GetSetting(e, propName, value); - ScriptInterface::ToJSVal(cx, vp, value); - break; - } - - case GUIST_float: - { - float value; - GUI::GetSetting(e, propName, value); - ScriptInterface::ToJSVal(cx, vp, value); - break; - } - - case GUIST_CGUIColor: - { - CGUIColor value; - GUI::GetSetting(e, propName, value); - ScriptInterface::ToJSVal(cx, vp, value); - break; - } - - case GUIST_CPos: - { - CPos value; - GUI::GetSetting(e, propName, value); - ScriptInterface::ToJSVal(cx, vp, value); - break; - } - - case GUIST_CClientArea: - { - CClientArea value; - GUI::GetSetting(e, propName, value); - ScriptInterface::ToJSVal(cx, vp, value); - break; - } - - case GUIST_CGUIString: - { - CGUIString value; - GUI::GetSetting(e, propName, value); - ScriptInterface::ToJSVal(cx, vp, value); - break; - } - - case GUIST_CStr: - { - CStr value; - GUI::GetSetting(e, propName, value); - ScriptInterface::ToJSVal(cx, vp, value); - break; - } - - case GUIST_CStrW: - { - CStrW value; - GUI::GetSetting(e, propName, value); - ScriptInterface::ToJSVal(cx, vp, value); - break; - } - - case GUIST_CGUISpriteInstance: - { - CGUISpriteInstance* value; - GUI::GetSettingPointer(e, propName, value); - ScriptInterface::ToJSVal(cx, vp, *value); - break; - } - - case GUIST_EAlign: - { - EAlign value; - GUI::GetSetting(e, propName, value); - ScriptInterface::ToJSVal(cx, vp, value); - break; - } - - case GUIST_EVAlign: - { - EVAlign value; - GUI::GetSetting(e, propName, value); - ScriptInterface::ToJSVal(cx, vp, value); - break; - } - - case GUIST_CGUIList: - { - CGUIList value; - GUI::GetSetting(e, propName, value); - ScriptInterface::ToJSVal(cx, vp, value); - break; - } - - case GUIST_CGUISeries: - { - CGUISeries value; - GUI::GetSetting(e, propName, value); - ScriptInterface::ToJSVal(cx, vp, value); - break; - } - - default: - JS_ReportError(cx, "Setting '%s' uses an unimplemented type", propName.c_str()); - DEBUG_WARN_ERR(ERR::LOGIC); - return false; - } - + e->m_Settings[propName].m_ToJSVal(cx, vp); return true; } + + JS_ReportError(cx, "Property '%s' does not exist!", propName.c_str()); + return false; } bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool UNUSED(strict), JS::MutableHandleValue vp) @@ -300,186 +167,11 @@ bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Handle return true; } - // Retrieve the setting's type (and make sure it actually exists) - EGUISettingType Type; - if (e->GetSettingType(propName, Type) != PSRETURN_OK) - { - JS_ReportError(cx, "Invalid setting '%s'", propName.c_str()); - return true; - } + if (e->SettingExists(propName)) + return e->m_Settings[propName].m_FromJSVal(cx, vp); - switch (Type) - { - case GUIST_CStr: - { - CStr value; - if (!ScriptInterface::FromJSVal(cx, vp, value)) - return false; - - GUI::SetSetting(e, propName, value); - break; - } - - case GUIST_CStrW: - { - CStrW value; - if (!ScriptInterface::FromJSVal(cx, vp, value)) - return false; - - GUI::SetSetting(e, propName, value); - break; - } - - case GUIST_CGUISpriteInstance: - { - CGUISpriteInstance value; - if (!ScriptInterface::FromJSVal(cx, vp, value)) - return false; - - GUI::SetSetting(e, propName, value); - break; - } - - case GUIST_CGUIString: - { - CGUIString value; - if (!ScriptInterface::FromJSVal(cx, vp, value)) - return false; - - GUI::SetSetting(e, propName, value); - break; - } - - case GUIST_EAlign: - { - EAlign a; - if (!ScriptInterface::FromJSVal(cx, vp, a)) - return false; - - GUI::SetSetting(e, propName, a); - break; - } - - case GUIST_EVAlign: - { - EVAlign a; - if (!ScriptInterface::FromJSVal(cx, vp, a)) - return false; - - GUI::SetSetting(e, propName, a); - break; - } - - case GUIST_int: - { - i32 value; - if (ScriptInterface::FromJSVal(cx, vp, value)) - GUI::SetSetting(e, propName, value); - else - { - JS_ReportError(cx, "Cannot convert value to i32"); - return false; - } - break; - } - - case GUIST_uint: - { - u32 value; - if (ScriptInterface::FromJSVal(cx, vp, value)) - GUI::SetSetting(e, propName, value); - else - { - JS_ReportError(cx, "Cannot convert value to u32"); - return false; - } - break; - } - - case GUIST_float: - { - float value; - if (ScriptInterface::FromJSVal(cx, vp, value)) - GUI::SetSetting(e, propName, value); - else - { - JS_ReportError(cx, "Cannot convert value to float"); - return false; - } - break; - } - - case GUIST_bool: - { - bool value; - if (!ScriptInterface::FromJSVal(cx, vp, value)) - return false; - - GUI::SetSetting(e, propName, value); - break; - } - - case GUIST_CClientArea: - { - CClientArea value; - if (!ScriptInterface::FromJSVal(cx, vp, value)) - return false; - - GUI::SetSetting(e, propName, value); - break; - } - - case GUIST_CPos: - { - CPos value; - if (!ScriptInterface::FromJSVal(cx, vp, value)) - return false; - - GUI::SetSetting(e, propName, value); - break; - } - - case GUIST_CGUIColor: - { - CGUIColor value; - if (!ScriptInterface::FromJSVal(cx, vp, value)) - return false; - GUI::SetSetting(e, propName, value); - break; - } - - case GUIST_CGUIList: - { - CGUIList list; - if (ScriptInterface::FromJSVal(cx, vp, list)) - GUI::SetSetting(e, propName, list); - else - { - JS_ReportError(cx, "Failed to get list '%s'", propName.c_str()); - return false; - } - break; - } - - case GUIST_CGUISeries: - { - CGUISeries series; - if (ScriptInterface::FromJSVal(cx, vp, series)) - GUI::SetSetting(e, propName, series); - else - { - JS_ReportError(cx, "Invalid value for chart series '%s'", propName.c_str()); - return false; - } - break; - } - - default: - JS_ReportError(cx, "Setting '%s' uses an unimplemented type", propName.c_str()); - break; - } - - return !JS_IsExceptionPending(cx); + JS_ReportError(cx, "Property '%s' does not exist!", propName.c_str()); + return false; } void JSI_IGUIObject::init(ScriptInterface& scriptInterface)