HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
label_widget.hpp
Go to the documentation of this file.
1// Copyright Take Vos 2020-2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
9#pragma once
10
11#include "../GUI/module.hpp"
12#include "text_widget.hpp"
13#include "icon_widget.hpp"
14#include "../geometry/module.hpp"
15#include "../layout/grid_layout.hpp"
16#include "../label.hpp"
17#include <memory>
18#include <string>
19#include <array>
20#include <optional>
21#include <future>
22
23namespace hi { inline namespace v1 {
24
25template<typename Context>
26concept label_widget_attribute = forward_of<Context, observer<hi::label>, observer<hi::alignment>>;
27
41template<fixed_string Name = "">
42class label_widget final : public widget {
43public:
44 using super = widget;
45 constexpr static auto prefix = Name / "label";
46
49 observer<label> label;
50
68 observer<alignment> alignment = hi::alignment::top_flush();
69
78 {
79 set_attributes(hi_forward(attributes)...);
80 }
81
83 [[nodiscard]] generator<widget const&> children(bool include_invisible) const noexcept override
84 {
85 co_yield *_icon_widget;
86 co_yield *_text_widget;
87 }
88
89 void layout() noexcept override
90 {
91 // Resolve as if in left-to-right mode, the grid will flip itself.
92 hilet resolved_alignment = resolve(*alignment, true);
93
94 if (to_bool(label->icon) and to_bool(label->text)) {
95 // Both of the icon and text are set, so configure the grid to hold both.
96 if (resolved_alignment == horizontal_alignment::left) {
97 // icon text
98 cell.set_child(_icon_widget.cell, 0, 0);
99 cell.set_child(_text_widget.cell, 1, 0);
100
101 } else if (resolved_alignment == horizontal_alignment::right) {
102 // text icon
103 cell.set_child(_text_widget.cell, 0, 0);
104 cell.set_child(_icon_widget.cell, 1, 0);
105
106 } else if (resolved_alignment == vertical_alignment::top) {
107 // icon
108 // text
109 cell.set_child(_icon_widget.cell, 0, 0);
110 cell.set_child(_text_widget.cell, 0, 1);
111
112 } else if (resolved_alignment == vertical_alignment::bottom) {
113 // text
114 // icon
115 cell.set_child(_text_widget.cell, 0, 0);
116 cell.set_child(_icon_widget.cell, 0, 1);
117
118 } else {
119 hi_no_default("alignment is not allowed to be middle-center.");
120 }
121 } else if (to_bool(label->icon)) {
122 // Only the icon-widget is used.
123 cell.set_child(_icon_widget.cell, 0, 0);
124
125 } else if (to_bool(label->text)) {
126 // Only the text-widget is used.
127 cell.set_child(_text_widget.cell, 0, 0);
128 }
129
130 hilet icon_size =
131 (resolved_alignment == horizontal_alignment::center or resolved_alignment == horizontal_alignment::justified) ?
132 theme<prefix>.size(this) :
133 extent2{theme<prefix>.line_height(this), theme<prefix>.line_height(this)};
134
135 _icon_widget->minimum = icon_size;
136 _icon_widget->maximum = icon_size;
137 }
138
139 void draw(widget_draw_context& context) noexcept override
140 {
142 _icon_widget->draw(context);
143 _text_widget->draw(context);
144 }
145 }
146
147 [[nodiscard]] hitbox hitbox_test(point2 position) const noexcept override
148 {
150 return _text_widget->hitbox_test(position);
151 } else {
152 return {};
153 }
154 }
156private:
157 float _icon_size;
158 float _inner_margin;
159
160 decltype(label)::callback_token _label_cbt;
161 decltype(alignment)::callback_token _alignment_cbt;
162
165 grid_layout<widget *> _grid;
166
167 void set_attributes() noexcept {}
168 void set_attributes(label_widget_attribute auto&& first, label_widget_attribute auto&&...rest) noexcept
169 {
170 if constexpr (forward_of<decltype(first), observer<hi::label>>) {
171 label = hi_forward(first);
172 } else if constexpr (forward_of<decltype(first), observer<hi::alignment>>) {
173 alignment = hi_forward(first);
174 } else {
176 }
177
178 set_attributes(hi_forward(rest)...);
179 }
180
181 label_widget(widget *parent) noexcept : super(parent)
182 {
184
185 _icon_widget = std::make_unique<icon_widget<prefix>>(this, label.get<"icon">());
186 _text_widget = std::make_unique<text_widget<prefix>>(this, label.get<"text">());
187 _text_widget->alignment = alignment;
188 _text_widget->mode = mode;
189
190 _alignment_cbt = alignment.subscribe([this](auto...) {
191 if (alignment == horizontal_alignment::center or alignment == horizontal_alignment::justified) {
192 _icon_widget->alignment = hi::alignment::middle_center();
193 } else {
194 _icon_widget->alignment = *alignment;
195 }
196 });
197 (*_alignment_cbt)(*alignment);
198 }
199};
200
201}} // namespace hi::v1
Functionality for labels, text and icons.
Defines icon_widget.
Defines text_widget.
#define hi_static_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:323
#define hi_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:279
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
#define hi_forward(x)
Forward a value, based on the decltype of the value.
Definition utility.hpp:29
geo::extent< float, 2 > extent2
A 2D extent.
Definition extent.hpp:502
@ invisible
The widget is invisible.
@ select
The widget is selectable.
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11
Definition widget.hpp:26
widget * parent
Pointer to the parent widget.
Definition widget.hpp:40
observer< widget_mode > mode
The widget mode.
Definition widget.hpp:49
The GUI widget displays and lays out text together with an icon.
Definition label_widget.hpp:42
label_widget(widget *parent, label_widget_attribute auto &&...attributes) noexcept
Construct a label widget.
Definition label_widget.hpp:77
observer< label > label
The label to display.
Definition label_widget.hpp:49
observer< alignment > alignment
How the label and icon are aligned.
Definition label_widget.hpp:68
Definition label_widget.hpp:26