11#include "../GUI/module.hpp"
14namespace hi {
inline namespace v1 {
16template<
typename Context>
51template<fixed_string Name =
"">
56 constexpr static auto prefix = Name /
"toggle";
58 enum class cell_type { toggle, label };
78 observer<hi::alignment>
alignment = alignment::top_left();
93 this->set_attributes<0>(
hi_forward(attributes)...);
99 _grid.
add_cell(0, 0, cell_type::toggle);
100 _grid.
add_cell(1, 0, cell_type::label);
102 _delegate_cbt = this->delegate->subscribe([&] {
103 ++global_counter<
"toggle_widget:delegate:redraw">;
105 state = this->delegate->state(
this);
113 this->delegate->init(*
this);
126 template<different_from<std::shared_ptr<delegate_type>> Value, toggle_w
idget_attribute... Attributes>
145 different_from<std::shared_ptr<delegate_type>> Value,
146 forward_of<observer<observer_decay_t<Value>>> OnValue,
147 toggle_widget_attribute... Attributes>
167 different_from<std::shared_ptr<delegate_type>> Value,
168 forward_of<observer<observer_decay_t<Value>>> OnValue,
169 forward_of<observer<observer_decay_t<Value>>> OffValue,
170 toggle_widget_attribute... Attributes>
184 for (
auto& cell : _grid) {
185 if (cell.value == cell_type::toggle) {
186 cell.set_constraints(
188 theme<prefix>.size(
this),
189 theme<prefix>.size(
this),
190 theme<prefix>.size(
this),
192 theme<prefix>.margin(
this)});
194 }
else if (cell.value == cell_type::label) {
195 cell.set_constraints(
196 max(_on_label_widget->update_constraints(),
197 _off_label_widget->update_constraints(),
198 _other_label_widget->update_constraints()));
205 return _grid.constraints(os_settings::left_to_right());
208 void set_layout(widget_layout
const& context)
noexcept override
211 _grid.
set_layout(context.shape, theme<prefix>.cap_height(
this));
214 for (
hilet& cell : _grid) {
215 if (cell.value == cell_type::toggle) {
219 _pip_edge_distance = (cell.shape.height() -
theme<prefix /
"pip">.height(
this)) / 2;
220 _pip_move_range = cell.shape.width() - _pip_edge_distance * 2 -
theme<prefix /
"pip">.width(
this);
222 }
else if (cell.value == cell_type::label) {
223 _on_label_widget->set_layout(context.transform(cell.shape, 0.0f));
224 _off_label_widget->set_layout(context.transform(cell.shape, 0.0f));
225 _other_label_widget->set_layout(context.transform(cell.shape, 0.0f));
233 void draw(widget_draw_context& context)
noexcept override
236 for (
hilet& cell : _grid) {
237 if (cell.value == cell_type::toggle) {
238 draw_toggle_button(context, cell.shape);
239 draw_toggle_pip(context, cell.shape);
241 }
else if (cell.value == cell_type::label) {
242 _on_label_widget->draw(context);
243 _off_label_widget->draw(context);
244 _other_label_widget->draw(context);
253 [[nodiscard]] generator<widget const&> children(
bool include_invisible)
const noexcept override
255 co_yield *_on_label_widget;
256 co_yield *_off_label_widget;
257 co_yield *_other_label_widget;
260 [[nodiscard]] hitbox hitbox_test(point2i position)
const noexcept final
265 return {
id, layout.
elevation, hitbox_type::button};
271 [[nodiscard]]
bool accepts_keyboard_focus(keyboard_focus_group group)
const noexcept override
277 void activate() noexcept
281 this->_state_changed();
284 bool handle_event(gui_event
const& event)
noexcept override
288 switch (event.type()) {
289 case gui_event_type::gui_activate:
296 case gui_event_type::mouse_down:
304 case gui_event_type::mouse_up:
308 if (layout.rectangle().
contains(event.mouse().position)) {
309 handle_event(gui_event_type::gui_activate);
325 grid_layout<cell_type> _grid;
331 notifier<>::callback_token _delegate_cbt;
333 animator<float> _animated_value = _animation_duration;
335 int _pip_edge_distance;
337 void draw_toggle_button(widget_draw_context& context, box_shape
const& shape)
noexcept
342 theme<prefix>.background_color(
this),
343 theme<prefix>.border_color(
this),
344 theme<prefix>.border_width(
this),
346 theme<prefix>.border_radius(
this));
349 void draw_toggle_pip(widget_draw_context& context, box_shape
const& shape)
noexcept
352 if (_animated_value.is_animating()) {
356 hilet move_offset = [&] {
357 if (os_settings::left_to_right()) {
358 return _pip_move_range * _animated_value.current_value();
360 return _pip_move_range * (1.0f - _animated_value.current_value());
364 hilet pip_rectangle = aarectanglei{point2i{_pip_edge_distance, _pip_edge_distance},
theme<prefix /
"pip">.size(
this)};
365 hilet pip_rectangle_ =
366 translate3{move_offset + shape.x(), 0.0f + shape.y(), 0.1f} * narrow_cast<aarectangle>(pip_rectangle);
371 theme<prefix / "pip">.background_color(
this),
372 theme<prefix / "pip">.border_color(
this),
373 theme<prefix / "pip">.border_width(
this),
375 theme<prefix / "pip">.border_radius(
this));
378 template<
size_t LabelCount>
379 void set_attributes() noexcept
383 template<
size_t LabelCount>
384 void set_attributes(toggle_widget_attribute
auto&& first, toggle_widget_attribute
auto&&...rest)
noexcept
386 if constexpr (forward_of<
decltype(first), observer<hi::label>>) {
387 if constexpr (LabelCount == 0) {
391 }
else if constexpr (LabelCount == 1) {
395 }
else if constexpr (LabelCount == 2) {
400 set_attributes<LabelCount + 1>(
hi_forward(rest)...);
402 }
else if constexpr (forward_of<
decltype(first), observer<hi::alignment>>) {
404 set_attributes<LabelCount>(
hi_forward(rest)...);
Defines toggle_delegate and some default toggle_delegate delegates.
#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 hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:253
#define hi_assert_not_null(x,...)
Assert if an expression is not nullptr.
Definition assert.hpp:238
#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
@ window_redraw
Request that part of the window gets redrawn on the next frame.
std::shared_ptr< toggle_delegate > make_default_toggle_delegate(auto &&value, auto &&...args) noexcept
Make a shared pointer to a toggle-button delegate.
Definition toggle_delegate.hpp:144
@ partial
A widget is partially enabled.
@ invisible
The widget is invisible.
@ display
The widget is in display-only mode.
DOXYGEN BUG.
Definition algorithm.hpp:13
constexpr auto join_path(fixed_string< L > const &lhs, fixed_string< R > const &rhs) noexcept
lhs / rhs
Definition fixed_string.hpp:273
geometry/margins.hpp
Definition cache.hpp:11
@ inside
The border is drawn inside the edge of a quad.
@ outside
The border is drawn outside the edge of a quad.
@ off
The widget in the off-state.
@ other
The widget is in the other-state.
@ on
The widget is in the on-state.
bool compare_store(T &lhs, U &&rhs) noexcept
Compare then store if there was a change.
Definition utility.hpp:212
auto theme
A tagged global variable to a theme model for a widget's component.
Definition theme_model.hpp:578
constexpr bool contains(point< value_type, 2 > const &rhs) const noexcept
Check if a 2D coordinate is inside the rectangle.
Definition axis_aligned_rectangle.hpp:265
widget_id id
The numeric identifier of a widget.
Definition widget.hpp:35
virtual void request_redraw() const noexcept
Request the widget to be redrawn on the next frame.
Definition widget.hpp:265
observer< bool > clicked
The widget is being clicked by the mouse.
Definition widget.hpp:57
observer< widget_state > state
The state of the widget.
Definition widget.hpp:65
virtual bool handle_event(gui_event const &event) noexcept
Handle command.
Definition widget.hpp:274
widget * parent
Pointer to the parent widget.
Definition widget.hpp:40
observer< widget_mode > mode
The widget mode.
Definition widget.hpp:49
constexpr bool contains(point3i mouse_position) const noexcept
Check if the mouse position is inside the widget.
Definition widget_layout.hpp:126
float elevation
The elevation of the widget above the window.
Definition widget_layout.hpp:72
2D constraints.
Definition box_constraints.hpp:22
constexpr reference add_cell(size_t first_column, size_t first_row, size_t last_column, size_t last_row, Value &&value, bool beyond_maximum=false) noexcept
Check if the cell on the grid is already in use.
Definition grid_layout.hpp:1056
constexpr void set_layout(box_shape const &shape, int baseline_adjustment) noexcept
Layout the cells based on the width and height.
Definition grid_layout.hpp:1132
The GUI widget displays and lays out text together with an icon.
Definition label_widget.hpp:42
A toggle delegate controls the state of a toggle widget.
Definition toggle_delegate.hpp:18
A GUI widget that permits the user to make a binary choice.
Definition toggle_widget.hpp:52
observer< label > other_label
The label to show when the button is in the 'other' state.
Definition toggle_widget.hpp:74
observer< label > on_label
The label to show when the button is in the 'on' state.
Definition toggle_widget.hpp:66
toggle_widget(widget *parent, Value &&value, OnValue &&on_value, Attributes &&...attributes) noexcept
Construct a toggle widget with a default button delegate.
Definition toggle_widget.hpp:148
observer< hi::alignment > alignment
The alignment of the button and on/off/other label.
Definition toggle_widget.hpp:78
toggle_widget(widget *parent, Value &&value, Attributes &&...attributes) noexcept
Construct a toggle widget with a default button delegate.
Definition toggle_widget.hpp:127
std::shared_ptr< delegate_type > delegate
The delegate that controls the button widget.
Definition toggle_widget.hpp:62
toggle_widget(widget *parent, std::shared_ptr< delegate_type > delegate, toggle_widget_attribute auto &&...attributes) noexcept
Construct a toggle widget.
Definition toggle_widget.hpp:89
toggle_widget(widget *parent, Value &&value, OnValue &&on_value, OffValue &&off_value, Attributes &&...attributes) noexcept
Construct a toggle widget with a default button delegate.
Definition toggle_widget.hpp:171
observer< label > off_label
The label to show when the button is in the 'off' state.
Definition toggle_widget.hpp:70
Definition label_widget.hpp:26
Definition toggle_widget.hpp:17