FifeGUI 0.2.0
A C++ GUI library designed for games.
container.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#include "fifechan/widgets/container.hpp"
6
7#include <algorithm>
8#include <list>
9#include <set>
10#include <string>
11
12#include "fifechan/exception.hpp"
13#include "fifechan/graphics.hpp"
14#include "fifechan/math.hpp"
15
16namespace fcn
17{
18 Container::Container() = default;
19
20 Container::~Container() = default;
21
22 void Container::draw(Graphics* graphics)
23 {
24 bool const active = isFocused();
25 if (isOpaque()) {
26 if (active &&
27 ((getSelectionMode() & Widget::SelectionMode::Background) == Widget::SelectionMode::Background)) {
28 graphics->setColor(getSelectionColor());
29 } else {
30 graphics->setColor(getBaseColor());
31 }
32 graphics->fillRectangle(
35 getWidth() - (2 * getBorderSize()),
36 getHeight() - (2 * getBorderSize()));
37 }
38 if (mBackgroundWidget != nullptr) {
39 Rectangle const rec(
42 getWidth() - (2 * getBorderSize()),
43 getHeight() - (2 * getBorderSize()));
44 mBackgroundWidget->setDimension(rec);
45 mBackgroundWidget->_draw(graphics);
46 }
47 if (getBorderSize() > 0) {
48 if (active && (getSelectionMode() & Widget::SelectionMode::Border) == Widget::SelectionMode::Border) {
49 drawSelectionFrame(graphics);
50 } else {
51 drawBorder(graphics);
52 }
53 }
54 }
55
56 void Container::setOpaque(bool opaque)
57 {
58 mOpaque = opaque;
59 }
60
62 {
63 return mOpaque;
64 }
65
66 void Container::add(Widget* widget)
67 {
68 Widget::add(widget);
70 }
71
72 void Container::addWidget(std::unique_ptr<Widget> widget)
73 {
74 if (widget == nullptr) {
75 return;
76 }
77
78 Widget* rawWidget = widget.release();
79 add(rawWidget);
80 }
81
82 void Container::add(Widget* widget, int x, int y)
83 {
84 widget->setPosition(x, y);
85 Widget::add(widget);
87 }
88
89 void Container::addWidget(std::unique_ptr<Widget> widget, int x, int y)
90 {
91 if (widget == nullptr) {
92 return;
93 }
94
95 Widget* rawWidget = widget.release();
96 add(rawWidget, x, y);
97 }
98
100 {
101 Widget::remove(widget);
103 }
104
109
110 Widget* Container::findWidgetById(std::string const & id)
111 {
112 return Widget::findWidgetById(id);
113 }
114
116 {
117 mContainerListeners.push_back(containerListener);
118 }
119
121 {
122 mContainerListeners.remove(containerListener);
123 }
124
126 {
128
129 for (iter = mContainerListeners.begin(); iter != mContainerListeners.end(); ++iter) {
130 ContainerEvent const event(source, this);
131 (*iter)->widgetAdded(event);
132 }
133 }
134
136 {
138
139 for (iter = mContainerListeners.begin(); iter != mContainerListeners.end(); ++iter) {
140 ContainerEvent const event(source, this);
141 (*iter)->widgetRemoved(event);
142 }
143 }
144
145 Widget* Container::getChild(unsigned int index) const
146 {
147 if (index >= getChildrenCount()) {
148 return nullptr;
149 }
150
151 auto const & children = getChildren();
152 auto iter = children.begin();
153 for (unsigned int i = 0; i < index; ++i) {
154 ++iter;
155 }
156
157 return *iter;
158 }
159
160 void Container::resizeToContent(bool recursion)
161 {
162 if (mLayout == LayoutPolicy::Absolute) {
163 if (recursion) {
164 std::list<Widget*>::const_iterator currChild(mChildren.begin());
165 std::list<Widget*>::const_iterator const endChildren(mChildren.end());
166 for (; currChild != endChildren; ++currChild) {
167 if (!(*currChild)->isVisible()) {
168 continue;
169 }
170 (*currChild)->resizeToContent(recursion);
171 }
172 }
173 return;
174 }
175
176 int childMaxW = 0;
177 int childMaxH = 0;
178 int layoutMaxW = 0;
179 int layoutMaxH = 0;
180 int totalW = 0;
181 int totalH = 0;
182 int visibleChilds = 0;
183
184 std::list<Widget*>::const_iterator currChild(mChildren.begin());
185 std::list<Widget*>::const_iterator endChildren(mChildren.end());
186 for (; currChild != endChildren; ++currChild) {
187 if (!(*currChild)->isVisible()) {
188 continue;
189 }
190 if (recursion) {
191 (*currChild)->resizeToContent(recursion);
192 }
193 Rectangle const & rec = (*currChild)->getDimension();
194 childMaxW = std::max(childMaxW, rec.width);
195 childMaxH = std::max(childMaxH, rec.height);
196 layoutMaxW =
197 std::max(layoutMaxW, rec.width + (*currChild)->getMarginLeft() + (*currChild)->getMarginRight());
198 layoutMaxH =
199 std::max(layoutMaxH, rec.height + (*currChild)->getMarginTop() + (*currChild)->getMarginBottom());
200 ++visibleChilds;
201 }
202
203 // diff means border, padding, ...
204 int const diffW = getDimension().width - getChildrenArea().width;
205 int const diffH = getDimension().height - getChildrenArea().height;
206 Rectangle dimensions(0, 0, childMaxW, childMaxH);
207
208 if (mLayout == LayoutPolicy::AutoSize && visibleChilds > 0) {
209 currChild = mChildren.begin();
210 endChildren = mChildren.end();
211 for (; currChild != endChildren; ++currChild) {
212 if (!(*currChild)->isVisible()) {
213 continue;
214 }
215 Rectangle const & rec = (*currChild)->getDimension();
216 int const childW = rec.x + rec.width + (*currChild)->getMarginLeft() + (*currChild)->getMarginRight();
217 int const childH = rec.y + rec.height + (*currChild)->getMarginTop() + (*currChild)->getMarginBottom();
218 totalW = std::max(totalW, childW);
219 totalH = std::max(totalH, childH);
220 }
221 totalW += diffW;
222 totalH += diffH;
223 } else if (mLayout == LayoutPolicy::Vertical && visibleChilds > 0) {
224 currChild = mChildren.begin();
225 endChildren = mChildren.end();
226 for (; currChild != endChildren; ++currChild) {
227 if (!(*currChild)->isVisible()) {
228 continue;
229 }
230 dimensions.x = (*currChild)->getMarginLeft();
231 dimensions.y += (*currChild)->getMarginTop();
232 int const layoutW = (*currChild)->getWidth() + (*currChild)->getMarginLeft() +
233 ((*currChild)->getMarginRight() > 0 ? (*currChild)->getMarginRight() : 0);
234 dimensions.width = (*currChild)->getWidth() + (layoutMaxW - layoutW);
235 dimensions.height = (*currChild)->getHeight();
236 (*currChild)->setDimension(dimensions);
237 dimensions.y += (*currChild)->getHeight() + (*currChild)->getMarginBottom() + getVerticalSpacing();
238 }
239 // remove last spacing
240 dimensions.y -= getVerticalSpacing();
241 totalW = std::max(layoutMaxW, childMaxW) + diffW;
242 totalH = dimensions.y + diffH;
243 } else if (mLayout == LayoutPolicy::Horizontal && visibleChilds > 0) {
244 currChild = mChildren.begin();
245 endChildren = mChildren.end();
246 for (; currChild != endChildren; ++currChild) {
247 if (!(*currChild)->isVisible()) {
248 continue;
249 }
250 dimensions.x += (*currChild)->getMarginLeft();
251 dimensions.y = (*currChild)->getMarginTop();
252 dimensions.width = (*currChild)->getWidth();
253 int const layoutH = (*currChild)->getHeight() + (*currChild)->getMarginTop() +
254 ((*currChild)->getMarginBottom() > 0 ? (*currChild)->getMarginBottom() : 0);
255 dimensions.height = (*currChild)->getHeight() + (layoutMaxH - layoutH);
256 (*currChild)->setDimension(dimensions);
257 dimensions.x += (*currChild)->getWidth() + (*currChild)->getMarginRight() + getHorizontalSpacing();
258 }
259 // remove last spacing
260 dimensions.x -= getHorizontalSpacing();
261 totalW = dimensions.x + diffW;
262 totalH = std::max(layoutMaxH, childMaxH) + diffH;
263 } else if (mLayout == LayoutPolicy::Circular && visibleChilds > 0) {
264 float const angle = 360.0F / visibleChilds;
265 auto const xRadius = static_cast<float>((childMaxW * 2) + getHorizontalSpacing());
266 auto const yRadius = static_cast<float>((childMaxH * 2) + getVerticalSpacing());
267 currChild = mChildren.begin();
268 endChildren = mChildren.end();
269 int w = 0;
270 int h = 0;
271 int i = 0;
272 int minW = 50000;
273 int minH = 50000;
274 int maxW = -50000;
275 int maxH = -50000;
276 for (; currChild != endChildren; ++currChild) {
277 if (!(*currChild)->isVisible()) {
278 continue;
279 }
280 float const tmpAngle =
281 static_cast<float>(static_cast<int>((angle * i) + 270) % 360) / (180.0F / Mathf::pi());
282 int const x = static_cast<int>(
283 (xRadius * std::cos(tmpAngle)) - (static_cast<float>((*currChild)->getWidth()) / 2.0F));
284 int const y = static_cast<int>(
285 (yRadius * std::sin(tmpAngle)) - (static_cast<float>((*currChild)->getHeight()) / 2.0F));
286 minW = std::min(minW, x);
287 maxW = std::max(maxW, x + (*currChild)->getWidth());
288 minH = std::min(minH, y);
289 maxH = std::max(maxH, y + (*currChild)->getHeight());
290
291 (*currChild)->setPosition(x, y);
292 ++i;
293 }
294
295 w = std::abs(minW) + std::abs(maxW);
296 h = std::abs(minH) + std::abs(maxH);
297
298 int const centerX = w / 2;
299 int const centerY = h / 2;
300
301 currChild = mChildren.begin();
302 endChildren = mChildren.end();
303 for (; currChild != endChildren; ++currChild) {
304 if (!(*currChild)->isVisible()) {
305 continue;
306 }
307 int const x = (*currChild)->getX() + centerX;
308 int const y = (*currChild)->getY() + centerY;
309
310 (*currChild)->setPosition(x, y);
311 }
312
313 totalW = w + diffW;
314 totalH = h + diffH;
315 }
316
317 setSize(totalW, totalH);
318 }
319
321 {
323 int const w = getWidth() + (2 * getBorderSize()) + getPaddingLeft() + getPaddingRight();
324 int const h = getHeight() + (2 * getBorderSize()) + getPaddingTop() + getPaddingBottom();
325 setSize(w, h);
326 }
327
328 // TODO(jakoch): This is a very complex method. It should be refactored.
329 void Container::expandContent(bool recursion)
330 {
331 if (mLayout == LayoutPolicy::Absolute) {
332 if (recursion) {
333 std::list<Widget*>::const_iterator currChild(mChildren.begin());
334 std::list<Widget*>::const_iterator const endChildren(mChildren.end());
335 for (; currChild != endChildren; ++currChild) {
336 if (!(*currChild)->isVisible()) {
337 continue;
338 }
339 (*currChild)->expandContent(recursion);
340 }
341 }
342 return;
343 }
344
345 if (mLayout == LayoutPolicy::AutoSize) {
346 return;
347 }
348
349 Rectangle const childrenArea = getChildrenArea();
350 int const spaceW = childrenArea.width;
351 int const spaceH = childrenArea.height;
352 int neededSpaceW = 0;
353 int neededSpaceH = 0;
354 int maxMinW = 0;
355 int maxMinH = 0;
356 int minMaxW = 50000;
357 int minMaxH = 50000;
358 int maxHExpander = 0;
359 int maxVExpander = 0;
360 int expanderNeededSpaceW = 0;
361 int expanderNeededSpaceH = 0;
362 unsigned int visibleChilds = 0;
363 std::list<Widget*> hExpander;
364 std::list<Widget*> vExpander;
365
366 std::list<Widget*>::const_iterator currChild(mChildren.begin());
367 std::list<Widget*>::const_iterator endChildren(mChildren.end());
368 for (; currChild != endChildren; ++currChild) {
369 if (!(*currChild)->isVisible()) {
370 continue;
371 }
372 ++visibleChilds;
373 // get needed space
374 neededSpaceW += (*currChild)->getWidth() + (*currChild)->getMarginLeft() + (*currChild)->getMarginRight() +
376 neededSpaceH += (*currChild)->getHeight() + (*currChild)->getMarginTop() + (*currChild)->getMarginBottom() +
378 // get expander and expander max/min size
379 if ((*currChild)->isVerticalExpand()) {
380 maxVExpander = std::max(maxVExpander, (*currChild)->getHeight());
381 maxMinH = std::max(maxMinH, (*currChild)->getMinSize().getHeight());
382 minMaxH = std::min(minMaxH, (*currChild)->getMaxSize().getHeight());
383 expanderNeededSpaceH += (*currChild)->getHeight() + getVerticalSpacing();
384 vExpander.push_back((*currChild));
385 }
386 if ((*currChild)->isHorizontalExpand()) {
387 maxHExpander = std::max(maxHExpander, (*currChild)->getWidth());
388 maxMinW = std::max(maxMinW, (*currChild)->getMinSize().getWidth());
389 minMaxW = std::min(minMaxW, (*currChild)->getMaxSize().getWidth());
390 expanderNeededSpaceW += (*currChild)->getWidth() + getHorizontalSpacing();
391 hExpander.push_back((*currChild));
392 }
393 }
394
395 if (mLayout == LayoutPolicy::Vertical && visibleChilds > 0) {
396 bool const hexpand = isHorizontalExpand() && (getParent() == nullptr);
397 neededSpaceH -= getVerticalSpacing();
398 int freeSpace = spaceH - neededSpaceH;
399 if (freeSpace > 0) {
400 if (!vExpander.empty()) {
401 expanderNeededSpaceH -= getVerticalSpacing();
402 }
403 if (mUniform) {
404 // check against the smallest maximal height
405 maxVExpander = std::min(minMaxH, maxVExpander);
406 // check against the largest minimal height
407 maxVExpander = std::max(maxMinH, maxVExpander);
408 int h = 0;
409 // calculate maximal height if all expanders get this max height
410 int const maxNeeded =
411 ((maxVExpander + getVerticalSpacing()) * vExpander.size()) - getVerticalSpacing();
412 int const tmpSpace = (freeSpace + expanderNeededSpaceH) - maxNeeded;
413 if (tmpSpace > 0) {
414 h = maxVExpander;
415 freeSpace = tmpSpace;
416 }
417 // distribute space
418 if (freeSpace > 0 || h > 0) {
419
420 auto it = vExpander.begin();
421
422 int expanders = vExpander.size();
423
424 for (; it != vExpander.end(); ++it) {
425 int const layoutH = (*it)->getHeight() + (*it)->getMarginTop() +
426 ((*it)->getMarginBottom() > 0 ? (*it)->getMarginBottom() : 0);
427 // divide the space so that all expanders get the same size
428 int const diff = h > 0 ? 0 : (*it)->getHeight() + (maxVExpander - layoutH);
429 int delta = ((freeSpace - diff) / expanders) + diff;
430 if (delta == 0) {
431 delta = 1;
432 }
433 delta = std::min(delta, freeSpace);
434 int const oldH = h > 0 ? h : (*it)->getHeight();
435 int tmpH = oldH + delta;
436 (*it)->setHeight(tmpH);
437 tmpH = (*it)->getHeight();
438 delta = tmpH - oldH;
439 freeSpace -= delta;
440 --expanders;
441 }
442 }
443
444 } else {
445 if (!vExpander.empty()) {
446 // simply add one to each expander until free space is empty
447 // or all expanders reached the max height
448 std::set<Widget*> maxExpanders;
449 while ((freeSpace != 0) && maxExpanders.size() < vExpander.size()) {
450 auto it = vExpander.begin();
451 for (; it != vExpander.end(); ++it) {
452 int const h = (*it)->getHeight();
453 (*it)->setHeight(h + 1);
454 if (h != (*it)->getHeight()) {
455 --freeSpace;
456 if (freeSpace == 0) {
457 break;
458 }
459 } else {
460 maxExpanders.insert(*it);
461 }
462 }
463 }
464 }
465 }
466 }
467 // adapt position
468 if (!hExpander.empty() || !vExpander.empty() || hexpand) {
469 Rectangle rec(0, 0, spaceW, 0);
470 currChild = mChildren.begin();
471 endChildren = mChildren.end();
472 for (; currChild != endChildren; ++currChild) {
473 if (!(*currChild)->isVisible()) {
474 continue;
475 }
476 if (hexpand || (*currChild)->isHorizontalExpand()) {
477 int const layoutW = (*currChild)->getMarginLeft() +
478 ((*currChild)->getMarginRight() > 0 ? (*currChild)->getMarginRight() : 0);
479 rec.width = spaceW - layoutW;
480 } else {
481 rec.width = (*currChild)->getWidth();
482 }
483 rec.x = (*currChild)->getMarginLeft();
484 rec.y += (*currChild)->getMarginTop();
485 rec.height = (*currChild)->getHeight();
486 (*currChild)->setDimension(rec);
487 rec.y += rec.height + (*currChild)->getMarginBottom() + getVerticalSpacing();
488 }
489 }
490 } else if (mLayout == LayoutPolicy::Horizontal && visibleChilds > 0) {
491 bool const vexpand = isVerticalExpand() || (getParent() == nullptr);
492 neededSpaceW -= getHorizontalSpacing();
493 int freeSpace = spaceW - neededSpaceW;
494 if (freeSpace > 0) {
495 if (mUniform) {
496 if (!hExpander.empty()) {
497 expanderNeededSpaceW -= getHorizontalSpacing();
498 }
499 // check against the smallest maximal width
500 maxHExpander = std::min(minMaxW, maxHExpander);
501 // check against the largest minimal width
502 maxHExpander = std::max(maxMinW, maxHExpander);
503 int w = 0;
504 // calculate maximal width if all expanders get this max width
505 int const maxNeeded =
506 ((maxHExpander + getHorizontalSpacing()) * hExpander.size()) - getHorizontalSpacing();
507 int const tmpSpace = (freeSpace + expanderNeededSpaceW) - maxNeeded;
508 if (tmpSpace > 0) {
509 w = maxHExpander;
510 freeSpace = tmpSpace;
511 }
512 // distribute space
513 if (freeSpace > 0 || w > 0) {
514 auto it = hExpander.begin();
515 int expanders = hExpander.size();
516 for (; it != hExpander.end(); ++it) {
517 // divide the space so that all expanders get the same size
518 int const layoutW = (*it)->getWidth() + (*it)->getMarginLeft() +
519 ((*it)->getMarginRight() > 0 ? (*it)->getMarginRight() : 0);
520 int const diff = w > 0 ? 0 : (*it)->getWidth() + (maxHExpander - layoutW);
521 int delta = ((freeSpace - diff) / expanders) + diff;
522 if (delta == 0) {
523 delta = 1;
524 }
525 delta = std::min(delta, freeSpace);
526 int const oldW = w > 0 ? w : (*it)->getWidth();
527 int tmpW = oldW + delta;
528 (*it)->setWidth(tmpW);
529 tmpW = (*it)->getWidth();
530 delta = tmpW - oldW;
531 freeSpace -= delta;
532 --expanders;
533 }
534 }
535 } else {
536 if (!hExpander.empty()) {
537 // simply add one to each expander until free space is empty
538 // or all expanders reached the max width
539 std::set<Widget*> maxExpanders;
540 while ((freeSpace != 0) && maxExpanders.size() < hExpander.size()) {
541 auto it = hExpander.begin();
542 for (; it != hExpander.end(); ++it) {
543 int const w = (*it)->getWidth();
544 (*it)->setWidth(w + 1);
545 if (w != (*it)->getWidth()) {
546 --freeSpace;
547 if (freeSpace == 0) {
548 break;
549 }
550 } else {
551 maxExpanders.insert(*it);
552 }
553 }
554 }
555 }
556 }
557 }
558 // adapt position
559 if (!hExpander.empty() || !vExpander.empty() || vexpand) {
560 Rectangle rec(0, 0, 0, spaceH);
561 currChild = mChildren.begin();
562 endChildren = mChildren.end();
563 for (; currChild != endChildren; ++currChild) {
564 if (!(*currChild)->isVisible()) {
565 continue;
566 }
567 if (vexpand || (*currChild)->isVerticalExpand()) {
568 int const layoutH = (*currChild)->getMarginTop() +
569 ((*currChild)->getMarginBottom() > 0 ? (*currChild)->getMarginBottom() : 0);
570 rec.height = spaceH - layoutH;
571 } else {
572 rec.height = (*currChild)->getHeight();
573 }
574 rec.x += (*currChild)->getMarginLeft();
575 rec.y = (*currChild)->getMarginTop();
576 rec.width = (*currChild)->getWidth();
577 (*currChild)->setDimension(rec);
578 rec.x += rec.width + (*currChild)->getMarginRight() + getHorizontalSpacing();
579 }
580 }
581 } else if (mLayout == LayoutPolicy::Circular && visibleChilds > 0) {
582 float const angle = 360.0F / visibleChilds;
583 int childMaxW = 0;
584 int childMaxH = 0;
585 currChild = mChildren.begin();
586 endChildren = mChildren.end();
587 for (; currChild != endChildren; ++currChild) {
588 if (!(*currChild)->isVisible()) {
589 continue;
590 }
591 childMaxW = std::max(childMaxW, (*currChild)->getWidth());
592 childMaxH = std::max(childMaxH, (*currChild)->getHeight());
593 }
594 // childMaxW += getHorizontalSpacing();
595 // childMaxH += getVerticalSpacing();
596 float xRadius = (spaceW - childMaxW) / 2.0F;
597 float yRadius = (spaceH - childMaxH) / 2.0F;
598 float const centerX = spaceW / 2.0F;
599 float const centerY = spaceH / 2.0F;
600 if (xRadius < 1) {
601 xRadius = static_cast<float>(childMaxW);
602 }
603 if (yRadius < 1) {
604 yRadius = static_cast<float>(childMaxH);
605 }
606 // this forces a uniform circle
607 // xRadius = std::max(xRadius, yRadius);
608 // yRadius = xRadius;
609 int i = 0;
610 currChild = mChildren.begin();
611 endChildren = mChildren.end();
612 for (; currChild != endChildren; ++currChild) {
613 if (!(*currChild)->isVisible()) {
614 continue;
615 }
616 float const tmpAngle =
617 static_cast<float>(static_cast<int>((angle * i) + 270) % 360) / (180.0F / Mathf::pi());
618 int x = static_cast<int>(centerX + (xRadius * std::cos(tmpAngle)));
619 int y = static_cast<int>(centerY + (yRadius * std::sin(tmpAngle)));
620 x -= (*currChild)->getWidth() / 2;
621 y -= (*currChild)->getHeight() / 2;
622
623 (*currChild)->setPosition(x, y);
624 ++i;
625 }
626 }
627
628 if (recursion) {
629 currChild = mChildren.begin();
630 endChildren = mChildren.end();
631 for (; currChild != endChildren; ++currChild) {
632 if (!(*currChild)->isVisible()) {
633 continue;
634 }
635 (*currChild)->expandContent(recursion);
636 }
637 }
638 }
639
641 {
642 mLayout = policy;
643 }
644
646 {
647 return mLayout;
648 }
649
650 void Container::setUniformSize(bool uniform)
651 {
652 mUniform = uniform;
653 }
654
656 {
657 return mUniform;
658 }
659
661 {
662 Rectangle rec;
663 rec.x = getBorderSize() + getPaddingLeft();
664 rec.y = getBorderSize() + getPaddingTop();
667 return rec;
668 }
669
670 void Container::setVerticalSpacing(unsigned int spacing)
671 {
672 mVerticalSpacing = spacing;
673 }
674
675 unsigned int Container::getVerticalSpacing() const
676 {
677 return mVerticalSpacing;
678 }
679
680 void Container::setHorizontalSpacing(unsigned int spacing)
681 {
682 mHorizontalSpacing = spacing;
683 }
684
686 {
687 return mHorizontalSpacing;
688 }
689
691 {
692 if (mBackgroundWidget == widget) {
693 return;
694 }
695
696 mBackgroundWidget = widget;
697 }
698
703} // namespace fcn
Represents changes within a container (e.g., widget added/removed).
Interface for listening to container modification events.
virtual bool isUniformSize() const
True if the container tries to expand the childs to a uniform size.
void remove(Widget *widget) override
Removes a widget from the Container.
Definition container.cpp:99
void draw(Graphics *graphics) override
Draws the widget.
Definition container.cpp:22
bool mOpaque
True if the container is opaque, false otherwise.
virtual void setLayout(LayoutPolicy policy)
Sets the layout of the container.
virtual void setHorizontalSpacing(unsigned int spacing)
Set the horizontal spacing between columns.
void addContainerListener(ContainerListener *containerListener)
Adds a container listener to the container.
Container()
Constructor.
unsigned int mVerticalSpacing
VerticalSpacing.
void distributeWidgetAddedEvent(Widget *source)
Distributes a widget added container event to all container listeners of the container.
LayoutPolicy mLayout
Layout.
unsigned int mHorizontalSpacing
HorizontalSpacing.
Widget * mBackgroundWidget
Optional widget that is rendered behind other children as the container background.
void expandContent()
Expands the child widgets to the size of this widget, calls recursively all childs.
Definition widget.hpp:1440
Widget * findWidgetById(std::string const &id) override
Finds a widget given an id.
virtual bool isOpaque() const
Checks if the container is opaque or not.
Definition container.cpp:61
void distributeWidgetRemovedEvent(Widget *source)
Distributes a widget removed container event to all container listeners of the container.
void setBackgroundWidget(Widget *widget)
Set a widget that will be rendered behind other children as the background.
virtual void add(Widget *widget)
Adds a widget to the container.
Definition container.cpp:66
LayoutPolicy
The layout policy of the container.
Definition container.hpp:38
void resizeToContent()
Resizes the widget's size to fit the content exactly, calls recursively all childs.
Definition widget.hpp:1417
ContainerListenerList::iterator ContainerListenerIterator
Typedef.
void removeAllChildren() override
Removes all widgets from the the container.
Rectangle getChildrenArea() override
Gets the area of the widget occupied by the widget's children.
virtual void setVerticalSpacing(unsigned int spacing)
Set the vertical spacing between rows.
virtual void addWidget(std::unique_ptr< Widget > widget)
Adds a widget to the container, transferring ownership.
Definition container.cpp:72
bool mUniform
Indicates if the childs should be expanded to a uniform size.
Widget * getBackgroundWidget()
Get the background widget if one is set.
virtual void setUniformSize(bool uniform)
If enabled, the free space is distributed in a way that the size of the childrens will be equal (if p...
virtual LayoutPolicy getLayout() const
Gets the layout of the container.
void removeContainerListener(ContainerListener *containerListener)
Removes a container listener from the container.
virtual unsigned int getHorizontalSpacing() const
Get the horizontal spacing between rows.
void adjustSize() override
Adjust the size of the container after layout computations.
Widget * getChild(unsigned int index) const
Gets child by index.
ContainerListenerList mContainerListeners
The container listeners of the container.
virtual void setOpaque(bool opaque)
Sets the container to be opaque or not.
Definition container.cpp:56
virtual unsigned int getVerticalSpacing() const
Get the vertical spacing between rows.
Abstract interface providing primitive drawing functions (lines, rectangles, etc.).
Definition graphics.hpp:57
virtual void setColor(Color const &color)=0
Sets the color to use when drawing.
virtual void fillRectangle(Rectangle const &rectangle)=0
Draws a filled rectangle.
static num_type pi()
Definition math.hpp:263
Represents a rectangular area (X, Y, Width, Height).
Definition rectangle.hpp:20
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.
Color const & getBaseColor() const
Gets the base color.
Definition widget.cpp:596
std::list< Widget * > const & getChildren() const
Gets the children of the widget.
Definition widget.cpp:1415
bool isHorizontalExpand() const
Gets if widget is horizontal expandable.
Definition widget.cpp:347
unsigned int getChildrenCount() const
Gets how many childs the widget have.
Definition widget.cpp:247
int getWidth() const
Gets the width of the widget.
Definition widget.cpp:170
virtual Widget * getParent() const
Gets the widget's parent container.
Definition widget.cpp:157
void add(Widget *widget)
Adds a child to the widget.
Definition widget.cpp:1272
void resizeToChildren()
Resizes the widget to fit it's children exactly.
Definition widget.cpp:1170
virtual Widget * findWidgetById(std::string const &id)
Finds a widget by id.
Definition widget.cpp:1184
virtual void remove(Widget *widget)
Removes a specific child from the widget.
Definition widget.cpp:1248
virtual bool isFocused() const
Checks if the widget is focused.
Definition widget.cpp:497
virtual void removeAllChildren()
Remvoes all children from the widget.
Definition widget.cpp:1228
unsigned int getPaddingLeft() const
Gets the left padding.
Definition widget.cpp:477
Widget()
Constructor.
Definition widget.cpp:36
void setSize(int width, int height)
Sets the size of the widget.
Definition widget.cpp:855
void setPosition(int x, int y)
Sets position of the widget.
Definition widget.cpp:214
Rectangle const & getDimension() const
Gets the dimension of the widget.
Definition widget.cpp:482
virtual void drawBorder(Graphics *graphics)
Called when a widget have a border.
Definition widget.cpp:111
unsigned int getPaddingTop() const
Gets the top padding.
Definition widget.cpp:447
unsigned int getBorderSize() const
Gets the size of the widget's border.
Definition widget.cpp:381
virtual void drawSelectionFrame(Graphics *graphics)
Called when a widget is "active" and the selection mode is Frame or FrameWithBackground.
Definition widget.cpp:135
std::list< Widget * > mChildren
Holds all children of the widget.
Definition widget.hpp:1842
unsigned int getPaddingBottom() const
Gets the bottom padding.
Definition widget.cpp:467
SelectionMode getSelectionMode() const
Gets the selection mode.
Definition widget.cpp:656
int getHeight() const
Gets the height of the widget.
Definition widget.cpp:183
unsigned int getPaddingRight() const
Gets the right padding.
Definition widget.cpp:457
Color const & getSelectionColor() const
Gets the selection color.
Definition widget.cpp:626
bool isVerticalExpand() const
Gets if widget is vertical expandable.
Definition widget.cpp:337