FifeGUI 0.3.0
A C++ GUI library designed for games.
label.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later OR BSD-3-Clause
2// SPDX-FileCopyrightText: 2004 - 2008 Olof Naessén and Per Larsson
3// SPDX-FileCopyrightText: 2013 - 2026 Fifengine contributors
4
5// Corresponding header include
6#include "fifechan/widgets/label.hpp"
7
8// Standard library includes
9#include <algorithm>
10#include <numeric>
11#include <string>
12#include <utility>
13#include <vector>
14
15// Project headers (subdirs before local)
16#include "fifechan/exception.hpp"
17#include "fifechan/font.hpp"
18#include "fifechan/graphics.hpp"
19
20namespace fcn
21{
22 Label::Label()
23 {
25 }
26
27 Label::Label(std::string caption) : mCaption(std::move(caption))
28 {
30 }
31
32 std::string const & Label::getCaption() const
33 {
34 return mCaption;
35 }
36
37 void Label::setCaption(std::string const & caption)
38 {
39 mCaption = caption;
41 }
42
44 {
45 mAlignment = alignment;
46 }
47
52
57
62
63 void Label::resizeToContent(bool recursion)
64 {
65 (void)recursion; // unused parameter
66
68 }
69
71 {
73 }
74
76 {
77 // Support multi-line captions by measuring each line separately.
78 std::vector<std::string> lines;
79 {
80 std::string::size_type start = 0;
81 while (start <= mCaption.size()) {
82 auto pos = mCaption.find('\n', start);
83 if (pos == std::string::npos) {
84 lines.push_back(mCaption.substr(start));
85 break;
86 }
87 lines.push_back(mCaption.substr(start, pos - start));
88 start = pos + 1;
89 }
90 }
91
92 int const maxWidth = std::accumulate(lines.begin(), lines.end(), 0, [&](int acc, std::string const & line) {
93 return std::max(acc, getFont()->getWidth(line));
94 });
95
96 int const lineCount = static_cast<int>(lines.size());
97 int const totalHeight = lineCount * getFont()->getHeight();
98
99 setSize(
100 (2 * getBorderSize()) + getPaddingLeft() + getPaddingRight() + maxWidth,
101 (2 * getBorderSize()) + getPaddingTop() + getPaddingBottom() + totalHeight);
102 }
103
104 void Label::draw(Graphics* graphics)
105 {
106 // draw border or frame
107 if (getBorderSize() > 0) {
108 if (isFocused() && (getSelectionMode() & Widget::SelectionMode::Border) == Widget::SelectionMode::Border) {
109 drawSelectionFrame(graphics);
110 } else {
111 drawBorder(graphics);
112 }
113 }
114
115 Rectangle const offsetRec(getBorderSize(), getBorderSize(), 2 * getBorderSize(), 2 * getBorderSize());
116
117 int const contentLeft = offsetRec.x + getPaddingLeft();
118 int const contentRight = getWidth() - offsetRec.x - getPaddingRight();
119 int const contentTop = offsetRec.y + getPaddingTop();
120 int const contentBottom = getHeight() - offsetRec.y - getPaddingBottom();
121
122 int const contentWidth = contentRight - contentLeft;
123 int const contentHeight = contentBottom - contentTop;
124
125 int const fontHeight = getFont()->getHeight();
126
127 // Count lines to compute total text block height for proper vertical alignment
128 int const lineCount = static_cast<int>(std::count(getCaption().begin(), getCaption().end(), '\n')) + 1;
129 int const totalTextHeight = lineCount * fontHeight;
130
131 int textX = 0;
132 int textY = 0;
133
134 // Vertical alignment
135 switch (mVerticalAlignment) {
136 case Graphics::VerticalAlignment::Top:
137 textY = contentTop;
138 break;
139 case Graphics::VerticalAlignment::Center:
140 textY = contentTop + ((contentHeight - totalTextHeight) / 2);
141 break;
142 case Graphics::VerticalAlignment::Bottom:
143 textY = contentBottom - totalTextHeight;
144 break;
145 default:
146 throwException("Unknown vertical alignment.");
147 }
148
149 // Horizontal alignment
150 switch (getAlignment()) {
151 case Graphics::Alignment::Left:
152 textX = contentLeft;
153 break;
154 case Graphics::Alignment::Center:
155 textX = contentLeft + (contentWidth / 2);
156 break;
157 case Graphics::Alignment::Right:
158 textX = contentRight;
159 break;
160 default:
161 throwException("Unknown alignment.");
162 }
163
164 graphics->setFont(getFont());
165 graphics->setColor(getForegroundColor());
166
167 // Draw multi-line caption by splitting on '\n' and drawing each line with font height spacing.
168 std::string::size_type start = 0;
169 int lineIndex = 0;
170 int const fontHeightLocal = getFont()->getHeight();
171 while (start <= getCaption().size()) {
172 auto pos = getCaption().find('\n', start);
173 std::string line;
174 if (pos == std::string::npos) {
175 line = getCaption().substr(start);
176 start = getCaption().size() + 1; // exit
177 } else {
178 line = getCaption().substr(start, pos - start);
179 start = pos + 1;
180 }
181
182 int const y = textY + (lineIndex * fontHeightLocal);
183
184 // For center/right alignment, Graphics::drawText uses alignment to offset x accordingly.
185 graphics->drawText(line, textX, y, getAlignment());
186
187 ++lineIndex;
188 }
189 }
190} // namespace fcn
virtual int getHeight() const =0
Gets the height of the glyphs in the font.
Abstract interface providing primitive drawing functions (lines, rectangles, etc.).
Definition graphics.hpp:58
VerticalAlignment
Vertical alignments for text drawing.
Definition graphics.hpp:74
Alignment
Horizontal alignments for text drawing.
Definition graphics.hpp:64
void drawText(std::string const &text, int x, int y)
Draws text with a default left alignment.
Definition graphics.hpp:401
virtual void setFont(Font *font)
Sets the font to use when drawing text.
Definition graphics.cpp:91
virtual void setColor(Color const &color)=0
Sets the color to use when drawing.
void draw(Graphics *graphics) override
Draws the widget.
Definition label.cpp:104
void setVerticalAlignment(Graphics::VerticalAlignment alignment)
Sets the vertical alignment of the caption.
Definition label.cpp:53
void setAlignment(Graphics::Alignment alignment)
Sets the alignment of the caption.
Definition label.cpp:43
void adjustSize() override
Resizes the widget's size to fit the content exactly.
Definition label.cpp:70
void resizeToContent(bool recursion=true) override
Resizes the widget's size to fit the content exactly, calls recursively all childs.
Definition label.cpp:63
std::string const & getCaption() const
Gets the caption of the label.
Definition label.cpp:32
Graphics::Alignment getAlignment() const
Gets the alignment of the caption.
Definition label.cpp:48
void setCaption(std::string const &caption)
Sets the caption of the label.
Definition label.cpp:37
Graphics::Alignment mAlignment
Holds the horizontal alignment of the caption.
Definition label.hpp:122
std::string mCaption
Holds the caption of the label.
Definition label.hpp:117
Graphics::VerticalAlignment mVerticalAlignment
Holds the vertical alignment of the caption.
Definition label.hpp:127
Graphics::VerticalAlignment getVerticalAlignment() const
Gets the vertical alignment of the caption.
Definition label.cpp:58
void adjustSizeImpl()
Adjusts the size of the label to fit the caption.
Definition label.cpp:75
Represents a rectangular area (X, Y, Width, Height).
Definition rectangle.hpp:22
int y
Holds the x coordinate of the rectangle.
int x
Holds the x coordinate of the rectangle.
int getWidth() const
Gets the width of the widget.
Definition widget.cpp:252
virtual bool isFocused() const
Checks if the widget is focused.
Definition widget.cpp:624
unsigned int getPaddingLeft() const
Gets the left padding.
Definition widget.cpp:604
virtual void setSize(int width, int height)
Sets the size of the widget.
Definition widget.cpp:1065
virtual void drawBorder(Graphics *graphics)
Called when a widget have a border.
Definition widget.cpp:156
unsigned int getPaddingTop() const
Gets the top padding.
Definition widget.cpp:574
unsigned int getBorderSize() const
Gets the size of the widget's border.
Definition widget.cpp:474
virtual void drawSelectionFrame(Graphics *graphics)
Called when a widget is "active" and the selection mode is Frame or FrameWithBackground.
Definition widget.cpp:217
unsigned int getPaddingBottom() const
Gets the bottom padding.
Definition widget.cpp:594
Color const & getForegroundColor() const
Gets the foreground color.
Definition widget.cpp:752
SelectionMode getSelectionMode() const
Gets the selection mode.
Definition widget.cpp:802
Font * getFont() const
Gets the font set for the widget.
Definition widget.cpp:1000
int getHeight() const
Gets the height of the widget.
Definition widget.cpp:265
unsigned int getPaddingRight() const
Gets the right padding.
Definition widget.cpp:584
Used replacement tokens by configure_file():
void throwException(std::string const &message, std::source_location location=std::source_location::current())
Throw an Exception capturing the current source location.