FifeGUI 0.3.0
A C++ GUI library designed for games.
statusbar.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later OR BSD-3-Clause
2// SPDX-FileCopyrightText: 2026 Fifengine contributors
3
4// Corresponding header include
5#include "fifechan/widgets/statusbar.hpp"
6
7// Standard library includes
8#include <cassert>
9#include <cstdio>
10#include <memory>
11#include <string>
12
13// Project headers
14#include "fifechan/font.hpp"
15#include "fifechan/graphics.hpp"
16
17namespace fcn
18{
19
21 {
22 setHeight(24);
23 setLayout(LayoutPolicy::Horizontal);
24
25 setExpandChildren(false);
26
27 // Create internal 3 areas:
28 // 1. icon (fixed)
29 // 2. left (flexible)
30 // 3. right (fixed)
31 mIconArea = std::make_unique<Container>();
32 mIconArea->setLayout(Container::LayoutPolicy::Horizontal);
33 mIconArea->setOpaque(false);
34 mIconArea->setWidth(24);
35 mIconArea->setHeight(24);
36 add(mIconArea.get());
37
38 mLeftArea = std::make_unique<Container>();
39 mLeftArea->setLayout(Container::LayoutPolicy::Horizontal);
40 mLeftArea->setOpaque(false);
41 add(mLeftArea.get());
42
43 mRightArea = std::make_unique<Container>();
44 mRightArea->setLayout(Container::LayoutPolicy::Horizontal);
45 mRightArea->setOpaque(false);
46 mRightArea->setWidth(100);
47 add(mRightArea.get());
48 }
49
50 void StatusBar::setText(std::string const & text)
51 {
52 mText = text;
53 }
54
55 std::string const & StatusBar::getText() const
56 {
57 return mText;
58 }
59
60 void StatusBar::draw(Graphics* graphics)
61 {
62 assert("graphics must not be null" && graphics != nullptr);
63
64 HorizontalBar::draw(graphics);
65
66 // Draw border/top line
67 if (isOpaque()) {
68 graphics->setColor(getForegroundColor());
69 graphics->drawLine(0, 0, getWidth(), 0);
70 }
71
72 std::string textToDraw = mText;
73
74 // Fixed widths
75 int const iconAreaWidth = 24;
76 int const rightAreaWidth = 100;
77 int const textPadding = 4;
78
79 // Get text width if we have text
80 int textWidth = 0;
81 Font* font = getFont();
82 if (!mText.empty() && font != nullptr) {
83 textWidth = font->getWidth(mText);
84 }
85
86 // Calculate minimum width needed
87 // iconArea (24) + rightArea (100) + text (with padding) = 128 + textWidth
88 int const minimumWidth = iconAreaWidth + rightAreaWidth + textWidth + textPadding;
89 int const currentWidth = getWidth();
90
91 // Apply shrink priority logic if enabled
92 if (mShrinkPriorityEnabled && currentWidth < minimumWidth) {
93 // First, calculate how much space is available for text after fixed areas
94 int const availableForText = currentWidth - iconAreaWidth - rightAreaWidth - textPadding;
95
96 // If there's still not enough space, truncate the text
97 if (availableForText < textWidth && availableForText > 0) {
98 if (mTruncateWithEllipsis && availableForText > 3) {
99 // Calculate how many characters fit, accounting for "..."
100 int const ellipsisWidth = font != nullptr ? font->getWidth("...") : 15;
101 int const availableForTextContent = availableForText - ellipsisWidth;
102
103 if (availableForTextContent > 0) {
104 // Find characters that fit
105 int charWidth = 0;
106 int charsToShow = 0;
107 for (size_t i = 0; i < mText.size(); ++i) {
108 charWidth += font != nullptr ? font->getWidth(std::string(1, mText.at(i))) : 8;
109 if (charWidth > availableForTextContent) {
110 break;
111 }
112 charsToShow = static_cast<int>(i) + 1;
113 }
114 textToDraw = mText.substr(0, charsToShow) + "...";
115 } else {
116 // Not even ellipsis fits, show just "..."
117 textToDraw = "...";
118 }
119 } else if (!mTruncateWithEllipsis) {
120 // Truncate without ellipsis
121 int charWidth = 0;
122 int charsToShow = 0;
123 for (size_t i = 0; i < mText.size(); ++i) {
124 charWidth += font != nullptr ? font->getWidth(std::string(1, mText.at(i))) : 8;
125 if (charWidth > availableForText) {
126 break;
127 }
128 charsToShow = static_cast<int>(i) + 1;
129 }
130 textToDraw = mText.substr(0, charsToShow);
131 }
132 }
133 // If availableForText <= 0, text won't be drawn (no space left)
134 }
135
136 // Draw text
137 if (!textToDraw.empty()) {
138
139 // Do we have a font?
140 if (font != nullptr) {
141 graphics->setFont(font);
142
143 // Vertically center text similar to other widgets
144 int const textY =
145 getPaddingTop() + ((getHeight() - getPaddingTop() - getPaddingBottom() - font->getHeight()) / 2);
146
147 // Clip text to avoid overlapping icon/right areas
148 Rectangle const clipArea(
149 textPadding + iconAreaWidth,
151 getWidth() - (iconAreaWidth + rightAreaWidth + (2 * textPadding)),
152 getHeight() - 1);
153
154 graphics->pushClipArea(clipArea);
155 graphics->setColor(getForegroundColor());
156 graphics->drawText(textToDraw, textPadding, textY, Graphics::Alignment::Left);
157 graphics->popClipArea();
158 }
159 // TODO should we use a fallback font?
160 // If no font is available, skip drawing text to avoid exceptions
161 }
162 }
163
165 {
166 return mIconArea.get();
167 }
168
170 {
171 return mLeftArea.get();
172 }
173
175 {
176 return mRightArea.get();
177 }
178
180 {
181 mShrinkPriorityEnabled = enabled;
182 }
183
185 {
186 return mShrinkPriorityEnabled;
187 }
188
190 {
191 mTruncateWithEllipsis = enabled;
192 }
193
195 {
196 return mTruncateWithEllipsis;
197 }
198} // namespace fcn
A composite widget capable of holding and managing child widgets.
Definition container.hpp:36
virtual void setLayout(LayoutPolicy policy)
Sets the layout of the container.
virtual bool isOpaque() const
Checks if the container is opaque or not.
Definition container.cpp:88
virtual void add(Widget *widget)
Adds a widget to the container.
Definition container.cpp:93
Abstract interface for font rendering.
Definition font.hpp:26
Abstract interface providing primitive drawing functions (lines, rectangles, etc.).
Definition graphics.hpp:58
virtual void popClipArea()
Removes the top most clip area from the stack.
Definition graphics.cpp:65
void drawText(std::string const &text, int x, int y)
Draws text with a default left alignment.
Definition graphics.hpp:401
virtual bool pushClipArea(Rectangle area)
Pushes a clip area onto the stack.
Definition graphics.cpp:25
virtual void setFont(Font *font)
Sets the font to use when drawing text.
Definition graphics.cpp:91
virtual void drawLine(int x1, int y1, int x2, int y2)=0
Draws a line.
virtual void setColor(Color const &color)=0
Sets the color to use when drawing.
void draw(Graphics *graphics) override
Draws the widget.
void setExpandChildren(bool expand)
Sets whether children should expand to fill available width.
Represents a rectangular area (X, Y, Width, Height).
Definition rectangle.hpp:22
StatusBar()
Constructor.
Definition statusbar.cpp:20
void draw(Graphics *graphics) override
Draws the status bar.
Definition statusbar.cpp:60
bool isShrinkPriorityEnabled() const
Checks if shrink priority handling is enabled.
bool isTruncateWithEllipsis() const
Checks if truncation with ellipsis is enabled.
std::string const & getText() const
Gets the status text.
Definition statusbar.cpp:55
Container * getLeftArea() const
Access to the left (flexible) area.
Container * getIconArea() const
Access to the icon area (fixed size, left).
void setShrinkPriorityEnabled(bool enabled)
Enables or disables shrink priority handling.
void setTruncateWithEllipsis(bool enabled)
Enables or disables truncation with ellipsis.
Container * getRightArea() const
Access to the right (fixed) area.
void setText(std::string const &text)
Sets the status text.
Definition statusbar.cpp:50
int getWidth() const
Gets the width of the widget.
Definition widget.cpp:252
unsigned int getPaddingTop() const
Gets the top padding.
Definition widget.cpp:574
unsigned int getPaddingBottom() const
Gets the bottom padding.
Definition widget.cpp:594
Color const & getForegroundColor() const
Gets the foreground color.
Definition widget.cpp:752
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
virtual void setHeight(int height)
Sets the height of the widget.
Definition widget.cpp:257
Used replacement tokens by configure_file():