HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
tab_widget.hpp
Go to the documentation of this file.
1// Copyright Take Vos 2021-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 "../GUI/module.hpp"
12#include "grid_widget.hpp"
13#include "tab_delegate.hpp"
14
15namespace hi { inline namespace v1 {
16
36template<fixed_string Name = "">
37class tab_widget final : public widget {
38public:
39 using super = widget;
40 using delegate_type = tab_delegate;
41 constexpr static auto prefix = Name + "tab";
42
44
46 {
47 hi_assert_not_null(delegate);
48 delegate->deinit(*this);
49 }
50
57 super(parent), delegate(std::move(delegate))
58 {
59 hi_axiom(loop::main().on_thread());
61
62 // The tab-widget will not draw itself, only its selected child.
64
65 hi_assert_not_null(this->delegate);
66 _delegate_cbt = this->delegate->subscribe([&] {
67 ++global_counter<"tab_widget:delegate:constrain">;
69 });
70
71 this->delegate->init(*this);
72 }
73
80 tab_widget(widget *parent, different_from<std::shared_ptr<delegate_type>> auto&& value) noexcept
81 requires requires { make_default_tab_delegate(hi_forward(value)); }
83 {
84 }
85
94 template<typename WidgetType, typename Key, typename... Args>
95 WidgetType& make_widget(Key const& key, Args&&...args)
96 {
97 hi_axiom(loop::main().on_thread());
98
99 auto tmp = std::make_unique<WidgetType>(this, std::forward<Args>(args)...);
100 auto& ref = *tmp;
101
102 hi_assert_not_null(delegate);
103 delegate->add_tab(*this, static_cast<std::size_t>(key), size(_children));
104 _children.push_back(std::move(tmp));
105 ++global_counter<"tab_widget:make_widget:constrain">;
106 process_event({gui_event_type::window_reconstrain});
107 return ref;
108 }
109
111 [[nodiscard]] generator<widget const&> children(bool include_invisible) const noexcept override
112 {
113 for (hilet& child : _children) {
114 co_yield *child;
115 }
116 }
117
118 [[nodiscard]] box_constraints update_constraints() noexcept override
119 {
120 auto& selected_child_ = selected_child();
121
122 if (_previous_selected_child != &selected_child_) {
123 _previous_selected_child = &selected_child_;
124 hi_log_info("tab_widget::update_constraints() selected tab changed");
125 process_event({gui_event_type::window_resize});
126 }
127
128 for (hilet& child : _children) {
129 child->mode = child.get() == &selected_child_ ? widget_mode::enabled : widget_mode::invisible;
130 }
131
132 return selected_child_.update_constraints();
133 }
134
135 void set_layout(widget_layout const& context) noexcept override
136 {
137 layout = context;
138
139 for (hilet& child : _children) {
140 if (*child->mode > widget_mode::invisible) {
141 child->set_layout(context);
142 }
143 }
144 }
145
146 void draw(widget_draw_context const& context) noexcept override
147 {
149 for (hilet& child : _children) {
150 child->draw(context);
151 }
152 }
153 }
154
155 [[nodiscard]] hitbox hitbox_test(point2i position) const noexcept override
156 {
157 hi_axiom(loop::main().on_thread());
158
159 if (*mode >= widget_mode::partial) {
160 auto r = hitbox{};
161 for (hilet& child : _children) {
162 r = child->hitbox_test_from_parent(position, r);
163 }
164 return r;
165 } else {
166 return {};
167 }
168 }
169
170 [[nodiscard]] widget_id find_next_widget(
171 widget_id current_widget,
172 keyboard_focus_group group,
173 keyboard_focus_direction direction) const noexcept override
174 {
175 hi_axiom(loop::main().on_thread());
176 return selected_child().find_next_widget(current_widget, group, direction);
177 }
179private:
180 widget const *_previous_selected_child = nullptr;
182 notifier<>::callback_token _delegate_cbt;
183
184 using const_iterator = decltype(_children)::const_iterator;
185
186 [[nodiscard]] const_iterator find_selected_child() const noexcept
187 {
188 hi_axiom(loop::main().on_thread());
189 hi_assert_not_null(delegate);
190
191 auto index = delegate->index(const_cast<tab_widget&>(*this));
192 if (index >= 0 and index < ssize(_children)) {
193 return _children.begin() + index;
194 }
195
196 return _children.end();
197 }
198
199 [[nodiscard]] widget& selected_child() const noexcept
200 {
201 hi_axiom(loop::main().on_thread());
202 hi_assert(not _children.empty());
203
204 auto i = find_selected_child();
205 if (i != _children.cend()) {
206 return **i;
207 } else {
208 return *_children.front();
209 }
210 }
211};
212
213}} // namespace hi::v1
Defines grid_widget.
Defines delegate_delegate and some default tab delegates.
#define hi_assert(expression,...)
Assert if expression is true.
Definition assert.hpp:199
#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 hilet
Invariant should be the default for variables.
Definition utility.hpp:23
#define hi_forward(x)
Forward a value, based on the decltype of the value.
Definition utility.hpp:29
@ window_reconstrain
Request that widget get constraint on the next frame.
@ window_resize
Request that the window resizes to desired constraints on the next frame.
std::shared_ptr< tab_delegate > make_default_tab_delegate(auto &&value) noexcept
Create a shared pointer to a default tab delegate.
Definition tab_delegate.hpp:101
@ partial
A widget is partially enabled.
@ invisible
The widget is invisible.
@ enabled
The widget is fully enabled.
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11
Definition widget.hpp:26
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
widget * parent
Pointer to the parent widget.
Definition widget.hpp:40
observer< widget_mode > mode
The widget mode.
Definition widget.hpp:53
size_t semantic_layer
The draw layer of the widget.
Definition widget.hpp:85
A delegate that controls the state of a tab_widget.
Definition tab_delegate.hpp:20
A graphical element that shows only one of a predefined set of mutually exclusive child widgets.
Definition tab_widget.hpp:37
tab_widget(widget *parent, different_from< std::shared_ptr< delegate_type > > auto &&value) noexcept
Construct a tab widget with an observer value.
Definition tab_widget.hpp:80
WidgetType & make_widget(Key const &key, Args &&...args)
Make and add a child widget.
Definition tab_widget.hpp:95
tab_widget(widget *parent, std::shared_ptr< delegate_type > delegate) noexcept
Construct a tab widget with a delegate.
Definition tab_widget.hpp:56
T begin(T... args)
T empty(T... args)
T end(T... args)
T front(T... args)
T move(T... args)