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;
77 set_attributes<0>(std::forward<Attributes>(attributes)...);
81 void set_attributes() noexcept
86 void set_attributes(First&& first, Rest&&...rest)
noexcept
89 if constexpr (I == 0) {
93 }
else if constexpr (I == 1) {
97 }
else if constexpr (I == 2) {
100 hi_static_no_default();
102 set_attributes<I + 1>(std::forward<Rest>(rest)...);
104 }
else if constexpr (forward_of<
decltype(first), observer<hi::alignment>>) {
106 set_attributes<I>(std::forward<Rest>(rest)...);
108 }
else if constexpr (forward_of<
decltype(first), observer<hi::semantic_text_style>>) {
110 set_attributes<I>(std::forward<Rest>(rest)...);
113 hi_static_no_default();
118 attributes_type attributes;
120 template<
typename... Args>
121 [[nodiscard]]
consteval static size_t num_default_delegate_arguments() noexcept
123 return button_widget_type::template num_default_delegate_arguments<Args...>();
126 template<
size_t N,
typename... Args>
127 [[nodiscard]]
static auto make_default_delegate(Args&&...args)
129 return button_widget_type::template make_default_delegate<N, Args...>(std::forward<Args>(args)...);
132 hi_call_right_arguments(
static, make_attributes, attributes_type);
135 widget_intf
const*
parent,
136 attributes_type attributes,
141 std::make_unique<button_widget_type>(
this, button_attributes_type{this->attributes.alignment},
std::move(delegate));
142 _on_label_widget = std::make_unique<label_widget>(
143 this, this->attributes.on_label, this->attributes.alignment, this->attributes.text_style);
144 _off_label_widget = std::make_unique<label_widget>(
145 this, this->attributes.off_label, this->attributes.alignment, this->attributes.text_style);
146 _other_label_widget = std::make_unique<label_widget>(
147 this, this->attributes.other_label, this->attributes.alignment, this->attributes.text_style);
149 _button_widget_cbt = _button_widget->subscribe([&] {
150 set_value(_button_widget->value());
160 _button_widget_cbt();
169 template<
typename... Args>
171 requires(num_default_delegate_arguments<Args...>() != 0)
175 make_attributes<num_default_delegate_arguments<Args...>()>(std::forward<Args>(args)...),
176 make_default_delegate<num_default_delegate_arguments<Args...>()>(std::forward<Args>(args)...))
186 auto const resolved_alignment = resolve(*attributes.alignment,
true);
191 _grid.
add_cell(0, 0, grid_cell_type::button);
192 _grid.
add_cell(1, 0, grid_cell_type::label,
true);
195 _grid.
add_cell(0, 0, grid_cell_type::label,
true);
196 _grid.
add_cell(1, 0, grid_cell_type::button);
200 _grid.
add_cell(0, 0, grid_cell_type::button);
201 _grid.
add_cell(0, 1, grid_cell_type::label,
true);
205 _grid.
add_cell(0, 0, grid_cell_type::label,
true);
206 _grid.
add_cell(0, 1, grid_cell_type::button);
208 hi_no_default(
"alignment is not allowed to be middle-center.");
211 for (
auto& cell : _grid) {
212 if (cell.value == grid_cell_type::button) {
213 cell.set_constraints(_button_widget->update_constraints());
215 }
else if (cell.value == grid_cell_type::label) {
216 auto const on_label_constraints = _on_label_widget->update_constraints();
217 auto const off_label_constraints = _off_label_widget->update_constraints();
218 auto const other_label_constraints = _other_label_widget->update_constraints();
219 cell.set_constraints(max(on_label_constraints, off_label_constraints, other_label_constraints));
226 return _grid.constraints(os_settings::left_to_right());
229 void set_layout(widget_layout
const& context)
noexcept override
232 _grid.
set_layout(context.shape, theme().baseline_adjustment());
235 for (
auto const& cell : _grid) {
236 if (cell.value == grid_cell_type::button) {
239 }
else if (cell.value == grid_cell_type::label) {
240 _on_label_widget->set_layout(context.transform(cell.shape));
241 _off_label_widget->set_layout(context.transform(cell.shape));
242 _other_label_widget->set_layout(context.transform(cell.shape));
250 void draw(draw_context
const& context)
noexcept override
253 for (
auto const& cell : _grid) {
254 if (cell.value == grid_cell_type::button) {
255 _button_widget->draw(context);
257 }
else if (cell.value == grid_cell_type::label) {
258 _on_label_widget->draw(context);
259 _off_label_widget->draw(context);
260 _other_label_widget->draw(context);
269 [[nodiscard]] generator<widget_intf&> children(
bool include_invisible)
noexcept override
271 co_yield *_button_widget;
273 co_yield *_on_label_widget;
276 co_yield *_off_label_widget;
279 co_yield *_other_label_widget;
283 [[nodiscard]] hitbox hitbox_test(point2 position)
const noexcept override
285 hi_axiom(loop::main().on_thread());
289 return {_button_widget->id, _layout.elevation, hitbox_type::button};
296 enum class grid_cell_type { button, label };
298 grid_layout<grid_cell_type> _grid;
306 callback<void()> _button_widget_cbt;