mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-10-09 07:59:40 +00:00
Don't leak all GUI objects on name ambiguity following 5cc814759f and remove ERROR_GROUP GUI.
Delete CGUI::UpdateObjects and don't recreate the entire object hierarchy by recursing through the existing one each time when inserting one GUI Object. Change CGUI::AddObject to only insert the one relevant pointer into the map hierarchy, return success value and delete the child upon failed insertion in the caller instead of leaking it. Defer GUIM_LOAD and UpdateCachedSize recursion until all XML files linked in the page XML file were loaded. Delete related ERROR_TYPE NameAmbiguity, ObjectNeedsName, and unrelated JSOpenFailed and in consistency with the rest, do the LOGERROR in the scope where the error occurs. Delete ERROR_TYPE InvalidSetting from90f6641c1dunused following85a622b13a,1a49ccb294, ERROR_TYPE OperationNeedsGUIObject from90f6641c1dunused followingd3e56f0f57, see alsoe1014aad3b, refs #128. This was SVN commit r23067.
This commit is contained in:
+40
-84
@@ -126,7 +126,6 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev)
|
||||
IGUIObject* pNearest = nullptr;
|
||||
|
||||
// TODO Gee: (2004-09-08) Big TODO, don't do the below if the SDL_Event is something like a keypress!
|
||||
try
|
||||
{
|
||||
PROFILE("mouse events");
|
||||
// TODO Gee: Optimizations needed!
|
||||
@@ -205,12 +204,6 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev)
|
||||
m_BaseObject.RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::UpdateMouseOver, static_cast<IGUIObject* const&>(pNearest));
|
||||
}
|
||||
}
|
||||
catch (PSERROR_GUI& e)
|
||||
{
|
||||
UNUSED2(e);
|
||||
debug_warn(L"CGUI::HandleEvent error");
|
||||
// TODO Gee: Handle
|
||||
}
|
||||
|
||||
// BUTTONUP's effect on m_MouseButtons is handled after
|
||||
// everything else, so that e.g. 'press' handlers (activated
|
||||
@@ -336,14 +329,7 @@ void CGUI::Draw()
|
||||
// drawn on top of everything else
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
try
|
||||
{
|
||||
m_BaseObject.RecurseObject(&IGUIObject::IsHidden, &IGUIObject::Draw);
|
||||
}
|
||||
catch (PSERROR_GUI& e)
|
||||
{
|
||||
LOGERROR("GUI draw error: %s", e.what());
|
||||
}
|
||||
m_BaseObject.RecurseObject(&IGUIObject::IsHidden, &IGUIObject::Draw);
|
||||
}
|
||||
|
||||
void CGUI::DrawSprite(const CGUISpriteInstance& Sprite, int CellID, const float& Z, const CRect& Rect, const CRect& UNUSED(Clipping))
|
||||
@@ -359,45 +345,26 @@ void CGUI::DrawSprite(const CGUISpriteInstance& Sprite, int CellID, const float&
|
||||
|
||||
void CGUI::UpdateResolution()
|
||||
{
|
||||
// Update ALL cached
|
||||
m_BaseObject.RecurseObject(nullptr, &IGUIObject::UpdateCachedSize);
|
||||
}
|
||||
|
||||
void CGUI::AddObject(IGUIObject* pObject)
|
||||
bool CGUI::AddObject(IGUIObject& parent, IGUIObject& child)
|
||||
{
|
||||
try
|
||||
if (child.m_Name.empty())
|
||||
{
|
||||
m_BaseObject.AddChild(pObject);
|
||||
|
||||
// Cache tree
|
||||
pObject->RecurseObject(nullptr, &IGUIObject::UpdateCachedSize);
|
||||
|
||||
SGUIMessage msg(GUIM_LOAD);
|
||||
pObject->RecurseObject(nullptr, &IGUIObject::HandleMessage, msg);
|
||||
}
|
||||
catch (PSERROR_GUI&)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void CGUI::UpdateObjects()
|
||||
{
|
||||
// We'll fill a temporary map until we know everything succeeded
|
||||
map_pObjects AllObjects;
|
||||
|
||||
try
|
||||
{
|
||||
// Fill freshly
|
||||
m_BaseObject.RecurseObject(nullptr, &IGUIObject::AddToPointersMap, AllObjects);
|
||||
}
|
||||
catch (PSERROR_GUI&)
|
||||
{
|
||||
throw;
|
||||
LOGERROR("Can't register an object without name!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Else actually update the real one
|
||||
m_pAllObjects.swap(AllObjects);
|
||||
if (m_pAllObjects.find(child.m_Name) != m_pAllObjects.end())
|
||||
{
|
||||
LOGERROR("Can't register more than one object of the name %s", child.m_Name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pAllObjects[child.m_Name] = &child;
|
||||
parent.AddChild(child);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGUI::ObjectExists(const CStr& Name) const
|
||||
@@ -511,31 +478,28 @@ void CGUI::LoadXmlFile(const VfsPath& Filename, boost::unordered_set<VfsPath>& P
|
||||
return;
|
||||
|
||||
XMBElement node = XeroFile.GetRoot();
|
||||
|
||||
CStr root_name(XeroFile.GetElementString(node.GetNodeName()));
|
||||
try
|
||||
{
|
||||
if (root_name == "objects")
|
||||
{
|
||||
Xeromyces_ReadRootObjects(node, &XeroFile, Paths);
|
||||
|
||||
// Re-cache all values so these gets cached too.
|
||||
//UpdateResolution();
|
||||
}
|
||||
else if (root_name == "sprites")
|
||||
Xeromyces_ReadRootSprites(node, &XeroFile);
|
||||
else if (root_name == "styles")
|
||||
Xeromyces_ReadRootStyles(node, &XeroFile);
|
||||
else if (root_name == "setup")
|
||||
Xeromyces_ReadRootSetup(node, &XeroFile);
|
||||
else
|
||||
debug_warn(L"CGUI::LoadXmlFile error");
|
||||
}
|
||||
catch (PSERROR_GUI& e)
|
||||
{
|
||||
LOGERROR("Errors loading GUI file %s (%u)", Filename.string8(), e.getCode());
|
||||
return;
|
||||
}
|
||||
if (root_name == "objects")
|
||||
Xeromyces_ReadRootObjects(node, &XeroFile, Paths);
|
||||
else if (root_name == "sprites")
|
||||
Xeromyces_ReadRootSprites(node, &XeroFile);
|
||||
else if (root_name == "styles")
|
||||
Xeromyces_ReadRootStyles(node, &XeroFile);
|
||||
else if (root_name == "setup")
|
||||
Xeromyces_ReadRootSetup(node, &XeroFile);
|
||||
else
|
||||
LOGERROR("CGUI::LoadXmlFile encountered an unknown XML root node type: %s", root_name.c_str());
|
||||
}
|
||||
|
||||
void CGUI::LoadedXmlFiles()
|
||||
{
|
||||
m_BaseObject.RecurseObject(nullptr, &IGUIObject::UpdateCachedSize);
|
||||
|
||||
SGUIMessage msg(GUIM_LOAD);
|
||||
m_BaseObject.RecurseObject(nullptr, &IGUIObject::HandleMessage, msg);
|
||||
|
||||
SendEventToAll("load");
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
@@ -662,7 +626,7 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
|
||||
for (XMBAttribute attr : attributes)
|
||||
{
|
||||
// If value is "null", then it is equivalent as never being entered
|
||||
if (CStr(attr.Value) == "null")
|
||||
if (attr.Value == "null")
|
||||
continue;
|
||||
|
||||
// Ignore "type" and "style", we've already checked it
|
||||
@@ -725,7 +689,7 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
|
||||
if (scriptfile.Load(g_VFS, filename) != PSRETURN_OK)
|
||||
{
|
||||
LOGERROR("Error opening GUI script action file '%s'", utf8_from_wstring(filename));
|
||||
throw PSERROR_GUI_JSOpenFailed();
|
||||
continue;
|
||||
}
|
||||
|
||||
code = scriptfile.DecodeUTF8(); // assume it's UTF-8
|
||||
@@ -886,17 +850,8 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
|
||||
object->SetSetting<float>("z", 10.f, false);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (pParent == &m_BaseObject)
|
||||
AddObject(object);
|
||||
else
|
||||
pParent->AddChild(object);
|
||||
}
|
||||
catch (PSERROR_GUI& e)
|
||||
{
|
||||
LOGERROR("GUI error: %s", e.what());
|
||||
}
|
||||
if (!AddObject(*pParent, *object))
|
||||
delete object;
|
||||
}
|
||||
|
||||
void CGUI::Xeromyces_ReadRepeat(XMBElement Element, CXeromyces* pFile, IGUIObject* pParent, std::vector<std::pair<CStr, CStr> >& NameSubst, boost::unordered_set<VfsPath>& Paths, u32 nesting_depth)
|
||||
@@ -1319,7 +1274,8 @@ void CGUI::Xeromyces_ReadTooltip(XMBElement Element, CXeromyces* pFile)
|
||||
object->SetSettingFromString(attr_name, attr_value.FromUTF8(), true);
|
||||
}
|
||||
|
||||
AddObject(object);
|
||||
if (!AddObject(m_BaseObject, *object))
|
||||
delete object;
|
||||
}
|
||||
|
||||
void CGUI::Xeromyces_ReadColor(XMBElement Element, CXeromyces* pFile)
|
||||
|
||||
Reference in New Issue
Block a user