Maelstrom: Added a delegate to be notified when a radio group changes value

https://github.com/libsdl-org/Maelstrom/commit/0dca5e3eea430a7bfe81bdd00a677cc09138da25

From 0dca5e3eea430a7bfe81bdd00a677cc09138da25 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 5 Nov 2011 14:14:33 -0400
Subject: [PATCH] Added a delegate to be notified when a radio group changes
 value

---
 screenlib/UIElementRadio.cpp | 47 ++++++++++++++++++++++++++++++++++--
 screenlib/UIElementRadio.h   | 12 +++++++++
 2 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/screenlib/UIElementRadio.cpp b/screenlib/UIElementRadio.cpp
index 924869d8..95c8469f 100644
--- a/screenlib/UIElementRadio.cpp
+++ b/screenlib/UIElementRadio.cpp
@@ -21,6 +21,23 @@
 
 #include "UIElementRadio.h"
 
+
+class SimpleRadioDelegate : public UIRadioDelegate
+{
+public:
+	SimpleRadioDelegate(void (*callback)(int value)) {
+		m_callback = callback;
+	}
+
+	virtual void OnValueChanged(int oldValue, int newValue) {
+		m_callback(newValue);
+	}
+
+protected:
+	void (*m_callback)(int value);
+};
+
+
 UIElementType UIElementRadioGroup::s_elementType;
 
 
@@ -29,6 +46,7 @@ UIElementRadioGroup::UIElementRadioGroup(UIBaseElement *parent, const char *name
 {
 	m_value = -1;
 	m_valueBinding = NULL;
+	m_delegate = NULL;
 }
 
 UIElementRadioGroup::~UIElementRadioGroup()
@@ -36,6 +54,9 @@ UIElementRadioGroup::~UIElementRadioGroup()
 	if (m_valueBinding) {
 		SDL_free(m_valueBinding);
 	}
+	if (m_delegate) {
+		delete m_delegate;
+	}
 }
 
 bool
@@ -89,12 +110,14 @@ UIElementRadioGroup::GetRadioButton(int id)
 void
 UIElementRadioGroup::SetValue(int value)
 {
+	int oldValue;
 	array<UIElementRadioButton*> buttons;
 
 	if (value == m_value) {
 		return;
 	}
 
+	oldValue = m_value;
 	m_value = value;
 
 	FindElements<UIElementRadioButton>(buttons);
@@ -105,6 +128,25 @@ UIElementRadioGroup::SetValue(int value)
 			buttons[i]->SetChecked(false);
 		}
 	}
+
+	if (m_delegate) {
+		m_delegate->OnValueChanged(oldValue, m_value);
+	}
+}
+
+void
+UIElementRadioGroup::SetCallback(void (*callback)(int value))
+{
+	SetDelegate(new SimpleRadioDelegate(callback));
+}
+
+void
+UIElementRadioGroup::SetDelegate(UIRadioDelegate *delegate)
+{
+	if (m_delegate) {
+		delete m_delegate;
+	}
+	m_delegate = delegate;
 }
 
 
@@ -120,12 +162,13 @@ UIElementRadioButton::UIElementRadioButton(UIBaseElement *parent, const char *na
 bool
 UIElementRadioButton::Load(rapidxml::xml_node<> *node, const UITemplates *templates)
 {
+	// Load the ID first so OnChecked() will do the right thing
+	LoadNumber(node, "id", m_id);
+
 	if (!UIElementCheckbox::Load(node, templates)) {
 		return false;
 	}
 
-	LoadNumber(node, "id", m_id);
-
 	return true;
 }
 
diff --git a/screenlib/UIElementRadio.h b/screenlib/UIElementRadio.h
index 266dc2b8..364ce9a7 100644
--- a/screenlib/UIElementRadio.h
+++ b/screenlib/UIElementRadio.h
@@ -25,6 +25,12 @@
 #include "UIElement.h"
 #include "UIElementCheckbox.h"
 
+class UIRadioDelegate
+{
+public:
+	virtual void OnValueChanged(int oldValue, int newValue) { }
+};
+
 //
 // This file has two classes:
 //
@@ -55,9 +61,15 @@ DECLARE_TYPESAFE_CLASS(UIElement)
 		return m_value;
 	}
 
+	// Setting a callback sets a simplified delegate
+	// Once set, the element owns the delegate and will free it.
+	void SetCallback(void (*callback)(int value));
+	void SetDelegate(UIRadioDelegate *delegate);
+
 protected:
 	int m_value;
 	char *m_valueBinding;
+	UIRadioDelegate *m_delegate;
 };
 
 class UIElementRadioButton : public UIElementCheckbox