Index: ps/trunk/source/gui/CGUI.h =================================================================== --- ps/trunk/source/gui/CGUI.h +++ ps/trunk/source/gui/CGUI.h @@ -103,7 +103,7 @@ * @param EventName String representation of event name * @param paramData JS::HandleValueArray storing the arguments passed to the event handler. */ - void SendEventToAll(const CStr& EventName, JS::HandleValueArray paramData); + void SendEventToAll(const CStr& EventName, const JS::HandleValueArray& paramData); /** * Displays the whole GUI Index: ps/trunk/source/gui/CGUI.cpp =================================================================== --- ps/trunk/source/gui/CGUI.cpp +++ ps/trunk/source/gui/CGUI.cpp @@ -95,9 +95,7 @@ m_MousePos = CPos((float)ev->ev.motion.x / g_GuiScale, (float)ev->ev.motion.y / g_GuiScale); SGUIMessage msg(GUIM_MOUSE_MOTION); - GUI::RecurseObject(GUIRR_HIDDEN | GUIRR_GHOST, m_BaseObject, - &IGUIObject::HandleMessage, - msg); + m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::HandleMessage, msg); } // Update m_MouseButtons. (BUTTONUP is handled later.) @@ -138,8 +136,7 @@ // Now we'll call UpdateMouseOver on *all* objects, // we'll input the one hovered, and they will each // update their own data and send messages accordingly - GUI::RecurseObject(GUIRR_HIDDEN | GUIRR_GHOST, - m_BaseObject, &IGUIObject::UpdateMouseOver, pNearest); + m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::UpdateMouseOver, static_cast(pNearest)); if (ev->ev.type == SDL_MOUSEBUTTONDOWN) { @@ -200,12 +197,10 @@ } // Reset all states on all visible objects - GUI<>::RecurseObject(GUIRR_HIDDEN, m_BaseObject, - &IGUIObject::ResetStates); + m_BaseObject->RecurseObject(&IGUIObject::IsHidden, &IGUIObject::ResetStates); // Since the hover state will have been reset, we reload it. - GUI::RecurseObject(GUIRR_HIDDEN | GUIRR_GHOST, - m_BaseObject, &IGUIObject::UpdateMouseOver, pNearest); + m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::UpdateMouseOver, static_cast(pNearest)); } } catch (PSERROR_GUI& e) @@ -257,9 +252,8 @@ void CGUI::TickObjects() { - CStr action = "tick"; - GUI::RecurseObject(0, m_BaseObject, - &IGUIObject::ScriptEvent, action); + const CStr action = "tick"; + m_BaseObject->RecurseObject(nullptr, &IGUIObject::ScriptEvent, action); m_Tooltip.Update(FindObjectUnderMouse(), m_MousePos, *this); } @@ -273,12 +267,14 @@ // (sending events here) wasn't converting to lower case, // leading to a similar problem. // now fixed; case is irrelevant since all are converted to lower. - GUI::RecurseObject(0, m_BaseObject, &IGUIObject::ScriptEvent, EventName.LowerCase()); + const CStr EventNameLower = EventName.LowerCase(); + m_BaseObject->RecurseObject(nullptr, &IGUIObject::ScriptEvent, EventNameLower); } -void CGUI::SendEventToAll(const CStr& EventName, JS::HandleValueArray paramData) +void CGUI::SendEventToAll(const CStr& EventName, const JS::HandleValueArray& paramData) { - GUI::RecurseObject(0, m_BaseObject, &IGUIObject::ScriptEvent, EventName.LowerCase(), paramData); + const CStr EventNameLower = EventName.LowerCase(); + m_BaseObject->RecurseObject(nullptr, &IGUIObject::ScriptEvent, EventNameLower, paramData); } CGUI::CGUI(const shared_ptr& runtime) @@ -340,9 +336,7 @@ try { - // Recurse IGUIObject::Draw() with restriction: hidden - // meaning all hidden objects won't call Draw (nor will it recurse its children) - GUI<>::RecurseObject(GUIRR_HIDDEN, m_BaseObject, &IGUIObject::Draw); + m_BaseObject->RecurseObject(&IGUIObject::IsHidden, &IGUIObject::Draw); } catch (PSERROR_GUI& e) { @@ -391,7 +385,7 @@ void CGUI::UpdateResolution() { // Update ALL cached - GUI<>::RecurseObject(0, m_BaseObject, &IGUIObject::UpdateCachedSize); + m_BaseObject->RecurseObject(nullptr, &IGUIObject::UpdateCachedSize); } void CGUI::AddObject(IGUIObject* pObject) @@ -401,10 +395,10 @@ m_BaseObject->AddChild(pObject); // Cache tree - GUI<>::RecurseObject(0, pObject, &IGUIObject::UpdateCachedSize); + pObject->RecurseObject(nullptr, &IGUIObject::UpdateCachedSize); SGUIMessage msg(GUIM_LOAD); - GUI::RecurseObject(0, pObject, &IGUIObject::HandleMessage, msg); + pObject->RecurseObject(nullptr, &IGUIObject::HandleMessage, msg); } catch (PSERROR_GUI&) { @@ -420,7 +414,7 @@ try { // Fill freshly - GUI::RecurseObject(0, m_BaseObject, &IGUIObject::AddToPointersMap, AllObjects); + m_BaseObject->RecurseObject(nullptr, &IGUIObject::AddToPointersMap, AllObjects); } catch (PSERROR_GUI&) { @@ -448,10 +442,7 @@ IGUIObject* CGUI::FindObjectUnderMouse() const { IGUIObject* pNearest = NULL; - - GUI::RecurseObject(GUIRR_HIDDEN | GUIRR_GHOST, m_BaseObject, - &IGUIObject::ChooseMouseOverAndClosest, pNearest); - + m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::ChooseMouseOverAndClosest, pNearest); return pNearest; } Index: ps/trunk/source/gui/CRadioButton.cpp =================================================================== --- ps/trunk/source/gui/CRadioButton.cpp +++ ps/trunk/source/gui/CRadioButton.cpp @@ -35,7 +35,7 @@ switch (Message.type) { case GUIM_PRESSED: - for (IGUIObject* const& obj : *GetParent()) + for (IGUIObject* const& obj : GetParent()->GetChildren()) { // 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 Index: ps/trunk/source/gui/GUIbase.h =================================================================== --- ps/trunk/source/gui/GUIbase.h +++ ps/trunk/source/gui/GUIbase.h @@ -125,20 +125,6 @@ bool skipped; }; -/** - * Recurse restrictions, when we recurse, if an object - * is hidden for instance, you might want it to skip - * the children also - * Notice these are flags! and we don't really need one - * for no restrictions, because then you'll just enter 0 - */ -enum -{ - GUIRR_HIDDEN = 0x00000001, - GUIRR_DISABLED = 0x00000010, - GUIRR_GHOST = 0x00000100 -}; - // Text alignments enum EAlign { EAlign_Left, EAlign_Right, EAlign_Center }; enum EVAlign { EVAlign_Top, EVAlign_Bottom, EVAlign_Center }; Index: ps/trunk/source/gui/GUIutil.h =================================================================== --- ps/trunk/source/gui/GUIutil.h +++ ps/trunk/source/gui/GUIutil.h @@ -181,144 +181,6 @@ * Updates some internal data depending on the setting changed. */ static PSRETURN SetSettingWrap(IGUIObject* pObject, const CStr& Setting, const bool& SkipMessage, const std::function& valueSet); - - // templated typedef of function pointer - typedef void (IGUIObject::*void_Object_pFunction_argT)(const T& arg); - typedef void (IGUIObject::*void_Object_pFunction_argRefT)(T& arg); - typedef void (IGUIObject::*void_Object_pFunction)(); - typedef void (IGUIObject::*void_Object_pFunction_argTJS)(const T& arg, JS::HandleValueArray paramData); - - /** - * If you want to call a IGUIObject-function - * on not just an object, but also on ALL of their children - * you want to use this recursion system. - * It recurses an object calling a function on itself - * and all children (and so forth). - * - * Restrictions:\n - * You can also set restrictions, so that if the recursion - * reaches an objects with certain setup, it just doesn't - * call the function on the object, nor it's children for - * that matter. i.e. it cuts that object off from the - * recursion tree. What setups that can cause restrictions - * are hardcoded and specific. Check out the defines - * GUIRR_* for all different setups. - * - * Error reports are either logged or thrown out of RecurseObject. - * Always use it with try/catch! - * - * @param RR Recurse Restrictions, set to 0 if no restrictions - * @param pObject Top object, this is where the iteration starts - * @param pFunc Function to recurse - * @param Argument Argument for pFunc of type T - * @throws PSERROR Depends on what pFunc might throw. PSERROR is standard. - * Itself doesn't throw anything. - */ - static void RecurseObject(int RR, IGUIObject* pObject, void_Object_pFunction_argT pFunc, const T& Argument) - { - // TODO Gee: Don't run this for the base object. - if (CheckIfRestricted(RR, pObject)) - return; - - (pObject->*pFunc)(Argument); - - // Iterate children - for (IGUIObject* const& obj : *pObject) - RecurseObject(RR, obj, pFunc, Argument); - } - - /** - * Argument is reference. - * - * @see RecurseObject() - */ - static void RecurseObject(int RR, IGUIObject* pObject, void_Object_pFunction_argRefT pFunc, T& Argument) - { - if (CheckIfRestricted(RR, pObject)) - return; - - (pObject->*pFunc)(Argument); - - // Iterate children - for (IGUIObject* const& obj : *pObject) - RecurseObject(RR, obj, pFunc, Argument); - } - - static void RecurseObject(int RR, IGUIObject* pObject, void_Object_pFunction_argTJS pFunc, const T& Argument, JS::HandleValueArray paramData) - { - if (CheckIfRestricted(RR, pObject)) - return; - - (pObject->*pFunc)(Argument, paramData); - - // Iterate children - for (IGUIObject* const& obj : *pObject) - RecurseObject(RR, obj, pFunc, Argument, paramData); - } - - /** - * With no argument. - * - * @see RecurseObject() - */ - static void RecurseObject(int RR, IGUIObject* pObject, void_Object_pFunction pFunc) - { - if (CheckIfRestricted(RR, pObject)) - return; - - (pObject->*pFunc)(); - - // Iterate children - for (IGUIObject* const& obj : *pObject) - RecurseObject(RR, obj, pFunc); - } - - /** - * Checks restrictions for the iteration, for instance if - * you tell the recursor to avoid all hidden objects, it - * will, and this function checks a certain object's - * restriction values. - * - * @param RR What kind of restriction, for instance hidden or disabled - * @param pObject Object - * @return true if restricted - */ - static bool CheckIfRestricted(int RR, IGUIObject* pObject) - { - // 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"); - static const CStr strEnabled("enabled"); - static const CStr strGhost("ghost"); - - if (RR & GUIRR_HIDDEN) - { - bool hidden = true; - GUI::GetSetting(pObject, strHidden, hidden); - - if (hidden) - return true; - } - if (RR & GUIRR_DISABLED) - { - bool enabled = false; - GUI::GetSetting(pObject, strEnabled, enabled); - - if (!enabled) - return true; - } - if (RR & GUIRR_GHOST) - { - bool ghost = true; - GUI::GetSetting(pObject, strGhost, ghost); - - if (ghost) - return true; - } - - // false means not restricted - return false; - } }; #endif // INCLUDED_GUIUTIL Index: ps/trunk/source/gui/GUIutil.cpp =================================================================== --- ps/trunk/source/gui/GUIutil.cpp +++ ps/trunk/source/gui/GUIutil.cpp @@ -164,12 +164,12 @@ // If setting was "size", we need to re-cache itself and all children if (Setting == "size") { - RecurseObject(0, pObject, &IGUIObject::UpdateCachedSize); + pObject->RecurseObject(nullptr, &IGUIObject::UpdateCachedSize); } else if (Setting == "hidden") { // Hiding an object requires us to reset it and all children - RecurseObject(0, pObject, &IGUIObject::ResetStates); + pObject->RecurseObject(nullptr, &IGUIObject::ResetStates); } if (!SkipMessage) Index: ps/trunk/source/gui/IGUIButtonBehavior.h =================================================================== --- ps/trunk/source/gui/IGUIButtonBehavior.h +++ ps/trunk/source/gui/IGUIButtonBehavior.h @@ -92,7 +92,7 @@ virtual void ResetStates() { // Notify the gui that we aren't hovered anymore - UpdateMouseOver(NULL); + UpdateMouseOver(nullptr); m_Pressed = false; m_PressedRight = false; } Index: ps/trunk/source/gui/IGUIObject.h =================================================================== --- ps/trunk/source/gui/IGUIObject.h +++ ps/trunk/source/gui/IGUIObject.h @@ -27,6 +27,7 @@ #include "IGUIObject.h" +#include "gui/CGUI.h" #include "gui/GUIbase.h" #include "gui/scripting/JSInterface_IGUIObject.h" #include "lib/input.h" // just for IN_PASS @@ -37,11 +38,11 @@ #include struct SGUIStyle; -class CGUI; - class JSObject; class IGUISetting; +template class GUI; + ERROR_TYPE(GUI, UnableToParse); /** @@ -128,16 +129,10 @@ */ void AddChild(IGUIObject* pChild); - //@} - //-------------------------------------------------------- - /** @name Iterate - * Used to iterate over all children of this object. + /** + * Return all child objects of the current object. */ - //-------------------------------------------------------- - //@{ - - vector_pObjects::iterator begin() { return m_Children.begin(); } - vector_pObjects::iterator end() { return m_Children.end(); } + std::vector& GetChildren() { return m_Children; } //@} //-------------------------------------------------------- @@ -154,6 +149,16 @@ bool SettingExists(const CStr& Setting) const; /** + * Returns whether this is object is set to be hidden. + */ + bool IsHidden(); + + /** + * Returns whether this object is set to be hidden or ghost. + */ + bool IsHiddenOrGhost(); + + /** * All sizes are relative to resolution, and the calculation * is not wanted in real time, therefore it is cached, update * the cached size with this function. @@ -235,6 +240,26 @@ */ virtual void HandleMessage(SGUIMessage& UNUSED(Message)) {} + /** + * Calls an IGUIObject member function recursively on this object and its children. + * Aborts recursion at IGUIObjects that have the isRestricted function return true. + * The arguments of the callback function must be references. + */ + template + void RecurseObject(bool(IGUIObject::*isRestricted)(), void(IGUIObject::*callbackFunction)(Args... args), Args&&... args) + { + if (this != m_pGUI.GetBaseObject()) + { + if (isRestricted && (this->*isRestricted)()) + return; + + (this->*callbackFunction)(args...); + } + + for (IGUIObject* const& obj : m_Children) + obj->RecurseObject(isRestricted, callbackFunction, args...); + } + protected: /** * Draws the object. @@ -364,7 +389,7 @@ * @param Action Name of action * @param paramData JS::HandleValueArray arguments to pass to the event. */ - void ScriptEvent(const CStr& Action, JS::HandleValueArray paramData); + void ScriptEvent(const CStr& Action, const JS::HandleValueArray& paramData); void SetScriptHandler(const CStr& Action, JS::HandleObject Function); Index: ps/trunk/source/gui/IGUIObject.cpp =================================================================== --- ps/trunk/source/gui/IGUIObject.cpp +++ ps/trunk/source/gui/IGUIObject.cpp @@ -390,7 +390,7 @@ } } -void IGUIObject::ScriptEvent(const CStr& Action, JS::HandleValueArray paramData) +void IGUIObject::ScriptEvent(const CStr& Action, const JS::HandleValueArray& paramData) { std::map >::iterator it = m_ScriptHandlers.find(Action); if (it == m_ScriptHandlers.end()) @@ -425,6 +425,20 @@ return m_JSObject.get(); } +bool IGUIObject::IsHidden() +{ + // 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 GUI::GetSetting(this, strHidden); +} + +bool IGUIObject::IsHiddenOrGhost() +{ + static const CStr strGhost("ghost"); + return IsHidden() || GUI::GetSetting(this, strGhost); +} + CStr IGUIObject::GetPresentableName() const { // __internal(), must be at least 13 letters to be able to be