41 using button_widget_type = ButtonWidget;
42 using button_attributes_type = button_widget_type::attributes_type;
43 using delegate_type = button_widget_type::delegate_type;
45 struct attributes_type {
58 attributes_type(attributes_type
const&)
noexcept =
default;
59 attributes_type(attributes_type&&) noexcept = default;
60 attributes_type& operator=(attributes_type const&) noexcept = default;
61 attributes_type& operator=(attributes_type&&) noexcept = default;
64 explicit attributes_type(Attributes&&... attributes) noexcept
70 void set_attributes() noexcept
75 void set_attributes(First&& first, Rest&&... rest)
noexcept
78 if constexpr (I == 0) {
80 }
else if constexpr (I == 1) {
83 hi_static_no_default();
87 }
else if constexpr (forward_of<First, observer<hi::alignment>>) {
92 hi_static_no_default();
99 template<
typename... Args>
100 [[nodiscard]]
consteval static size_t num_default_delegate_arguments() noexcept
102 return button_widget_type::template num_default_delegate_arguments<Args...>();
105 template<
size_t N,
typename... Args>
106 [[nodiscard]]
static auto make_default_delegate(Args&&... args)
108 return button_widget_type::template make_default_delegate<N, Args...>(
std::forward<Args>(args)...);
113 menu_button_widget(
attributes_type attributes, std::shared_ptr<delegate_type> delegate) noexcept :
114 super(), attributes(
std::move(attributes))
116 _button_widget = std::make_unique<button_widget_type>(
117 button_attributes_type{this->attributes.alignment, keyboard_focus_group::menu},
std::move(delegate));
118 _button_widget->set_parent(
this);
120 _label_widget = std::make_unique<label_widget>(this->attributes.label, this->attributes.alignment);
121 _label_widget->set_parent(
this);
123 _shortcut_widget = std::make_unique<label_widget>(this->attributes.shortcut, this->attributes.alignment);
124 _shortcut_widget->set_parent(
this);
127 _button_widget->state =
state;
129 _button_widget_cbt = _button_widget->subscribe([&] {
134 _button_widget_cbt();
143 template<
typename... Args>
148 make_attributes<num_default_delegate_arguments<Args...>()>(
std::forward<Args>(args)...),
149 make_default_delegate<num_default_delegate_arguments<Args...>()>(
std::forward<Args>(args)...))
159 _grid.
add_cell(0, 0, grid_cell_type::button);
160 _grid.
add_cell(1, 0, grid_cell_type::label,
true);
161 _grid.
add_cell(2, 0, grid_cell_type::shortcut);
163 for (
auto& cell : _grid) {
164 if (cell.value == grid_cell_type::button) {
165 auto constraints = _button_widget->update_constraints();
166 inplace_max(constraints.minimum.width(), theme().size() * 2.0f);
167 inplace_max(constraints.preferred.width(), theme().size() * 2.0f);
168 inplace_max(constraints.maximum.width(), theme().size() * 2.0f);
169 cell.set_constraints(constraints);
171 }
else if (cell.value == grid_cell_type::label) {
172 cell.set_constraints(_label_widget->update_constraints());
174 }
else if (cell.value == grid_cell_type::shortcut) {
175 auto constraints = _shortcut_widget->update_constraints();
176 inplace_max(constraints.minimum.width(), theme().size() * 3.0f);
177 inplace_max(constraints.preferred.width(), theme().size() * 3.0f);
178 inplace_max(constraints.maximum.width(), theme().size() * 3.0f);
179 cell.set_constraints(constraints);
186 auto constraints = _grid.constraints(os_settings::left_to_right());
190 constraints.margins = {};
194 void set_layout(widget_layout
const& context)
noexcept override
197 auto shape = context.shape;
199 _grid.set_layout(shape, theme().baseline_adjustment());
202 for (
auto const& cell : _grid) {
203 if (cell.value == grid_cell_type::button) {
206 }
else if (cell.value == grid_cell_type::label) {
207 _label_widget->set_layout(context.transform(cell.shape));
209 }
else if (cell.value == grid_cell_type::shortcut) {
210 _shortcut_widget->set_layout(context.transform(cell.shape));
218 void draw(draw_context
const& context)
noexcept override
221 auto outline_color = focus() ? focus_color() : background_color();
225 for (
auto const& cell : _grid) {
226 if (cell.value == grid_cell_type::button) {
227 _button_widget->draw(context);
229 }
else if (cell.value == grid_cell_type::label) {
230 _label_widget->draw(context);
232 }
else if (cell.value == grid_cell_type::shortcut) {
233 _shortcut_widget->draw(context);
242 [[nodiscard]] generator<widget_intf&> children(
bool include_invisible)
noexcept override
244 co_yield *_button_widget;
245 co_yield *_label_widget;
246 co_yield *_shortcut_widget;
249 [[nodiscard]] hitbox hitbox_test(point2 position)
const noexcept override
251 hi_axiom(loop::main().on_thread());
255 return {_button_widget->id, _layout.elevation, hitbox_type::button};
262 enum class grid_cell_type { button, label, shortcut };
264 grid_layout<grid_cell_type> _grid;
266 std::unique_ptr<button_widget_type> _button_widget;
268 std::unique_ptr<label_widget> _label_widget;
269 std::unique_ptr<label_widget> _shortcut_widget;
271 callback<void()> _button_widget_cbt;