FifeGUI 0.3.0
A C++ GUI library designed for games.
widget.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/widget.hpp"
7
8// Standard library includes
9#include <algorithm>
10#include <iostream>
11#include <list>
12#include <ranges>
13#include <string>
14#include <utility>
15
16// Project headers (subdirs before local)
17#include "fifechan/defaultfont.hpp"
18#include "fifechan/events/actionevent.hpp"
19#include "fifechan/events/dragevent.hpp"
20#include "fifechan/events/event.hpp"
21#include "fifechan/exception.hpp"
22#include "fifechan/focushandler.hpp"
23#include "fifechan/graphics.hpp"
24#include "fifechan/listeners/actionlistener.hpp"
25#include "fifechan/listeners/deathlistener.hpp"
26#include "fifechan/listeners/droptargetlistener.hpp"
27#include "fifechan/listeners/keylistener.hpp"
28#include "fifechan/listeners/mouselistener.hpp"
29#include "fifechan/listeners/visibilityeventhandler.hpp"
30#include "fifechan/listeners/widgetlistener.hpp"
31#include "fifechan/rectangle.hpp"
32#include "fifechan/size.hpp"
33
34namespace fcn
35{
36 namespace
37 {
38 std::list<Widget*>& widgetInstancesRegistry()
39 {
40 static std::list<Widget*> instances;
41 return instances;
42 }
43 } // namespace
44
45 Font* Widget::mGlobalFont = nullptr;
47 std::list<Widget*> Widget::mWidgetInstances;
51
53 {
54 widgetInstancesRegistry().push_back(this);
55 }
56
57 Widget::~Widget()
58 {
59 // We're in a destructor, we can't throw.
60 // We can only catch and print the error message.
61 try {
62
65 }
66
67 // Remove from Parent
68 if (mParent != nullptr) {
69 mParent->remove(this);
70 }
71
72 // Detach All Children
73 // - children are not deleted, just detached from this widget
74 // - prevent children from referencing a destroyed parent
75 std::list<Widget*>::const_iterator childrenIter;
76 for (childrenIter = mChildren.begin(); childrenIter != mChildren.end(); ++childrenIter) {
77 (*childrenIter)->_setParent(nullptr);
78 }
79
80 // Notify Death Listeners
81 // - call death event to notify listeners that this widget is being destroyed
82 std::list<DeathListener*>::const_iterator deathIter;
83 for (deathIter = mDeathListeners.begin(); deathIter != mDeathListeners.end(); ++deathIter) {
84 Event const event(this);
85 (*deathIter)->death(event);
86 }
87
88 // Notify GUI Death Listener
89 // - call death event to notify the GUI that this widget is being destroyed
90 if (mGuiDeathListener != nullptr) {
91 Event const event(this);
92 mGuiDeathListener->death(event);
93 }
94
95 // Clear Listener Containers
96 mActionListeners.clear();
97 mDeathListeners.clear();
98 mKeyListeners.clear();
99 mFocusListeners.clear();
100 mMouseListeners.clear();
101 mWidgetListeners.clear();
102
103 // Cleanup Focus Handlers
104 // - release keyboard/modal focus of the widget
105 // - remove widget from focus handler
106 // - prevent focus handler from referencing a destroyed widget
107 if (mFocusHandler != nullptr) {
108 mFocusHandler->releaseFocus(this);
109 Widget const * modalMouse = mFocusHandler->getMouseCaptureOwner();
110 if (modalMouse == this) {
111 mFocusHandler->popModal();
112 }
113 Widget const * modalFocus = mFocusHandler->getFocusOwner();
114 if (modalFocus == this) {
115 mFocusHandler->popModal();
116 }
117 mFocusHandler->remove(this);
118 mFocusHandler = nullptr;
119 }
120
121 // Remove from global Widget registry
122 widgetInstancesRegistry().remove(this);
123
124 } catch (fcn::Exception const & e) {
125 std::cerr << "Exception caught in Widget destructor: " << e.what() << '\n';
126 } catch (std::exception const & e) {
127 std::cerr << "Exception caught in Widget destructor: " << e.what() << '\n';
128 } catch (...) {
129 std::cerr << "Unknown exception caught in Widget destructor" << '\n';
130 }
131 }
132
134 {
135 Color const outlineColor = getOutlineColor();
136 Color highlightColor;
137 Color shadowColor;
138 int const alpha = getBaseColor().a;
139 int const width = getWidth() + (getOutlineSize() * 2) - 1;
140 int const height = getHeight() + (getOutlineSize() * 2) - 1;
141 highlightColor = outlineColor + 0x303030;
142 highlightColor.a = alpha;
143 shadowColor = outlineColor - 0x303030;
144 shadowColor.a = alpha;
145
146 for (unsigned int i = 0; i < getOutlineSize(); ++i) {
147 graphics->setColor(shadowColor);
148 graphics->drawLine(i, i, width - i, i);
149 graphics->drawLine(i, i + 1, i, height - i - 1);
150 graphics->setColor(highlightColor);
151 graphics->drawLine(width - i, i + 1, width - i, height - i);
152 graphics->drawLine(i, height - i, width - i - 1, height - i);
153 }
154 }
155
157 {
158 drawBorder(graphics, mBorderSides);
159 }
160
161 void Widget::drawBorder(Graphics* graphics, unsigned int sides) const
162 {
163 Color const borderColor = getBorderColor();
164 Color highlightColor;
165 Color shadowColor;
166 int const alpha = getBaseColor().a;
167 int const width = getWidth() - 1;
168 int const height = getHeight() - 1;
169 highlightColor = borderColor + 0x303030;
170 highlightColor.a = alpha;
171 shadowColor = borderColor - 0x303030;
172 shadowColor.a = alpha;
173
174 unsigned int const style = mBorderStyle;
175
176 for (int i = 0; std::cmp_less(i, getBorderSize()); ++i) {
177 if (style == BORDER_STYLE_FLAT) {
178 // Flat style: use borderColor for all requested sides
179 if ((sides & Widget::BORDER_TOP) != 0U) {
180 graphics->setColor(borderColor);
181 graphics->drawLine(i, i, width - i, i);
182 }
183 if ((sides & Widget::BORDER_LEFT) != 0U) {
184 graphics->setColor(borderColor);
185 graphics->drawLine(i, i + 1, i, height - i - 1);
186 }
187 if ((sides & Widget::BORDER_RIGHT) != 0U) {
188 graphics->setColor(borderColor);
189 graphics->drawLine(width - i, i + 1, width - i, height - i);
190 }
191 if ((sides & Widget::BORDER_BOTTOM) != 0U) {
192 graphics->setColor(borderColor);
193 graphics->drawLine(i, height - i, width - i - 1, height - i);
194 }
195 } else {
196 // Bevel style (default): shadow on top/left, highlight on right/bottom
197 if ((sides & Widget::BORDER_TOP) != 0U) {
198 graphics->setColor(shadowColor);
199 graphics->drawLine(i, i, width - i, i);
200 }
201 if ((sides & Widget::BORDER_LEFT) != 0U) {
202 graphics->setColor(shadowColor);
203 graphics->drawLine(i, i + 1, i, height - i - 1);
204 }
205 if ((sides & Widget::BORDER_RIGHT) != 0U) {
206 graphics->setColor(highlightColor);
207 graphics->drawLine(width - i, i + 1, width - i, height - i);
208 }
209 if ((sides & Widget::BORDER_BOTTOM) != 0U) {
210 graphics->setColor(highlightColor);
211 graphics->drawLine(i, height - i, width - i - 1, height - i);
212 }
213 }
214 }
215 }
216
218 {
219 int const width = getWidth() - 1;
220 int const height = getHeight() - 1;
221 graphics->setColor(getSelectionColor());
222
223 // currently border size is used here too, not sure an extra frame size is really needed.
224 for (unsigned int i = 0; i < getBorderSize(); ++i) {
225 // would be better but causes problems with OpenGL
226 // graphics->drawRectangle(i, i, width - 2 * i, height - 2 * i);
227 graphics->drawLine(i, i, width - i, i);
228 graphics->drawLine(i, i + 1, i, height - i - 1);
229 graphics->drawLine(width - i, i + 1, width - i, height - i);
230 graphics->drawLine(i, height - i, width - i - 1, height - i);
231 }
232 }
233
235 {
236 mParent = parent;
237 }
238
240 {
241 return mParent;
242 }
243
244 void Widget::setWidth(int width)
245 {
246 Rectangle newDimension = mDimension;
247 newDimension.width = width;
248
249 setDimension(newDimension);
250 }
251
253 {
254 return mDimension.width;
255 }
256
257 void Widget::setHeight(int height)
258 {
259 Rectangle newDimension = mDimension;
260 newDimension.height = height;
261
262 setDimension(newDimension);
263 }
264
266 {
267 return mDimension.height;
268 }
269
270 bool Widget::contains(int x, int y) const
271 {
272 return x >= 0 && x < getWidth() && y >= 0 && y < getHeight();
273 }
274
275 bool Widget::isMouseInside(MouseEvent const & mouseEvent) const
276 {
277 return contains(mouseEvent.getX(), mouseEvent.getY());
278 }
279
280 void Widget::setX(int x)
281 {
282 Rectangle newDimension = mDimension;
283 newDimension.x = x;
284
285 setDimension(newDimension);
286 }
287
288 int Widget::getX() const
289 {
290 return mDimension.x;
291 }
292
293 void Widget::setY(int y)
294 {
295 Rectangle newDimension = mDimension;
296 newDimension.y = y;
297
298 setDimension(newDimension);
299 }
300
301 int Widget::getY() const
302 {
303 return mDimension.y;
304 }
305
306 void Widget::setPosition(int x, int y)
307 {
308 Rectangle newDimension = mDimension;
309 newDimension.x = x;
310 newDimension.y = y;
311
312 setDimension(newDimension);
313 }
314
315 void Widget::setDimension(Rectangle const & dimension)
316 {
317 Rectangle const oldDimension = mDimension;
318 mDimension = dimension;
319
320 if (mDimension.width != oldDimension.width || mDimension.height != oldDimension.height) {
322 if (mDimension.width != oldDimension.width || mDimension.height != oldDimension.height) {
324 }
325 }
326
327 if (mDimension.x != oldDimension.x || mDimension.y != oldDimension.y) {
329
330 auto currChild(mChildren.begin());
331 auto const endChildren(mChildren.end());
332
333 for (; currChild != endChildren; ++currChild) {
334 (*currChild)->distributeAncestorMovedEvent(this);
335 }
336 }
337 }
338
339 unsigned int Widget::getChildrenCount() const
340 {
341 unsigned int childs = 0;
342 auto currChild(mChildren.begin());
343 auto const endChildren(mChildren.end());
344 for (; currChild != endChildren; ++currChild) {
345 ++childs;
346 }
347 return childs;
348 }
349
351 {
352 unsigned int childs = 0;
353 auto currChild(mChildren.begin());
354 auto const endChildren(mChildren.end());
355 for (; currChild != endChildren; ++currChild) {
356 if ((*currChild)->isVisible()) {
357 ++childs;
358 }
359 }
360 return childs;
361 }
362
363 void Widget::setMinSize(Size const & size)
364 {
365 mMinSize = size;
367 }
368
369 Size const & Widget::getMinSize() const
370 {
371 return mMinSize;
372 }
373
374 void Widget::setMaxSize(Size const & size)
375 {
376 mMaxSize = size;
378 }
379
380 Size const & Widget::getMaxSize() const
381 {
382 return mMaxSize;
383 }
384
385 void Widget::setFixedSize(Size const & size)
386 {
387 mFixedSize = size;
388 if (mFixedSize.getWidth() < 0 || mFixedSize.getHeight() < 0) {
389 mFixedSizeUsed = false;
390 } else {
391 mFixedSizeUsed = true;
393 }
394 }
395
397 {
398 return mFixedSize;
399 }
400
402 {
403 return mFixedSizeUsed;
404 }
405
407 {
408 if (mFixedSizeUsed) {
409 mDimension.width = mFixedSize.getWidth();
410 mDimension.height = mFixedSize.getHeight();
411 return;
412 }
413
414 int const minWidth = mMinSize.getWidth();
415 int const minHeight = mMinSize.getHeight();
416 int const maxWidth = mMaxSize.getWidth();
417 int const maxHeight = mMaxSize.getHeight();
418 int const currWidth = mDimension.width;
419 int const currHeight = mDimension.height;
420
421 mDimension.width = std::max(std::min(currWidth, maxWidth), minWidth);
422 mDimension.height = std::max(std::min(currHeight, maxHeight), minHeight);
423 }
424
426 {
427 mVExpand = expand;
428 }
429
431 {
432 return mVExpand;
433 }
434
436 {
437 mHExpand = expand;
438 }
439
441 {
442 return mHExpand;
443 }
444
445 void Widget::adaptLayout(bool top)
446 {
447 Widget* widget = this;
448 while ((widget->getParent() != nullptr) && top) {
449 Widget* parent = widget->getParent();
450 if (!parent->isLayouted()) {
451 break;
452 }
453 widget = parent;
454 }
455 widget->resizeToContent();
456 widget->expandContent();
457 }
458
459 void Widget::setOutlineSize(unsigned int size)
460 {
461 mOutlineSize = size;
462 }
463
464 unsigned int Widget::getOutlineSize() const
465 {
466 return mOutlineSize;
467 }
468
469 void Widget::setBorderSize(unsigned int size)
470 {
471 mBorderSize = size;
472 }
473
474 unsigned int Widget::getBorderSize() const
475 {
476 return mBorderSize;
477 }
478
479 void Widget::setBorderSides(unsigned int sides)
480 {
481 mBorderSides = sides;
482 }
483
484 unsigned int Widget::getBorderSides() const
485 {
486 return mBorderSides;
487 }
488
489 void Widget::setBorderStyle(unsigned int style)
490 {
491 mBorderStyle = style;
492 }
493
494 unsigned int Widget::getBorderStyle() const
495 {
496 return mBorderStyle;
497 }
498
499 void Widget::setBorderTop(unsigned int size, unsigned int style)
500 {
501 setBorderSize(size);
502 setBorderSides(BORDER_TOP);
503 setBorderStyle(style);
504 }
505
506 void Widget::setBorderBottom(unsigned int size, unsigned int style)
507 {
508 setBorderSize(size);
509 setBorderSides(BORDER_BOTTOM);
510 setBorderStyle(style);
511 }
512
513 void Widget::setMargin(int margin)
514 {
515 mMarginTop = margin;
516 mMarginRight = margin;
517 mMarginBottom = margin;
518 mMarginLeft = margin;
519 }
520
521 void Widget::setMarginTop(int margin)
522 {
523 mMarginTop = margin;
524 }
525
527 {
528 return mMarginTop;
529 }
530
531 void Widget::setMarginRight(int margin)
532 {
533 mMarginRight = margin;
534 }
535
537 {
538 return mMarginRight;
539 }
540
541 void Widget::setMarginBottom(int margin)
542 {
543 mMarginBottom = margin;
544 }
545
547 {
548 return mMarginBottom;
549 }
550
551 void Widget::setMarginLeft(int margin)
552 {
553 mMarginLeft = margin;
554 }
555
557 {
558 return mMarginLeft;
559 }
560
561 void Widget::setPadding(unsigned int padding)
562 {
563 mPaddingTop = padding;
564 mPaddingRight = padding;
565 mPaddingBottom = padding;
566 mPaddingLeft = padding;
567 }
568
569 void Widget::setPaddingTop(unsigned int padding)
570 {
571 mPaddingTop = padding;
572 }
573
574 unsigned int Widget::getPaddingTop() const
575 {
576 return mPaddingTop;
577 }
578
579 void Widget::setPaddingRight(unsigned int padding)
580 {
581 mPaddingRight = padding;
582 }
583
584 unsigned int Widget::getPaddingRight() const
585 {
586 return mPaddingRight;
587 }
588
589 void Widget::setPaddingBottom(unsigned int padding)
590 {
591 mPaddingBottom = padding;
592 }
593
594 unsigned int Widget::getPaddingBottom() const
595 {
596 return mPaddingBottom;
597 }
598
599 void Widget::setPaddingLeft(unsigned int padding)
600 {
601 mPaddingLeft = padding;
602 }
603
604 unsigned int Widget::getPaddingLeft() const
605 {
606 return mPaddingLeft;
607 }
608
610 {
611 return mDimension;
612 }
613
614 std::string const & Widget::getActionEventId() const
615 {
616 return mActionEventId;
617 }
618
619 void Widget::setActionEventId(std::string const & actionEventId)
620 {
621 mActionEventId = actionEventId;
622 }
623
624 bool Widget::isFocused() const
625 {
626 return mFocused;
627 }
628
629 void Widget::setFocused(bool focused)
630 {
631 if (mFocused == focused) {
632 return;
633 }
634
635 mFocused = focused;
636
637 if (focused) {
639 } else {
640 onFocusLost();
641 }
642
644 }
645
646 void Widget::setFocusable(bool focusable)
647 {
648 if (!focusable && isFocused()) {
649 mFocusHandler->focusNone();
650 }
651
652 mFocusable = focusable;
653 }
654
656 {
657 return mFocusable && isVisible() && isEnabled();
658 }
659
661 {
662 if (mFocusHandler == nullptr) {
663 throwException("No focus handler is set (did you add the widget to the GUI?)");
664 }
665
666 if (isFocusable()) {
667 mFocusHandler->requestFocus(this);
668 }
669 }
670
672 {
673 if (mParent != nullptr) {
674 mParent->moveToTop(this);
675 }
676 }
677
679 {
680 if (mParent != nullptr) {
681 mParent->moveToBottom(this);
682 }
683 }
684
685 void Widget::setVisible(bool visible)
686 {
687 VisibilityEventHandler* visibilityEventHandler = _getVisibilityEventHandler();
688
689 if (!visible && isFocused()) {
690 if (mFocusHandler != nullptr) {
691 mFocusHandler->focusNone();
692 }
693 }
694
695 if (visible) {
696 if (visibilityEventHandler != nullptr) {
697 visibilityEventHandler->widgetShown(Event(this));
698 }
700
701 auto currChild(mChildren.begin());
702 auto const endChildren(mChildren.end());
703
704 for (; currChild != endChildren; ++currChild) {
705 (*currChild)->distributeAncestorShownEvent(this);
706 }
707 } else {
708 if (visibilityEventHandler != nullptr) {
709 visibilityEventHandler->widgetHidden(Event(this));
710 }
712
713 auto currChild(mChildren.begin());
714 auto const endChildren(mChildren.end());
715
716 for (; currChild != endChildren; ++currChild) {
717 (*currChild)->distributeAncestorHiddenEvent(this);
718 }
719 }
720
721 mVisible = visible;
722 }
723
724 bool Widget::isVisible() const
725 {
726 if (getParent() == nullptr) {
727 return mVisible;
728 }
729 return mVisible && getParent()->isVisible();
730 }
731
733 {
734 return mVisible;
735 }
736
737 void Widget::setBaseColor(Color const & color)
738 {
739 mBaseColor = color;
740 }
741
743 {
744 return mBaseColor;
745 }
746
748 {
749 mForegroundColor = color;
750 }
751
753 {
754 return mForegroundColor;
755 }
756
758 {
759 mBackgroundColor = color;
760 }
761
763 {
764 return mBackgroundColor;
765 }
766
768 {
769 mSelectionColor = color;
770 }
771
773 {
774 return mSelectionColor;
775 }
776
777 void Widget::setOutlineColor(Color const & color)
778 {
779 mOutlineColor = color;
780 }
781
783 {
784 return mOutlineColor;
785 }
786
787 void Widget::setBorderColor(Color const & color)
788 {
789 mBorderColor = color;
790 }
791
793 {
794 return mBorderColor;
795 }
796
798 {
799 mSelectionMode = mode;
800 }
801
806
808 {
809 if (mFocusHandler != nullptr) {
810 mFocusHandler->releaseFocus(this);
811 if (mFocusHandler->getMouseCaptureOwner() == this) {
812 mFocusHandler->popModal();
813 }
814 if (mFocusHandler->getFocusOwner() == this) {
815 mFocusHandler->popModal();
816 }
817 mFocusHandler->remove(this);
818 }
819
820 if (focusHandler != nullptr) {
821 focusHandler->add(this);
822 }
823
824 mFocusHandler = focusHandler;
825
826 if (mInternalFocusHandler != nullptr) {
827 return;
828 }
829
830 std::list<Widget*>::const_iterator iter;
831 for (iter = mChildren.begin(); iter != mChildren.end(); ++iter) {
832 if (widgetExists(*iter)) {
833 (*iter)->_setFocusHandler(focusHandler);
834 }
835 }
836 }
837
842
844 {
845 mVisibilityEventHandler = visibilityEventHandler;
846 }
847
852
854 {
855 mGuiDeathListener = deathListener;
856 }
857
862
864 {
865 mActionListeners.push_back(actionListener);
866 }
867
868 // cppcheck-suppress constParameterPointer
870 {
871 mActionListeners.remove(actionListener);
872 }
873
875 {
876 mDeathListeners.push_back(deathListener);
877 }
878
879 // cppcheck-suppress constParameterPointer
881 {
882 mDeathListeners.remove(deathListener);
883 }
884
886 {
887 mKeyListeners.push_back(keyListener);
888 }
889
890 // cppcheck-suppress constParameterPointer
892 {
893 mKeyListeners.remove(keyListener);
894 }
895
897 {
898 mFocusListeners.push_back(focusListener);
899 }
900
901 // cppcheck-suppress constParameterPointer
903 {
904 mFocusListeners.remove(focusListener);
905 }
906
908 {
909 mMouseListeners.push_back(mouseListener);
910 }
911
912 // cppcheck-suppress constParameterPointer
914 {
915 mMouseListeners.remove(mouseListener);
916 }
917
919 {
920 mWidgetListeners.push_back(widgetListener);
921 }
922
923 // cppcheck-suppress constParameterPointer
925 {
926 mWidgetListeners.remove(widgetListener);
927 }
928
930 {
931 bool accepted = false;
932 for (auto* listener : mDropTargetListeners) {
933 if (listener != nullptr && listener->dragEntered(event)) {
934 accepted = true;
935 }
936 }
937 return accepted;
938 }
939
941 {
942 for (auto* listener : mDropTargetListeners) {
943 if (listener != nullptr) {
944 listener->dragExited(event);
945 }
946 }
947 }
948
950 {
951 for (auto* listener : mDropTargetListeners) {
952 if (listener != nullptr) {
953 listener->dragHovered(event);
954 }
955 }
956 }
957
959 {
960 for (auto* listener : mDropTargetListeners) {
961 if (listener != nullptr) {
962 listener->dragDropped(event);
963 }
964 }
965 }
966
968 {
969 mDropTargetListeners.push_back(listener);
970 }
971
972 // cppcheck-suppress constParameterPointer
974 {
975 mDropTargetListeners.remove(listener);
976 }
977
978 void Widget::getAbsolutePosition(int& x, int& y) const
979 {
980 if (getParent() == nullptr) {
981 if (isLastPositionSet()) {
982 x = mLastX;
983 y = mLastY;
984 } else {
985 x = mDimension.x;
986 y = mDimension.y;
987 }
988 return;
989 }
990
991 int parentX = 0;
992 int parentY = 0;
993
994 getParent()->getAbsolutePosition(parentX, parentY);
995
996 x = parentX + mDimension.x + getParent()->getChildrenArea().x;
997 y = parentY + mDimension.y + getParent()->getChildrenArea().y;
998 }
999
1001 {
1002 if (mCurrentFont == nullptr) {
1003 if (mGlobalFont == nullptr) {
1004 return &mDefaultFont;
1005 }
1006
1007 return mGlobalFont;
1008 }
1009
1010 return mCurrentFont;
1011 }
1012
1014 {
1015 assert("Global font must not be null" && font != nullptr);
1016 mGlobalFont = font;
1017
1018 std::list<Widget*>::iterator iter;
1019 for (iter = widgetInstancesRegistry().begin(); iter != widgetInstancesRegistry().end(); ++iter) {
1020 if ((*iter)->mCurrentFont == nullptr) {
1021 (*iter)->fontChanged();
1022 }
1023 }
1024 }
1025
1027 {
1028 mGlobalFont = nullptr;
1029 }
1030
1032 {
1033 mCurrentFont = font;
1034 fontChanged();
1035 }
1036
1037 bool Widget::widgetExists(Widget const * widget)
1038 {
1039 auto iter = std::ranges::find_if(widgetInstancesRegistry(), [widget](Widget const * w) {
1040 return w == widget;
1041 });
1042 return iter != widgetInstancesRegistry().end();
1043 }
1044
1046 {
1047 return mTabIn;
1048 }
1049
1050 void Widget::setTabInEnabled(bool enabled)
1051 {
1052 mTabIn = enabled;
1053 }
1054
1056 {
1057 return mTabOut;
1058 }
1059
1060 void Widget::setTabOutEnabled(bool enabled)
1061 {
1062 mTabOut = enabled;
1063 }
1064
1065 void Widget::setSize(int width, int height)
1066 {
1067 Rectangle newDimension = mDimension;
1068 newDimension.width = width;
1069 newDimension.height = height;
1070
1071 setDimension(newDimension);
1072 }
1073
1074 void Widget::setEnabled(bool enabled)
1075 {
1076 mEnabled = enabled;
1077 }
1078
1080 {
1081 return mEnabled && isVisible();
1082 }
1083
1085 {
1086 if (mFocusHandler == nullptr) {
1087 throwException("No focus handler is set (did you add the widget to the GUI?)");
1088 return false;
1089 }
1090 return !mFocusHandler->hasModalFocus();
1091 }
1092
1094 {
1095 if (mFocusHandler == nullptr) {
1096 throwException("No focus handler is set (did you add the widget to the GUI?)");
1097 return false;
1098 }
1099 return mFocusHandler->getMouseCaptureOwner() == nullptr;
1100 }
1101
1103 {
1104 if (mFocusHandler == nullptr) {
1105 throwException("No focus handler is set (did you add the widget to the GUI?)");
1106 }
1107
1108 if (getParent() != nullptr) {
1109 return (mFocusHandler->getFocusOwner() == this) || getParent()->isModalFocused();
1110 }
1111
1112 return mFocusHandler->getFocusOwner() == this;
1113 }
1114
1116 {
1117 if (mFocusHandler == nullptr) {
1118 throwException("No focus handler is set (did you add the widget to the GUI?)");
1119 }
1120
1121 if (getParent() != nullptr) {
1122 return (mFocusHandler->getMouseCaptureOwner() == this) || getParent()->isUnderMouseModal();
1123 }
1124
1125 return mFocusHandler->getMouseCaptureOwner() == this;
1126 }
1127
1128 Widget* Widget::getWidgetAt(int x, int y, Widget* exclude)
1129 {
1130 Rectangle const r = getChildrenArea();
1131
1132 if (!r.isContaining(x, y)) {
1133 return nullptr;
1134 }
1135
1136 x -= r.x;
1137 y -= r.y;
1138
1139 std::list<Widget*>::reverse_iterator iter;
1140 for (iter = mChildren.rbegin(); iter != mChildren.rend(); ++iter) {
1141 Widget* widget = (*iter);
1142
1143 if (widget != exclude && widget->isVisible() && widget->getDimension().isContaining(x, y)) {
1144 return widget;
1145 }
1146 }
1147
1148 return nullptr;
1149 }
1150
1151 std::list<MouseListener*> const & Widget::_getMouseListeners()
1152 {
1153 return mMouseListeners;
1154 }
1155
1156 std::list<KeyListener*> const & Widget::_getKeyListeners()
1157 {
1158 return mKeyListeners;
1159 }
1160
1161 std::list<FocusListener*> const & Widget::_getFocusListeners()
1162 {
1163 return mFocusListeners;
1164 }
1165
1167 {
1168 return {0, 0, 0, 0};
1169 }
1170
1175
1177 {
1178 mInternalFocusHandler = focusHandler;
1179
1180 std::list<Widget*>::const_iterator iter;
1181 for (iter = mChildren.begin(); iter != mChildren.end(); ++iter) {
1182 if (mInternalFocusHandler == nullptr) {
1183 (*iter)->_setFocusHandler(_getFocusHandler());
1184 } else {
1185 (*iter)->_setFocusHandler(mInternalFocusHandler);
1186 }
1187 }
1188 }
1189
1190 void Widget::setId(std::string const & id)
1191 {
1192 mId = id;
1193 }
1194
1195 std::string const & Widget::getId() const
1196 {
1197 return mId;
1198 }
1199
1201 {
1202 std::list<WidgetListener*>::const_iterator iter;
1203 for (iter = mWidgetListeners.begin(); iter != mWidgetListeners.end(); ++iter) {
1204 Event const event(this);
1205 (*iter)->widgetResized(event);
1206 }
1207 }
1208
1210 {
1211 std::list<WidgetListener*>::const_iterator iter;
1212 for (iter = mWidgetListeners.begin(); iter != mWidgetListeners.end(); ++iter) {
1213 Event const event(this);
1214 (*iter)->widgetMoved(event);
1215 }
1216 }
1217
1219 {
1220 std::list<WidgetListener*>::const_iterator iter;
1221 for (iter = mWidgetListeners.begin(); iter != mWidgetListeners.end(); ++iter) {
1222 Event const event(this);
1223 (*iter)->widgetHidden(event);
1224 }
1225 }
1226
1228 {
1229 auto currWidgetListener(mWidgetListeners.begin());
1230 auto const endWidgetListeners(mWidgetListeners.end());
1231 Event const event(ancestor);
1232
1233 for (; currWidgetListener != endWidgetListeners; ++currWidgetListener) {
1234 (*currWidgetListener)->ancestorMoved(event);
1235 }
1236
1237 auto currChild(mChildren.begin());
1238 auto const endChildren(mChildren.end());
1239
1240 for (; currChild != endChildren; ++currChild) {
1241 (*currChild)->distributeAncestorMovedEvent(ancestor);
1242 }
1243 }
1244
1246 {
1247 // additional call VisibilityEventHandler, needed to get new focus / MouseEvent::Entered or Exited
1248 if (_getVisibilityEventHandler() != nullptr) {
1250 }
1251
1252 auto currWidgetListener(mWidgetListeners.begin());
1253 auto const endWidgetListeners(mWidgetListeners.end());
1254 Event const event(ancestor);
1255
1256 for (; currWidgetListener != endWidgetListeners; ++currWidgetListener) {
1257 (*currWidgetListener)->ancestorHidden(event);
1258 }
1259
1260 auto currChild(mChildren.begin());
1261 auto const endChildren(mChildren.end());
1262
1263 for (; currChild != endChildren; ++currChild) {
1264 (*currChild)->distributeAncestorHiddenEvent(ancestor);
1265 }
1266 }
1267
1269 {
1270 // additional call VisibilityEventHandler, needed to get new focus / MouseEvent::Entered or Exited
1271 if (_getVisibilityEventHandler() != nullptr) {
1273 }
1274
1275 auto currWidgetListener(mWidgetListeners.begin());
1276 auto const endWidgetListeners(mWidgetListeners.end());
1277 Event const event(ancestor);
1278
1279 for (; currWidgetListener != endWidgetListeners; ++currWidgetListener) {
1280 (*currWidgetListener)->ancestorShown(event);
1281 }
1282
1283 auto currChild(mChildren.begin());
1284 auto const endChildren(mChildren.end());
1285
1286 for (; currChild != endChildren; ++currChild) {
1287 (*currChild)->distributeAncestorShownEvent(ancestor);
1288 }
1289 }
1290
1292 {
1293 std::list<ActionListener*>::const_iterator iter;
1294 for (iter = mActionListeners.begin(); iter != mActionListeners.end(); ++iter) {
1295 ActionEvent const actionEvent(this, mActionEventId);
1296 (*iter)->action(actionEvent);
1297 }
1298 }
1299
1301 {
1302 std::list<WidgetListener*>::const_iterator iter;
1303 for (iter = mWidgetListeners.begin(); iter != mWidgetListeners.end(); ++iter) {
1304 Event const event(this);
1305 (*iter)->widgetShown(event);
1306 }
1307 }
1308
1310 {
1311 if (mParent != nullptr) {
1312 mParent->showWidgetPart(this, rectangle);
1313 }
1314 }
1315
1317 {
1318 if (getParent() == nullptr) {
1319 return nullptr;
1320 }
1321
1322 Widget* widget = getParent();
1323 Widget* parent = getParent()->getParent();
1324
1325 while (parent != nullptr) {
1326 widget = parent;
1327 parent = parent->getParent();
1328 }
1329
1330 return widget;
1331 }
1332
1333 std::list<Widget*> Widget::getWidgetsIn(Rectangle const & area, Widget* ignore)
1334 {
1335 std::list<Widget*> result;
1336
1337 std::ranges::copy_if(mChildren, std::back_inserter(result), [&](auto const & widget) {
1338 return ignore != widget && widget->getDimension().isIntersecting(area);
1339 });
1340
1341 return result;
1342 }
1343
1345 {
1346 int w = 0;
1347 int h = 0;
1348 std::list<Widget*>::const_iterator iter;
1349 for (iter = mChildren.begin(); iter != mChildren.end(); ++iter) {
1350 Widget const * widget = (*iter);
1351 w = std::max(widget->getX() + widget->getWidth(), w);
1352 h = std::max(widget->getY() + widget->getHeight(), h);
1353 }
1354
1355 setSize(w, h);
1356 }
1357
1358 Widget* Widget::findWidgetById(std::string const & id)
1359 {
1360 std::list<Widget*>::const_iterator iter;
1361 for (iter = mChildren.begin(); iter != mChildren.end(); ++iter) {
1362 Widget* widget = (*iter);
1363
1364 if (widget->getId() == id) {
1365 return widget;
1366 }
1367
1368 Widget* child = widget->findWidgetById(id);
1369
1370 if (child != nullptr) {
1371 return child;
1372 }
1373 }
1374
1375 return nullptr;
1376 }
1377
1379 {
1380 Rectangle const widgetArea = getChildrenArea();
1381
1382 area.x += widget->getX();
1383 area.y += widget->getY();
1384
1385 if (area.x + area.width > widgetArea.width) {
1386 widget->setX(widget->getX() - area.x - area.width + widgetArea.width);
1387 }
1388
1389 if (area.y + area.height > widgetArea.height) {
1390 widget->setY(widget->getY() - area.y - area.height + widgetArea.height);
1391 }
1392
1393 if (area.x < 0) {
1394 widget->setX(widget->getX() - area.x);
1395 }
1396
1397 if (area.y < 0) {
1398 widget->setY(widget->getY() - area.y);
1399 }
1400 }
1401
1403 {
1404 std::list<Widget*>::const_iterator iter;
1405 for (iter = mChildren.begin(); iter != mChildren.end(); ++iter) {
1406 Widget* widget = (*iter);
1407 int x = 0;
1408 int y = 0;
1409 widget->getAbsolutePosition(x, y);
1410 widget->setLastPosition(x, y);
1411 widget->_setFocusHandler(nullptr);
1412 widget->_setParent(nullptr);
1413 // thats more a hack but needed
1414 if (_getVisibilityEventHandler() != nullptr) {
1416 }
1417 }
1418
1419 mChildren.clear();
1420 }
1421
1423 {
1424 auto it = std::ranges::find(mChildren, widget);
1425
1426 if (it == std::ranges::end(mChildren)) {
1427 throwException("There is no such widget in this container.");
1428 } else {
1429 int x = 0;
1430 int y = 0;
1431 widget->getAbsolutePosition(x, y);
1432 widget->setLastPosition(x, y);
1433
1434 mChildren.erase(it);
1435
1436 widget->_setFocusHandler(nullptr);
1437 widget->_setParent(nullptr);
1438
1439 // TODO thats more a hack but needed
1440 if (_getVisibilityEventHandler() != nullptr) {
1442 }
1443 }
1444 }
1445
1446 void Widget::add(Widget* widget)
1447 {
1448 mChildren.push_back(widget);
1449
1450 if (mInternalFocusHandler == nullptr) {
1452 } else {
1454 }
1455
1456 widget->_setParent(this);
1457 setLastPosition(0, 0);
1458 // thats more a hack but needed
1459 if (_getVisibilityEventHandler() != nullptr) {
1461 }
1462 }
1463
1465 {
1466 std::list<Widget*>::iterator iter;
1467 iter = std::ranges::find(mChildren, widget);
1468
1469 if (iter == mChildren.end()) {
1470 throwException("There is no such widget in this widget.");
1471 }
1472
1473 mChildren.remove(widget);
1474 mChildren.push_back(widget);
1475 }
1476
1478 {
1479 std::list<Widget*>::iterator iter;
1480 iter = std::ranges::find(mChildren, widget);
1481
1482 if (iter == mChildren.end()) {
1483 throwException("There is no such widget in this widget.");
1484 }
1485
1486 mChildren.remove(widget);
1487 mChildren.push_front(widget);
1488 }
1489
1491 {
1492 if (mChildren.empty()) {
1493 return;
1494 }
1495
1496 auto focused = std::ranges::find_if(mChildren, [](auto* w) {
1497 return w->isFocused();
1498 });
1499
1500 auto next = (focused == std::ranges::end(mChildren)) ? std::ranges::begin(mChildren) : std::next(focused);
1501
1502 auto it = std::ranges::find_if(next, std::ranges::end(mChildren), [](auto* w) {
1503 return w->isFocusable();
1504 });
1505
1506 if (it == std::ranges::end(mChildren)) {
1507 it = std::ranges::find_if(std::ranges::begin(mChildren), next, [](auto* w) {
1508 return w->isFocusable();
1509 });
1510 }
1511
1512 if (it != next) {
1513 (*it)->requestFocus();
1514 }
1515 }
1516
1518 {
1519 if (mChildren.empty()) {
1520 return;
1521 }
1522
1523 auto rev = std::ranges::reverse_view(mChildren);
1524
1525 auto focused = std::ranges::find_if(rev, [](auto* w) {
1526 return w->isFocused();
1527 });
1528
1529 auto next = (focused == std::ranges::end(rev)) ? std::ranges::begin(rev) : std::next(focused);
1530
1531 auto rit = std::ranges::find_if(next, std::ranges::end(rev), [](auto* w) {
1532 return w->isFocusable();
1533 });
1534
1535 if (rit == std::ranges::end(rev)) {
1536 rit = std::ranges::find_if(std::ranges::begin(rev), next, [](auto* w) {
1537 return w->isFocusable();
1538 });
1539 }
1540
1541 if (rit != next) {
1542 (*rit)->requestFocus();
1543 }
1544 }
1545
1546 void Widget::_draw(Graphics* graphics)
1547 {
1548 if (mOutlineSize > 0) {
1549 Rectangle rec = mDimension;
1550 rec.x -= mOutlineSize;
1551 rec.y -= mOutlineSize;
1552 rec.width += 2 * mOutlineSize;
1553 rec.height += 2 * mOutlineSize;
1554 graphics->pushClipArea(rec);
1555 drawOutline(graphics);
1556 graphics->popClipArea();
1557 }
1558
1559 graphics->pushClipArea(mDimension);
1560 draw(graphics);
1561
1562 if (!mChildren.empty()) {
1563 Rectangle const & childrenArea = getChildrenArea();
1564 graphics->pushClipArea(childrenArea);
1565
1566 for (auto* widget : mChildren) {
1567 // Only draw a widget:
1568 // if it's visible
1569 // and inside the children area.
1570 if (widget->isVisible() && childrenArea.isIntersecting(widget->getDimension())) {
1571 widget->_draw(graphics);
1572 }
1573 }
1574 graphics->popClipArea();
1575 }
1576 graphics->popClipArea();
1577 }
1578
1580 {
1581 logic();
1582
1583 std::list<Widget*>::const_iterator iter;
1584 for (iter = mChildren.begin(); iter != mChildren.end(); ++iter) {
1585 (*iter)->_logic();
1586 }
1587 }
1588
1589 std::list<Widget*> const & Widget::getChildren() const
1590 {
1591 return mChildren;
1592 }
1593
1594 void Widget::getLastPosition(int& x, int& y) const
1595 {
1596 x = mLastX;
1597 y = mLastY;
1598 }
1599
1600 void Widget::setLastPosition(int x, int y)
1601 {
1602 mLastX = x;
1603 mLastY = y;
1604 }
1605
1607 {
1608 return mLastX != 0 || mLastY != 0;
1609 }
1610
1612 {
1613 // disallow capture if another widget already has it
1614 if (sMouseCapture != nullptr) {
1615 return false;
1616 }
1617 sMouseCapture = this;
1618 return true;
1619 }
1620
1622 {
1623 // safe to call even if we don't have capture
1624 if (sMouseCapture == this) {
1625 sMouseCapture = nullptr;
1626 }
1627 }
1628
1630 {
1631 return sMouseCapture;
1632 }
1633
1635 {
1636 return sMouseCapture == this;
1637 }
1638
1639 bool Widget::isDescendantOf(Widget const * ancestor) const noexcept
1640 {
1641 if (ancestor == nullptr) {
1642 return false;
1643 }
1644 Widget const * current = this;
1645 while (current != nullptr) {
1646 if (current == ancestor) {
1647 return true;
1648 }
1649 current = current->getParent();
1650 }
1651 return false;
1652 }
1653
1655 {
1656 if (mFocusHandler == nullptr) {
1657 return false;
1658 }
1659 Widget const * modal = mFocusHandler->getMouseCaptureOwner();
1660 return (modal != nullptr) && isDescendantOf(modal);
1661 }
1662} // namespace fcn
Represents an action trigger (e.g., button click).
Interface for listening to action events from widgets.
Color.
Definition color.hpp:58
uint8_t a
Alpha color component (0-255).
Definition color.hpp:350
Interface for listening to widget destruction events.
A basic font implementation capable only of drawing rectangles (placeholder).
Drag and drop event type container.
Definition dragevent.hpp:23
Listener interface for widgets that accept dragged payloads.
Base class for all GUI event objects.
Definition event.hpp:25
char const * what() const noexcept override
Returns a pointer to a null-terminated string with a description of the exception.
Definition exception.hpp:57
Manages focus navigation and assignment among widgets within a Gui instance.
virtual void add(Widget *widget)
Adds a widget to by handles by the focus handler.
Interface for listening to focus gain/loss events.
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
virtual bool pushClipArea(Rectangle area)
Pushes a clip area onto the stack.
Definition graphics.cpp:25
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.
Interface for listening to keyboard events.
Represents a mouse event.
int getX() const
Gets the x coordinate of the mouse event.
int getY() const
Gets the y coordinate of the mouse event.
Interface for listening to mouse events.
Represents a rectangular area (X, Y, Width, Height).
Definition rectangle.hpp:22
bool isContaining(int x, int y) const
Checks the rectangle contains a point.
Definition rectangle.cpp:63
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.
bool isIntersecting(Rectangle const &rectangle) const
Checks if another rectangle intersects with the rectangle.
Definition rectangle.cpp:34
Represents dimensions defined by width and height.
Definition size.hpp:21
Handles changes in widget visibility states.
void widgetHidden(Event const &e) override
Informs gui that a widget was hidden.
void widgetShown(Event const &e) override
Informs gui that a widget was shown.
Interface for receiving generic events from widgets.
Abstract base class defining the common behavior, properties, and lifecycle of all GUI elements.
Definition widget.hpp:56
std::list< FocusListener * > mFocusListeners
Holds the focus listeners of the widget.
Definition widget.hpp:1846
void setActionEventId(std::string const &actionEventId)
Sets the action event identifier of the widget.
Definition widget.cpp:619
bool mHExpand
True if the widget can be horizontal expanded.
Definition widget.hpp:2055
void addFocusListener(FocusListener *focusListener)
Adds a focus listener to the widget.
Definition widget.cpp:896
void setMaxSize(Size const &size)
Sets the maximal dimension of the widget.
Definition widget.cpp:374
void setLastPosition(int x, int y)
Stores the last known position for this widget.
Definition widget.cpp:1600
Color const & getBaseColor() const
Gets the base color.
Definition widget.cpp:742
unsigned int mBorderSides
Which sides to draw the border on (bitmask of BorderSide).
Definition widget.hpp:1930
void setVisible(bool visible)
Sets the widget to be visible, or not.
Definition widget.cpp:685
void setMargin(int margin)
Sets all 4 margins to one value.
Definition widget.cpp:513
void distributeShownEvent()
Distributes shown events to all of the widget's listeners.
Definition widget.cpp:1300
Widget * mParent
Holds the parent of the widget.
Definition widget.hpp:1903
bool mFocused
True if the widget has focus, false otherwise.
Definition widget.hpp:1997
void removeDropTargetListener(DropTargetListener *listener)
Removes an added drop target listener from the widget.
Definition widget.cpp:973
std::list< Widget * > const & getChildren() const
Gets the children of the widget.
Definition widget.cpp:1589
bool isHorizontalExpand() const
Gets if widget is horizontal expandable.
Definition widget.cpp:440
int getY() const
Gets the y coordinate of the widget.
Definition widget.cpp:301
std::list< DeathListener * > mDeathListeners
Holds the death listeners of the widget.
Definition widget.hpp:1841
void setFocusable(bool focusable)
Sets the widget to be focusable, or not.
Definition widget.cpp:646
virtual FocusHandler * _getFocusHandler()
Gets the focus handler used.
Definition widget.cpp:838
virtual void onFocusGained()
Called when the widget gains focus.
Definition widget.hpp:1169
virtual void fontChanged()
Called when the font has changed.
Definition widget.hpp:1160
bool contains(int x, int y) const
Checks if a point is within the widget's bounds.
Definition widget.cpp:270
bool isMouseInside(MouseEvent const &mouseEvent) const
Checks if a mouse event occurred within this widget.
Definition widget.cpp:275
static DefaultFont mDefaultFont
Holds the default font used by the widget.
Definition widget.hpp:2065
unsigned int getChildrenCount() const
Gets how many childs the widget have.
Definition widget.cpp:339
static Widget * getMouseCapture()
Gets the widget that currently has mouse capture.
Definition widget.cpp:1629
virtual bool isModalFocused() const
Checks if the widget or it's parent has modal focus.
Definition widget.cpp:1102
virtual void onFocusLost()
Called when the widget loses focus.
Definition widget.hpp:1178
FocusHandler * mFocusHandler
Holds the focus handler used by the widget.
Definition widget.hpp:1891
void setEnabled(bool enabled)
Sets the widget to enabled, or not.
Definition widget.cpp:1074
Size mMinSize
Holds the min size.
Definition widget.hpp:2027
int mMarginTop
Holds the top margin of the widget.
Definition widget.hpp:1947
virtual bool isUnderMouseModal() const
Checks if the widget or its parent is under a mouse modal.
Definition widget.cpp:1115
int getWidth() const
Gets the width of the widget.
Definition widget.cpp:252
virtual void drawOutline(Graphics *graphics)
Called when a widget is given a chance to draw a outline around itself.
Definition widget.cpp:133
virtual Widget * getParent() const
Gets the widget's parent container.
Definition widget.cpp:239
void setMinSize(Size const &size)
Sets the minimal dimension of the widget.
Definition widget.cpp:363
virtual bool isLayouted()
Helper function to decide if we need to layout.
Definition widget.hpp:1614
void setBorderSize(unsigned int size)
Sets the size of the widget's border.
Definition widget.cpp:469
void add(Widget *widget)
Adds a child to the widget.
Definition widget.cpp:1446
Size const & getFixedSize() const
Gets the fixed size of the widget.
Definition widget.cpp:396
void distributeDragHover(DragEvent &event)
Distribute a drag hover event to listeners.
Definition widget.cpp:949
int mLastY
Last stored Y coordinate used for layout and event calculations.
Definition widget.hpp:2105
void removeWidgetListener(WidgetListener *widgetListener)
Removes an added widget listener from the widget.
Definition widget.cpp:924
std::list< KeyListener * > mKeyListeners
Holds the key listeners of the widget.
Definition widget.hpp:1831
std::list< ActionListener * > mActionListeners
Holds the action listeners of the widget.
Definition widget.hpp:1836
void resizeToChildren()
Resizes the widget to fit it's children exactly.
Definition widget.cpp:1344
void setTabInEnabled(bool enabled)
Sets tab in enabled, or not.
Definition widget.cpp:1050
virtual Widget * findWidgetById(std::string const &id)
Finds a widget by id.
Definition widget.cpp:1358
void setOutlineSize(unsigned int size)
Sets the size of the widget's outline.
Definition widget.cpp:459
Size const & getMaxSize() const
Gets the maximal dimension of the widget.
Definition widget.cpp:380
void distributeHiddenEvent()
Distributes hidden events to all of the widget's listeners.
Definition widget.cpp:1218
virtual void requestMoveToBottom()
Requests a move to the bottom in the parent widget.
Definition widget.cpp:678
SelectionMode
Selection mode.
Definition widget.hpp:83
void setBorderSides(unsigned int sides)
Select which sides the border should be drawn on.
Definition widget.cpp:479
void setMarginTop(int margin)
Sets the top margin.
Definition widget.cpp:521
unsigned int getOutlineSize() const
Gets the size of the widget's outline.
Definition widget.cpp:464
virtual std::list< KeyListener * > const & _getKeyListeners()
Gets the key listeners of the widget.
Definition widget.cpp:1156
void removeKeyListener(KeyListener *keyListener)
Removes an added key listener from the widget.
Definition widget.cpp:891
static std::list< Widget * > mWidgetInstances
Holds a list of all instances of widgets.
Definition widget.hpp:2075
virtual Rectangle getChildrenArea()
Gets the area of the widget occupied by the widget's children.
Definition widget.cpp:1166
virtual void moveToTop(Widget *widget)
Moves a widget to the top of this widget.
Definition widget.cpp:1464
virtual void logic()
Called for all widgets in the GUI each time Gui::logic is called.
Definition widget.hpp:467
virtual void setOutlineColor(Color const &color)
Sets the outline color.
Definition widget.cpp:777
virtual void remove(Widget *widget)
Removes a specific child from the widget.
Definition widget.cpp:1422
int getX() const
Gets the x coordinate of the widget.
Definition widget.cpp:288
void removeMouseListener(MouseListener *mouseListener)
Removes an added mouse listener from the widget.
Definition widget.cpp:913
unsigned int mPaddingTop
Holds the top padding of the widget.
Definition widget.hpp:1967
virtual bool isFocused() const
Checks if the widget is focused.
Definition widget.cpp:624
bool isTabOutEnabled() const
Checks if tab out is enabled.
Definition widget.cpp:1055
virtual void setDimension(Rectangle const &dimension)
Sets the dimension of the widget.
Definition widget.cpp:315
virtual void showPart(Rectangle rectangle)
Shows a certain part of a widget in the widget's parent.
Definition widget.cpp:1309
Rectangle mDimension
Holds the dimension of the widget.
Definition widget.hpp:1908
void setMarginRight(int margin)
Sets the right margin.
Definition widget.cpp:531
virtual void setFocused(bool focused)
Sets the widget as focused, or not.
Definition widget.cpp:629
bool mTabOut
True if the widget has tab in enabled, false otherwise.
Definition widget.hpp:2012
bool isInsideActiveMouseModal() const noexcept
Checks if this widget is inside the active mouse modal root.
Definition widget.cpp:1654
void removeActionListener(ActionListener *actionListener)
Removes an added action listener from the widget.
Definition widget.cpp:869
bool isEnabled() const
Checks if the widget is enabled.
Definition widget.cpp:1079
virtual void removeAllChildren()
Remvoes all children from the widget.
Definition widget.cpp:1402
unsigned int getPaddingLeft() const
Gets the left padding.
Definition widget.cpp:604
Color mForegroundColor
Holds the foreground color of the widget.
Definition widget.hpp:1861
std::string mActionEventId
Holds the action event of the widget.
Definition widget.hpp:1987
int getMarginBottom() const
Gets the bottom margin.
Definition widget.cpp:546
Widget()
Constructor.
Definition widget.cpp:52
void expandContent()
Expands the child widgets to the size of this widget, calls recursively all childs.
Definition widget.hpp:1597
virtual void setSize(int width, int height)
Sets the size of the widget.
Definition widget.cpp:1065
void setPaddingTop(unsigned int padding)
Sets the top padding.
Definition widget.cpp:569
virtual void _setParent(Widget *parent)
Sets the parent of the widget.
Definition widget.cpp:234
Color mOutlineColor
Holds the outline color of the widget.
Definition widget.hpp:1881
virtual void requestFocus()
Requests focus for the widget.
Definition widget.cpp:660
virtual void showWidgetPart(Widget *widget, Rectangle area)
Tries to show a specific part of a widget by moving it.
Definition widget.cpp:1378
Color mBorderColor
Holds the border color of the widget.
Definition widget.hpp:1886
virtual FocusHandler * _getInternalFocusHandler()
Gets the internal focus handler used.
Definition widget.cpp:1171
void setBorderStyle(unsigned int style)
Set border drawing style (bevel or flat).
Definition widget.cpp:489
void setPaddingRight(unsigned int padding)
Sets the right padding.
Definition widget.cpp:579
virtual void _logic()
Called whenever a widget should perform logic.
Definition widget.cpp:1579
bool isLastPositionSet() const
Returns whether a last position has been stored for this widget.
Definition widget.cpp:1606
std::string const & getActionEventId() const
Gets the action event identifier of the widget.
Definition widget.cpp:614
Color const & getOutlineColor() const
Gets the outline color.
Definition widget.cpp:782
std::list< WidgetListener * > mWidgetListeners
Holds the widget listeners of the widget.
Definition widget.hpp:1851
Color const & getBorderColor() const
Gets the border color.
Definition widget.cpp:792
void distributeAncestorHiddenEvent(Widget *ancestor)
Distributes ancestor hidden events to all of the widget's listeners.
Definition widget.cpp:1245
bool isVisible() const
Checks if the widget is visible.
Definition widget.cpp:724
Color const & getBackgroundColor() const
Gets the background color.
Definition widget.cpp:762
bool isSetVisible() const
Checks if the widget setting is visible.
Definition widget.cpp:732
void distributeResizedEvent()
Distributes resized events to all of the widget's listeners.
Definition widget.cpp:1200
virtual void setForegroundColor(Color const &color)
Sets the foreground color.
Definition widget.cpp:747
bool distributeDragEnter(DragEvent &event)
Distribute a drag enter event to listeners.
Definition widget.cpp:929
Size mFixedSize
Holds the fixed size.
Definition widget.hpp:2040
void addMouseListener(MouseListener *mouseListener)
Adds a mouse listener to the widget.
Definition widget.cpp:907
virtual void requestMoveToTop()
Requests a move to the top in the parent widget.
Definition widget.cpp:671
FocusHandler * mInternalFocusHandler
Holds the focus handler used by the widget.
Definition widget.hpp:1897
void setHorizontalExpand(bool expand)
Sets the widget to horizontal expandable.
Definition widget.cpp:435
Widget * getWidgetAt(int x, int y)
Gets a widget at a certain position in the widget.
Definition widget.hpp:1287
bool isDescendantOf(Widget const *ancestor) const noexcept
Checks if this widget is a descendant of (or equal to) the given ancestor.
Definition widget.cpp:1639
void setPosition(int x, int y)
Sets position of the widget.
Definition widget.cpp:306
void addDeathListener(DeathListener *deathListener)
Adds a death listener to the widget.
Definition widget.cpp:874
unsigned int getBorderStyle() const
Get the current border drawing style.
Definition widget.cpp:494
void setY(int y)
Sets the y coordinate of the widget.
Definition widget.cpp:293
SelectionMode mSelectionMode
Holds the selection mode.
Definition widget.hpp:1942
void calculateSize()
Checks the size against the size constraints.
Definition widget.cpp:406
void setX(int x)
Sets the x coordinate of the widget.
Definition widget.cpp:280
int getMarginLeft() const
Gets the left margin.
Definition widget.cpp:556
void addWidgetListener(WidgetListener *widgetListener)
Adds a widget listener to the widget.
Definition widget.cpp:918
void distributeAncestorShownEvent(Widget *ancestor)
Distributes ancestor shown events to all of the widget's listeners.
Definition widget.cpp:1268
void addActionListener(ActionListener *actionListener)
Adds an action listener to the widget.
Definition widget.cpp:863
virtual void setBorderColor(Color const &color)
Sets the border color.
Definition widget.cpp:787
std::list< MouseListener * > mMouseListeners
Holds the mouse listeners of the widget.
Definition widget.hpp:1826
static bool widgetExists(Widget const *widget)
Checks if a widget exists or not, that is if it still exists an instance of the object.
Definition widget.cpp:1037
static void _setGuiDeathListener(DeathListener *deathListener)
Set the global GUI death listener used to observe widget deletions.
Definition widget.cpp:853
virtual std::list< MouseListener * > const & _getMouseListeners()
Gets the mouse listeners of the widget.
Definition widget.cpp:1151
void adaptLayout()
Execute the layouting.
Definition widget.hpp:1560
unsigned int mBorderSize
Holds the border size of the widget.
Definition widget.hpp:1923
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
int getMarginRight() const
Gets the right margin.
Definition widget.cpp:536
static Widget * sMouseCapture
Holds the widget that currently has mouse capture.
Definition widget.hpp:2094
unsigned int mBorderStyle
Border drawing style (see BorderStyle).
Definition widget.hpp:1937
virtual void onFocusChanged()
Called when the widget focus changes.
Definition widget.hpp:1187
void addKeyListener(KeyListener *keyListener)
Adds a key listener to the widget.
Definition widget.cpp:885
virtual std::list< FocusListener * > const & _getFocusListeners()
Gets the focus listeners of the widget.
Definition widget.cpp:1161
void setBorderTop(unsigned int size, unsigned int style)
Convenience helper: set a top-only border with size and style.
Definition widget.cpp:499
void setPaddingLeft(unsigned int padding)
Sets the left padding.
Definition widget.cpp:599
void distributeAncestorMovedEvent(Widget *ancestor)
Distributes ancestor moved events to all of the widget's listeners.
Definition widget.cpp:1227
std::string const & getId() const
Gets the id of a widget.
Definition widget.cpp:1195
bool captureMouse()
Attempts to capture mouse input to this widget.
Definition widget.cpp:1611
static void _setVisibilityEventHandler(VisibilityEventHandler *visibilityEventHandler)
Sets the visibility event handler to be used.
Definition widget.cpp:843
unsigned int mPaddingBottom
Holds the bottom padding of the widget.
Definition widget.hpp:1977
int mLastX
Last stored X coordinate used for layout and event calculations.
Definition widget.hpp:2102
int mMarginRight
Holds the top right of the widget.
Definition widget.hpp:1952
void setInternalFocusHandler(FocusHandler *internalFocusHandler)
Sets the internal focus handler.
Definition widget.cpp:1176
std::list< DropTargetListener * > mDropTargetListeners
Holds the drop target listeners of the widget.
Definition widget.hpp:1856
Rectangle const & getDimension() const
Gets the dimension of the widget.
Definition widget.cpp:609
bool isTabInEnabled() const
Checks if tab in is enabled.
Definition widget.cpp:1045
void setTabOutEnabled(bool enabled)
Sets tab out enabled.
Definition widget.cpp:1060
static DeathListener * _getGuiDeathListener()
Get the global GUI death listener.
Definition widget.cpp:858
void addDropTargetListener(DropTargetListener *listener)
Adds a drop target listener to the widget.
Definition widget.cpp:967
virtual void drawBorder(Graphics *graphics)
Called when a widget have a border.
Definition widget.cpp:156
static DeathListener * mGuiDeathListener
Holds the death listener used by the widgets.
Definition widget.hpp:2089
static Font * mGlobalFont
Holds the global font used by the widget.
Definition widget.hpp:2070
bool hasMouseCapture() const
Checks if this widget currently has mouse capture.
Definition widget.cpp:1634
static void setGlobalFont(Font *font)
Sets the global font to be used by default for all widgets.
Definition widget.cpp:1013
virtual bool isModalFocusable() const
Checks if a widget is modal focusable.
Definition widget.cpp:1084
unsigned int getPaddingTop() const
Gets the top padding.
Definition widget.cpp:574
virtual void _draw(Graphics *graphics)
Called whenever a widget should draw itself.
Definition widget.cpp:1546
unsigned int getBorderSize() const
Gets the size of the widget's border.
Definition widget.cpp:474
Size const & getMinSize() const
Gets the minimal dimension of the widget.
Definition widget.cpp:369
virtual void drawSelectionFrame(Graphics *graphics)
Called when a widget is "active" and the selection mode is Frame or FrameWithBackground.
Definition widget.cpp:217
virtual bool isModalMouseInputFocusable() const
Checks if a widget is modal mouse input focusable.
Definition widget.cpp:1093
std::list< Widget * > mChildren
Holds all children of the widget.
Definition widget.hpp:2099
std::list< Widget * > getWidgetsIn(Rectangle const &area)
Gets all widgets inside a certain area of the widget.
Definition widget.hpp:1312
bool mEnabled
True if the widget is enabled, false otherwise.
Definition widget.hpp:2017
unsigned int mOutlineSize
Holds the outline size of the widget.
Definition widget.hpp:1918
unsigned int getVisibleChildrenCount() const
Gets how many visible childs the widget have.
Definition widget.cpp:350
void removeFocusListener(FocusListener *focusListener)
Removes an added focus listener from the widget.
Definition widget.cpp:902
Color mBaseColor
Holds the base color of the widget.
Definition widget.hpp:1871
bool mVisible
True if the widget visible, false otherwise.
Definition widget.hpp:2002
virtual void focusPrevious()
Focuses the previous widget in the widget.
Definition widget.cpp:1517
void getLastPosition(int &x, int &y) const
Retrieves the last stored position used by layout or event logic.
Definition widget.cpp:1594
virtual void focusNext()
Focuses the next widget in the widget.
Definition widget.cpp:1490
virtual Widget * getTop() const
Gets the top widget, or top parent, of this widget.
Definition widget.cpp:1316
int getMarginTop() const
Gets the top margin.
Definition widget.cpp:526
unsigned int getPaddingBottom() const
Gets the bottom padding.
Definition widget.cpp:594
Color mSelectionColor
Holds the selection color of the widget.
Definition widget.hpp:1876
void releaseMouse()
Releases mouse capture from this widget, if it has capture.
Definition widget.cpp:1621
bool mVExpand
True if the widget can be vertical expanded.
Definition widget.hpp:2050
virtual void setBaseColor(Color const &color)
Sets the base color of the widget.
Definition widget.cpp:737
unsigned int mPaddingLeft
Holds the left padding of the widget.
Definition widget.hpp:1982
void setBorderBottom(unsigned int size, unsigned int style)
Convenience helper: set a bottom-only border with size and style.
Definition widget.cpp:506
void setId(std::string const &id)
Sets an id of a widget.
Definition widget.cpp:1190
void distributeDragLeave(DragEvent &event)
Distribute a drag leave event to listeners.
Definition widget.cpp:940
Font * mCurrentFont
Holds the font used by the widget.
Definition widget.hpp:2060
Color const & getForegroundColor() const
Gets the foreground color.
Definition widget.cpp:752
virtual void setFont(Font *font)
Sets the font for the widget.
Definition widget.cpp:1031
SelectionMode getSelectionMode() const
Gets the selection mode.
Definition widget.cpp:802
bool mFocusable
True if the widget focusable, false otherwise.
Definition widget.hpp:1992
bool isFocusable() const
Checks if a widget is focusable.
Definition widget.cpp:655
Color mBackgroundColor
Holds the background color of the widget.
Definition widget.hpp:1866
Font * getFont() const
Gets the font set for the widget.
Definition widget.cpp:1000
virtual void getAbsolutePosition(int &x, int &y) const
Gets the absolute position on the screen for the widget.
Definition widget.cpp:978
static VisibilityEventHandler * _getVisibilityEventHandler()
Gets the visibility event handler of this widget.
Definition widget.cpp:848
void distributeDragDrop(DragEvent &event)
Distribute a drop event to listeners.
Definition widget.cpp:958
static void resetGlobalFont()
Resets the global font, detaching it from the Widget class.
Definition widget.cpp:1026
void setVerticalExpand(bool expand)
Sets the widget to vertical expandable.
Definition widget.cpp:425
void setFixedSize(Size const &size)
Sets the dimension of the widget to a fixed size.
Definition widget.cpp:385
int mMarginLeft
Holds the left margin of the widget.
Definition widget.hpp:1962
int mMarginBottom
Holds the bottom margin of the widget.
Definition widget.hpp:1957
void distributeActionEvent()
Distributes an action event to all action listeners of the widget.
Definition widget.cpp:1291
virtual void draw(Graphics *graphics)=0
Draws the widget.
void removeDeathListener(DeathListener *deathListener)
Removes an added death listener from the widget.
Definition widget.cpp:880
virtual void resizeToContent(bool recursion=true)
Resizes the widget's size to fit the content exactly, calls recursively all childs.
Definition widget.hpp:1580
bool mFixedSizeUsed
True if the widget used a fixed size.
Definition widget.hpp:2045
int getHeight() const
Gets the height of the widget.
Definition widget.cpp:265
void setMarginLeft(int margin)
Sets the left margin.
Definition widget.cpp:551
void setPaddingBottom(unsigned int padding)
Sets the bottom padding.
Definition widget.cpp:589
bool mTabIn
True if the widget has tab in enabled, false otherwise.
Definition widget.hpp:2007
std::string mId
Holds the id of the widget.
Definition widget.hpp:2022
void setMarginBottom(int margin)
Sets the bottom margin.
Definition widget.cpp:541
virtual void _setFocusHandler(FocusHandler *focusHandler)
Sets the focus handler to be used.
Definition widget.cpp:807
virtual void setSelectionColor(Color const &color)
Sets the selection color.
Definition widget.cpp:767
virtual void setHeight(int height)
Sets the height of the widget.
Definition widget.cpp:257
unsigned int getPaddingRight() const
Gets the right padding.
Definition widget.cpp:584
Color const & getSelectionColor() const
Gets the selection color.
Definition widget.cpp:772
virtual void setBackgroundColor(Color const &color)
Sets the background color.
Definition widget.cpp:757
void setPadding(unsigned int padding)
Sets all 4 paddings to one value.
Definition widget.cpp:561
bool isFixedSize() const
Gets if the widget use a fixed size.
Definition widget.cpp:401
virtual void setSelectionMode(SelectionMode mode)
Sets the selection mode.
Definition widget.cpp:797
virtual void moveToBottom(Widget *widget)
Moves a widget in this widget to the bottom of this widget.
Definition widget.cpp:1477
void distributeMovedEvent()
Distributes moved events to all of the widget's listeners.
Definition widget.cpp:1209
Size mMaxSize
Holds the max size.
Definition widget.hpp:2035
bool isVerticalExpand() const
Gets if widget is vertical expandable.
Definition widget.cpp:430
static VisibilityEventHandler * mVisibilityEventHandler
Holds the visibility event handler used by the widgets.
Definition widget.hpp:2084
unsigned int getBorderSides() const
Get the currently selected border sides.
Definition widget.cpp:484
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.