summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYohann Ferreira <yohann_dot_ferreira_at_orange_dot_efer>2011-06-16 18:07:46 +0200
committerYohann Ferreira <yohann_dot_ferreira_at_orange_dot_efer>2011-06-16 19:13:27 +0200
commitc8fb331e7506e4b2616f8bb30809adeb9f348615 (patch)
tree9e66a473316bf56554a6216f8fcd68a4b662937b
parentbe64806b1f8f3da2459771e268fd839ee04aa7ba (diff)
downloadmana-c8fb331e7506e4b2616f8bb30809adeb9f348615.tar.gz
mana-c8fb331e7506e4b2616f8bb30809adeb9f348615.tar.bz2
mana-c8fb331e7506e4b2616f8bb30809adeb9f348615.tar.xz
mana-c8fb331e7506e4b2616f8bb30809adeb9f348615.zip
Added image support to the button widgets.
Resolves: Mana-mantis #96. Reviewed-by: Crush. Note that the option to set the image position next to the text is still needed and will be handled in another issue.
-rw-r--r--src/gui/widgets/button.cpp155
-rw-r--r--src/gui/widgets/button.h24
2 files changed, 156 insertions, 23 deletions
diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp
index 3d3a07c2..edf9e590 100644
--- a/src/gui/widgets/button.cpp
+++ b/src/gui/widgets/button.cpp
@@ -36,6 +36,7 @@
int Button::mInstances = 0;
float Button::mAlpha = 1.0;
+ImageRect *Button::mButton;
enum{
BUTTON_STANDARD, // 0
@@ -59,22 +60,74 @@ static ButtonData const data[BUTTON_COUNT] = {
{ "button_disabled.png", 25, 23 }
};
-ImageRect Button::button[BUTTON_COUNT];
-
-Button::Button()
+Button::Button():
+ mButtonIcon(0)
{
init();
+ adjustSize();
}
Button::Button(const std::string &caption, const std::string &actionEventId,
gcn::ActionListener *listener):
- gcn::Button(caption)
+ gcn::Button(caption),
+ mButtonIcon(0)
{
init();
setActionEventId(actionEventId);
if (listener)
addActionListener(listener);
+
+ adjustSize();
+}
+
+void Button::setButtonIcon(const std::string& iconFile, int frameHeight,
+ int frameWidth)
+{
+ // We clean up possible older references.
+ if (mButtonIcon)
+ removeButtonIcon();
+
+ // If nothing relevant was set, we can quit now.
+ if (iconFile.empty() || !frameWidth || !frameHeight)
+ return;
+
+ // Load the icon frames.
+ Image *btnIcons = Theme::getImageFromTheme(iconFile);
+ if (!btnIcons)
+ return;
+
+ if (btnIcons->getWidth() > 0 && btnIcons->getHeight() > 0)
+ {
+ mButtonIcon = new Image*[BUTTON_COUNT];
+ for (int mode = 0; mode < BUTTON_COUNT; ++mode)
+ {
+ mButtonIcon[mode] = btnIcons->getSubImage(mode * frameWidth
+ + (mode ? 1 : 0), 0,
+ frameWidth, frameHeight);
+ }
+
+ adjustSize();
+ }
+
+ btnIcons->decRef();
+}
+
+void Button::removeButtonIcon()
+{
+ if (!mButtonIcon)
+ return;
+
+ // Delete potential button icons
+ for (int mode = 0; mode < BUTTON_COUNT; ++mode)
+ {
+ delete mButtonIcon[mode];
+ mButtonIcon[mode] = 0;
+ }
+ delete[] mButtonIcon;
+ mButtonIcon = 0;
+
+ adjustSize();
}
void Button::init()
@@ -85,10 +138,11 @@ void Button::init()
{
// Load the skin
Image *btn[BUTTON_COUNT];
+ mButton = new ImageRect[BUTTON_COUNT];
int a, x, y, mode;
- for (mode = 0; mode < BUTTON_COUNT; mode++)
+ for (mode = 0; mode < BUTTON_COUNT; ++mode)
{
btn[mode] = Theme::getImageFromTheme(data[mode].file);
a = 0;
@@ -96,7 +150,7 @@ void Button::init()
{
for (x = 0; x < 3; x++)
{
- button[mode].grid[a] = btn[mode]->getSubImage(
+ mButton[mode].grid[a] = btn[mode]->getSubImage(
data[x].gridX, data[y].gridY,
data[x + 1].gridX - data[x].gridX + 1,
data[y + 1].gridY - data[y].gridY + 1);
@@ -116,11 +170,14 @@ Button::~Button()
if (mInstances == 0)
{
- for (int mode = 0; mode < BUTTON_COUNT; mode++)
+ for (int mode = 0; mode < BUTTON_COUNT; ++mode)
{
- for_each(button[mode].grid, button[mode].grid + 9, dtor<Image*>());
+ for_each(mButton[mode].grid, mButton[mode].grid + 9,
+ dtor<Image*>());
}
+ delete[] mButton;
}
+ removeButtonIcon();
}
void Button::updateAlpha()
@@ -131,12 +188,10 @@ void Button::updateAlpha()
if (mAlpha != alpha)
{
mAlpha = alpha;
- for (int a = 0; a < 9; a++)
+ for (int mode = 0; mode < BUTTON_COUNT; ++mode)
{
- button[BUTTON_DISABLED].grid[a]->setAlpha(mAlpha);
- button[BUTTON_PRESSED].grid[a]->setAlpha(mAlpha);
- button[BUTTON_HIGHLIGHTED].grid[a]->setAlpha(mAlpha);
- button[BUTTON_STANDARD].grid[a]->setAlpha(mAlpha);
+ for (int a = 0; a < 9; ++a)
+ mButton[mode].grid[a]->setAlpha(mAlpha);
}
}
}
@@ -157,35 +212,93 @@ void Button::draw(gcn::Graphics *graphics)
updateAlpha();
static_cast<Graphics*>(graphics)->
- drawImageRect(0, 0, getWidth(), getHeight(), button[mode]);
+ drawImageRect(0, 0, getWidth(), getHeight(), mButton[mode]);
if (mode == BUTTON_DISABLED)
graphics->setColor(Theme::getThemeColor(Theme::BUTTON_DISABLED));
else
graphics->setColor(Theme::getThemeColor(Theme::BUTTON));
- int textX;
+ int textX = 0;
int textY = getHeight() / 2 - getFont()->getHeight() / 2;
+ int btnIconX = 0;
+ int btnIconY = getHeight() / 2
+ - ((mButtonIcon && mButtonIcon[mode]) ?
+ mButtonIcon[mode]->getHeight() / 2 : 0);
+
+ int btnIconWidth = (mButtonIcon && mButtonIcon[mode]) ?
+ mButtonIcon[mode]->getWidth() : 0;
switch (getAlignment())
{
case gcn::Graphics::LEFT:
- textX = 4;
+ if (btnIconWidth)
+ {
+ btnIconX = 4;
+ textX = btnIconX + mButtonIcon[mode]->getWidth() + 2;
+ }
+ else
+ {
+ textX = 4;
+ }
break;
case gcn::Graphics::CENTER:
- textX = getWidth() / 2;
+ if (btnIconWidth)
+ {
+ btnIconX = getWidth() / 2 - (getFont()->getWidth(mCaption)
+ + mButtonIcon[mode]->getWidth() + 2) / 2;
+ textX = getWidth() / 2 + mButtonIcon[mode]->getWidth() / 2 + 2;
+ }
+ else
+ {
+ textX = getWidth() / 2;
+ }
break;
case gcn::Graphics::RIGHT:
+ if (btnIconWidth)
+ btnIconX = getWidth() - 4 - getFont()->getWidth(mCaption) - 2;
textX = getWidth() - 4;
break;
default:
- throw GCN_EXCEPTION("Button::draw. Unknown alignment.");
+ throw GCN_EXCEPTION("Button::draw(). Unknown alignment.");
}
graphics->setFont(getFont());
if (isPressed())
- graphics->drawText(getCaption(), textX + 1, textY + 1, getAlignment());
- else
- graphics->drawText(getCaption(), textX, textY, getAlignment());
+ {
+ textX++; textY++;
+ btnIconX++; btnIconY++;
+ }
+
+ if (btnIconWidth)
+ static_cast<Graphics*>(graphics)->drawImage(mButtonIcon[mode],
+ btnIconX, btnIconY);
+ graphics->drawText(getCaption(), textX, textY, getAlignment());
+}
+
+void Button::adjustSize()
+{
+ // Size of the image button.
+ int iconWidth = 0, iconHeight = 0;
+ if (mButtonIcon)
+ {
+ for (int mode = 0; mode < BUTTON_COUNT; ++mode)
+ {
+ iconWidth = std::max(iconWidth, mButtonIcon[mode] ?
+ mButtonIcon[mode]->getWidth() + 2 : 0);
+ iconHeight = std::max(iconHeight, mButtonIcon[mode] ?
+ mButtonIcon[mode]->getHeight() : 0);
+ }
+ }
+
+ setWidth(std::max(getFont()->getWidth(mCaption) + iconWidth + 2, iconWidth)
+ + 2 * mSpacing);
+ setHeight(std::max(getFont()->getHeight(), iconHeight) + 2 * mSpacing);
+}
+
+void Button::setCaption(const std::string& caption)
+{
+ mCaption = caption;
+ adjustSize();
}
diff --git a/src/gui/widgets/button.h b/src/gui/widgets/button.h
index b750d9bb..6d8f773c 100644
--- a/src/gui/widgets/button.h
+++ b/src/gui/widgets/button.h
@@ -25,6 +25,7 @@
#include <guichan/widgets/button.hpp>
class ImageRect;
+class Image;
/**
* Button widget. Same as the Guichan button but with custom look.
@@ -58,12 +59,31 @@ class Button : public gcn::Button
*/
void updateAlpha();
+ void adjustSize();
+
+ void setCaption(const std::string& caption);
+
+ /**
+ * Set the icons available next to the text
+ *
+ * @note: The image given must be formatted to give horizontally
+ * frames of the given width and height for the following states:
+ * Standard, Highlighted, Pressed, and Disabled.
+ * If the image is too short, the missing states won't be loaded.
+ */
+ void setButtonIcon(const std::string& iconFile = std::string(),
+ int frameHeight = 0, int frameWidth = 0);
+
private:
void init();
- static ImageRect button[4]; /**< Button state graphics */
- static int mInstances; /**< Number of button instances */
+ void removeButtonIcon();
+
+ static ImageRect* mButton; /**< Button state graphics */
+ static int mInstances; /**< Number of button instances */
static float mAlpha;
+
+ Image** mButtonIcon; /**< Button Icons graphics */
};
#endif