FifeGUI 0.2.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 <cstdio>
9#include <memory>
10#include <string>
11
12// Project headers
13#include "fifechan/font.hpp"
14#include "fifechan/graphics.hpp"
15
16namespace fcn
17{
18
20 {
21 setHeight(24);
22 setLayout(LayoutPolicy::Horizontal);
23
24 setExpandChildren(false);
25
26 // Create internal 3 areas:
27 // 1. icon (fixed)
28 // 2. left (flexible)
29 // 3. right (fixed)
30 mIconArea = std::make_unique<Container>();
31 mIconArea->setLayout(Container::LayoutPolicy::Horizontal);
32 mIconArea->setOpaque(false);
33 mIconArea->setWidth(24);
34 mIconArea->setHeight(24);
35 add(mIconArea.get());
36
37 mLeftArea = std::make_unique<Container>();
38 mLeftArea->setLayout(Container::LayoutPolicy::Horizontal);
39 mLeftArea->setOpaque(false);
40 add(mLeftArea.get());
41
42 mRightArea = std::make_unique<Container>();
43 mRightArea->setLayout(Container::LayoutPolicy::Horizontal);
44 mRightArea->setOpaque(false);
45 mRightArea->setWidth(100);
46 add(mRightArea.get());
47 }
48
49 void StatusBar::setText(std::string const & text)
50 {
51 mText = text;
52 }
53
54 std::string const & StatusBar::getText() const
55 {
56 return mText;
57 }
58
59 void StatusBar::draw(Graphics* graphics)
60 {
61 Container::draw(graphics);
62
63 // Draw border/top line
64 if (isOpaque()) {
65 graphics->setColor(getForegroundColor());
66 graphics->drawLine(0, 0, getWidth(), 0);
67 }
68
69 std::string textToDraw = mText;
70
71 // Fixed widths
72 int const iconAreaWidth = 24;
73 int const rightAreaWidth = 100;
74 int const textPadding = 4;
75
76 // Get text width if we have text
77 int textWidth = 0;
78 Font* font = getFont();
79 if (!mText.empty() && font != nullptr) {
80 textWidth = font->getWidth(mText);
81 }
82
83 // Calculate minimum width needed
84 // iconArea (24) + rightArea (100) + text (with padding) = 128 + textWidth
85 int const minimumWidth = iconAreaWidth + rightAreaWidth + textWidth + textPadding;
86 int const currentWidth = getWidth();
87
88 // Apply shrink priority logic if enabled
89 if (mShrinkPriorityEnabled && currentWidth < minimumWidth) {
90 // First, calculate how much space is available for text after fixed areas
91 int const availableForText = currentWidth - iconAreaWidth - rightAreaWidth - textPadding;
92
93 // If there's still not enough space, truncate the text
94 if (availableForText < textWidth && availableForText > 0) {
95 if (mTruncateWithEllipsis && availableForText > 3) {
96 // Calculate how many characters fit, accounting for "..."
97 int const ellipsisWidth = font != nullptr ? font->getWidth("...") : 15;
98 int const availableForTextContent = availableForText - ellipsisWidth;
99
100 if (availableForTextContent > 0) {
101 // Find characters that fit
102 int charWidth = 0;
103 int charsToShow = 0;
104 for (size_t i = 0; i < mText.size(); ++i) {
105 charWidth += font != nullptr ? font->getWidth(std::string(1, mText.at(i))) : 8;
106 if (charWidth > availableForTextContent) {
107 break;
108 }
109 charsToShow = static_cast<int>(i) + 1;
110 }
111 textToDraw = mText.substr(0, charsToShow) + "...";
112 } else {
113 // Not even ellipsis fits, show just "..."
114 textToDraw = "...";
115 }
116 } else if (!mTruncateWithEllipsis) {
117 // Truncate without ellipsis
118 int charWidth = 0;
119 int charsToShow = 0;
120 for (size_t i = 0; i < mText.size(); ++i) {
121 charWidth += font != nullptr ? font->getWidth(std::string(1, mText.at(i))) : 8;
122 if (charWidth > availableForText) {
123 break;
124 }
125 charsToShow = static_cast<int>(i) + 1;
126 }
127 textToDraw = mText.substr(0, charsToShow);
128 }
129 }
130 // If availableForText <= 0, text won't be drawn (no space left)
131 }
132
133 // Draw text
134 if (!textToDraw.empty()) {
135
136 // Do we have a font?
137 if (font != nullptr) {
138 graphics->setFont(font);
139
140 // Vertically center text similar to other widgets
141 int const textY =
142 getPaddingTop() + ((getHeight() - getPaddingTop() - getPaddingBottom() - font->getHeight()) / 2);
143
144 // Clip text to avoid overlapping icon/right areas
145 Rectangle const clipArea(
146 textPadding + iconAreaWidth,
148 getWidth() - (iconAreaWidth + rightAreaWidth + (2 * textPadding)),
149 getHeight() - 1);
150
151 graphics->pushClipArea(clipArea);
152 graphics->setColor(getForegroundColor());
153 graphics->drawText(textToDraw, textPadding, textY, Graphics::Alignment::Left);
154 graphics->popClipArea();
155 }
156 // TODO should we use a fallback font?
157 // If no font is available, skip drawing text to avoid exceptions
158 }
159 }
160
162 {
163 return mIconArea.get();
164 }
165
167 {
168 return mLeftArea.get();
169 }
170
172 {
173 return mRightArea.get();
174 }
175
177 {
178 mShrinkPriorityEnabled = enabled;
179 }
180
182 {
183 return mShrinkPriorityEnabled;
184 }
185
187 {
188 mTruncateWithEllipsis = enabled;
189 }
190
192 {
193 return mTruncateWithEllipsis;
194 }
195} // namespace fcn
A composite widget capable of holding and managing child widgets.
Definition container.hpp:36
void draw(Graphics *graphics) override
Draws the widget.
Definition container.cpp:25
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:87
virtual void add(Widget *widget)
Adds a widget to the container.
Definition container.cpp:92
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 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:19
void draw(Graphics *graphics) override
Draws the status bar.
Definition statusbar.cpp:59
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:54
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:49
int getWidth() const
Gets the width of the widget.
Definition widget.cpp:251
unsigned int getPaddingTop() const
Gets the top padding.
Definition widget.cpp:573
unsigned int getPaddingBottom() const
Gets the bottom padding.
Definition widget.cpp:593
Color const & getForegroundColor() const
Gets the foreground color.
Definition widget.cpp:751
Font * getFont() const
Gets the font set for the widget.
Definition widget.cpp:999
int getHeight() const
Gets the height of the widget.
Definition widget.cpp:264
virtual void setHeight(int height)
Sets the height of the widget.
Definition widget.cpp:256
Used replacement tokens by configure_file():