HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
tab_view_widget.hpp
1// Copyright Take Vos 2020-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 "abstract_container_widget.hpp"
8#include "grid_layout_widget.hpp"
9
10namespace tt {
11
12template<typename T>
14public:
16 using value_type = T;
17
18 observable<value_type> value = 0;
19
20 template<typename Value>
22 super(window, parent), value(std::forward<Value>(value))
23 {
24 if (parent) {
25 // The tab-widget will not draw itself, only its selected child.
26 ttlet lock = std::scoped_lock(gui_system_mutex);
27 _draw_layer = parent->draw_layer();
28 _semantic_layer = parent->semantic_layer();
29 }
30 _margin = 0.0f;
31
32 _value_callback = value.subscribe([this](auto...) {
33 this->_request_reconstrain = true;
34 });
35 }
36
38
39 [[nodiscard]] bool update_constraints(hires_utc_clock::time_point display_time_point, bool need_reconstrain) noexcept override
40 {
41 tt_axiom(gui_system_mutex.recurse_lock_count());
42
43 auto has_updated_contraints = super::update_constraints(display_time_point, need_reconstrain);
44 if (has_updated_contraints) {
45
46 ttlet &child = selected_child();
47 _preferred_base_line = child.preferred_base_line();
48 if (compare_then_assign(_preferred_size, child.preferred_size())) {
49 // The size of the selected child has changed, resize the window.
50 window.requestResize = true;
51 }
52 }
53
54 return has_updated_contraints;
55 }
56
57 [[nodiscard]] void update_layout(hires_utc_clock::time_point display_time_point, bool need_layout) noexcept override
58 {
59 tt_axiom(gui_system_mutex.recurse_lock_count());
60
61 need_layout |= std::exchange(_request_relayout, false);
62 if (need_layout) {
63 for (auto &child : _children) {
64 tt_axiom(child);
65 child->set_layout_parameters(_window_rectangle, _window_clipping_rectangle, _window_base_line);
66 }
67 }
68
69 super::update_layout(display_time_point, need_layout);
70 }
71
72 void draw(draw_context context, hires_utc_clock::time_point display_time_point) noexcept override
73 {
74 tt_axiom(gui_system_mutex.recurse_lock_count());
75
76 draw_child(context, display_time_point, selected_child());
77 // Do not call super::draw, only the selected child should be drawn.
78 }
79
80 [[nodiscard]] hit_box hitbox_test(f32x4 window_position) const noexcept override
81 {
82 ttlet lock = std::scoped_lock(gui_system_mutex);
83 return selected_child().hitbox_test(window_position);
84 }
85
87 std::shared_ptr<widget> const &current_widget,
88 keyboard_focus_group group,
89 keyboard_focus_direction direction) const noexcept
90 {
91 ttlet lock = std::scoped_lock(gui_system_mutex);
92 return selected_child().find_next_widget(current_widget, group, direction);
93 }
94
95 template<typename WidgetType = grid_layout_widget, typename... Args>
96 std::shared_ptr<WidgetType> make_widget(value_type value, Args &&... args) noexcept
97 {
98 ttlet lock = std::scoped_lock(gui_system_mutex);
99
100 auto widget = super::make_widget<WidgetType>(std::forward<Args>(args)...);
101 _children_keys.push_back(std::move(value));
102 return widget;
103 }
104
105private:
106 typename decltype(value)::callback_ptr_type _value_callback;
107
108 std::vector<value_type> _children_keys;
109
110 [[nodiscard]] auto find_child(value_type index) const noexcept
111 {
112 tt_axiom(gui_system_mutex.recurse_lock_count());
113 tt_axiom(std::size(_children_keys) == std::size(_children));
114
115 ttlet child_key_it = std::find(_children_keys.cbegin(), _children_keys.cend(), index);
116 if (child_key_it != _children_keys.cend()) {
117 ttlet child_index = std::distance(_children_keys.cbegin(), child_key_it);
118 return _children.begin() + child_index;
119 } else {
120 return _children.cend();
121 }
122 }
123
124 [[nodiscard]] auto find_child(value_type index) noexcept
125 {
126 tt_axiom(gui_system_mutex.recurse_lock_count());
127 tt_axiom(std::size(_children_keys) == std::size(_children));
128
129 ttlet child_key_it = std::find(_children_keys.cbegin(), _children_keys.cend(), index);
130 if (child_key_it != _children_keys.cend()) {
131 ttlet child_index = std::distance(_children_keys.cbegin(), child_key_it);
132 return _children.cbegin() + child_index;
133 } else {
134 return _children.cend();
135 }
136 }
137
138 [[nodiscard]] auto find_selected_child() const noexcept
139 {
140 tt_axiom(gui_system_mutex.recurse_lock_count());
141 return find_child(*value);
142 }
143
144 [[nodiscard]] auto find_selected_child() noexcept
145 {
146 tt_axiom(gui_system_mutex.recurse_lock_count());
147 return find_child(*value);
148 }
149
150 [[nodiscard]] widget const &selected_child() const noexcept
151 {
152 tt_axiom(gui_system_mutex.recurse_lock_count());
153 tt_axiom(std::ssize(_children) != 0);
154
155 auto i = find_selected_child();
156 if (i != _children.cend()) {
157 return *(*i);
158 } else {
159 return *_children.front();
160 }
161 }
162
163 [[nodiscard]] widget &selected_child() noexcept
164 {
165 tt_axiom(gui_system_mutex.recurse_lock_count());
166 tt_axiom(std::ssize(_children) != 0);
167
168 auto i = find_selected_child();
169 if (i != _children.cend()) {
170 return *(*i);
171 } else {
172 return *_children.front();
173 }
174 }
175
176 void draw_child(draw_context context, hires_utc_clock::time_point displayTimePoint, widget &child) noexcept
177 {
178 tt_axiom(gui_system_mutex.recurse_lock_count());
179 child.draw(child.make_draw_context(context), displayTimePoint);
180 }
181};
182
183} // namespace tt
Draw context for drawing using the TTauri shaders.
Definition draw_context.hpp:33
Definition gui_window.hpp:39
std::atomic< bool > requestResize
When set to true the window will resize to the size of the contained widget.
Definition gui_window.hpp:60
Definition hit_box.hpp:15
Definition observable.hpp:20
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
void update_layout(hires_utc_clock::time_point display_time_point, bool need_layout) noexcept
Update the internal layout of the widget.
Definition abstract_container_widget.hpp:111
bool update_constraints(hires_utc_clock::time_point display_time_point, bool need_reconstrain) noexcept
Update the constraints of the widget.
Definition abstract_container_widget.hpp:96
Definition grid_layout_widget.hpp:16
Definition tab_view_widget.hpp:13
std::shared_ptr< widget > find_next_widget(std::shared_ptr< widget > const &current_widget, keyboard_focus_group group, keyboard_focus_direction direction) const noexcept
Find the next widget that handles keyboard focus.
Definition tab_view_widget.hpp:86
void draw(draw_context context, hires_utc_clock::time_point display_time_point) noexcept override
Draw the widget.
Definition tab_view_widget.hpp:72
bool update_constraints(hires_utc_clock::time_point display_time_point, bool need_reconstrain) noexcept override
Update the constraints of the widget.
Definition tab_view_widget.hpp:39
hit_box hitbox_test(f32x4 window_position) const noexcept override
Find the widget that is under the mouse cursor.
Definition tab_view_widget.hpp:80
void update_layout(hires_utc_clock::time_point display_time_point, bool need_layout) noexcept override
Update the internal layout of the widget.
Definition tab_view_widget.hpp:57
Definition widget.hpp:96
float draw_layer() const noexcept
The first drawing layer of the widget.
Definition widget.hpp:149
widget(gui_window &window, std::shared_ptr< abstract_container_widget > parent) noexcept
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.
virtual hit_box hitbox_test(f32x4 window_position) const noexcept
Find the widget that is under the mouse cursor.
Definition widget.hpp:366
gui_window & window
Convenient reference to the Window.
Definition widget.hpp:100
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
T cbegin(T... args)
T distance(T... args)
T cend(T... args)
T find(T... args)
T move(T... args)
T push_back(T... args)