Maelstrom: Defer deleting panels until we're done with the tick/draw cycle, to prevent crashes.

https://github.com/libsdl-org/Maelstrom/commit/b254839f6eb7c001b9d26c92f7af1a387c6a3f3c

From b254839f6eb7c001b9d26c92f7af1a387c6a3f3c Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sun, 6 Nov 2011 10:56:17 -0500
Subject: [PATCH] Defer deleting panels until we're done with the tick/draw
 cycle, to prevent crashes.

---
 screenlib/UIManager.cpp | 21 +++++++++++++++++++--
 screenlib/UIManager.h   |  1 +
 screenlib/UIPanel.cpp   |  6 +++++-
 screenlib/UIPanel.h     |  1 +
 4 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/screenlib/UIManager.cpp b/screenlib/UIManager.cpp
index aa348b07..b9fbb98f 100644
--- a/screenlib/UIManager.cpp
+++ b/screenlib/UIManager.cpp
@@ -218,17 +218,26 @@ UIManager::DeletePanel(UIPanel *panel)
 		// Remove us so we don't recurse in HidePanel() or callbacks
 		m_panels.remove(panel);
 		HidePanel(panel);
-		delete panel;
+		m_delete.add(panel);
 	}
 }
 
 void
 UIManager::Draw(bool fullUpdate)
 {
+	int i;
+
+	// Run the tick before we draw in case it changes drawing state
+	for (i = 0; i < m_visible.length(); ++i) {
+		UIPanel *panel = m_visible[i];
+
+		panel->Tick();
+	}
+
 	if (fullUpdate) {
 		m_screen->Clear();
 	}
-	for (int i = 0; i < m_visible.length(); ++i) {
+	for (i = 0; i < m_visible.length(); ++i) {
 		UIPanel *panel = m_visible[i];
 
 		panel->Draw();
@@ -236,6 +245,14 @@ UIManager::Draw(bool fullUpdate)
 	if (fullUpdate) {
 		m_screen->Update();
 	}
+
+	// Clean up any deleted panels when we're done...
+	if (!m_delete.empty()) {
+		for (i = 0; i < m_delete.length(); ++i) {
+			delete m_delete[i];
+		}
+		m_delete.clear();
+	}
 }
 
 bool
diff --git a/screenlib/UIManager.h b/screenlib/UIManager.h
index 4df91be5..bf0289d5 100644
--- a/screenlib/UIManager.h
+++ b/screenlib/UIManager.h
@@ -111,6 +111,7 @@ class UIManager : public UIArea, public UIFontInterface, public UISoundInterface
 	UITemplates m_templates;
 	array<UIPanel *> m_panels;
 	array<UIPanel *> m_visible;
+	array<UIPanel *> m_delete;
 };
 
 #endif // _UIManager_h
diff --git a/screenlib/UIPanel.cpp b/screenlib/UIPanel.cpp
index c911b714..f586b4c8 100644
--- a/screenlib/UIPanel.cpp
+++ b/screenlib/UIPanel.cpp
@@ -130,12 +130,16 @@ UIPanel::HideAll()
 }
 
 void
-UIPanel::Draw()
+UIPanel::Tick()
 {
 	if (m_delegate) {
 		m_delegate->OnTick();
 	}
+}
 
+void
+UIPanel::Draw()
+{
 	UIBaseElement::Draw();
 
 	if (m_delegate) {
diff --git a/screenlib/UIPanel.h b/screenlib/UIPanel.h
index 8a5d27bb..137a6bc0 100644
--- a/screenlib/UIPanel.h
+++ b/screenlib/UIPanel.h
@@ -74,6 +74,7 @@ DECLARE_TYPESAFE_CLASS(UIBaseElement)
 
 	void HideAll();
 
+	virtual void Tick();
 	override void Draw();
 	override bool HandleEvent(const SDL_Event &event);