https://github.com/libsdl-org/Maelstrom/commit/cf8bd825a815065f1493b407fc3883343b0611e6
From cf8bd825a815065f1493b407fc3883343b0611e6 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 5 Nov 2011 16:19:10 -0400
Subject: [PATCH] Created a more flexible callback structure, allowing member
function callbacks.
---
main.cpp | 48 +++++++++++++++----------------
screenlib/UIDialog.cpp | 2 +-
screenlib/UIDialog.h | 4 +--
screenlib/UIElement.cpp | 42 +++++++--------------------
screenlib/UIElement.h | 56 +++++++++++++++++++++++++++++++-----
screenlib/UIElementRadio.cpp | 41 ++++++--------------------
screenlib/UIElementRadio.h | 56 +++++++++++++++++++++++++++++++-----
7 files changed, 144 insertions(+), 105 deletions(-)
diff --git a/main.cpp b/main.cpp
index 71e3028d..b97f4c25 100644
--- a/main.cpp
+++ b/main.cpp
@@ -59,24 +59,24 @@ int gNoDelay;
// Main Menu actions:
-static void RunDoAbout(void)
+static void RunDoAbout(void*)
{
ui->ShowPanel(PANEL_ABOUT);
}
-static void RunPlayGame(void)
+static void RunPlayGame(void*)
{
gStartLevel = 1;
gStartLives = 3;
gNoDelay = 0;
NewGame();
}
-static void RunQuitGame(void)
+static void RunQuitGame(void*)
{
while ( sound->Playing() )
Delay(SOUND_DELAY);
gRunning = false;
}
-static void IncrementSound(void)
+static void IncrementSound(void*)
{
if ( gSoundLevel < 8 ) {
sound->Volume(++gSoundLevel);
@@ -86,7 +86,7 @@ static void IncrementSound(void)
gUpdateBuffer = true;
}
}
-static void DecrementSound(void)
+static void DecrementSound(void*)
{
if ( gSoundLevel > 0 ) {
sound->Volume(--gSoundLevel);
@@ -108,7 +108,7 @@ static void SetSoundLevel(int volume)
/* -- Draw the new sound level */
gUpdateBuffer = true;
}
-static void RunToggleFullscreen(void)
+static void RunToggleFullscreen(void*)
{
screen->ToggleFullScreen();
}
@@ -152,17 +152,17 @@ static void CheatDialogDone(UIDialog *dialog, int status)
NewGame();
}
}
-static void RunScreenshot(void)
+static void RunScreenshot(void*)
{
screen->ScreenDump("ScoreDump", 64, 48, 298, 384);
}
-class SetVolumeDelegate : public UIClickDelegate
+class SetVolumeCallback : public UIClickCallback
{
public:
- SetVolumeDelegate(int volume) : m_volume(volume) { }
+ SetVolumeCallback(int volume) : m_volume(volume) { }
- virtual void OnClick() {
+ virtual void operator()() {
SetSoundLevel(m_volume);
}
private:
@@ -309,7 +309,7 @@ int main(int argc, char *argv[])
/* -- Handle window close requests */
if ( event.type == SDL_QUIT ) {
- RunQuitGame();
+ RunQuitGame(0);
}
}
Delay(FRAME_DELAY);
@@ -343,11 +343,11 @@ MainPanelDelegate::OnLoad()
}
button = m_panel->GetElement<UIElementButton>("ControlsButton");
if (button) {
- button->SetClickDelegate(new UIDialogLauncher(ui, DIALOG_CONTROLS));
+ button->SetClickCallback(new UIDialogLauncher(ui, DIALOG_CONTROLS));
}
button = m_panel->GetElement<UIElementButton>("ZapButton");
if (button) {
- button->SetClickDelegate(new UIDialogLauncher(ui, DIALOG_ZAP, NULL, ZapHighScores));
+ button->SetClickCallback(new UIDialogLauncher(ui, DIALOG_ZAP, NULL, ZapHighScores));
}
button = m_panel->GetElement<UIElementButton>("AboutButton");
if (button) {
@@ -371,11 +371,11 @@ MainPanelDelegate::OnLoad()
}
button = m_panel->GetElement<UIElementButton>("Cheat");
if (button) {
- button->SetClickDelegate(new UIDialogLauncher(ui, DIALOG_CHEAT, CheatDialogInit, CheatDialogDone));
+ button->SetClickCallback(new UIDialogLauncher(ui, DIALOG_CHEAT, CheatDialogInit, CheatDialogDone));
}
button = m_panel->GetElement<UIElementButton>("Special");
if (button) {
- button->SetClickDelegate(new UIDialogLauncher(ui, DIALOG_DAWN));
+ button->SetClickCallback(new UIDialogLauncher(ui, DIALOG_DAWN));
}
button = m_panel->GetElement<UIElementButton>("Screenshot");
if (button) {
@@ -384,39 +384,39 @@ MainPanelDelegate::OnLoad()
button = m_panel->GetElement<UIElementButton>("SetVolume0");
if (button) {
- button->SetClickDelegate(new SetVolumeDelegate(0));
+ button->SetClickCallback(new SetVolumeCallback(0));
}
button = m_panel->GetElement<UIElementButton>("SetVolume1");
if (button) {
- button->SetClickDelegate(new SetVolumeDelegate(1));
+ button->SetClickCallback(new SetVolumeCallback(1));
}
button = m_panel->GetElement<UIElementButton>("SetVolume2");
if (button) {
- button->SetClickDelegate(new SetVolumeDelegate(2));
+ button->SetClickCallback(new SetVolumeCallback(2));
}
button = m_panel->GetElement<UIElementButton>("SetVolume3");
if (button) {
- button->SetClickDelegate(new SetVolumeDelegate(3));
+ button->SetClickCallback(new SetVolumeCallback(3));
}
button = m_panel->GetElement<UIElementButton>("SetVolume4");
if (button) {
- button->SetClickDelegate(new SetVolumeDelegate(4));
+ button->SetClickCallback(new SetVolumeCallback(4));
}
button = m_panel->GetElement<UIElementButton>("SetVolume5");
if (button) {
- button->SetClickDelegate(new SetVolumeDelegate(5));
+ button->SetClickCallback(new SetVolumeCallback(5));
}
button = m_panel->GetElement<UIElementButton>("SetVolume6");
if (button) {
- button->SetClickDelegate(new SetVolumeDelegate(6));
+ button->SetClickCallback(new SetVolumeCallback(6));
}
button = m_panel->GetElement<UIElementButton>("SetVolume7");
if (button) {
- button->SetClickDelegate(new SetVolumeDelegate(7));
+ button->SetClickCallback(new SetVolumeCallback(7));
}
button = m_panel->GetElement<UIElementButton>("SetVolume8");
if (button) {
- button->SetClickDelegate(new SetVolumeDelegate(8));
+ button->SetClickCallback(new SetVolumeCallback(8));
}
return true;
diff --git a/screenlib/UIDialog.cpp b/screenlib/UIDialog.cpp
index cc66f8b4..2c2ed851 100644
--- a/screenlib/UIDialog.cpp
+++ b/screenlib/UIDialog.cpp
@@ -102,7 +102,7 @@ UIDialogLauncher::UIDialogLauncher(UIManager *ui, const char *name, UIDialogInit
}
void
-UIDialogLauncher::OnClick()
+UIDialogLauncher::operator()()
{
UIDialog *dialog;
diff --git a/screenlib/UIDialog.h b/screenlib/UIDialog.h
index 2d4c2b7f..c8994f0c 100644
--- a/screenlib/UIDialog.h
+++ b/screenlib/UIDialog.h
@@ -78,12 +78,12 @@ DECLARE_TYPESAFE_CLASS(UIPanel)
//
// A class to make it easy to launch a dialog from a button
//
-class UIDialogLauncher : public UIClickDelegate
+class UIDialogLauncher : public UIClickCallback
{
public:
UIDialogLauncher(UIManager *ui, const char *name, UIDialogInitHandler = NULL, UIDialogDoneHandler handleDone = NULL);
- override void OnClick();
+ override void operator()();
protected:
UIManager *m_ui;
diff --git a/screenlib/UIElement.cpp b/screenlib/UIElement.cpp
index 0a248c86..fb9e3d3a 100644
--- a/screenlib/UIElement.cpp
+++ b/screenlib/UIElement.cpp
@@ -24,22 +24,6 @@
#include "SDL_FrameBuf.h"
#include "UIElement.h"
-
-class SimpleClickDelegate : public UIClickDelegate
-{
-public:
- SimpleClickDelegate(void (*callback)(void)) {
- m_callback = callback;
- }
-
- virtual void OnClick() {
- m_callback();
- }
-
-protected:
- void (*m_callback)(void);
-};
-
UIElementType UIElement::s_elementType;
@@ -66,7 +50,7 @@ UIElement::UIElement(UIBaseElement *parent, const char *name, UIDrawEngine *draw
m_mouseEnabled = false;
m_mouseInside = false;
m_mousePressed = false;
- m_clickDelegate = NULL;
+ m_clickCallback = NULL;
SetDrawEngine(drawEngine);
}
@@ -88,8 +72,8 @@ UIElement::~UIElement()
if (m_image) {
m_screen->FreeImage(m_image);
}
- if (m_clickDelegate) {
- delete m_clickDelegate;
+ if (m_clickCallback) {
+ delete m_clickCallback;
}
}
@@ -579,21 +563,15 @@ UIElement::HandleEvent(const SDL_Event &event)
}
void
-UIElement::SetClickCallback(void (*callback)(void))
-{
- SetClickDelegate(new SimpleClickDelegate(callback));
-}
-
-void
-UIElement::SetClickDelegate(UIClickDelegate *delegate)
+UIElement::SetClickCallback(UIClickCallback *callback)
{
- if (m_clickDelegate) {
- delete m_clickDelegate;
+ if (m_clickCallback) {
+ delete m_clickCallback;
}
- m_clickDelegate = delegate;
+ m_clickCallback = callback;
- if (m_clickDelegate) {
+ if (m_clickCallback) {
m_mouseEnabled = true;
}
}
@@ -634,7 +612,7 @@ UIElement::OnMouseUp()
void
UIElement::OnClick()
{
- if (m_clickDelegate) {
- m_clickDelegate->OnClick();
+ if (m_clickCallback) {
+ (*m_clickCallback)();
}
}
diff --git a/screenlib/UIElement.h b/screenlib/UIElement.h
index f70032c5..bc9e8cfb 100644
--- a/screenlib/UIElement.h
+++ b/screenlib/UIElement.h
@@ -26,10 +26,47 @@
#include "UIDrawEngine.h"
#include "UIFontInterface.h"
-class UIClickDelegate
+class UIClickCallback
{
public:
- virtual void OnClick() { }
+ virtual void operator()() = 0;
+};
+
+template <class C>
+class UIObjectClickCallback : public UIClickCallback
+{
+public:
+ UIObjectClickCallback(C *obj, void (C::*callback)(void*), void *param) : UIClickCallback() {
+ m_obj = obj;
+ m_callback = callback;
+ m_param = param;
+ }
+
+ virtual void operator()() {
+ (m_obj->*m_callback)(m_param);
+ }
+
+protected:
+ C *m_obj;
+ void (C::*m_callback)(void*);
+ void *m_param;
+};
+
+class UIFunctionClickCallback : public UIClickCallback
+{
+public:
+ UIFunctionClickCallback(void (*callback)(void*), void *param) : UIClickCallback() {
+ m_callback = callback;
+ m_param = param;
+ }
+
+ virtual void operator()() {
+ (*m_callback)(m_param);
+ }
+
+protected:
+ void (*m_callback)(void*);
+ void *m_param;
};
// This is the basic thing you see on the screen.
@@ -131,10 +168,15 @@ DECLARE_TYPESAFE_CLASS(UIBaseElement)
// Events
override bool HandleEvent(const SDL_Event &event);
- // Setting a click callback sets a simplified delegate
- // Once set, the element owns the click delegate and will free it.
- void SetClickCallback(void (*callback)(void));
- void SetClickDelegate(UIClickDelegate *delegate);
+ // Once set, the element owns the click callback and will free it.
+ template <class C>
+ void SetClickCallback(C *obj, void (C::*callback)(void*), void *param = 0) {
+ SetClickCallback(new UIObjectClickCallback<C>(obj, callback, param));
+ }
+ void SetClickCallback(void (*callback)(void*), void *param = 0) {
+ SetClickCallback(new UIFunctionClickCallback(callback, param));
+ }
+ void SetClickCallback(UIClickCallback *callback);
// These can be overridden by inheriting classes
virtual void OnMouseEnter();
@@ -164,7 +206,7 @@ DECLARE_TYPESAFE_CLASS(UIBaseElement)
bool m_mouseEnabled;
bool m_mouseInside;
bool m_mousePressed;
- UIClickDelegate *m_clickDelegate;
+ UIClickCallback *m_clickCallback;
protected:
bool LoadColor(rapidxml::xml_node<> *node, const char *name, Uint32 &value);
diff --git a/screenlib/UIElementRadio.cpp b/screenlib/UIElementRadio.cpp
index 95c8469f..a94d4029 100644
--- a/screenlib/UIElementRadio.cpp
+++ b/screenlib/UIElementRadio.cpp
@@ -21,23 +21,6 @@
#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;
@@ -46,7 +29,7 @@ UIElementRadioGroup::UIElementRadioGroup(UIBaseElement *parent, const char *name
{
m_value = -1;
m_valueBinding = NULL;
- m_delegate = NULL;
+ m_callback = NULL;
}
UIElementRadioGroup::~UIElementRadioGroup()
@@ -54,8 +37,8 @@ UIElementRadioGroup::~UIElementRadioGroup()
if (m_valueBinding) {
SDL_free(m_valueBinding);
}
- if (m_delegate) {
- delete m_delegate;
+ if (m_callback) {
+ delete m_callback;
}
}
@@ -129,24 +112,18 @@ UIElementRadioGroup::SetValue(int value)
}
}
- if (m_delegate) {
- m_delegate->OnValueChanged(oldValue, m_value);
+ if (m_callback) {
+ (*m_callback)(m_value);
}
}
void
-UIElementRadioGroup::SetCallback(void (*callback)(int value))
-{
- SetDelegate(new SimpleRadioDelegate(callback));
-}
-
-void
-UIElementRadioGroup::SetDelegate(UIRadioDelegate *delegate)
+UIElementRadioGroup::SetValueCallback(UIRadioCallback *callback)
{
- if (m_delegate) {
- delete m_delegate;
+ if (m_callback) {
+ delete m_callback;
}
- m_delegate = delegate;
+ m_callback = callback;
}
diff --git a/screenlib/UIElementRadio.h b/screenlib/UIElementRadio.h
index 364ce9a7..911531b0 100644
--- a/screenlib/UIElementRadio.h
+++ b/screenlib/UIElementRadio.h
@@ -25,10 +25,47 @@
#include "UIElement.h"
#include "UIElementCheckbox.h"
-class UIRadioDelegate
+class UIRadioCallback
{
public:
- virtual void OnValueChanged(int oldValue, int newValue) { }
+ virtual void operator ()(int value) = 0;
+};
+
+template <class C>
+class UIObjectRadioCallback : public UIRadioCallback
+{
+public:
+ UIObjectRadioCallback(C *obj, void (C::*callback)(void*, int), void *param) : UIRadioCallback() {
+ m_obj = obj;
+ m_callback = callback;
+ m_param = param;
+ }
+
+ virtual void operator()(int value) {
+ (m_obj->*m_callback)(m_param, value);
+ }
+
+protected:
+ C *m_obj;
+ void (C::*m_callback)(void*, int);
+ void *m_param;
+};
+
+class UIFunctionRadioCallback : public UIRadioCallback
+{
+public:
+ UIFunctionRadioCallback(void (*callback)(void*, int), void *param) : UIRadioCallback() {
+ m_callback = callback;
+ m_param = param;
+ }
+
+ virtual void operator()(int value) {
+ (*m_callback)(m_param, value);
+ }
+
+protected:
+ void (*m_callback)(void*, int);
+ void *m_param;
};
//
@@ -61,15 +98,20 @@ 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);
+ // Once set, the element owns the callback and will free it.
+ template <class C>
+ void SetValueCallback(C *obj, void (C::*callback)(void*, int), void *param = 0) {
+ SetValueCallback(new UIObjectRadioCallback<C>(obj, callback, param));
+ }
+ void SetValueCallback(void (*callback)(void*, int), void *param = 0) {
+ SetValueCallback(new UIFunctionRadioCallback(callback, param));
+ }
+ void SetValueCallback(UIRadioCallback *callback);
protected:
int m_value;
char *m_valueBinding;
- UIRadioDelegate *m_delegate;
+ UIRadioCallback *m_callback;
};
class UIElementRadioButton : public UIElementCheckbox