FifeGUI 0.3.0
A C++ GUI library designed for games.
adjustingcontainer.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/adjustingcontainer.hpp"
7
8// Standard library includes
9#include <algorithm>
10#include <cassert>
11#include <numeric>
12#include <utility>
13
14// Project headers (subdirs before local)
15#include "fifechan/exception.hpp"
16
17namespace fcn
18{
19 AdjustingContainer::AdjustingContainer()
20 {
21 setPadding(0);
24 mColumnWidths.push_back(0);
25 mRowHeights.push_back(0);
26 mColumnAlignment.push_back(Alignment::Left);
27 }
28
29 AdjustingContainer::~AdjustingContainer() = default;
30
31 void AdjustingContainer::setNumberOfColumns(unsigned int numberOfColumns)
32 {
33 assert("number of columns must be positive" && numberOfColumns > 0);
34 mNumberOfColumns = numberOfColumns;
35
36 if (mColumnAlignment.size() < numberOfColumns) {
37 while (mColumnAlignment.size() < numberOfColumns) {
38 mColumnAlignment.push_back(Alignment::Left);
39 }
40 } else {
41 while (mColumnAlignment.size() > numberOfColumns) {
42 mColumnAlignment.pop_back();
43 }
44 }
45 }
46
48 {
49 return mNumberOfColumns;
50 }
51
52 void AdjustingContainer::setColumnAlignment(unsigned int column, Alignment alignment)
53 {
54 assert("column index out of range" && column < mColumnAlignment.size());
55 mColumnAlignment.at(column) = alignment;
56 }
57
59 {
60 if (column < mColumnAlignment.size()) {
61 return mColumnAlignment.at(column);
62 }
63 return Alignment::Left;
64 }
65
67 {
70 }
71
73 {
74 }
75
77 {
78 Rectangle rec;
79 rec.x = getBorderSize();
80 rec.y = getBorderSize();
81 rec.width = getWidth() - (2 * getBorderSize());
82 rec.height = getHeight() - (2 * getBorderSize());
83 return rec;
84 }
85
86 // void AdjustingContainer::logic()
87 //{
88 // Container::logic();
89 // adjustContent();
90 // }
91
93 {
94 Container::add(widget);
95 mContainedWidgets.push_back(widget);
96 }
97
98 void AdjustingContainer::add(Widget* widget, int /*x*/, int /*y*/)
99 {
100 add(widget);
101 }
102
108
110 {
111 assert("widget must not be null" && widget != nullptr);
112 Container::remove(widget);
113 auto it = std::ranges::find_if(mContainedWidgets, [widget](fcn::Widget const * w) {
114 return w == widget;
115 });
116 if (it != mContainedWidgets.end()) {
117 mContainedWidgets.erase(it);
118 }
119 }
120
122 {
123 assert("number of columns must be set" && mNumberOfColumns > 0);
124 // TODO(jakoch): is this calc correct?
126
127 mColumnWidths.clear();
128
129 unsigned int i = 0;
130
131 for (i = 0; i < mNumberOfColumns; i++) {
132 mColumnWidths.push_back(0);
133 }
134
135 mRowHeights.clear();
136
137 for (i = 0; i < mNumberOfRows; i++) {
138 mRowHeights.push_back(0);
139 }
140
141 for (i = 0; i < mNumberOfColumns; i++) {
142 unsigned int j = 0;
143 for (j = 0; j < mNumberOfRows && (mNumberOfColumns * j) + i < mContainedWidgets.size(); j++) {
144 if (std::cmp_greater(
145 mContainedWidgets.at((mNumberOfColumns * j) + i)->getWidth(), mColumnWidths.at(i))) {
146 mColumnWidths.at(i) = mContainedWidgets.at((mNumberOfColumns * j) + i)->getWidth();
147 }
148 if (std::cmp_greater(
149 mContainedWidgets.at((mNumberOfColumns * j) + i)->getHeight(), mRowHeights.at(j))) {
150 mRowHeights.at(j) = mContainedWidgets.at((mNumberOfColumns * j) + i)->getHeight();
151 }
152 }
153 }
154
155 // width calculation
157 mWidth += std::accumulate(mColumnWidths.begin(), mColumnWidths.end(), 0U);
161
162 // height calculation
164 mHeight += std::accumulate(mRowHeights.begin(), mRowHeights.end(), 0U);
168
170 setWidth(mWidth + (2 * getBorderSize()));
171 }
172
174 {
175 assert("column alignments must cover all columns" && mColumnAlignment.size() >= mNumberOfColumns);
176 adjustSize();
177
178 unsigned int columnCount = 0;
179 unsigned int rowCount = 0;
180 unsigned int y = mPaddingTop;
181
182 for (auto& mContainedWidget : mContainedWidgets) {
183
184 // calculate the x position of the widget
185 unsigned basex = 0;
186 if ((columnCount % mNumberOfColumns) != 0U) {
187 basex = mPaddingLeft;
188 basex += std::accumulate(mColumnWidths.begin(), mColumnWidths.begin() + columnCount, 0U);
189 basex += columnCount * mHorizontalSpacing;
190 } else {
191 basex = mPaddingLeft;
192 }
193
194 switch (mColumnAlignment.at(columnCount)) {
195 case Alignment::Left:
196 mContainedWidget->setX(basex);
197 break;
198 case Alignment::Center:
199 mContainedWidget->setX(basex + ((mColumnWidths.at(columnCount) - mContainedWidget->getWidth()) / 2));
200 break;
201 case Alignment::Right:
202 mContainedWidget->setX(basex + mColumnWidths.at(columnCount) - mContainedWidget->getWidth());
203 break;
204 default:
205 throwException("Unknown alignment.");
206 }
207
208 mContainedWidget->setY(y);
209 columnCount++;
210
211 if (columnCount == mNumberOfColumns) {
212 columnCount = 0;
213 y += mRowHeights.at(rowCount) + mVerticalSpacing;
214 rowCount++;
215 }
216 }
217 }
218} // namespace fcn
Alignment getColumnAlignment(unsigned int column) const
Get a specific column's alignment.
virtual void adjustContent()
Rearrange the widgets and resize the container.
unsigned int mNumberOfRows
Number of rows in the layout (derived from children count).
std::vector< Alignment > mColumnAlignment
The alignment of each column.
unsigned int mWidth
Cached container width used during layout.
std::vector< unsigned int > mColumnWidths
Computed width for each column (in pixels).
void adjustSize() override
Resizes the widget's size to fit the content exactly.
virtual void setNumberOfColumns(unsigned int numberOfColumns)
Set the number of columns to divide the widgets into.
virtual unsigned int getNumberOfColumns() const
Get the number of columns the widget is divided.
Rectangle getChildrenArea() override
Gets the area of the widget occupied by the widget's children.
virtual void setColumnAlignment(unsigned int column, Alignment alignment)
Set a specific column's alignment.
unsigned int mHeight
Cached container height used during layout.
void resizeToContent(bool recursion=true) override
Resize the adjusting container to fit its children.
std::vector< Widget * > mContainedWidgets
The widgets contained in the adjusting container in layout order.
unsigned int mNumberOfColumns
Number of columns in the layout.
void remove(Widget *widget) override
Removes a specific child from the widget.
Alignment
Possible alignment values for each column.
std::vector< unsigned int > mRowHeights
Computed height for each row (in pixels).
void removeAllChildren() override
Remvoes all children from the widget.
void add(Widget *widget) override
Adds a widget to the container.
void remove(Widget *widget) override
Removes a widget from the Container.
virtual void setHorizontalSpacing(unsigned int spacing)
Set the horizontal spacing between columns.
unsigned int mVerticalSpacing
VerticalSpacing.
unsigned int mHorizontalSpacing
HorizontalSpacing.
void resizeToContent(bool recursion=true) override
Resize this container to fit its children.
virtual void add(Widget *widget)
Adds a widget to the container.
Definition container.cpp:93
void removeAllChildren() override
Removes all widgets from the the container.
virtual void setVerticalSpacing(unsigned int spacing)
Set the vertical spacing between rows.
Represents a rectangular area (X, Y, Width, Height).
Definition rectangle.hpp:22
int width
Holds the width of the rectangle.
int y
Holds the x coordinate of the rectangle.
int x
Holds the x coordinate of the rectangle.
int height
Holds the height of the rectangle.
Abstract base class defining the common behavior, properties, and lifecycle of all GUI elements.
Definition widget.hpp:56
int getWidth() const
Gets the width of the widget.
Definition widget.cpp:252
unsigned int mPaddingTop
Holds the top padding of the widget.
Definition widget.hpp:1967
void expandContent()
Expands the child widgets to the size of this widget, calls recursively all childs.
Definition widget.hpp:1597
unsigned int mPaddingRight
Holds the right padding of the widget.
Definition widget.hpp:1972
virtual void setWidth(int width)
Sets the width of the widget.
Definition widget.cpp:244
unsigned int mPaddingBottom
Holds the bottom padding of the widget.
Definition widget.hpp:1977
unsigned int getBorderSize() const
Gets the size of the widget's border.
Definition widget.cpp:474
unsigned int mPaddingLeft
Holds the left padding of the widget.
Definition widget.hpp:1982
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
void setPadding(unsigned int padding)
Sets all 4 paddings to one value.
Definition widget.cpp:561
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.