7#include "widget_id.hpp"
8#include "widget_mode.hpp"
9#include "widget_state.hpp"
10#include "widget_layout.hpp"
12#include "keyboard_focus_group.hpp"
14#include "widget_draw_context.hpp"
15#include "../theme/module.hpp"
16#include "../geometry/module.hpp"
17#include "../layout/box_constraints.hpp"
18#include "../observer.hpp"
19#include "../generator.hpp"
22namespace hi {
inline namespace v1 {
28 using callback_token = notifier<void()>::callback_token;
29 using awaiter_type = notifier<void()>::awaiter_type;
93 observer<extent2i>
maximum = extent2i::large();
106 _mode_cbt =
mode.subscribe([&](
auto...) {
107 ++global_counter<
"widget:mode:constrain">;
112 widget(widget
const&) =
delete;
113 widget(widget&&) =
delete;
114 widget& operator=(widget&&) =
delete;
115 widget& operator=(widget
const&) =
delete;
119 [[nodiscard]]
virtual generator<widget const&>
children(
bool include_invisible)
const noexcept
124 [[nodiscard]] generator<widget&>
children(
bool include_invisible)
noexcept
126 for (
auto& child : const_cast<
widget const *>(this)->
children(include_invisible)) {
127 co_yield const_cast<widget&
>(child);
138 [[nodiscard]]
virtual hitbox
hitbox_test(point2i position)
const noexcept
178 void reset_layout(gui_window *new_window, gfx_surface *new_surface,
float new_scale)
noexcept
183 _scale = narrow_cast<int>(
std::round(new_scale * -4.0));
236 auto s = theme_state{};
238 s |= theme_state::disabled;
240 s |= theme_state::active;
242 s |= theme_state::hover;
244 s |= theme_state::enabled;
248 s |= theme_state::focus;
252 s |= theme_state::on;
255 s |=
static_cast<theme_state
>((
semantic_layer % 4) * to_underlying(theme_state::layer_1));
256 return sub_theme_selector_type{s, _scale};
259 virtual bool process_event(gui_event
const& event)
const noexcept
262 return parent->process_event(event);
283 switch (event.type()) {
288 ++global_counter<
"widget:keyboard_enter:redraw">;
294 ++global_counter<
"widget:keyboard_exit:redraw">;
300 ++global_counter<
"widget:mouse_enter:redraw">;
306 ++global_counter<
"widget:mouse_exit:redraw">;
310 case gui_widget_next:
312 gui_event::window_set_keyboard_target(
id, keyboard_focus_group::normal, keyboard_focus_direction::forward));
315 case gui_widget_prev:
317 gui_event::window_set_keyboard_target(
id, keyboard_focus_group::normal, keyboard_focus_direction::backward));
320 case gui_activate_next:
321 process_event(gui_activate);
322 return process_event(gui_widget_next);
324 case gui_event_type::gui_toolbar_next:
326 not is_last(keyboard_focus_group::toolbar)) {
328 gui_event::window_set_keyboard_target(
id, keyboard_focus_group::toolbar, keyboard_focus_direction::forward));
333 case gui_event_type::gui_toolbar_prev:
335 not is_first(keyboard_focus_group::toolbar)) {
337 gui_event::window_set_keyboard_target(
id, keyboard_focus_group::toolbar, keyboard_focus_direction::backward));
360 auto handled =
false;
362 for (
auto& child :
children(false)) {
363 handled |= child.handle_event_recursive(event, reject_list);
366 if (not std::ranges::any_of(reject_list, [&](
hilet& x) {
389 widget_id current_keyboard_widget,
390 keyboard_focus_group group,
391 keyboard_focus_direction direction)
const noexcept
401 }
else if (current_keyboard_widget ==
id) {
406 for (
auto& child :
children(
false)) {
410 if (direction == keyboard_focus_direction::backward) {
414 for (
auto *child : children_) {
419 if (
auto tmp = child->find_next_widget({}, group, direction)) {
424 auto tmp = child->find_next_widget(current_keyboard_widget, group, direction);
425 if (tmp == current_keyboard_widget) {
430 }
else if (tmp !=
nullptr) {
442 return current_keyboard_widget;
448 [[nodiscard]] widget_id find_first_widget(keyboard_focus_group group)
const noexcept
452 for (
auto& child :
children(false)) {
453 if (child.accepts_keyboard_focus(group)) {
460 [[nodiscard]] widget_id find_last_widget(keyboard_focus_group group)
const noexcept
464 auto found = widget_id{};
465 for (
auto& child :
children(false)) {
466 if (child.accepts_keyboard_focus(group)) {
474 [[nodiscard]]
bool is_first(keyboard_focus_group group)
const noexcept
477 return parent->find_first_widget(group) ==
id;
480 [[nodiscard]]
bool is_last(keyboard_focus_group group)
const noexcept
483 return parent->find_last_widget(group) ==
id;
512 while (to_bool(w = w->parent)) {
530 template<forward_of<
void()> Callback>
531 [[nodiscard]] callback_token subscribe(Callback&& callback, callback_flags flags = callback_flags::synchronous)
const noexcept
533 return _state_changed.subscribe(std::forward<Callback>(callback), flags);
536 [[nodiscard]] awaiter_type
operator co_await()
const noexcept
538 return _state_changed.operator
co_await();
553 mutable notifier<void()> _state_changed;
564 [[nodiscard]] aarectanglei make_overlay_rectangle(aarectanglei requested_rectangle)
const noexcept
572 hilet response_window_rectangle =
fit(window_bounds, requested_window_rectangle);
573 return layout.
from_window * response_window_rectangle;
577 decltype(
mode)::callback_token _mode_cbt;
580inline widget *get_if(widget *start, widget_id
id,
bool include_invisible)
noexcept
584 if (start->id ==
id) {
587 for (
auto& child : start->children(include_invisible)) {
588 if (
hilet r = get_if(&child,
id, include_invisible); r !=
nullptr) {
595inline widget& get(widget& start, widget_id
id,
bool include_invisible)
597 if (
auto r = get_if(
std::addressof(start),
id, include_invisible); r !=
nullptr) {
600 throw not_found_error(
"get widget by id");
603template<std::invocable<w
idget&> F>
604inline void apply(widget& start,
bool include_invisible, F
const& f)
606 for (
auto& child : start.children(include_invisible)) {
607 apply(child, include_invisible, f);
612template<std::invocable<w
idget&> F>
613inline void apply(widget& start, F
const& f)
615 return apply(start,
true, f);
Definition of GUI event types.
#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 hi_axiom_not_null(expression,...)
Assert if an expression is not nullptr.
Definition assert.hpp:272
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
@ end
Start from the end of the file.
@ begin
Start from the beginning of the file.
gui_event_type
GUI event type.
Definition gui_event_type.hpp:21
@ window_redraw
Request that part of the window gets redrawn on the next frame.
@ window_reconstrain
Request that widget get constraint on the next frame.
@ rectangle
The gui_event has rectangle data.
@ disabled
The widget is disabled.
@ partial
A widget is partially enabled.
@ enabled
The widget is fully enabled.
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11
aarectangle fit(aarectangle const &bounds, aarectangle const &rectangle) noexcept
Make a rectangle fit inside bounds.
@ off
The widget in the off-state.
auto theme
A tagged global variable to a theme model for a widget's component.
Definition theme_model.hpp:433
A user interface event.
Definition gui_event.hpp:75
virtual void draw(widget_draw_context const &context) noexcept
Draw the widget.
Definition widget.hpp:232
widget_id id
The numeric identifier of a widget.
Definition widget.hpp:35
virtual void set_layout(widget_layout const &context) noexcept
Update the internal layout of the widget.
Definition widget.hpp:213
observer< extent2i > minimum
The minimum size this widget is allowed to be.
Definition widget.hpp:89
observer< bool > hover
Mouse cursor is hovering over the widget.
Definition widget.hpp:57
virtual void scroll_to_show(hi::aarectanglei rectangle) noexcept
Scroll to show the given rectangle on the window.
Definition widget.hpp:492
virtual void request_redraw() const noexcept
Request the widget to be redrawn on the next frame.
Definition widget.hpp:270
void reset_layout(gui_window *new_window, gfx_surface *new_surface, float new_scale) noexcept
Reset the layout.
Definition widget.hpp:178
virtual bool handle_event_recursive(gui_event const &event, std::vector< widget_id > const &reject_list=std::vector< widget_id >{}) noexcept
Handle command recursive.
Definition widget.hpp:356
virtual hitbox hitbox_test_from_parent(point2i position, hitbox sibling_hitbox) const noexcept
Call hitbox_test from a parent widget.
Definition widget.hpp:161
virtual generator< widget const & > children(bool include_invisible) const noexcept
Get a list of child widgets.
Definition widget.hpp:119
virtual bool is_tab_button() const noexcept
Check if this widget is a tab-button.
Definition widget.hpp:525
virtual box_constraints update_constraints() noexcept
Update the constraints of the widget.
Definition widget.hpp:197
observer< bool > clicked
The widget is being clicked by the mouse.
Definition widget.hpp:61
gfx_surface * surface
The surface this widget is drawn on.
Definition widget.hpp:48
virtual bool accepts_keyboard_focus(keyboard_focus_group group) const noexcept
Check if the widget will accept keyboard focus.
Definition widget.hpp:169
observer< widget_state > state
The state of the widget.
Definition widget.hpp:69
virtual bool handle_event(gui_event const &event) noexcept
Handle command.
Definition widget.hpp:279
virtual widget_id find_next_widget(widget_id current_keyboard_widget, keyboard_focus_group group, keyboard_focus_direction direction) const noexcept
Find the next widget that handles keyboard focus.
Definition widget.hpp:388
std::vector< widget_id > parent_chain() const noexcept
Get a list of parents of a given widget.
Definition widget.hpp:504
gui_window * window
The window this widget is on.
Definition widget.hpp:44
observer< extent2i > maximum
The maximum size this widget is allowed to be.
Definition widget.hpp:93
widget * parent
Pointer to the parent widget.
Definition widget.hpp:40
observer< widget_mode > mode
The widget mode.
Definition widget.hpp:53
observer< bool > focus
The widget has keyboard focus.
Definition widget.hpp:65
size_t semantic_layer
The draw layer of the widget.
Definition widget.hpp:85
virtual hitbox hitbox_test(point2i position) const noexcept
Find the widget that is under the mouse cursor.
Definition widget.hpp:138
virtual hitbox hitbox_test_from_parent(point2i position) const noexcept
Call hitbox_test from a parent widget.
Definition widget.hpp:149
Draw context for drawing using the HikoGUI shaders.
Definition widget_draw_context.hpp:204
The layout of a widget.
Definition widget_layout.hpp:37
extent2i window_size
Size of the window.
Definition widget_layout.hpp:68
translate2i to_parent
This matrix transforms local coordinates to the coordinates of the parent widget.
Definition widget_layout.hpp:52
translate2i from_parent
This matrix transforms parent widget's coordinates to local coordinates.
Definition widget_layout.hpp:56
translate2i from_window
This matrix transforms window coordinates to local coordinates.
Definition widget_layout.hpp:64
constexpr aarectanglei clipping_rectangle_on_window() const noexcept
Get the clipping rectangle in window coordinate system.
Definition widget_layout.hpp:145
2D constraints.
Definition box_constraints.hpp:22
Definition theme_model.hpp:148