https://github.com/libsdl-org/Maelstrom/commit/f8513d4c35b5711845a6fb4c132ffbd67e9e1e28
From f8513d4c35b5711845a6fb4c132ffbd67e9e1e28 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 29 Oct 2011 03:51:18 -0400
Subject: [PATCH] Added an easy way to bind buttons to launch dialogs. Added a
way to set dialog completion callbacks, which are passed the ID of the button
that closed the dialog.
---
UI/dawn.xml | 2 +-
UI/zap.xml | 4 ++--
UIDialog.cpp | 44 +++++++++++++++++++++++++++++++++++---
UIDialog.h | 49 +++++++++++++++++++++++++++++++++++++++++++
UIDialogButton.cpp | 12 ++++++++++-
UIDialogButton.h | 1 +
main.cpp | 29 +++----------------------
scores.cpp | 22 ++++++++++---------
scores.h | 4 +++-
screenlib/UIManager.h | 11 ++++++++--
10 files changed, 132 insertions(+), 46 deletions(-)
diff --git a/UI/dawn.xml b/UI/dawn.xml
index 1aeddd61..cd4f32e1 100644
--- a/UI/dawn.xml
+++ b/UI/dawn.xml
@@ -24,7 +24,7 @@
<Anchor anchorFrom="TOPLEFT" anchorTo="BOTTOMRIGHT" anchor="line5" x="2" y="2"/>
</DialogLabel>
- <DialogButton text="OK" default="true" closeDialog="true">
+ <DialogButton text="OK" default="true">
<Size w="90"/>
<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" x="210" y="160"/>
</DialogButton>
diff --git a/UI/zap.xml b/UI/zap.xml
index 41e5353a..6079c6ba 100644
--- a/UI/zap.xml
+++ b/UI/zap.xml
@@ -5,10 +5,10 @@
<Title id="102">
<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" x="4" y="4"/>
</Icon>
- <DialogButton name="clearButton" text="Clear" closeDialog="true">
+ <DialogButton name="clearButton" text="Clear" id="1">
<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" x="99" y="74"/>
</DialogButton>
- <DialogButton text="Cancel" default="true" closeDialog="true">
+ <DialogButton text="Cancel" default="true">
<Anchor anchorFrom="TOPLEFT" anchorTo="TOPRIGHT" anchor="clearButton"x="13"/>
</DialogButton>
</Elements>
diff --git a/UIDialog.cpp b/UIDialog.cpp
index afafe96a..f6a539b9 100644
--- a/UIDialog.cpp
+++ b/UIDialog.cpp
@@ -7,6 +7,9 @@
#define EXPAND_STEPS 30
+UIElementType UIDialog::s_elementType;
+
+
UIDialog::UIDialog(UIManager *ui, const char *name) :
UIPanel(ui, name)
{
@@ -19,6 +22,8 @@ UIDialog::UIDialog(UIManager *ui, const char *name) :
m_colors[COLOR_WHITE] = m_screen->MapRGB(0xFF, 0xFF, 0xFF);
m_expand = true;
m_step = 0;
+ m_status = 0;
+ m_handler = NULL;
}
UIDialog::~UIDialog()
@@ -28,8 +33,6 @@ UIDialog::~UIDialog()
bool
UIDialog::Load(rapidxml::xml_node<> *node, const UITemplates *templates)
{
- rapidxml::xml_attribute<> *attr;
-
if (!UIPanel::Load(node, templates)) {
return false;
}
@@ -47,6 +50,19 @@ UIDialog::Show()
} else {
m_step = EXPAND_STEPS;
}
+ m_status = 0;
+
+ UIPanel::Show();
+}
+
+void
+UIDialog::Hide()
+{
+ UIPanel::Hide();
+
+ if (m_handler) {
+ m_handler(this, m_status);
+ }
}
void
@@ -100,7 +116,9 @@ UIDialog::Draw()
bool
UIDialog::HandleEvent(const SDL_Event &event)
{
- UIPanel::HandleEvent(event);
+ if (UIPanel::HandleEvent(event)) {
+ return true;
+ }
if (event.type != SDL_QUIT) {
/* Press escape to cancel out of dialogs */
@@ -112,3 +130,23 @@ UIDialog::HandleEvent(const SDL_Event &event)
}
return false;
}
+
+UIDialogLauncher::UIDialogLauncher(UIManager *ui, const char *name, UIDialogHandler handler)
+{
+ m_ui = ui;
+ m_name = name;
+ m_handler = handler;
+}
+
+void
+UIDialogLauncher::OnClick()
+{
+ UIDialog *dialog;
+
+ dialog = m_ui->GetPanel<UIDialog>(m_name);
+ if (dialog) {
+ dialog->SetDialogHandler(m_handler);
+
+ m_ui->ShowPanel(dialog);
+ }
+}
diff --git a/UIDialog.h b/UIDialog.h
index 3c2a6c8d..625e9062 100644
--- a/UIDialog.h
+++ b/UIDialog.h
@@ -3,7 +3,14 @@
#define _UIDialog_h
#include "screenlib/UIPanel.h"
+#include "screenlib/UIElementButton.h"
+class UIDialog;
+
+/* This function gets called when the dialog is hidden.
+ The status defaults to 0, but can be changed by dialog buttons.
+ */
+typedef void (*UIDialogHandler)(UIDialog *dialog, int status);
class UIDialog : public UIPanel
{
@@ -11,9 +18,22 @@ class UIDialog : public UIPanel
UIDialog(UIManager *ui, const char *name);
virtual ~UIDialog();
+ virtual bool IsA(UIElementType type) {
+ return UIPanel::IsA(type) || type == GetType();
+ }
+
+ /* Set a function that's called when the dialog is hidden */
+ void SetDialogHandler(UIDialogHandler handler) {
+ m_handler = handler;
+ }
+ void SetDialogStatus(int status) {
+ m_status = status;
+ }
+
virtual bool Load(rapidxml::xml_node<> *node, const UITemplates *templates);
virtual void Show();
+ virtual void Hide();
virtual void Draw();
virtual bool HandleEvent(const SDL_Event &event);
@@ -29,6 +49,35 @@ class UIDialog : public UIPanel
Uint32 m_colors[NUM_COLORS];
bool m_expand;
int m_step;
+ int m_status;
+ UIDialogHandler m_handler;
+
+protected:
+ static UIElementType s_elementType;
+
+public:
+ static UIElementType GetType() {
+ if (!s_elementType) {
+ s_elementType = GenerateType();
+ }
+ return s_elementType;
+ }
+};
+
+//
+// A class to make it easy to launch a dialog from a button
+//
+class UIDialogLauncher : public UIButtonDelegate
+{
+public:
+ UIDialogLauncher(UIManager *ui, const char *name, UIDialogHandler handler = NULL);
+
+ virtual void OnClick();
+
+protected:
+ UIManager *m_ui;
+ const char *m_name;
+ UIDialogHandler m_handler;
};
#endif // _UIDialog_h
diff --git a/UIDialogButton.cpp b/UIDialogButton.cpp
index abef44a5..1b655a3e 100644
--- a/UIDialogButton.cpp
+++ b/UIDialogButton.cpp
@@ -1,6 +1,7 @@
#include "screenlib/SDL_FrameBuf.h"
#include "screenlib/UIManager.h"
+#include "UIDialog.h"
#include "UIDialogButton.h"
#include "UIDialogLabel.h"
@@ -15,8 +16,9 @@ UIElementType UIDialogButton::s_elementType;
UIDialogButton::UIDialogButton(UIBaseElement *parent, const char *name) :
UIElementButton(parent, name)
{
+ m_statusID = 0;
m_default = false;
- m_closeDialog = false;
+ m_closeDialog = true;
m_colors[0] = m_screen->MapRGB(0xFF, 0xFF, 0xFF);
m_colors[1] = m_screen->MapRGB(0x00, 0x00, 0x00);
@@ -37,6 +39,8 @@ UIDialogButton::Load(rapidxml::xml_node<> *node, const UITemplates *templates)
return false;
}
+ LoadNumber(node, "id", m_statusID);
+
LoadBool(node, "default", m_default);
if (m_default) {
m_hotkey = SDLK_RETURN;
@@ -156,6 +160,12 @@ UIDialogButton::OnClick()
{
UIElementButton::OnClick();
+ if (m_statusID) {
+ UIPanel *panel = GetUI()->GetCurrentPanel();
+ if (panel->IsA(UIDialog::GetType())) {
+ static_cast<UIDialog*>(panel)->SetDialogStatus(m_statusID);
+ }
+ }
if (m_closeDialog) {
GetUI()->HidePanel(GetUI()->GetCurrentPanel());
}
diff --git a/UIDialogButton.h b/UIDialogButton.h
index 0e872e67..757617b4 100644
--- a/UIDialogButton.h
+++ b/UIDialogButton.h
@@ -24,6 +24,7 @@ class UIDialogButton : public UIElementButton
protected:
Uint32 m_colors[2];
+ int m_statusID;
bool m_default;
bool m_closeDialog;
diff --git a/main.cpp b/main.cpp
index acd94fdf..37424e39 100644
--- a/main.cpp
+++ b/main.cpp
@@ -18,6 +18,7 @@
#include "main.h"
#include "screenlib/UIElementLabel.h"
+#include "UIDialog.h"
#include "UIElementKeyButton.h"
/* External functions used in this file */
@@ -89,26 +90,6 @@ static void SetSoundLevel(int volume)
/* -- Draw the new sound level */
gUpdateBuffer = true;
}
-static void SetupZapScores(void)
-{
- UIPanel *panel;
- UIElementButton *button;
-
- panel = ui->GetPanel(DIALOG_ZAP);
- if (!panel) {
- return;
- }
-
- button = panel->GetElement<UIElementButton>("clearButton");
- if (button) {
- button->SetClickCallback(ZapHighScores);
- }
-}
-static void RunZapScores(void)
-{
- SetupZapScores();
- ui->ShowPanel(DIALOG_ZAP);
-}
static void RunToggleFullscreen(void)
{
screen->ToggleFullScreen();
@@ -123,10 +104,6 @@ static void RunCheat(void)
NewGame();
}
}
-static void RunShowDawn(void)
-{
- ui->ShowPanel(DIALOG_DAWN);
-}
static void RunScreenshot(void)
{
screen->ScreenDump("ScoreDump", 64, 48, 298, 384);
@@ -385,7 +362,7 @@ MainPanelDelegate::OnLoad()
}
button = m_panel->GetElement<UIElementButton>("ZapButton");
if (button) {
- button->SetClickCallback(RunZapScores);
+ button->SetButtonDelegate(new UIDialogLauncher(ui, DIALOG_ZAP, ZapHighScores));
}
button = m_panel->GetElement<UIElementButton>("AboutButton");
if (button) {
@@ -413,7 +390,7 @@ MainPanelDelegate::OnLoad()
}
button = m_panel->GetElement<UIElementButton>("Special");
if (button) {
- button->SetClickCallback(RunShowDawn);
+ button->SetButtonDelegate(new UIDialogLauncher(ui, DIALOG_DAWN));
}
button = m_panel->GetElement<UIElementButton>("Screenshot");
if (button) {
diff --git a/scores.cpp b/scores.cpp
index 89ca8460..5c4c6a0b 100644
--- a/scores.cpp
+++ b/scores.cpp
@@ -99,17 +99,19 @@ void PrintHighScores(void)
}
}
-void ZapHighScores(void)
+void ZapHighScores(UIDialog *dialog, int status)
{
- memset(hScores, 0, sizeof(hScores));
- SaveScores();
- gLastHigh = -1;
-
- /* Fade the screen and redisplay scores */
- screen->FadeOut();
- Delay(SOUND_DELAY);
- sound->PlaySound(gExplosionSound, 5);
- gUpdateBuffer = true;
+ if (status) {
+ memset(hScores, 0, sizeof(hScores));
+ SaveScores();
+ gLastHigh = -1;
+
+ /* Fade the screen and redisplay scores */
+ screen->FadeOut();
+ Delay(SOUND_DELAY);
+ sound->PlaySound(gExplosionSound, 5);
+ gUpdateBuffer = true;
+ }
}
diff --git a/scores.h b/scores.h
index 49d27df3..ef4a9e91 100644
--- a/scores.h
+++ b/scores.h
@@ -1,8 +1,10 @@
+class UIDialog;
+
// Functions from scores.cc
extern void LoadScores(void);
extern void SaveScores(void);
-extern void ZapHighScores(void);
+extern void ZapHighScores(UIDialog *dialog, int status);
extern int GetStartLevel(void);
extern void PrintHighScores(void);
diff --git a/screenlib/UIManager.h b/screenlib/UIManager.h
index 806fd42c..99782f92 100644
--- a/screenlib/UIManager.h
+++ b/screenlib/UIManager.h
@@ -26,14 +26,13 @@
#include "SDL.h"
#include "../utils/array.h"
#include "UIArea.h"
+#include "UIPanel.h"
#include "UIFontInterface.h"
#include "UISoundInterface.h"
#include "UITemplates.h"
class FrameBuf;
class UIBaseElement;
-class UIPanel;
-class UIPanelDelegate;
class UIElement;
class UIManager : public UIArea, public UIFontInterface, public UISoundInterface
@@ -53,6 +52,14 @@ class UIManager : public UIArea, public UIFontInterface, public UISoundInterface
bool LoadTemplates(const char *file);
UIPanel *LoadPanel(const char *name);
UIPanel *GetPanel(const char *name, bool allowLoad = true);
+ template <typename T>
+ T *GetPanel(const char *name) {
+ UIPanel *panel = GetPanel(name);
+ if (panel && panel->IsA(T::GetType())) {
+ return (T*)panel;
+ }
+ return NULL;
+ }
UIPanel *GetCurrentPanel();
/* These are called by the UIPanel class */