https://github.com/libsdl-org/Maelstrom/commit/36b77cc558834450f067009e793680bfb6ae3f55
From 36b77cc558834450f067009e793680bfb6ae3f55 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sun, 30 Oct 2011 09:25:10 -0400
Subject: [PATCH] Added a simple editbox to the UI system Converted the cheat
dialog over to the new UI system.
---
MacDialogButton.cpp | 14 ++-
MacDialogEditbox.cpp | 69 +++++++++++
MacDialogEditbox.h | 25 ++++
MaelstromUI.cpp | 7 +-
Maelstrom_Globals.h | 1 +
Makefile.am | 2 +
UI/cheat.xml | 41 +++++++
UI/zap.xml | 4 +-
main.cpp | 44 ++++++-
scores.cpp | 96 ---------------
scores.h | 1 -
screenlib/Makefile.am | 2 +
screenlib/UIBaseElement.h | 40 +++++++
screenlib/UIElementButton.h | 4 +-
screenlib/UIElementCheckbox.h | 5 +-
screenlib/UIElementEditbox.cpp | 211 +++++++++++++++++++++++++++++++++
screenlib/UIElementEditbox.h | 84 +++++++++++++
screenlib/UIElementLabel.cpp | 11 +-
screenlib/UIElementRadio.cpp | 12 +-
19 files changed, 549 insertions(+), 124 deletions(-)
create mode 100644 MacDialogEditbox.cpp
create mode 100644 MacDialogEditbox.h
create mode 100644 UI/cheat.xml
create mode 100644 screenlib/UIElementEditbox.cpp
create mode 100644 screenlib/UIElementEditbox.h
diff --git a/MacDialogButton.cpp b/MacDialogButton.cpp
index cdb5f5eb..074303e8 100644
--- a/MacDialogButton.cpp
+++ b/MacDialogButton.cpp
@@ -23,7 +23,11 @@ MacDialogButton::MacDialogButton(UIBaseElement *parent, const char *name) :
UIElementLabel *
MacDialogButton::CreateLabel()
{
- return new MacDialogLabel(this, "label");
+ MacDialogLabel *label;
+
+ label = new MacDialogLabel(this, "label");
+ label->SetTextColor(m_colors[1]);
+ return label;
}
void
@@ -123,12 +127,12 @@ MacDialogButton::OnMouseUp()
void
MacDialogButton::SetElementColor(Uint32 color)
{
+ array<UIElementLabel*> labels;
Uint8 R, G, B;
m_screen->GetRGB(color, &R, &G, &B);
- for (unsigned i = 0; i < m_elements.length(); ++i) {
- if (m_elements[i]->IsA(UIElementLabel::GetType())) {
- static_cast<UIElementLabel*>(m_elements[i])->SetTextColor(R, G, B);
- }
+ FindElements<UIElementLabel>(labels);
+ for (unsigned i = 0; i < labels.length(); ++i) {
+ labels[i]->SetTextColor(R, G, B);
}
}
diff --git a/MacDialogEditbox.cpp b/MacDialogEditbox.cpp
new file mode 100644
index 00000000..1cfde099
--- /dev/null
+++ b/MacDialogEditbox.cpp
@@ -0,0 +1,69 @@
+
+#include "screenlib/SDL_FrameBuf.h"
+#include "MacDialogEditbox.h"
+#include "MacDialogLabel.h"
+
+UIElementType MacDialogEditbox::s_elementType;
+
+
+MacDialogEditbox::MacDialogEditbox(UIBaseElement *parent, const char *name) :
+ UIElementEditbox(parent, name)
+{
+ m_colors[0] = m_screen->MapRGB(0xFF, 0xFF, 0xFF);
+ m_colors[1] = m_screen->MapRGB(0x00, 0x00, 0x00);
+}
+
+UIElementLabel *
+MacDialogEditbox::CreateLabel()
+{
+ MacDialogLabel *label;
+
+ label = new MacDialogLabel(this, "label");
+ label->SetTextColor(m_colors[1]);
+ label->SetAnchor(LEFT, LEFT, this, 3, 0);
+ return label;
+}
+
+void
+MacDialogEditbox::OnHighlightChanged()
+{
+ SetElementColor(m_colors[!m_highlight]);
+}
+
+void
+MacDialogEditbox::Draw()
+{
+ Uint32 bg, fg;
+
+ /* The colors are inverted when the editbox is highlighted */
+ bg = m_colors[m_highlight];
+ fg = m_colors[!m_highlight];
+
+ // Draw the outline, always in the real foreground color
+ m_screen->DrawRect(X(), Y(), Width(), Height(), m_colors[1]);
+
+ if (m_highlight) {
+ // Draw the highlight
+ m_screen->FillRect(X()+3, Y()+3, Width()-6, Height()-6, bg);
+ } else if (m_focus) {
+ // Draw the cursor
+ int x = m_label->X() + m_label->Width();
+
+ m_screen->DrawLine(x, Y()+3, x, Y()+3+Height()-6-1, fg);
+ }
+
+ UIElementEditbox::Draw();
+}
+
+void
+MacDialogEditbox::SetElementColor(Uint32 color)
+{
+ array<UIElementLabel*> labels;
+ Uint8 R, G, B;
+
+ m_screen->GetRGB(color, &R, &G, &B);
+ FindElements<UIElementLabel>(labels);
+ for (unsigned i = 0; i < labels.length(); ++i) {
+ labels[i]->SetTextColor(R, G, B);
+ }
+}
diff --git a/MacDialogEditbox.h b/MacDialogEditbox.h
new file mode 100644
index 00000000..e1a9c185
--- /dev/null
+++ b/MacDialogEditbox.h
@@ -0,0 +1,25 @@
+#ifndef _MacDialogEditbox_h
+#define _MacDialogEditbox_h
+
+#include "screenlib/UIElementEditbox.h"
+
+
+class MacDialogEditbox : public UIElementEditbox
+{
+DECLARE_TYPESAFE_CLASS(UIElementEditbox)
+public:
+ MacDialogEditbox(UIBaseElement *parent, const char *name = "");
+
+ override void Draw();
+
+protected:
+ override UIElementLabel *CreateLabel();
+ override void OnHighlightChanged();
+
+ void SetElementColor(Uint32 color);
+
+protected:
+ Uint32 m_colors[2];
+};
+
+#endif // _MacDialogEditbox_h
diff --git a/MaelstromUI.cpp b/MaelstromUI.cpp
index 880a1d8d..f6ec15e8 100644
--- a/MaelstromUI.cpp
+++ b/MaelstromUI.cpp
@@ -8,6 +8,7 @@
#include "MacDialog.h"
#include "MacDialogButton.h"
#include "MacDialogCheckbox.h"
+#include "MacDialogEditbox.h"
#include "MacDialogLabel.h"
#include "MacDialogRadioButton.h"
#include "UIElementIcon.h"
@@ -15,7 +16,7 @@
#include "UIElementSprite.h"
#include "UIElementTitle.h"
#include "screenlib/UIElementButton.h"
-#include "screenlib/UIElementCheckbox.h"
+#include "screenlib/UIElementLabel.h"
#include "screenlib/UIElementLine.h"
#include "screenlib/UIElementRadio.h"
#include "screenlib/UIElementRect.h"
@@ -187,6 +188,8 @@ MaelstromUI::CreateElement(UIBaseElement *parent, const char *type, const char *
return new UIElementRadioGroup(parent, name);
} else if (strcasecmp(type, "DialogRadioButton") == 0) {
return new MacDialogRadioButton(parent, name);
+ } else if (strcasecmp(type, "DialogEditbox") == 0) {
+ return new MacDialogEditbox(parent, name);
} else if (strcasecmp(type, "KeyButton") == 0) {
return new UIElementKeyButton(parent, name);
} else if (strcasecmp(type, "Icon") == 0) {
@@ -196,5 +199,5 @@ MaelstromUI::CreateElement(UIBaseElement *parent, const char *type, const char *
} else if (strcasecmp(type, "Title") == 0) {
return new UIElementTitle(parent, name);
}
- return UIManager::CreateElement(parent, name, type);;
+ return UIManager::CreateElement(parent, name, type);
}
diff --git a/Maelstrom_Globals.h b/Maelstrom_Globals.h
index 92c50ab5..b71ca8ab 100644
--- a/Maelstrom_Globals.h
+++ b/Maelstrom_Globals.h
@@ -111,6 +111,7 @@ extern Bool gNetScores;
#define DIALOG_CONTROLS "controls"
#define DIALOG_ZAP "zap"
#define DIALOG_DAWN "dawn"
+#define DIALOG_CHEAT "cheat"
// Sound resource definitions...
#define gShotSound 100
diff --git a/Makefile.am b/Makefile.am
index c8b09a02..b04b199b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,6 +38,8 @@ Maelstrom_SOURCES = \
MacDialogButton.h \
MacDialogCheckbox.cpp \
MacDialogCheckbox.h \
+ MacDialogEditbox.cpp \
+ MacDialogEditbox.h \
MacDialogLabel.cpp \
MacDialogLabel.h \
MacDialogRadioButton.cpp\
diff --git a/UI/cheat.xml b/UI/cheat.xml
new file mode 100644
index 00000000..970e9fd7
--- /dev/null
+++ b/UI/cheat.xml
@@ -0,0 +1,41 @@
+<Dialog>
+ <Size w="338" h="128"/>
+ <Elements>
+ <Icon name="image" id="103">
+ <Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" x="14" y="14"/>
+ </Icon>
+ <DialogLabel name="line1" text="Enter the level to start from (1-40). This">
+ <Anchor anchorFrom="TOPLEFT" anchorTo="TOPRIGHT" anchor="image" x="14"/>
+ </DialogLabel>
+ <DialogLabel name="line2" text="disqualifies you from a high score...">
+ <Anchor anchorFrom="TOPLEFT" anchorTo="BOTTOMLEFT" anchor="line1" y="2"/>
+ </DialogLabel>
+
+ <DialogEditbox name="level" numeric="true" maxlen="2" text="10">
+ <Size w="30" h="21"/>
+ <Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" x="78" y="60"/>
+ </DialogEditbox>
+ <DialogLabel text="Level:">
+ <Anchor anchorFrom="RIGHT" anchorTo="LEFT" anchor="level" x="-2"/>
+ </DialogLabel>
+ <DialogEditbox name="lives" numeric="true" maxlen="2" text="3">
+ <Size w="30" h="21"/>
+ <Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" x="78" y="86"/>
+ </DialogEditbox>
+ <DialogLabel text="Lives:">
+ <Anchor anchorFrom="RIGHT" anchorTo="LEFT" anchor="lives" x="-2"/>
+ </DialogLabel>
+
+ <DialogCheckbox name="turbofunk" text="Turbofunk On">
+ <Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" x="136" y="64"/>
+ </DialogCheckbox>
+
+ <DialogButton name="cancelButton" text="Cancel">
+ <Size w="73"/>
+ <Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" x="166" y="96"/>
+ </DialogButton>
+ <DialogButton text="Do it!" default="true" id="1">
+ <Anchor anchorFrom="LEFT" anchorTo="RIGHT" anchor="cancelButton" x="14"/>
+ </DialogButton>
+ </Elements>
+</Dialog>
diff --git a/UI/zap.xml b/UI/zap.xml
index 6079c6ba..c0c87844 100644
--- a/UI/zap.xml
+++ b/UI/zap.xml
@@ -4,12 +4,12 @@
<Elements>
<Title id="102">
<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" x="4" y="4"/>
- </Icon>
+ </Title>
<DialogButton name="clearButton" text="Clear" id="1">
<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" x="99" y="74"/>
</DialogButton>
<DialogButton text="Cancel" default="true">
- <Anchor anchorFrom="TOPLEFT" anchorTo="TOPRIGHT" anchor="clearButton"x="13"/>
+ <Anchor anchorFrom="TOPLEFT" anchorTo="TOPRIGHT" anchor="clearButton" x="13"/>
</DialogButton>
</Elements>
</Dialog>
diff --git a/main.cpp b/main.cpp
index e29d239b..1d5d9b43 100644
--- a/main.cpp
+++ b/main.cpp
@@ -17,8 +17,10 @@
#include "netlogic/about.h"
#include "main.h"
-#include "screenlib/UIElementLabel.h"
#include "screenlib/UIDialog.h"
+#include "screenlib/UIElementCheckbox.h"
+#include "screenlib/UIElementEditbox.h"
+#include "screenlib/UIElementLabel.h"
#include "UIElementKeyButton.h"
/* External functions used in this file */
@@ -43,8 +45,8 @@ static void RunDoAbout(void)
}
static void RunPlayGame(void)
{
- gStartLives = 3;
gStartLevel = 1;
+ gStartLives = 3;
gNoDelay = 0;
NewGame();
}
@@ -90,10 +92,40 @@ static void RunToggleFullscreen(void)
{
screen->ToggleFullScreen();
}
-static void RunCheat(void)
+static void CheatDialogInit(UIDialog *dialog)
+{
+ UIElementEditbox *editbox;
+
+ editbox = dialog->GetElement<UIElementEditbox>("level");
+ if (editbox) {
+ editbox->SetFocus(true);
+ }
+}
+static void CheatDialogDone(UIDialog *dialog, int status)
{
- gStartLevel = GetStartLevel();
- if ( gStartLevel > 0 ) {
+ UIElementEditbox *editbox;
+ UIElementCheckbox *checkbox;
+
+ if (status > 0) {
+ editbox = dialog->GetElement<UIElementEditbox>("level");
+ if (editbox) {
+ gStartLevel = editbox->GetNumber();
+ if (gStartLevel < 1 || gStartLevel > 40) {
+ return;
+ }
+ }
+
+ editbox = dialog->GetElement<UIElementEditbox>("lives");
+ if (editbox) {
+ gStartLives = editbox->GetNumber();
+ if (gStartLives < 1 || gStartLives > 40) {
+ gStartLives = 3;
+ }
+ }
+
+ checkbox = dialog->GetElement<UIElementCheckbox>("turbofunk");
+ gNoDelay = checkbox->IsChecked();
+
Delay(SOUND_DELAY);
sound->PlaySound(gNewLife, 5);
Delay(SOUND_DELAY);
@@ -382,7 +414,7 @@ MainPanelDelegate::OnLoad()
}
button = m_panel->GetElement<UIElementButton>("Cheat");
if (button) {
- button->SetClickCallback(RunCheat);
+ button->SetButtonDelegate(new UIDialogLauncher(ui, DIALOG_CHEAT, CheatDialogInit, CheatDialogDone));
}
button = m_panel->GetElement<UIElementButton>("Special");
if (button) {
diff --git a/scores.cpp b/scores.cpp
index 5c4c6a0b..e36d39a3 100644
--- a/scores.cpp
+++ b/scores.cpp
@@ -114,99 +114,3 @@ void ZapHighScores(UIDialog *dialog, int status)
}
}
-
-#define LVL_DIALOG_WIDTH 346
-#define LVL_DIALOG_HEIGHT 136
-
-static int do_level;
-
-static int Level_callback(void) {
- do_level = 1;
- return(1);
-}
-static int Cancel2_callback(void) {
- do_level = 0;
- return(1);
-}
-
-int GetStartLevel(void)
-{
- static const char *Ltext1 =
- "Enter the level to start from (1-40). This";
- static const char *Ltext2 =
- "disqualifies you from a high score...";
- static const char *Ltext3 = "Level:";
- static const char *Ltext4 = "Lives:";
- MFont *chicago;
- Maclike_Dialog *dialog;
- SDL_Texture *splash;
- SDL_Texture *text1, *text2, *text3, *text4;
- static const char *turbotext = "Turbofunk On";
- int x, y, X, Y;
- Mac_Button *doit;
- Mac_Button *cancel;
- Mac_NumericEntry *numeric_entry;
- Mac_CheckBox *checkbox;
- int startlevel=10, startlives=5, turbofunk=0;
-
- /* Set up all the components of the dialog box */
- chicago = fonts[CHICAGO_12];
- if ( (splash = GetCIcon(screen, 103)) == NULL ) {
- error("Can't load alien level splash!\n");
- return(0);
- }
- X=(SCREEN_WIDTH-LVL_DIALOG_WIDTH)/2;
- Y=(SCREEN_HEIGHT-LVL_DIALOG_HEIGHT)/2;
- dialog = new Maclike_Dialog(X, Y, LVL_DIALOG_WIDTH, LVL_DIALOG_HEIGHT,
- screen);
- x = y = 14;
- dialog->Add_Image(splash, x, y);
- x += (screen->GetImageWidth(splash)+14);
- text1 = fontserv->TextImage(Ltext1,chicago,STYLE_NORM,0x00,0x00,0x00);
- dialog->Add_Image(text1, x, y);
- y += (screen->GetImageHeight(text1)+2);
- text2 = fontserv->TextImage(Ltext2, chicago, STYLE_NORM,
- 0x00, 0x00, 0x00);
- dialog->Add_Image(text2, x, y);
- do_level = 0;
- cancel = new Mac_Button(166, 96, 73, BUTTON_HEIGHT,
- "Cancel", chicago, fontserv, Cancel2_callback);
- dialog->Add_Dialog(cancel);
- doit = new Mac_DefaultButton(166+73+14, 96, BUTTON_WIDTH, BUTTON_HEIGHT,
- "Do it!", chicago, fontserv, Level_callback);
- dialog->Add_Dialog(doit);
- numeric_entry = new Mac_NumericEntry(X, Y, chicago, fontserv);
- numeric_entry->Add_Entry(78, 60, 3, 1, &startlevel);
- text3 = fontserv->TextImage(Ltext3,chicago,STYLE_NORM,0x00,0x00,0x00);
- dialog->Add_Image(text3, 78-screen->GetImageWidth(text3)-2, 60+3);
- numeric_entry->Add_Entry(78, 86, 3, 0, &startlives);
- text4 = fontserv->TextImage(Ltext4,chicago,STYLE_NORM,0x00,0x00,0x00);
- dialog->Add_Image(text4, 78-screen->GetImageWidth(text3)-2, 86+3);
- dialog->Add_Dialog(numeric_entry);
- checkbox = new Mac_CheckBox(&turbofunk, 136, 64, turbotext,
- chicago, fontserv);
- dialog->Add_Dialog(checkbox);
-
- /* Run the dialog box */
- dialog->Run(EXPAND_STEPS);
-
- /* Clean up and return */
- screen->FreeImage(splash);
- fontserv->FreeText(text1);
- fontserv->FreeText(text2);
- fontserv->FreeText(text3);
- fontserv->FreeText(text4);
- delete dialog;
- if ( do_level ) {
- if ( ! startlives || (startlives > 40) )
- startlives = 3;
- gStartLives = startlives;
- if ( startlevel > 40 )
- startlevel = 0;
- gStartLevel = startlevel;
- gNoDelay = turbofunk;
- return(gStartLevel);
- }
- return(0);
-}
-
diff --git a/scores.h b/scores.h
index ef4a9e91..04c5b19a 100644
--- a/scores.h
+++ b/scores.h
@@ -5,7 +5,6 @@ class UIDialog;
extern void LoadScores(void);
extern void SaveScores(void);
extern void ZapHighScores(UIDialog *dialog, int status);
-extern int GetStartLevel(void);
extern void PrintHighScores(void);
/* The high scores structure */
diff --git a/screenlib/Makefile.am b/screenlib/Makefile.am
index cd66cabe..1a21e5f8 100644
--- a/screenlib/Makefile.am
+++ b/screenlib/Makefile.am
@@ -19,6 +19,8 @@ libSDLscreen_a_SOURCES = \
UIElementButton.h \
UIElementCheckbox.cpp \
UIElementCheckbox.h \
+ UIElementEditbox.cpp \
+ UIElementEditbox.h \
UIElementLabel.cpp \
UIElementLabel.h \
UIElementLine.cpp \
diff --git a/screenlib/UIBaseElement.h b/screenlib/UIBaseElement.h
index 2abfe918..045795be 100644
--- a/screenlib/UIBaseElement.h
+++ b/screenlib/UIBaseElement.h
@@ -74,6 +74,46 @@ class UIBaseElement : public UIArea
}
return NULL;
}
+ template <typename T>
+ T *FindElement(UIBaseElement *start = NULL) {
+ unsigned i, j;
+ if (start) {
+ // Find the starting element
+ for (i = 0; i < m_elements.length(); ++i) {
+ if (m_elements[i] == start) {
+ break;
+ }
+ }
+ if (i == m_elements.length()) {
+ return NULL;
+ }
+ // Find the next element of that type
+ j = (i+1)%m_elements.length();
+ for ( ; j != i; j = (j+1)%m_elements.length()) {
+ UIBaseElement *element = m_elements[j];
+ if (element->IsA(T::GetType())) {
+ return (T*)element;
+ }
+ }
+ } else {
+ for (i = 0; i < m_elements.length(); ++i) {
+ UIBaseElement *element = m_elements[i];
+ if (element->IsA(T::GetType())) {
+ return (T*)element;
+ }
+ }
+ }
+ return NULL;
+ }
+ template <typename T>
+ void FindElements(array<T*> &elements) {
+ for (unsigned i = 0; i < m_elements.length(); ++i) {
+ UIBaseElement *element = m_elements[i];
+ if (element->IsA(T::GetType())) {
+ elements.add((T*)element);
+ }
+ }
+ }
void RemoveElement(UIBaseElement *element) {
m_elements.remove(element);
}
diff --git a/screenlib/UIElementButton.h b/screenlib/UIElementButton.h
index ae8aba56..ad75d416 100644
--- a/screenlib/UIElementButton.h
+++ b/screenlib/UIElementButton.h
@@ -44,14 +44,14 @@ DECLARE_TYPESAFE_CLASS(UIElement)
override bool HandleEvent(const SDL_Event &event);
- void SetText(const char *text);
+ virtual void SetText(const char *text);
// Setting a click callback sets a simplified delegate
void SetClickCallback(void (*callback)(void));
void SetButtonDelegate(UIButtonDelegate *delegate, bool autodelete = true);
protected:
- // These can be overridden by inherited classes
+ // These can be overridden by inheriting classes
virtual void OnMouseEnter() { }
virtual void OnMouseLeave() { }
virtual void OnMouseDown() { }
diff --git a/screenlib/UIElementCheckbox.h b/screenlib/UIElementCheckbox.h
index 0f833ae2..bbd28e4b 100644
--- a/screenlib/UIElementCheckbox.h
+++ b/screenlib/UIElementCheckbox.h
@@ -21,10 +21,13 @@ DECLARE_TYPESAFE_CLASS(UIElementButton)
bool IsChecked() const {
return m_checked;
}
- virtual void OnChecked(bool checked) { }
override void OnClick();
+protected:
+ // This can be overridden by inheriting classes
+ virtual void OnChecked(bool checked) { }
+
protected:
bool m_checked;
};
diff --git a/screenlib/UIElementEditbox.cpp b/screenlib/UIElementEditbox.cpp
new file mode 100644
index 00000000..e61d6136
--- /dev/null
+++ b/screenlib/UIElementEditbox.cpp
@@ -0,0 +1,211 @@
+/*
+ SCREENLIB: A framebuffer library based on the SDL library
+ Copyright (C) 1997 Sam Lantinga
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#include "UIElementEditbox.h"
+#include "UIElementLabel.h"
+
+UIElementType UIElementEditbox::s_elementType;
+
+
+UIElementEditbox::UIElementEditbox(UIBaseElement *parent, const char *name) :
+ UIElementButton(parent, name)
+{
+ m_focus = false;
+ m_highlight = false;
+ m_numeric = false;
+
+ // This is a reasonable default for a non-wrapping editbox
+ m_textMax = 128;
+ m_textLen = 0;
+ m_text = new char[m_textMax];
+ m_text[0] = '\0';
+}
+
+UIElementEditbox::~UIElementEditbox()
+{
+ delete[] m_text;
+}
+
+bool
+UIElementEditbox::Load(rapidxml::xml_node<> *node, const UITemplates *templates)
+{
+ if (!UIElementButton::Load(node, templates)) {
+ return false;
+ }
+
+ LoadBool(node, "numeric", m_numeric);
+
+ int maxLen;
+ if (LoadNumber(node, "maxLen", maxLen)) {
+ SetTextMax(maxLen);
+ }
+
+ return true;
+}
+
+bool
+UIElementEditbox::FinishLoading()
+{
+ if (!m_label) {
+ m_label = CreateLabel();
+ if (!m_label) {
+ fprintf(stderr, "Warning: Couldn't create editbox label\n");
+ return false;
+ }
+ AddElement(m_label);
+ }
+}
+
+bool
+UIElementEditbox::HandleEvent(const SDL_Event &event)
+{
+ if (!m_focus) {
+ return UIElementButton::HandleEvent(event);
+ }
+
+ if (event.type == SDL_KEYUP) {
+ switch (event.key.keysym.sym) {
+ case SDLK_ESCAPE:
+ SetFocus(false);
+ return true;
+ case SDLK_TAB:
+ SetFocusNext();
+ return true;
+ case SDLK_DELETE:
+ case SDLK_BACKSPACE:
+ if (m_textLen > 0) {
+ if (m_highlight) {
+ m_textLen = 0;
+ m_text[0] = '\0';
+ } else {
+ --m_textLen;
+ m_text[m_textLen] = '\0';
+ }
+ }
+ SetHighlight(false);
+ OnTextChanged();
+ return true;
+ default:
+ break;
+ }
+ }
+
+ if (event.type == SDL_TEXTINPUT) {
+ // Note, this doesn't support non-ASCII characters at the moment
+ // To do that we would have to separate m_textMax and the size
+ // of the text buffer and it gets complicated for in-line editing.
+ char ch = event.text.text[0];
+ bool valid;
+ if (m_numeric) {
+ valid = (ch >= '0' && ch <= '9');
+ } else {
+ valid = (ch >= ' ' && ch <= '~');
+ }
+ if (valid && (m_highlight || (m_textLen < m_textMax))) {
+ if (m_highlight) {
+ m_textLen = 0;
+ }
+ m_text[m_textLen++] = ch;
+ m_text[m_textLen] = '\0';
+ SetHighlight(false);
+ OnTextChanged();
+ }
+ return true;
+ }
+
+ return UIElementButton::HandleEvent(event);
+}
+
+void
+UIElementEditbox::SetFocus(bool focus)
+{
+ m_focus = focus;
+
+ if (m_focus) {
+ array<UIElementEditbox*> editboxes;
+
+ SetHighlight(true);
+
+ // Take focus away from other editboxes
+ m_parent->FindElements<UIElementEditbox>(editboxes);
+ for (unsigned i = 0; i < editboxes.length(); ++i) {
+ if (editboxes[i] != this) {
+ editboxes[i]->SetFocus(false);
+ }
+ }
+ } else {
+ SetHighlight(false);
+ }
+}
+
+void
+UIElementEditbox::SetHighlight(bool highlight)
+{
+ if (highlight != m_highlight) {
+ m_highlight = highlight;
+ OnHighlightChanged();
+ }
+}
+
+void
+UIElementEditbox::SetFocusNext()
+{
+ UIElementEditbox *editbox;
+ unsigned i, j;
+
+ // We always lose focus even if we don't find another editbox
+ SetFocus(false);
+
+ editbox = m_parent->FindElement<UIElementEditbox>(this);
+ if (editbox) {
+ editbox->SetFocus(true);
+ }
+}
+
+void
+UIElementEditbox::SetTextMax(int maxLen)
+{
+ char *oldText = m_text;
+
+ m_textMax = maxLen;
+ m_text = new char[m_textMax+1];
+ if (m_textLen <= m_textMax) {
+ SDL_strlcpy(m_text, oldText, m_textMax+1);
+ } else {
+ SetText(oldText);
+ }
+ delete[] oldText;
+}
+
+void
+UIElementEditbox::SetText(const char *text)
+{
+ SDL_strlcpy(m_text, text, m_textMax+1);
+ m_textLen = SDL_strlen(m_text);
+ OnTextChanged();
+}
+
+void
+UIElementEditbox::OnTextChanged()
+{
+ UIElementButton::SetText(m_text);
+}
diff --git a/screenlib/UIElementEditbox.h b/screenlib/UIElementEditbox.h
new file mode 100644
index 00000000..67d3cf04
--- /dev/null
+++ b/screenlib/UIElementEditbox.h
@@ -0,0 +1,84 @@
+/*
+ SCREENLIB: A framebuffer library based on the SDL library
+ Copyright (C) 1997 Sam Lantinga
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifndef _UIElementEditbox_h
+#define _UIElementEditbox_h
+
+// This is a simple editbox class
+// It currently doesn't support multiline or editing within the line,
+// though the latter could be supported fairly easily.
+
+#include "UIElementButton.h"
+
+
+class UIElementEditbox : public UIElementButton
+{
+DECLARE_TYPESAFE_CLASS(UIElement)
+public:
+ UIElementEditbox(UIBaseElement *parent, const char *name = "");
+ virtual ~UIElementEditbox();
+
+ override bool Load(rapidxml::xml_node<> *node, const UITemplates *templates);
+ override bool FinishLoading();
+
+ override bool HandleEvent(const SDL_Event &event);
+
+ override void OnClick() {
+ SetFocus(true);
+ }
+
+ void SetFocus(bool focus);
+ void SetFocusNext();
+
+ void SetTextMax(int maxLen);
+
+ override void SetText(const char *text);
+ const char *GetText() const {
+ return m_text;
+ }
+
+ void SetNumber(int value) {
+ char buffer[32];
+ sprintf(buffer, "%d", value);
+ SetText(buffer);
+ }
+ int GetNumber() const {
+ return SDL_atoi(m_text);
+ }
+
+protected:
+ // These can be overridden by inheriting classes
+ virtual void OnHighlightChanged() { }
+ virtual void OnTextChanged();
+
+ void SetHighlight(bool highlight);
+
+protected:
+ bool m_focus;
+ bool m_highlight;
+ bool m_numeric;
+ int m_textMax;
+ int m_textLen;
+ char *m_text;
+};
+
+#endif // _UIElementEditbox_h
diff --git a/screenlib/UIElementLabel.cpp b/screenlib/UIElementLabel.cpp
index 7bdcad4f..eb403501 100644
--- a/screenlib/UIElementLabel.cpp
+++ b/screenlib/UIElementLabel.cpp
@@ -110,13 +110,18 @@ UIElementLabel::SetText(const char *text)
}
if (m_texture) {
GetUI()->FreeText(m_texture);
+ m_texture = NULL;
}
m_text = SDL_strdup(text);
- m_texture = GetUI()->CreateText(m_text, m_fontName, m_fontSize, m_fontStyle, m_color);
+ if (*m_text) {
+ m_texture = GetUI()->CreateText(m_text, m_fontName, m_fontSize, m_fontStyle, m_color);
- SetSize(m_screen->GetImageWidth(m_texture),
- m_screen->GetImageHeight(m_texture));
+ SetSize(m_screen->GetImageWidth(m_texture),
+ m_screen->GetImageHeight(m_texture));
+ } else {
+ SetWidth(0);
+ }
}
void
diff --git a/screenlib/UIElementRadio.cpp b/screenlib/UIElementRadio.cpp
index e354b122..6267f2f0 100644
--- a/screenlib/UIElementRadio.cpp
+++ b/screenlib/UIElementRadio.cpp
@@ -32,12 +32,12 @@ UIElementRadioGroup::GetRadioButton(int id)
void
UIElementRadioGroup::RadioButtonChecked(UIElementRadioButton *button)
{
- for (unsigned i = 0; i < m_elements.length(); ++i) {
- if (!m_elements[i]->IsA(UIElementRadioButton::GetType())) {
- continue;
- }
- if (m_elements[i] != button) {
- static_cast<UIElementRadioButton*>(m_elements[i])->SetChecked(false);
+ array<UIElementRadioButton*> buttons;
+
+ FindElements<UIElementRadioButton>(buttons);
+ for (unsigned i = 0; i < buttons.length(); ++i) {
+ if (buttons[i] != button) {
+ buttons[i]->SetChecked(false);
}
}
m_value = button->GetID();