https://github.com/libsdl-org/Maelstrom/commit/e6e2ae725428e6eb02dfe92b8491eccef87b7976
From e6e2ae725428e6eb02dfe92b8491eccef87b7976 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 6 Nov 2012 00:43:14 -0800
Subject: [PATCH] Added support for image buttons
---
screenlib/UIDrawEngine.cpp | 10 ++--
screenlib/UIElement.cpp | 24 ++++++----
screenlib/UIElement.h | 8 +++-
screenlib/UIElementButton.cpp | 86 ++++++++++++++++++++++++++++++++++-
screenlib/UIElementButton.h | 13 ++++++
screenlib/UITexture.cpp | 1 +
screenlib/UITexture.h | 9 ++++
7 files changed, 135 insertions(+), 16 deletions(-)
diff --git a/screenlib/UIDrawEngine.cpp b/screenlib/UIDrawEngine.cpp
index cd7dad94..ce2beaa6 100644
--- a/screenlib/UIDrawEngine.cpp
+++ b/screenlib/UIDrawEngine.cpp
@@ -132,19 +132,21 @@ UIDrawEngine::OnDraw()
if (m_textImage) {
UIArea *area = m_element->GetTextArea();
- int x, y;
- if (m_element->GetTextShadowOffset(&x, &y)) {
+ int x, y, shadowX, shadowY;
+ m_element->GetTextOffset(&x, &y);
+
+ if (m_element->GetTextShadowOffset(&shadowX, &shadowY)) {
Uint8 r, g, b;
m_screen->GetRGB(m_element->GetTextShadowColor(), &r, &g, &b);
SDL_SetTextureColorMod(m_textImage->Texture(), r, g, b);
- m_screen->QueueBlit(m_textImage->Texture(), area->X()+x, area->Y()+y, area->Width(), area->Height(), NOCLIP);
+ m_screen->QueueBlit(m_textImage->Texture(), area->X()+x+shadowX, area->Y()+y+shadowY, area->Width(), area->Height(), NOCLIP);
m_screen->GetRGB(m_element->GetCurrentColor(), &r, &g, &b);
SDL_SetTextureColorMod(m_textImage->Texture(), r, g, b);
}
- m_screen->QueueBlit(m_textImage->Texture(), area->X(), area->Y(), area->Width(), area->Height(), NOCLIP);
+ m_screen->QueueBlit(m_textImage->Texture(), area->X()+x, area->Y()+y, area->Width(), area->Height(), NOCLIP);
}
}
diff --git a/screenlib/UIElement.cpp b/screenlib/UIElement.cpp
index b4b73109..3dce4db3 100644
--- a/screenlib/UIElement.cpp
+++ b/screenlib/UIElement.cpp
@@ -42,8 +42,10 @@ UIElement::UIElement(UIBaseElement *parent, const char *name, UIDrawEngine *draw
m_fontStyle = UIFONT_STYLE_NORMAL;
m_text = NULL;
m_textBinding = NULL;
- m_textShadowOffsetX = 0;
- m_textShadowOffsetY = 0;
+ m_textOffset.x = 0;
+ m_textOffset.y = 0;
+ m_textShadowOffset.x = 0;
+ m_textShadowOffset.y = 0;
m_textShadowColor = m_screen->MapRGB(0x00, 0x00, 0x00);
m_image = NULL;
m_mouseEnabled = false;
@@ -71,7 +73,7 @@ UIElement::~UIElement()
if (m_textBinding) {
SDL_free(m_textBinding);
}
- if (m_image) {
+ if (m_image && !m_image->IsLocked()) {
m_ui->FreeImage(m_image);
}
if (m_clickCallback) {
@@ -123,6 +125,10 @@ UIElement::Load(rapidxml::xml_node<> *node, const UITemplates *templates)
SetColor(color);
}
+ if (LoadColor(node, "disabledColor", color)) {
+ SetDisabledColor(color);
+ }
+
attr = node->first_attribute("font", 0, false);
if (attr) {
if (!ParseFont(attr->value())) {
@@ -445,16 +451,16 @@ UIElement::SetText(const char *text)
void
UIElement::SetTextShadowOffset(int x, int y)
{
- m_textShadowOffsetX = x;
- m_textShadowOffsetY = y;
+ m_textShadowOffset.x = x;
+ m_textShadowOffset.y = y;
}
bool
UIElement::GetTextShadowOffset(int *x, int *y) const
{
- if (m_textShadowOffsetX || m_textShadowOffsetY) {
- *x = m_textShadowOffsetX;
- *y = m_textShadowOffsetY;
+ if (m_textShadowOffset.x || m_textShadowOffset.y) {
+ *x = m_textShadowOffset.y;
+ *y = m_textShadowOffset.y;
return true;
} else {
*x = 0;
@@ -493,7 +499,7 @@ UIElement::SetImage(const char *file)
void
UIElement::SetImage(UITexture *image)
{
- if (m_image) {
+ if (m_image && !m_image->IsLocked()) {
m_ui->FreeImage(m_image);
}
m_image = image;
diff --git a/screenlib/UIElement.h b/screenlib/UIElement.h
index 7e3f39cc..ab0125d4 100644
--- a/screenlib/UIElement.h
+++ b/screenlib/UIElement.h
@@ -149,6 +149,10 @@ DECLARE_TYPESAFE_CLASS(UIBaseElement)
UIArea *GetTextArea() {
return &m_textArea;
}
+ void GetTextOffset(int *x, int *y) const {
+ *x = m_textOffset.x;
+ *y = m_textOffset.y;
+ }
void SetTextShadowOffset(int x, int y);
bool GetTextShadowOffset(int *x, int *y) const;
void SetTextShadowColor(Uint8 R, Uint8 G, Uint8 B);
@@ -204,8 +208,8 @@ DECLARE_TYPESAFE_CLASS(UIBaseElement)
char *m_text;
char *m_textBinding;
UIArea m_textArea;
- int m_textShadowOffsetX;
- int m_textShadowOffsetY;
+ SDL_Point m_textOffset;
+ SDL_Point m_textShadowOffset;
Uint32 m_textShadowColor;
UITexture *m_image;
UIArea m_imageArea;
diff --git a/screenlib/UIElementButton.cpp b/screenlib/UIElementButton.cpp
index 43c30a20..787c963f 100644
--- a/screenlib/UIElementButton.cpp
+++ b/screenlib/UIElementButton.cpp
@@ -36,6 +36,8 @@ UIElementButton::UIElementButton(UIBaseElement *parent, const char *name, UIDraw
m_hotkeyMod = KMOD_NONE;
m_clickSound = 0;
m_clickPanel = NULL;
+ m_buttonState = NUM_BUTTON_STATES;
+ SDL_zero(m_stateImages);
}
UIElementButton::~UIElementButton()
@@ -43,6 +45,14 @@ UIElementButton::~UIElementButton()
if (m_clickPanel) {
SDL_free(m_clickPanel);
}
+
+ for (int i = 0; i < SDL_arraysize(m_stateImages); ++i) {
+ UITexture *image = m_stateImages[i];
+ if (image) {
+ image->SetLocked(false);
+ m_ui->FreeImage(image);
+ }
+ }
}
bool
@@ -87,7 +97,31 @@ UIElementButton::Load(rapidxml::xml_node<> *node, const UITemplates *templates)
}
}
-
+ // Load the button state images, if any
+ static const char *stateImageNames[] = {
+ "normal_image",
+ "pressed_image",
+ "disabled_image",
+ };
+ SDL_COMPILE_TIME_ASSERT(stateImageNames, SDL_arraysize(stateImageNames) == NUM_BUTTON_STATES);
+
+ for (int i = 0; i < NUM_BUTTON_STATES; ++i) {
+ attr = node->first_attribute(stateImageNames[i], 0, false);
+ if (!attr) {
+ continue;
+ }
+
+ UITexture *image = m_ui->CreateImage(attr->value());
+ if (image) {
+ image->SetLocked(true);
+ m_stateImages[i] = image;
+ } else {
+ fprintf(stderr, "Warning: Couldn't load image '%s'\n", attr->value());
+ return false;
+ }
+ }
+ SetButtonState(BUTTON_STATE_NORMAL);
+
LoadNumber(node, "clickSound", m_clickSound);
LoadString(node, "clickPanel", m_clickPanel);
@@ -146,6 +180,56 @@ UIElementButton::HandleEvent(const SDL_Event &event)
return UIElement::HandleEvent(event);
}
+void
+UIElementButton::OnMouseDown()
+{
+ UIElement::OnMouseDown();
+
+ SetButtonState(BUTTON_STATE_PRESSED);
+}
+
+void
+UIElementButton::OnMouseUp()
+{
+ UIElement::OnMouseUp();
+
+ SetButtonState(BUTTON_STATE_NORMAL);
+}
+
+void
+UIElementButton::UpdateDisabledState()
+{
+ UIElement::UpdateDisabledState();
+
+ if (IsDisabled()) {
+ SetButtonState(BUTTON_STATE_DISABLED);
+ } else {
+ SetButtonState(BUTTON_STATE_NORMAL);
+ }
+}
+
+void
+UIElementButton::SetButtonState(BUTTON_STATE state)
+{
+ if (state == m_buttonState) {
+ return;
+ }
+
+ if (state == BUTTON_STATE_PRESSED) {
+ m_textOffset.x = 1;
+ m_textOffset.y = 1;
+ } else {
+ m_textOffset.x = 0;
+ m_textOffset.y = 0;
+ }
+
+ if (m_stateImages[state]) {
+ SetImage(m_stateImages[state]);
+ }
+
+ m_buttonState = state;
+}
+
void
UIElementButton::OnClick()
{
diff --git a/screenlib/UIElementButton.h b/screenlib/UIElementButton.h
index 62d65ac5..6f578342 100644
--- a/screenlib/UIElementButton.h
+++ b/screenlib/UIElementButton.h
@@ -35,8 +35,19 @@ DECLARE_TYPESAFE_CLASS(UIElement)
override bool Load(rapidxml::xml_node<> *node, const UITemplates *templates);
override bool HandleEvent(const SDL_Event &event);
+ override void OnMouseDown();
+ override void OnMouseUp();
protected:
+ enum BUTTON_STATE {
+ BUTTON_STATE_NORMAL,
+ BUTTON_STATE_PRESSED,
+ BUTTON_STATE_DISABLED,
+ NUM_BUTTON_STATES
+ };
+ void SetButtonState(BUTTON_STATE state);
+
+ override void UpdateDisabledState();
override void OnClick();
bool ShouldHandleKey(SDL_Keycode key);
@@ -46,6 +57,8 @@ DECLARE_TYPESAFE_CLASS(UIElement)
int m_hotkeyMod;
int m_clickSound;
char *m_clickPanel;
+ BUTTON_STATE m_buttonState;
+ UITexture *m_stateImages[NUM_BUTTON_STATES];
};
#endif // _UIElementButton_h
diff --git a/screenlib/UITexture.cpp b/screenlib/UITexture.cpp
index d11d2b84..2c3a1d20 100644
--- a/screenlib/UITexture.cpp
+++ b/screenlib/UITexture.cpp
@@ -29,4 +29,5 @@ UITexture::UITexture(SDL_Texture *texture, float scale)
m_texture = texture;
m_scale = scale;
SDL_QueryTexture(texture, NULL, NULL, &m_textureWidth, &m_textureHeight);
+ m_locked = false;
}
diff --git a/screenlib/UITexture.h b/screenlib/UITexture.h
index c23aba9e..f37adfdd 100644
--- a/screenlib/UITexture.h
+++ b/screenlib/UITexture.h
@@ -57,11 +57,20 @@ class UITexture
m_scale = scale;
}
+ // When a texture is locked it shouldn't be freed
+ void SetLocked(bool locked) {
+ m_locked = locked;
+ }
+ bool IsLocked() const {
+ return m_locked;
+ }
+
protected:
SDL_Texture *m_texture;
int m_textureWidth;
int m_textureHeight;
float m_scale;
+ bool m_locked;
};
#endif // _UITexture_h