diff options
-rw-r--r-- | gui/gui-manager.cpp | 28 | ||||
-rw-r--r-- | gui/gui-manager.h | 16 | ||||
-rw-r--r-- | gui/launcher.cpp | 5 | ||||
-rw-r--r-- | gui/options.cpp | 5 |
4 files changed, 52 insertions, 2 deletions
diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp index d28a0df8c2..feb4e50ce2 100644 --- a/gui/gui-manager.cpp +++ b/gui/gui-manager.cpp @@ -254,6 +254,23 @@ Dialog *GuiManager::getTopDialog() const { return _dialogStack.top(); } +void GuiManager::addToTrash(GuiObject* object, Dialog* parent) { + debug(7, "Adding Gui Object %p to trash", object); + GuiObjectTrashItem t; + t.object = object; + t.parent = 0; + // If a dialog was provided, check it is in the dialog stack + if (parent != 0) { + for (int i = 0 ; i < _dialogStack.size() ; ++i) { + if (_dialogStack[i] == parent) { + t.parent = parent; + break; + } + } + } + _guiObjectTrash.push_back(t); +} + void GuiManager::runLoop() { Dialog * const activeDialog = getTopDialog(); bool didSaveState = false; @@ -341,6 +358,17 @@ void GuiManager::runLoop() { } } + // Delete GuiObject that have been added to the trash for a delayed deletion + Common::List<GuiObjectTrashItem>::iterator it = _guiObjectTrash.begin(); + while (it != _guiObjectTrash.end()) { + if ((*it).parent == 0 || (*it).parent == activeDialog) { + debug(7, "Delayed deletion of Gui Object %p", (*it).object); + delete (*it).object; + it = _guiObjectTrash.erase(it); + } else + ++it; + } + if (_lastMousePosition.time + kTooltipDelay < _system->getMillis(true)) { Widget *wdg = activeDialog->findWidget(_lastMousePosition.x, _lastMousePosition.y); if (wdg && wdg->hasTooltip() && !(wdg->getFlags() & WIDGET_PRESSED)) { diff --git a/gui/gui-manager.h b/gui/gui-manager.h index 4dc9af95fb..82a8aa9cfd 100644 --- a/gui/gui-manager.h +++ b/gui/gui-manager.h @@ -27,6 +27,7 @@ #include "common/singleton.h" #include "common/stack.h" #include "common/str.h" +#include "common/list.h" #include "gui/ThemeEngine.h" @@ -44,6 +45,7 @@ namespace GUI { class Dialog; class ThemeEval; +class GuiObject; #define g_gui (GUI::GuiManager::instance()) @@ -99,6 +101,13 @@ public: */ bool checkScreenChange(); + /** + * Tell the GuiManager to delete the given GuiObject later. If a parent + * dialog is provided and is present in the DialogStack, the object will + * only be deleted when that dialog is the top level dialog. + */ + void addToTrash(GuiObject*, Dialog* parent = 0); + bool _launched; protected: @@ -137,6 +146,13 @@ protected: int _cursorAnimateTimer; byte _cursor[2048]; + // delayed deletion of GuiObject + struct GuiObjectTrashItem { + GuiObject* object; + Dialog* parent; + }; + Common::List<GuiObjectTrashItem> _guiObjectTrash; + void initKeymap(); void pushKeymap(); void popKeymap(); diff --git a/gui/launcher.cpp b/gui/launcher.cpp index f96dd17d46..f60fecf509 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -204,7 +204,10 @@ void LauncherDialog::clean() { while (_firstWidget) { Widget* w = _firstWidget; removeWidget(w); - delete w; + // This is called from rebuild() which may result from handleCommand being called by + // a child widget sendCommand call. In such a case sendCommand is still being executed + // so we should not delete yet the child widget. Thus delay the deletion. + g_gui.addToTrash(w, this); } delete _browser; delete _loadDialog; diff --git a/gui/options.cpp b/gui/options.cpp index 7a22a9ba3f..179fa65991 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -423,7 +423,10 @@ void OptionsDialog::clean() { while (_firstWidget) { Widget* w = _firstWidget; removeWidget(w); - delete w; + // This is called from rebuild() which may result from handleCommand being called by + // a child widget sendCommand call. In such a case sendCommand is still being executed + // so we should not delete yet the child widget. Thus delay the deletion. + g_gui.addToTrash(w, this); } init(); } |