diff options
author | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2025-03-31 15:34:22 +0200 |
---|---|---|
committer | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2025-03-31 16:56:38 +0200 |
commit | 49beab3c3415d40d9a1d4326474d16547c4ae9ac (patch) | |
tree | 7065a4dcca9089e711eeba2ef4206cbcd955f80c /src/gui | |
parent | 83339662e47270f2b38e7430775090f409348ae2 (diff) | |
download | mana-49beab3c3415d40d9a1d4326474d16547c4ae9ac.tar.gz mana-49beab3c3415d40d9a1d4326474d16547c4ae9ac.tar.bz2 mana-49beab3c3415d40d9a1d4326474d16547c4ae9ac.tar.xz mana-49beab3c3415d40d9a1d4326474d16547c4ae9ac.zip |
GUI: Support customizing widget text format through theme
The following widgets now support setting the font, text color, outline
color and shadow color through the theme:
* Button
* Tab
* Window (title)
* ProgressBar
The text format can be specified differently per skin state.
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/widgets/button.cpp | 48 | ||||
-rw-r--r-- | src/gui/widgets/label.cpp | 35 | ||||
-rw-r--r-- | src/gui/widgets/label.h | 27 | ||||
-rw-r--r-- | src/gui/widgets/tab.cpp | 33 | ||||
-rw-r--r-- | src/gui/widgets/tab.h | 2 | ||||
-rw-r--r-- | src/gui/widgets/window.cpp | 32 |
6 files changed, 138 insertions, 39 deletions
diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp index 31fab2c4..31c3a677 100644 --- a/src/gui/widgets/button.cpp +++ b/src/gui/widgets/button.cpp @@ -28,6 +28,7 @@ #include "resources/image.h" #include "resources/theme.h" +#include "textrenderer.h" #include <guichan/exception.hpp> #include <guichan/font.hpp> @@ -125,33 +126,32 @@ void Button::init() void Button::draw(gcn::Graphics *graphics) { - WidgetState state(this); + WidgetState widgetState(this); if (mHasMouse) - state.flags |= STATE_HOVERED; + widgetState.flags |= STATE_HOVERED; if (isPressed()) - state.flags |= STATE_SELECTED; + widgetState.flags |= STATE_SELECTED; - gui->getTheme()->drawSkin(static_cast<Graphics *>(graphics), SkinType::Button, state); + auto &skin = gui->getTheme()->getSkin(SkinType::Button); + skin.draw(static_cast<Graphics *>(graphics), widgetState); + + auto skinState = skin.getState(widgetState.flags); + auto font = (skinState && skinState->textFormat.bold) ? boldFont : getFont(); int mode; - if (state.flags & STATE_DISABLED) + if (widgetState.flags & STATE_DISABLED) mode = BUTTON_DISABLED; - else if (state.flags & STATE_SELECTED) + else if (widgetState.flags & STATE_SELECTED) mode = BUTTON_PRESSED; - else if (state.flags & (STATE_HOVERED | STATE_FOCUSED)) + else if (widgetState.flags & (STATE_HOVERED | STATE_FOCUSED)) mode = BUTTON_HIGHLIGHTED; else mode = BUTTON_STANDARD; - if (mode == BUTTON_DISABLED) - graphics->setColor(Theme::getThemeColor(Theme::BUTTON_DISABLED)); - else - graphics->setColor(Theme::getThemeColor(Theme::BUTTON)); - Image *icon = mButtonIcon.empty() ? nullptr : mButtonIcon[mode].get(); int textX = 0; - int textY = getHeight() / 2 - getFont()->getHeight() / 2; + int textY = getHeight() / 2 - font->getHeight() / 2; int btnIconX = 0; int btnIconY = getHeight() / 2 - (icon ? icon->getHeight() / 2 : 0); int btnIconWidth = icon ? icon->getWidth() : 0; @@ -172,9 +172,8 @@ void Button::draw(gcn::Graphics *graphics) case gcn::Graphics::CENTER: if (btnIconWidth) { - btnIconX = getWidth() / 2 - (getFont()->getWidth(mCaption) - + icon->getWidth() + 2) / 2; - textX = getWidth() / 2 + icon->getWidth() / 2 + 2; + btnIconX = (getWidth() - font->getWidth(mCaption) - icon->getWidth() - 2) / 2; + textX = (getWidth() + icon->getWidth()) / 2 + 2; } else { @@ -183,15 +182,13 @@ void Button::draw(gcn::Graphics *graphics) break; case gcn::Graphics::RIGHT: if (btnIconWidth) - btnIconX = getWidth() - 4 - getFont()->getWidth(mCaption) - 2; + btnIconX = getWidth() - 4 - font->getWidth(mCaption) - 2; textX = getWidth() - 4; break; default: throw GCN_EXCEPTION("Button::draw(). Unknown alignment."); } - graphics->setFont(getFont()); - if (isPressed()) { textX++; textY++; @@ -200,7 +197,18 @@ void Button::draw(gcn::Graphics *graphics) if (btnIconWidth) static_cast<Graphics *>(graphics)->drawImage(icon, btnIconX, btnIconY); - graphics->drawText(getCaption(), textX, textY, getAlignment()); + + if (auto skinState = skin.getState(widgetState.flags)) + { + auto &textFormat = skinState->textFormat; + TextRenderer::renderText(static_cast<Graphics *>(graphics), + getCaption(), + textX, + textY, + getAlignment(), + font, + textFormat); + } } void Button::adjustSize() diff --git a/src/gui/widgets/label.cpp b/src/gui/widgets/label.cpp index af5220ef..53a82e14 100644 --- a/src/gui/widgets/label.cpp +++ b/src/gui/widgets/label.cpp @@ -21,8 +21,13 @@ #include "gui/widgets/label.h" +#include "textrenderer.h" + #include "resources/theme.h" +#include <guichan/exception.hpp> +#include <guichan/font.hpp> + Label::Label() { setForegroundColor(Theme::getThemeColor(Theme::TEXT)); @@ -36,5 +41,33 @@ Label::Label(const std::string &caption) : void Label::draw(gcn::Graphics *graphics) { - gcn::Label::draw(static_cast<gcn::Graphics*>(graphics)); + int textX; + int textY = getHeight() / 2 - getFont()->getHeight() / 2; + + switch (getAlignment()) + { + case Graphics::LEFT: + textX = 0; + break; + case Graphics::CENTER: + textX = getWidth() / 2; + break; + case Graphics::RIGHT: + textX = getWidth(); + break; + default: + throw GCN_EXCEPTION("Unknown alignment."); + } + + TextRenderer::renderText(static_cast<Graphics *>(graphics), + getCaption(), + textX, + textY, + getAlignment(), + getForegroundColor(), + getFont(), + mOutlineColor.has_value(), + mShadowColor.has_value(), + mOutlineColor, + mShadowColor); } diff --git a/src/gui/widgets/label.h b/src/gui/widgets/label.h index a383517f..85bcbe23 100644 --- a/src/gui/widgets/label.h +++ b/src/gui/widgets/label.h @@ -22,10 +22,11 @@ #pragma once #include <guichan/widgets/label.hpp> +#include <optional> /** * Label widget. Same as the Guichan label but modified to use the palette - * system. + * system and support outlines and shadows. * * \ingroup GUI */ @@ -41,7 +42,31 @@ class Label : public gcn::Label Label(const std::string &caption); /** + * Sets the color of the outline. + */ + void setOutlineColor(std::optional<gcn::Color> color); + + /** + * Sets the color of the shadow. + */ + void setShadowColor(std::optional<gcn::Color> color); + + /** * Draws the label. */ void draw(gcn::Graphics *graphics) override; + + private: + std::optional<gcn::Color> mOutlineColor; + std::optional<gcn::Color> mShadowColor; }; + +inline void Label::setOutlineColor(std::optional<gcn::Color> color) +{ + mOutlineColor = color; +} + +inline void Label::setShadowColor(std::optional<gcn::Color> color) +{ + mShadowColor = color; +} diff --git a/src/gui/widgets/tab.cpp b/src/gui/widgets/tab.cpp index 3bfa405f..b2779c4f 100644 --- a/src/gui/widgets/tab.cpp +++ b/src/gui/widgets/tab.cpp @@ -24,17 +24,22 @@ #include "graphics.h" #include "gui/gui.h" +#include "gui/widgets/label.h" #include "gui/widgets/tabbedarea.h" #include "resources/theme.h" #include <guichan/widgets/label.hpp> -Tab::Tab() : - mTabColor(&Theme::getThemeColor(Theme::TAB)) +Tab::Tab() { setFocusable(false); + // Replace the label with customized version + delete mLabel; + mLabel = new Label(); + add(mLabel); + auto &skin = gui->getTheme()->getSkin(SkinType::Tab); setFrameSize(skin.frameSize); mPadding = skin.padding; @@ -62,10 +67,26 @@ void Tab::draw(gcn::Graphics *graphics) if (mTabbedArea && mTabbedArea->isTabSelected(this)) mFlash = false; - if (mFlash) - mLabel->setForegroundColor(Theme::getThemeColor(Theme::TAB_FLASH)); - else - mLabel->setForegroundColor(*mTabColor); + uint8_t flags = 0; + if (mHasMouse) + flags |= STATE_HOVERED; + if (mTabbedArea && mTabbedArea->isTabSelected(this)) + flags |= STATE_SELECTED; + + auto &skin = gui->getTheme()->getSkin(SkinType::Tab); + if (auto state = skin.getState(flags)) + { + gcn::Color foregroundColor = state->textFormat.color; + if (mFlash) + foregroundColor = Theme::getThemeColor(Theme::TAB_FLASH); + else if (mTabColor) + foregroundColor = *mTabColor; + + auto label = static_cast<Label*>(mLabel); + label->setForegroundColor(foregroundColor); + label->setOutlineColor(state->textFormat.outlineColor); + label->setShadowColor(state->textFormat.shadowColor); + } // draw label drawChildren(graphics); diff --git a/src/gui/widgets/tab.h b/src/gui/widgets/tab.h index d67321c6..534abaff 100644 --- a/src/gui/widgets/tab.h +++ b/src/gui/widgets/tab.h @@ -66,7 +66,7 @@ class Tab : public gcn::Tab virtual void setCurrent() {} private: - const gcn::Color *mTabColor; + const gcn::Color *mTabColor = nullptr; bool mFlash = false; int mPadding = 8; }; diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp index 15267019..4a0b8286 100644 --- a/src/gui/widgets/window.cpp +++ b/src/gui/widgets/window.cpp @@ -23,6 +23,7 @@ #include "configuration.h" #include "log.h" +#include "textrenderer.h" #include "gui/gui.h" #include "gui/viewport.h" @@ -124,21 +125,26 @@ void Window::drawFrame(gcn::Graphics *graphics) auto g = static_cast<Graphics*>(graphics); auto theme = gui->getTheme(); - WidgetState state(this); - state.width += getFrameSize() * 2; - state.height += getFrameSize() * 2; + WidgetState widgetState(this); + widgetState.width += getFrameSize() * 2; + widgetState.height += getFrameSize() * 2; auto &skin = theme->getSkin(SkinType::Window); - skin.draw(g, state); + skin.draw(g, widgetState); if (mShowTitle) { - g->setColor(Theme::getThemeColor(Theme::TEXT)); - g->setFont(getFont()); - g->drawText(getCaption(), - getFrameSize() + skin.titleOffsetX, - getFrameSize() + skin.titleOffsetY, - gcn::Graphics::LEFT); + if (auto skinState = skin.getState(widgetState.flags)) + { + auto &textFormat = skinState->textFormat; + TextRenderer::renderText(g, + getCaption(), + getFrameSize() + skin.titleOffsetX, + getFrameSize() + skin.titleOffsetY, + gcn::Graphics::LEFT, + textFormat.bold ? boldFont : getFont(), + textFormat); + } } } @@ -686,6 +692,9 @@ int Window::getResizeHandles(gcn::MouseEvent &event) gcn::Rectangle Window::getCloseButtonRect() const { + if (!mCloseButton) + return {}; + auto theme = gui->getTheme(); auto &closeButtonSkin = theme->getSkin(SkinType::ButtonClose); @@ -702,6 +711,9 @@ gcn::Rectangle Window::getCloseButtonRect() const gcn::Rectangle Window::getStickyButtonRect() const { + if (!mStickyButton) + return {}; + auto theme = gui->getTheme(); auto &closeButtonSkin = theme->getSkin(SkinType::ButtonClose); |