HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
abstract_button_widget.hpp
Go to the documentation of this file.
1// Copyright Take Vos 2021-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
8
9#pragma once
10
11#include "widget.hpp"
12#include "button_delegate.hpp"
13#include "label_widget.hpp"
14#include "../algorithm/algorithm.hpp"
15#include "../l10n/l10n.hpp"
16#include "../observer/observer.hpp"
17#include "../macros.hpp"
18#include <memory>
19#include <string>
20#include <array>
21#include <optional>
22#include <future>
23#include <coroutine>
24
25hi_export_module(hikogui.widgets.abstract_button_widget);
26
27hi_export namespace hi { inline namespace v1 {
28
29template<typename Context>
31
37public:
38 using super = widget;
39 using delegate_type = button_delegate;
40
44
48
52
56
60
61 ~abstract_button_widget()
62 {
63 hi_assert_not_null(delegate);
64 delegate->deinit(*this);
65 }
66
68 super(), delegate(std::move(delegate))
69 {
70 hi_assert_not_null(this->delegate);
71
72 _on_label_widget = std::make_unique<label_widget>(on_label, alignment);
73 _on_label_widget->set_parent(this);
74 _off_label_widget = std::make_unique<label_widget>(off_label, alignment);
75 _off_label_widget->set_parent(this);
76 _other_label_widget = std::make_unique<label_widget>(other_label, alignment);
77 _other_label_widget->set_parent(this);
78
79 this->delegate->init(*this);
80 _delegate_cbt = this->delegate->subscribe([&] {
81 set_value(this->delegate->state(*this));
82 });
83 _delegate_cbt();
84 }
85
87 [[nodiscard]] box_constraints update_constraints() noexcept override
88 {
89 _layout = {};
90 _on_label_constraints = _on_label_widget->update_constraints();
91 _off_label_constraints = _off_label_widget->update_constraints();
92 _other_label_constraints = _other_label_widget->update_constraints();
93 return max(_on_label_constraints, _off_label_constraints, _other_label_constraints);
94 }
95
96 void set_layout(widget_layout const& context) noexcept override
97 {
98 _on_label_widget->set_mode(value() == widget_value::on ? widget_mode::display : widget_mode::invisible);
99 _off_label_widget->set_mode(value() == widget_value::off ? widget_mode::display : widget_mode::invisible);
100 _other_label_widget->set_mode(value() == widget_value::other ? widget_mode::display : widget_mode::invisible);
101
102 _on_label_widget->set_layout(context.transform(_on_label_shape));
103 _off_label_widget->set_layout(context.transform(_off_label_shape));
104 _other_label_widget->set_layout(context.transform(_other_label_shape));
105 }
106
107 [[nodiscard]] generator<widget_intf&> children(bool include_invisible) noexcept override
108 {
109 co_yield *_on_label_widget;
110 co_yield *_off_label_widget;
111 co_yield *_other_label_widget;
112 }
113
114 [[nodiscard]] color background_color() const noexcept override
115 {
116 hi_axiom(loop::main().on_thread());
117 if (phase() == widget_phase::pressed) {
118 return theme().fill_color(_layout.layer + 2);
119 } else {
120 return super::background_color();
121 }
122 }
123
124 [[nodiscard]] hitbox hitbox_test(point2 position) const noexcept override
125 {
126 hi_axiom(loop::main().on_thread());
127
128 if (mode() >= widget_mode::partial and layout().contains(position)) {
129 return {id, _layout.elevation, hitbox_type::button};
130 } else {
131 return {};
132 }
133 }
134
135 [[nodiscard]] bool accepts_keyboard_focus(keyboard_focus_group group) const noexcept override
136 {
137 hi_axiom(loop::main().on_thread());
138 return mode() >= widget_mode::partial and to_bool(group & hi::keyboard_focus_group::normal);
139 }
140
141 void activate() noexcept
142 {
143 hi_assert_not_null(delegate);
144 delegate->activate(*this);
145
146 notifier();
147 }
148
149 bool handle_event(gui_event const& event) noexcept override
150 {
151 hi_axiom(loop::main().on_thread());
152
153 switch (event.type()) {
154 case gui_event_type::gui_activate:
155 if (mode() >= widget_mode::partial) {
156 activate();
157 return true;
158 }
159 break;
160
161 case gui_event_type::mouse_down:
162 if (mode() >= widget_mode::partial and event.mouse().cause.left_button) {
163 set_pressed(true);
164 return true;
165 }
166 break;
167
168 case gui_event_type::mouse_up:
169 if (mode() >= widget_mode::partial and event.mouse().cause.left_button) {
170 set_pressed(false);
171
172 if (layout().rectangle().contains(event.mouse().position)) {
173 handle_event(gui_event_type::gui_activate);
174 }
175 return true;
176 }
177 break;
178
179 default:;
180 }
181
182 return super::handle_event(event);
183 }
185protected:
186 std::unique_ptr<label_widget> _on_label_widget;
187 box_constraints _on_label_constraints;
188 box_shape _on_label_shape;
189
190 std::unique_ptr<label_widget> _off_label_widget;
191 box_constraints _off_label_constraints;
192 box_shape _off_label_shape;
193
194 std::unique_ptr<label_widget> _other_label_widget;
195 box_constraints _other_label_constraints;
196 box_shape _other_label_shape;
197
198 callback<void()> _delegate_cbt;
199
200 template<size_t I>
201 void set_attributes() noexcept
202 {
203 }
204
205 template<size_t I, button_widget_attribute First, button_widget_attribute... Rest>
206 void set_attributes(First&& first, Rest&&...rest) noexcept
207 {
208 if constexpr (forward_of<First, observer<hi::label>>) {
209 if constexpr (I == 0) {
210 on_label = first;
211 off_label = first;
213 } else if constexpr (I == 1) {
214 other_label.reset();
215 off_label.reset();
217 } else if constexpr (I == 2) {
219 } else {
220 hi_static_no_default();
221 }
222 set_attributes<I + 1>(std::forward<Rest>(rest)...);
223
224 } else if constexpr (forward_of<First, observer<hi::alignment>>) {
226 set_attributes<I>(std::forward<Rest>(rest)...);
227
228 } else {
229 hi_static_no_default();
230 }
231 }
232
233 void draw_button(draw_context const& context) noexcept
234 {
235 _on_label_widget->draw(context);
236 _off_label_widget->draw(context);
237 _other_label_widget->draw(context);
238 }
239};
240
241}} // namespace hi::v1
Defines widget.
Defines label_widget.
Defines button_delegate and some default button delegates.
@ rectangle
The gui_event has rectangle data.
Definition gui_event_variant.hpp:44
@ partial
A widget is partially enabled.
Definition widget_state.hpp:73
@ invisible
The widget is invisible.
Definition widget_state.hpp:41
@ display
The widget is in display-only mode.
Definition widget_state.hpp:55
The HikoGUI namespace.
Definition array_generic.hpp:21
The HikoGUI API version 1.
Definition array_generic.hpp:22
@ color
A color value was modified.
Definition style_modify_mask.hpp:27
Horizontal/Vertical alignment combination.
Definition alignment.hpp:244
notifier< void()> notifier
Notifier which is called after an action is completed by a widget.
Definition widget_intf.hpp:45
widget_id id
The numeric identifier of a widget.
Definition widget_intf.hpp:31
widget_layout const & layout() const noexcept
Get the current layout for this widget.
Definition widget_intf.hpp:241
A localizable message.
Definition txt.hpp:100
A observer pointing to the whole or part of a observed_base.
Definition observer_intf.hpp:32
Base class for implementing button widgets.
Definition abstract_button_widget.hpp:36
observer< label > other_label
The label to show when the button is in the 'other' state.
Definition abstract_button_widget.hpp:55
std::shared_ptr< delegate_type > delegate
The delegate that controls the button widget.
Definition abstract_button_widget.hpp:43
observer< label > on_label
The label to show when the button is in the 'on' state.
Definition abstract_button_widget.hpp:47
observer< label > off_label
The label to show when the button is in the 'off' state.
Definition abstract_button_widget.hpp:51
observer< alignment > alignment
The alignment of the button and on/off/other label.
Definition abstract_button_widget.hpp:59
A button delegate controls the state of a button widget.
Definition button_delegate.hpp:28
widget() noexcept
Constructor for creating sub views.
Definition widget.hpp:50
box_constraints update_constraints() noexcept override
Update the constraints of the widget.
Definition widget.hpp:110
bool handle_event(gui_event const &event) noexcept override
Handle command.
Definition widget.hpp:145
Definition abstract_button_widget.hpp:30
Definition label_widget.hpp:30
T forward(T... args)
T max(T... args)
T move(T... args)