HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
widget.hpp
1// Copyright Take Vos 2019-2021.
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
5#pragma once
6
7#include "../GUI/gui_window.hpp"
8#include "../GUI/gui_device.hpp"
9#include "../GUI/mouse_event.hpp"
10#include "../GUI/hit_box.hpp"
11#include "../GUI/keyboard_event.hpp"
12#include "../GUI/theme.hpp"
13#include "../GUI/draw_context.hpp"
14#include "../GUI/keyboard_focus_direction.hpp"
15#include "../GUI/keyboard_focus_group.hpp"
16#include "../text/shaped_text.hpp"
17#include "../alignment.hpp"
18#include "../graphic_path.hpp"
19#include "../color/sfloat_rgba16.hpp"
20#include "../color/sfloat_rg32.hpp"
21#include "../URL.hpp"
22#include "../vspan.hpp"
23#include "../utils.hpp"
24#include "../cpu_utc_clock.hpp"
25#include "../observable.hpp"
26#include "../command.hpp"
27#include "../unfair_recursive_mutex.hpp"
28#include "../interval_vec2.hpp"
29#include "../flow_layout.hpp"
30#include "../ranged_numeric.hpp"
31#include <limits>
32#include <memory>
33#include <vector>
34#include <mutex>
35#include <typeinfo>
36
37namespace tt::pipeline_image {
38struct Image;
39struct vertex;
40} // namespace tt::pipeline_image
41namespace tt::pipeline_SDF {
42struct vertex;
43}
44namespace tt::pipeline_flat {
45struct vertex;
46}
47namespace tt::pipeline_box {
48struct vertex;
49}
50
51namespace tt {
52class abstract_container_widget;
53
96class widget : public std::enable_shared_from_this<widget> {
97public:
101
102
106
110
111 virtual ~widget();
112 widget(const widget &) = delete;
113 widget &operator=(const widget &) = delete;
114 widget(widget &&) = delete;
115 widget &operator=(widget &&) = delete;
116
119 virtual void init() noexcept {}
120
128 [[nodiscard]] float margin() const noexcept
129 {
130 tt_axiom(gui_system_mutex.recurse_lock_count());
131 return _margin;
132 }
133
149 [[nodiscard]] float draw_layer() const noexcept
150 {
151 tt_axiom(gui_system_mutex.recurse_lock_count());
152 return _draw_layer;
153 }
154
165 [[nodiscard]] int logical_layer() const noexcept
166 {
167 tt_axiom(gui_system_mutex.recurse_lock_count());
168 return _logical_layer;
169 }
170
189 [[nodiscard]] int semantic_layer() const noexcept
190 {
191 tt_axiom(gui_system_mutex.recurse_lock_count());
192 return _semantic_layer;
193 }
194
204 [[nodiscard]] ranged_int<3> width_resistance() const noexcept
205 {
206 tt_axiom(gui_system_mutex.recurse_lock_count());
207 return _width_resistance;
208 }
209
219 [[nodiscard]] ranged_int<3> height_resistance() const noexcept
220 {
221 tt_axiom(gui_system_mutex.recurse_lock_count());
222 return _height_resistance;
223 }
224
233 [[nodiscard]] interval_vec2 preferred_size() const noexcept
234 {
235 tt_axiom(gui_system_mutex.recurse_lock_count());
236 return _preferred_size;
237 }
238
252 [[nodiscard]] relative_base_line preferred_base_line() const noexcept
253 {
254 tt_axiom(gui_system_mutex.recurse_lock_count());
255 return _preferred_base_line;
256 }
257
278 {
280 window_base_line = _preferred_base_line.position(window_rectangle.bottom(), window_rectangle.top());
281 }
282
283 tt_axiom(gui_system_mutex.recurse_lock_count());
284
285 if (_window_rectangle != window_rectangle) {
286 // The previous position needs to be redrawn.
287 window.request_redraw(_window_clipping_rectangle);
288
289 _window_rectangle = window_rectangle;
290 _request_relayout = true;
291 }
292
293 ttlet window_clipping_rectangle_clean =
294 intersect(window_clipping_rectangle, expand(_window_rectangle, theme::global->borderWidth));
295 if (_window_clipping_rectangle != window_clipping_rectangle_clean) {
296 _window_clipping_rectangle = window_clipping_rectangle_clean;
297 _request_relayout = true;
298 }
299
300 if (_window_base_line != window_base_line) {
301 _window_base_line = window_base_line;
302 _request_relayout = true;
303 }
304 }
305
310 [[nodiscard]] aarect window_rectangle() const noexcept
311 {
312 tt_axiom(gui_system_mutex.recurse_lock_count());
313 return _window_rectangle;
314 }
315
320 [[nodiscard]] virtual aarect window_clipping_rectangle() const noexcept
321 {
322 tt_axiom(gui_system_mutex.recurse_lock_count());
323 return _window_clipping_rectangle;
324 }
325
330 [[nodiscard]] float window_base_line() const noexcept
331 {
332 tt_axiom(gui_system_mutex.recurse_lock_count());
333 return _window_base_line;
334 }
335
340 [[nodiscard]] aarect rectangle() const noexcept
341 {
342 tt_axiom(gui_system_mutex.recurse_lock_count());
343 return aarect{_window_rectangle.extent()};
344 }
345
350 [[nodiscard]] float base_line() const noexcept
351 {
352 tt_axiom(gui_system_mutex.recurse_lock_count());
353 return _window_base_line - _window_rectangle.y();
354 }
355
356 [[nodiscard]] gui_device *device() const noexcept;
357
366 [[nodiscard]] virtual hit_box hitbox_test(f32x4 window_position) const noexcept
367 {
368 ttlet lock = std::scoped_lock(gui_system_mutex);
369
370 if (_window_clipping_rectangle.contains(window_position) && _window_rectangle.contains(window_position)) {
371 return hit_box{weak_from_this(), _draw_layer};
372 } else {
373 return {};
374 }
375 }
376
381 [[nodiscard]] virtual bool accepts_keyboard_focus(keyboard_focus_group group) const noexcept
382 {
383 tt_axiom(gui_system_mutex.recurse_lock_count());
384 return false;
385 }
386
410 [[nodiscard]] virtual bool update_constraints(hires_utc_clock::time_point display_time_point, bool need_reconstrain) noexcept;
411
431 [[nodiscard]] virtual void update_layout(hires_utc_clock::time_point display_time_point, bool need_layout) noexcept;
432
443 virtual draw_context make_draw_context(draw_context context) const noexcept;
444
460 virtual void draw(draw_context context, hires_utc_clock::time_point display_time_point) noexcept
461 {
462 tt_axiom(gui_system_mutex.recurse_lock_count());
463 }
464
469 [[nodiscard]] virtual bool handle_event(command command) noexcept;
470
471 [[nodiscard]] virtual bool handle_event(std::vector<command> const &commands) noexcept
472 {
473 for (ttlet command : commands) {
474 if (handle_event(command)) {
475 return true;
476 }
477 }
478 return false;
479 }
480
488 [[nodiscard]] virtual bool
489 handle_command_recursive(command command, std::vector<std::shared_ptr<widget>> const &reject_list) noexcept;
490
505 [[nodiscard]] virtual bool handle_event(mouse_event const &event) noexcept;
506
513 [[nodiscard]] virtual bool handle_event(keyboard_event const &event) noexcept;
514
528 std::shared_ptr<widget> const &current_keyboard_widget,
529 keyboard_focus_group group,
530 keyboard_focus_direction direction) const noexcept;
531
535
538 [[nodiscard]] std::shared_ptr<abstract_container_widget> shared_parent() noexcept;
539
543 [[nodiscard]] abstract_container_widget const &parent() const noexcept;
544
548 [[nodiscard]] abstract_container_widget &parent() noexcept;
549
552 [[nodiscard]] bool is_first(keyboard_focus_group group) const noexcept;
553
556 [[nodiscard]] bool is_last(keyboard_focus_group group) const noexcept;
557
561 [[nodiscard]] static std::vector<std::shared_ptr<widget>> parent_chain(std::shared_ptr<tt::widget> const &child_widget) noexcept;
562
563protected:
567 std::weak_ptr<abstract_container_widget> _parent;
568
571 bool _hover = false;
572
575 bool _focus = false;
576
579 matrix3 _from_window_transform;
580
583 matrix3 _to_window_transform;
584
587 bool _request_reconstrain = true;
588
591 bool _request_relayout = true;
592
595 aarect _window_rectangle;
596
599 float _window_base_line;
600
603 aarect _window_clipping_rectangle;
604
605 interval_vec2 _preferred_size;
606
607 relative_base_line _preferred_base_line = relative_base_line{};
608
609 ranged_int<3> _width_resistance = 1;
610 ranged_int<3> _height_resistance = 1;
611
612 float _margin = theme::global->margin;
613
623 float _draw_layer;
624
631 int _semantic_layer;
632
638 int _logical_layer;
639
640private:
641 typename decltype(enabled)::callback_ptr_type _enabled_callback;
642};
643
644} // namespace tt
STL namespace.
numeric_array< T, 4 > extent() const noexcept
Get size of the rectangle.
Definition aarect.hpp:225
bool contains(numeric_array< T, 4 > const &rhs) const noexcept
Check if a 2D coordinate is inside the rectangle.
Definition aarect.hpp:300
Definition alignment.hpp:104
constexpr float position(float bottom, float top) const noexcept
Get a base-line position.
Definition alignment.hpp:126
Draw context for drawing using the TTauri shaders.
Definition draw_context.hpp:33
Definition gui_device.hpp:22
Definition gui_window.hpp:39
void request_redraw(aarect rectangle=aarect::infinity()) noexcept
Request a rectangle on the window to be redrawn.
Definition gui_window.hpp:115
Definition hit_box.hpp:15
Definition keyboard_event.hpp:39
Definition mouse_event.hpp:13
A 2D vector using interval arithmetic.
Definition interval_vec2.hpp:18
Definition observable.hpp:20
A ranged integer.
Definition ranged_numeric.hpp:21
int recurse_lock_count() const noexcept
This function should be used in tt_axiom() to check if the lock is held by current thread.
Definition unfair_recursive_mutex.hpp:60
Definition abstract_container_widget.hpp:11
Definition widget.hpp:96
bool is_last(keyboard_focus_group group) const noexcept
Is this widget the last widget in the parent container.
virtual void init() noexcept
Should be called right after allocating and constructing a widget.
Definition widget.hpp:119
virtual bool handle_event(mouse_event const &event) noexcept
float draw_layer() const noexcept
The first drawing layer of the widget.
Definition widget.hpp:149
float margin() const noexcept
Get the margin around the Widget.
Definition widget.hpp:128
virtual void update_layout(hires_utc_clock::time_point display_time_point, bool need_layout) noexcept
Update the internal layout of the widget.
virtual draw_context make_draw_context(draw_context context) const noexcept
Make a draw context for this widget.
observable< bool > enabled
The widget is enabled.
Definition widget.hpp:105
virtual bool handle_command_recursive(command command, std::vector< std::shared_ptr< widget > > const &reject_list) noexcept
Handle command recursive.
int logical_layer() const noexcept
The logical layer of the widget.
Definition widget.hpp:165
widget(gui_window &window, std::shared_ptr< abstract_container_widget > parent) noexcept
ranged_int< 3 > width_resistance() const noexcept
Get the resistance in width.
Definition widget.hpp:204
virtual std::shared_ptr< widget > find_next_widget(std::shared_ptr< widget > const &current_keyboard_widget, keyboard_focus_group group, keyboard_focus_direction direction) const noexcept
Find the next widget that handles keyboard focus.
static std::vector< std::shared_ptr< widget > > parent_chain(std::shared_ptr< tt::widget > const &child_widget) noexcept
Get a list of parents of a given widget.
interval_vec2 preferred_size() const noexcept
Get the size-range of the widget.
Definition widget.hpp:233
virtual hit_box hitbox_test(f32x4 window_position) const noexcept
Find the widget that is under the mouse cursor.
Definition widget.hpp:366
virtual bool handle_event(command command) noexcept
Handle command.
gui_window & window
Convenient reference to the Window.
Definition widget.hpp:100
virtual void draw(draw_context context, hires_utc_clock::time_point display_time_point) noexcept
Draw the widget.
Definition widget.hpp:460
std::shared_ptr< abstract_container_widget const > shared_parent() const noexcept
Get a shared_ptr to the parent.
float window_base_line() const noexcept
Get the base-line distance from the bottom of the window.
Definition widget.hpp:330
relative_base_line preferred_base_line() const noexcept
Get the relative_base_line of the widget.
Definition widget.hpp:252
void set_layout_parameters(aarect const &window_rectangle, aarect const &window_clipping_rectangle, float window_base_line=std::numeric_limits< float >::infinity()) noexcept
Set the location and size of the widget inside the window.
Definition widget.hpp:274
float base_line() const noexcept
Get the base-line in local coordinates.
Definition widget.hpp:350
bool is_first(keyboard_focus_group group) const noexcept
Is this widget the first widget in the parent container.
virtual bool handle_event(keyboard_event const &event) noexcept
Handle keyboard event.
virtual bool update_constraints(hires_utc_clock::time_point display_time_point, bool need_reconstrain) noexcept
Update the constraints of the widget.
virtual bool accepts_keyboard_focus(keyboard_focus_group group) const noexcept
Check if the widget will accept keyboard focus.
Definition widget.hpp:381
abstract_container_widget const & parent() const noexcept
Get a reference to the parent.
int semantic_layer() const noexcept
The semantic layer of the widget.
Definition widget.hpp:189
virtual aarect window_clipping_rectangle() const noexcept
Get the clipping-rectangle in window coordinates.
Definition widget.hpp:320
ranged_int< 3 > height_resistance() const noexcept
Get the resistance in height.
Definition widget.hpp:219
aarect window_rectangle() const noexcept
Get the rectangle in window coordinates.
Definition widget.hpp:310
aarect rectangle() const noexcept
Get the rectangle in local coordinates.
Definition widget.hpp:340
T isinf(T... args)