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 ttlet &child = selected_child();
46 tt_axiom(&child.parent() == this);
47 if (compare_then_assign(_preferred_size, child.preferred_size())) {
48 // The size of the selected child has changed, resize the window.
49 window.requestResize = true;
50 }
51 }
52
53 return has_updated_contraints;
54 }
55
56 [[nodiscard]] void update_layout(hires_utc_clock::time_point display_time_point, bool need_layout) noexcept override
57 {
58 tt_axiom(gui_system_mutex.recurse_lock_count());
59
60 auto &child = selected_child();
61 tt_axiom(&child.parent() == this);
62
63 need_layout |= std::exchange(_request_relayout, false);
64 if (need_layout) {
65 child.set_layout_parameters_from_parent(rectangle());
66 }
67 child.update_layout(display_time_point, need_layout);
68
69 // THIS DOES NOT CALL THROUGH THE ABSTRACT_CONTAINER_WIDGET AND SKIPS DIRECTLY TO WIDGET.
70 widget::update_layout(display_time_point, need_layout);
71 }
72
73 void draw(draw_context context, hires_utc_clock::time_point display_time_point) noexcept override
74 {
75 tt_axiom(gui_system_mutex.recurse_lock_count());
76
77 draw_child(context, display_time_point, selected_child());
78 // Do not call super::draw, only the selected child should be drawn.
79 }
80
81 [[nodiscard]] hit_box hitbox_test(point2 position) const noexcept override
82 {
83 tt_axiom(gui_system_mutex.recurse_lock_count());
84 ttlet &child = selected_child();
85 return child.hitbox_test(point2{child.parent_to_local() * position});
86 }
87
89 std::shared_ptr<widget> const &current_widget,
90 keyboard_focus_group group,
91 keyboard_focus_direction direction) const noexcept
92 {
93 ttlet lock = std::scoped_lock(gui_system_mutex);
94 return selected_child().find_next_widget(current_widget, group, direction);
95 }
96
97 template<typename WidgetType = grid_layout_widget, typename... Args>
98 std::shared_ptr<WidgetType> make_widget(value_type value, Args &&...args) noexcept
99 {
100 ttlet lock = std::scoped_lock(gui_system_mutex);
101
102 auto widget = super::make_widget<WidgetType>(std::forward<Args>(args)...);
103 _children_keys.push_back(std::move(value));
104 return widget;
105 }
106
107private:
108 typename decltype(value)::callback_ptr_type _value_callback;
109
110 std::vector<value_type> _children_keys;
111
112 [[nodiscard]] auto find_child(value_type index) const noexcept
113 {
114 tt_axiom(gui_system_mutex.recurse_lock_count());
115 tt_axiom(std::size(_children_keys) == std::size(_children));
116
117 ttlet child_key_it = std::find(_children_keys.cbegin(), _children_keys.cend(), index);
118 if (child_key_it != _children_keys.cend()) {
119 ttlet child_index = std::distance(_children_keys.cbegin(), child_key_it);
120 return _children.begin() + child_index;
121 } else {
122 return _children.cend();
123 }
124 }
125
126 [[nodiscard]] auto find_child(value_type index) noexcept
127 {
128 tt_axiom(gui_system_mutex.recurse_lock_count());
129 tt_axiom(std::size(_children_keys) == std::size(_children));
130
131 ttlet child_key_it = std::find(_children_keys.cbegin(), _children_keys.cend(), index);
132 if (child_key_it != _children_keys.cend()) {
133 ttlet child_index = std::distance(_children_keys.cbegin(), child_key_it);
134 return _children.cbegin() + child_index;
135 } else {
136 return _children.cend();
137 }
138 }
139
140 [[nodiscard]] auto find_selected_child() const noexcept
141 {
142 tt_axiom(gui_system_mutex.recurse_lock_count());
143 return find_child(*value);
144 }
145
146 [[nodiscard]] auto find_selected_child() noexcept
147 {
148 tt_axiom(gui_system_mutex.recurse_lock_count());
149 return find_child(*value);
150 }
151
152 [[nodiscard]] widget const &selected_child() const noexcept
153 {
154 tt_axiom(gui_system_mutex.recurse_lock_count());
155 tt_axiom(std::ssize(_children) != 0);
156
157 auto i = find_selected_child();
158 if (i != _children.cend()) {
159 return *(*i);
160 } else {
161 return *_children.front();
162 }
163 }
164
165 [[nodiscard]] widget &selected_child() noexcept
166 {
167 tt_axiom(gui_system_mutex.recurse_lock_count());
168 tt_axiom(std::ssize(_children) != 0);
169
170 auto i = find_selected_child();
171 if (i != _children.cend()) {
172 return *(*i);
173 } else {
174 return *_children.front();
175 }
176 }
177
178 void draw_child(draw_context context, hires_utc_clock::time_point displayTimePoint, widget &child) noexcept
179 {
180 tt_axiom(gui_system_mutex.recurse_lock_count());
181 auto child_context =
182 context.make_child_context(child.parent_to_local(), child.local_to_window(), child.clipping_rectangle());
183 child.draw(child_context, displayTimePoint);
184 }
185};
186
187} // namespace tt
Draw context for drawing using the TTauri shaders.
Definition draw_context.hpp:33
Definition gui_window.hpp:37
std::atomic< bool > requestResize
When set to true the window will resize to the size of the contained widget.
Definition gui_window.hpp:58
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
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:95
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:88
void draw(draw_context context, hires_utc_clock::time_point display_time_point) noexcept override
Draw the widget.
Definition tab_view_widget.hpp:73
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(point2 position) const noexcept override
Find the widget that is under the mouse cursor.
Definition tab_view_widget.hpp:81
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:56
Definition widget.hpp:97
float draw_layer() const noexcept
The first drawing layer of the widget.
Definition widget.hpp:149
virtual void update_layout(hires_utc_clock::time_point display_time_point, bool need_layout) noexcept
Update the internal layout of the widget.
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.
aarectangle rectangle() const noexcept
Get the rectangle in local coordinates.
Definition widget.hpp:342
gui_window & window
Convenient reference to the Window.
Definition widget.hpp:101
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)