summaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2025-03-31 15:34:22 +0200
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2025-03-31 16:56:38 +0200
commit49beab3c3415d40d9a1d4326474d16547c4ae9ac (patch)
tree7065a4dcca9089e711eeba2ef4206cbcd955f80c /src/gui
parent83339662e47270f2b38e7430775090f409348ae2 (diff)
downloadmana-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.cpp48
-rw-r--r--src/gui/widgets/label.cpp35
-rw-r--r--src/gui/widgets/label.h27
-rw-r--r--src/gui/widgets/tab.cpp33
-rw-r--r--src/gui/widgets/tab.h2
-rw-r--r--src/gui/widgets/window.cpp32
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);