diff options
author | Yohann Ferreira <yohann_dot_ferreira_at_orange_dot_efer> | 2011-06-16 18:07:46 +0200 |
---|---|---|
committer | Yohann Ferreira <yohann_dot_ferreira_at_orange_dot_efer> | 2011-06-16 19:13:27 +0200 |
commit | c8fb331e7506e4b2616f8bb30809adeb9f348615 (patch) | |
tree | 9e66a473316bf56554a6216f8fcd68a4b662937b | |
parent | be64806b1f8f3da2459771e268fd839ee04aa7ba (diff) | |
download | mana-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.cpp | 155 | ||||
-rw-r--r-- | src/gui/widgets/button.h | 24 |
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 |