aboutsummaryrefslogtreecommitdiff
path: root/gui
diff options
context:
space:
mode:
authorThierry Crozat2017-03-10 02:02:58 +0000
committerThierry Crozat2017-03-10 02:02:58 +0000
commitcc75d17e9c9d4074d94826165fb3831090a502b1 (patch)
tree1027a56b5effa9977deb2ae076385e674193b629 /gui
parent6bb953e25bca80f763f8cd7c2df1863a529ba889 (diff)
downloadscummvm-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.cpp28
-rw-r--r--gui/gui-manager.h16
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();