41class with_label_widget :
public widget {
44 using button_widget_type = ButtonWidget;
45 using button_attributes_type = button_widget_type::attributes_type;
46 using delegate_type = button_widget_type::delegate_type;
48 struct attributes_type {
65 attributes_type(attributes_type
const&)
noexcept =
default;
66 attributes_type(attributes_type&&) noexcept = default;
67 attributes_type& operator=(attributes_type const&) noexcept = default;
68 attributes_type& operator=(attributes_type&&) noexcept = default;
71 explicit attributes_type(Attributes&&... attributes) noexcept
77 void set_attributes() noexcept
82 void set_attributes(First&& first, Rest&&... rest)
noexcept
85 if constexpr (I == 0) {
89 }
else if constexpr (I == 1) {
93 }
else if constexpr (I == 2) {
96 hi_static_no_default();
100 }
else if constexpr (forward_of<
decltype(first), observer<hi::alignment>>) {
105 hi_static_no_default();
112 template<
typename... Args>
113 [[nodiscard]]
consteval static size_t num_default_delegate_arguments() noexcept
115 return button_widget_type::template num_default_delegate_arguments<Args...>();
118 template<
size_t N,
typename... Args>
119 [[nodiscard]]
static auto make_default_delegate(Args&&... args)
121 return button_widget_type::template make_default_delegate<N, Args...>(
std::forward<Args>(args)...);
126 with_label_widget(
attributes_type attributes, std::shared_ptr<delegate_type> delegate) noexcept :
127 super(), attributes(
std::move(attributes))
130 std::make_unique<button_widget_type>(button_attributes_type{this->attributes.alignment},
std::move(delegate));
131 _button_widget->set_parent(
this);
133 _on_label_widget = std::make_unique<label_widget>(this->attributes.on_label, this->attributes.alignment);
134 _on_label_widget->set_parent(
this);
136 _off_label_widget = std::make_unique<label_widget>(this->attributes.off_label, this->attributes.alignment);
137 _off_label_widget->set_parent(
this);
139 _other_label_widget = std::make_unique<label_widget>(this->attributes.other_label, this->attributes.alignment);
140 _other_label_widget->set_parent(
this);
142 _button_widget_cbt = _button_widget->subscribe([&] {
143 set_value(_button_widget->value());
153 _button_widget_cbt();
162 template<
typename... Args>
166 make_attributes<num_default_delegate_arguments<Args...>()>(
std::forward<Args>(args)...),
167 make_default_delegate<num_default_delegate_arguments<Args...>()>(
std::forward<Args>(args)...))
177 auto const resolved_alignment = resolve(*attributes.alignment,
true);
182 _grid.
add_cell(0, 0, grid_cell_type::button);
183 _grid.
add_cell(1, 0, grid_cell_type::label,
true);
186 _grid.
add_cell(0, 0, grid_cell_type::label,
true);
187 _grid.
add_cell(1, 0, grid_cell_type::button);
191 _grid.add_cell(0, 0, grid_cell_type::button);
192 _grid.add_cell(0, 1, grid_cell_type::label,
true);
196 _grid.add_cell(0, 0, grid_cell_type::label,
true);
197 _grid.add_cell(0, 1, grid_cell_type::button);
199 hi_no_default(
"alignment is not allowed to be middle-center.");
202 for (
auto& cell : _grid) {
203 if (cell.value == grid_cell_type::button) {
204 cell.set_constraints(_button_widget->update_constraints());
206 }
else if (cell.value == grid_cell_type::label) {
207 auto const on_label_constraints = _on_label_widget->update_constraints();
208 auto const off_label_constraints = _off_label_widget->update_constraints();
209 auto const other_label_constraints = _other_label_widget->update_constraints();
210 cell.set_constraints(
max(on_label_constraints, off_label_constraints, other_label_constraints));
217 return _grid.constraints(os_settings::left_to_right());
220 void set_layout(widget_layout
const& context)
noexcept override
223 _grid.set_layout(context.shape, theme().baseline_adjustment());
226 for (
auto const& cell : _grid) {
227 if (cell.value == grid_cell_type::button) {
230 }
else if (cell.value == grid_cell_type::label) {
231 _on_label_widget->set_layout(context.transform(cell.shape));
232 _off_label_widget->set_layout(context.transform(cell.shape));
233 _other_label_widget->set_layout(context.transform(cell.shape));
241 void draw(draw_context
const& context)
noexcept override
244 for (
auto const& cell : _grid) {
245 if (cell.value == grid_cell_type::button) {
246 _button_widget->draw(context);
248 }
else if (cell.value == grid_cell_type::label) {
249 _on_label_widget->draw(context);
250 _off_label_widget->draw(context);
251 _other_label_widget->draw(context);
260 [[nodiscard]] generator<widget_intf&> children(
bool include_invisible)
noexcept override
262 co_yield *_button_widget;
264 co_yield *_on_label_widget;
267 co_yield *_off_label_widget;
270 co_yield *_other_label_widget;
274 [[nodiscard]] hitbox hitbox_test(point2 position)
const noexcept override
276 hi_axiom(loop::main().on_thread());
280 return {_button_widget->id, _layout.elevation, hitbox_type::button};
287 enum class grid_cell_type { button, label };
289 grid_layout<grid_cell_type> _grid;
291 std::unique_ptr<button_widget_type> _button_widget;
293 std::unique_ptr<label_widget> _on_label_widget;
294 std::unique_ptr<label_widget> _off_label_widget;
295 std::unique_ptr<label_widget> _other_label_widget;
297 callback<void()> _button_widget_cbt;