diff options
author | Thierry Crozat | 2017-03-10 02:02:58 +0000 |
---|---|---|
committer | Thierry Crozat | 2017-03-10 02:02:58 +0000 |
commit | cc75d17e9c9d4074d94826165fb3831090a502b1 (patch) | |
tree | 1027a56b5effa9977deb2ae076385e674193b629 /gui | |
parent | 6bb953e25bca80f763f8cd7c2df1863a529ba889 (diff) | |
download | scummvm-rg350-cc75d17e9c9d4074d94826165fb3831090a502b1.tar.gz scummvm-rg350-cc75d17e9c9d4074d94826165fb3831090a502b1.tar.bz2 scummvm-rg350-cc75d17e9c9d4074d94826165fb3831090a502b1.zip |
GUI: Allow delayed deletion of GuiObject
This is achieved by adding a list of GuiObject to delete to GuiManager
and doing the deletion in GuiManager::runLoop.
The main purpose of this is to avoid the deletion of ButtonWidget object
while their ButtonWidget::sendCommand function is being called. For
example the sendCommand of the Apply button of the OptionsDialog
may cause a rebuild (if the GUI language was changed) which tries to
delete the widgets inside the OptionsDialog, including the Apply button.
Diffstat (limited to 'gui')
-rw-r--r-- | gui/gui-manager.cpp | 28 | ||||
-rw-r--r-- | gui/gui-manager.h | 16 |
2 files changed, 44 insertions, 0 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(); |