HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
widget.hpp
Go to the documentation of this file.
1// Copyright Take Vos 2019-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
9#pragma once
10
11#include "widget_layout.hpp"
12#include "widget_mode.hpp"
13#include "../GFX/draw_context.hpp"
14#include "../GUI/theme.hpp"
15#include "../GUI/hitbox.hpp"
16#include "../GUI/keyboard_focus_direction.hpp"
17#include "../GUI/keyboard_focus_group.hpp"
18#include "../GUI/gui_event.hpp"
19#include "../GUI/widget_id.hpp"
20#include "../layout/box_constraints.hpp"
21#include "../geometry/module.hpp"
22#include "../observer.hpp"
23#include "../chrono.hpp"
24#include "../generator.hpp"
25#include "../cache.hpp"
26#include "../os_settings.hpp"
27#include "../tagged_id.hpp"
28#include <memory>
29#include <vector>
30#include <string>
31#include <ranges>
32
33namespace hi { inline namespace v1 {
34class gui_window;
35class gfx_surface;
36
46class widget : public std::enable_shared_from_this<widget> {
47public:
51 widget *parent = nullptr;
52
57 widget_id id = {};
58
62 observer<widget_mode> mode = widget_mode::enabled;
63
66 observer<bool> hover = false;
67
70 observer<bool> focus = false;
71
87
96
99 observer<extent2i> minimum = extent2i{};
100
103 observer<extent2i> maximum = extent2i::large();
104
107 explicit widget(widget *parent) noexcept;
108
109 virtual ~widget();
110 widget(const widget&) = delete;
111 widget& operator=(const widget&) = delete;
112 widget(widget&&) = delete;
113 widget& operator=(widget&&) = delete;
114
117 [[nodiscard]] virtual generator<widget const&> children(bool include_invisible) const noexcept
118 {
119 co_return;
120 }
121
122 [[nodiscard]] generator<widget&> children(bool include_invisible) noexcept
123 {
124 for (auto& child : const_cast<widget const *>(this)->children(include_invisible)) {
125 co_yield const_cast<widget&>(child);
126 }
127 }
128
136 [[nodiscard]] virtual hitbox hitbox_test(point2i position) const noexcept
137 {
138 return {};
139 }
140
147 [[nodiscard]] virtual hitbox hitbox_test_from_parent(point2i position) const noexcept
148 {
149 return hitbox_test(_layout.from_parent * position);
150 }
151
159 [[nodiscard]] virtual hitbox hitbox_test_from_parent(point2i position, hitbox sibling_hitbox) const noexcept
160 {
161 return std::max(sibling_hitbox, hitbox_test(_layout.from_parent * position));
162 }
163
167 [[nodiscard]] virtual bool accepts_keyboard_focus(keyboard_focus_group group) const noexcept
168 {
169 hi_axiom(loop::main().on_thread());
170 return false;
171 }
172
184 virtual [[nodiscard]] box_constraints update_constraints() noexcept
185 {
186 _layout = {};
187 return {*minimum, *minimum, *maximum};
188 }
189
201 virtual void set_layout(widget_layout const& context) noexcept
202 {
203 _layout = context;
204 }
205
208 widget_layout const& layout() const noexcept
209 {
210 return _layout;
211 }
212
227 virtual void draw(draw_context const& context) noexcept {}
228
229 virtual bool process_event(gui_event const& event) const noexcept
230 {
231 if (parent != nullptr) {
232 return parent->process_event(event);
233 } else {
234 return true;
235 }
236 }
237
240 virtual void request_redraw() const noexcept
241 {
243 }
244
249 virtual bool handle_event(gui_event const& event) noexcept;
250
258 virtual bool
260
274 [[nodiscard]] virtual widget_id find_next_widget(
275 widget_id current_keyboard_widget,
276 keyboard_focus_group group,
277 keyboard_focus_direction direction) const noexcept;
278
279 [[nodiscard]] widget_id find_first_widget(keyboard_focus_group group) const noexcept;
280
281 [[nodiscard]] widget_id find_last_widget(keyboard_focus_group group) const noexcept;
282
285 [[nodiscard]] bool is_first(keyboard_focus_group group) const noexcept;
286
289 [[nodiscard]] bool is_last(keyboard_focus_group group) const noexcept;
290
297 virtual void scroll_to_show(hi::aarectanglei rectangle) noexcept;
298
301 void scroll_to_show() noexcept
302 {
304 }
305
309 [[nodiscard]] std::vector<widget_id> parent_chain() const noexcept;
310
311 [[nodiscard]] virtual gui_window *window() const noexcept
312 {
313 if (parent) {
314 return parent->window();
315 } else {
316 return nullptr;
317 }
318 }
319
320 [[nodiscard]] virtual hi::theme const& theme() const noexcept
321 {
323 return parent->theme();
324 }
325
326 [[nodiscard]] virtual gfx_surface const *surface() const noexcept
327 {
328 if (parent) {
329 return parent->surface();
330 } else {
331 return nullptr;
332 }
333 }
334
335 [[nodiscard]] virtual color background_color() const noexcept;
336
337 [[nodiscard]] virtual color foreground_color() const noexcept;
338
339 [[nodiscard]] virtual color focus_color() const noexcept;
340
341 [[nodiscard]] virtual color accent_color() const noexcept;
342
343 [[nodiscard]] virtual color label_color() const noexcept;
344
345protected:
346 widget_layout _layout;
347
348 decltype(mode)::callback_token _mode_cbt;
349
359 [[nodiscard]] aarectanglei make_overlay_rectangle(aarectanglei requested_rectangle) const noexcept;
360};
361
362inline widget *get_if(widget *start, widget_id id, bool include_invisible) noexcept
363{
364 hi_assert_not_null(start);
365
366 if (start->id == id) {
367 return start;
368 }
369 for (auto& child : start->children(include_invisible)) {
370 if (hilet r = get_if(&child, id, include_invisible); r != nullptr) {
371 return r;
372 }
373 }
374 return nullptr;
375}
376
377inline widget& get(widget& start, widget_id id, bool include_invisible)
378{
379 if (auto r = get_if(std::addressof(start), id, include_invisible); r != nullptr) {
380 return *r;
381 }
382 throw not_found_error("get widget by id");
383}
384
385}} // namespace hi::v1
Defines widget_layout.
Defines widget_mode.
Definition of GUI event types.
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:238
#define hi_assert_not_null(x,...)
Assert if an expression is not nullptr.
Definition assert.hpp:223
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
@ window_redraw
Request that part of the window gets redrawn on the next frame.
@ rectangle
The gui_event has rectangle data.
@ enabled
The widget is fully enabled.
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11
Draw context for drawing using the HikoGUI shaders.
Definition draw_context.hpp:211
A user interface event.
Definition gui_event.hpp:74
2D constraints.
Definition box_constraints.hpp:22
An interactive graphical object as part of the user-interface.
Definition widget.hpp:46
virtual void draw(draw_context const &context) noexcept
Draw the widget.
Definition widget.hpp:227
widget_layout const & layout() const noexcept
Get the current layout for this widget.
Definition widget.hpp:208
bool is_first(keyboard_focus_group group) const noexcept
Is this widget the first widget in the parent container.
int logical_layer
The logical layer of the widget.
Definition widget.hpp:95
virtual void set_layout(widget_layout const &context) noexcept
Update the internal layout of the widget.
Definition widget.hpp:201
int semantic_layer
The draw layer of the widget.
Definition widget.hpp:86
observer< extent2i > minimum
The minimum size this widget is allowed to be.
Definition widget.hpp:99
observer< bool > hover
Mouse cursor is hovering over the widget.
Definition widget.hpp:66
virtual void scroll_to_show(hi::aarectanglei rectangle) noexcept
Scroll to show the given rectangle on the window.
virtual void request_redraw() const noexcept
Request the widget to be redrawn on the next frame.
Definition widget.hpp:240
virtual bool handle_event_recursive(gui_event const &event, std::vector< widget_id > const &reject_list=std::vector< widget_id >{}) noexcept
Handle command recursive.
widget(widget *parent) noexcept
virtual hitbox hitbox_test_from_parent(point2i position, hitbox sibling_hitbox) const noexcept
Call hitbox_test from a parent widget.
Definition widget.hpp:159
virtual generator< widget const & > children(bool include_invisible) const noexcept
Get a list of child widgets.
Definition widget.hpp:117
virtual box_constraints update_constraints() noexcept
Update the constraints of the widget.
Definition widget.hpp:184
virtual bool accepts_keyboard_focus(keyboard_focus_group group) const noexcept
Check if the widget will accept keyboard focus.
Definition widget.hpp:167
virtual bool handle_event(gui_event const &event) noexcept
Handle command.
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.
std::vector< widget_id > parent_chain() const noexcept
Get a list of parents of a given widget.
observer< extent2i > maximum
The maximum size this widget is allowed to be.
Definition widget.hpp:103
widget * parent
Pointer to the parent widget.
Definition widget.hpp:51
bool is_last(keyboard_focus_group group) const noexcept
Is this widget the last widget in the parent container.
void scroll_to_show() noexcept
Scroll to show the important part of the widget.
Definition widget.hpp:301
observer< widget_mode > mode
The widget mode.
Definition widget.hpp:62
observer< bool > focus
The widget has keyboard focus.
Definition widget.hpp:70
virtual hitbox hitbox_test(point2i position) const noexcept
Find the widget that is under the mouse cursor.
Definition widget.hpp:136
virtual hitbox hitbox_test_from_parent(point2i position) const noexcept
Call hitbox_test from a parent widget.
Definition widget.hpp:147
The layout of a widget.
Definition widget_layout.hpp:38
translate2i from_parent
This matrix transforms parent widget's coordinates to local coordinates.
Definition widget_layout.hpp:57
constexpr aarectanglei clipping_rectangle_on_window() const noexcept
Get the clipping rectangle in window coordinate system.
Definition widget_layout.hpp:146
T addressof(T... args)
T max(T... args)