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
8
9#pragma once
10
11#include "widget.hpp"
12#include "grid_widget.hpp"
13#include "tab_delegate.hpp"
14#include "../macros.hpp"
15#include <coroutine>
16
17hi_export_module(hikogui.widgets.tab_widget);
18
19hi_export namespace hi { inline namespace v1 {
20
40class tab_widget : public widget {
41public:
42 using super = widget;
43 using delegate_type = tab_delegate;
44
46
48 {
49 hi_assert_not_null(delegate);
50 delegate->deinit(*this);
51 }
52
58 tab_widget(std::shared_ptr<delegate_type> delegate) noexcept : super(), delegate(std::move(delegate))
59 {
60 hi_axiom(loop::main().on_thread());
61
62 hi_assert_not_null(this->delegate);
63 _delegate_cbt = this->delegate->subscribe([&] {
64 ++global_counter<"tab_widget:delegate:constrain">;
66 });
67
68 this->delegate->init(*this);
69 }
70
77 template<incompatible_with<std::shared_ptr<delegate_type>> Value>
78 tab_widget(Value&& value) noexcept
79 requires requires { make_default_tab_delegate(std::forward<Value>(value)); }
81 {
82 }
83
84 void add(size_t index, std::unique_ptr<widget> child)
85 {
86 hi_assert_not_null(delegate);
87
88 child->set_parent(this);
89 delegate->add_tab(*this, index, _children.size());
90 _children.push_back(std::move(child));
91
92 ++global_counter<"tab_widget:emplace:constrain">;
94 }
95
104 template<typename WidgetType, typename Key, typename... Args>
105 WidgetType& emplace(Key const& key, Args&&...args)
106 {
107 hi_axiom(loop::main().on_thread());
108
109 auto tmp = std::make_unique<WidgetType>(std::forward<Args>(args)...);
110 auto& ref = *tmp;
111 add(static_cast<size_t>(key), std::move(tmp));
112 return ref;
113 }
114
116 [[nodiscard]] generator<widget_intf &> children(bool include_invisible) noexcept override
117 {
118 for (auto const& child : _children) {
119 co_yield *child;
120 }
121 }
122
123 [[nodiscard]] box_constraints update_constraints() noexcept override
124 {
125 _layout = {};
126
127 auto& selected_child_ = selected_child();
128
129 if (_previous_selected_child != &selected_child_) {
130 _previous_selected_child = &selected_child_;
131 hi_log_info("tab_widget::update_constraints() selected tab changed");
133 }
134
135 for (auto const& child : _children) {
136 child->set_mode(child.get() == &selected_child_ ? widget_mode::enabled : widget_mode::invisible);
137 }
138
139 return selected_child_.update_constraints();
140 }
141
142 void set_layout(widget_layout const& context) noexcept override
143 {
144 _layout = context;
145
146 for (auto const& child : _children) {
147 if (child->mode() > widget_mode::invisible) {
148 child->set_layout(context);
149 }
150 }
151 }
152
153 void draw(draw_context const& context) noexcept override
154 {
155 if (mode() > widget_mode::invisible) {
156 for (auto const& child : _children) {
157 child->draw(context);
158 }
159 }
160 }
161
162 [[nodiscard]] hitbox hitbox_test(point2 position) const noexcept override
163 {
164 hi_axiom(loop::main().on_thread());
165
166 if (mode() >= widget_mode::partial) {
167 auto r = hitbox{};
168 for (auto const& child : _children) {
169 r = child->hitbox_test_from_parent(position, r);
170 }
171 return r;
172 } else {
173 return {};
174 }
175 }
176
177 [[nodiscard]] widget_id find_next_widget(
178 widget_id current_widget,
179 keyboard_focus_group group,
180 keyboard_focus_direction direction) const noexcept override
181 {
182 hi_axiom(loop::main().on_thread());
183 return selected_child().find_next_widget(current_widget, group, direction);
184 }
186private:
187 widget const *_previous_selected_child = nullptr;
188 std::vector<std::unique_ptr<widget>> _children;
189 callback<void()> _delegate_cbt;
190
191 using const_iterator = decltype(_children)::const_iterator;
192
193 [[nodiscard]] const_iterator find_selected_child() const noexcept
194 {
195 hi_axiom(loop::main().on_thread());
196 hi_assert_not_null(delegate);
197
198 auto index = delegate->index(const_cast<tab_widget&>(*this));
199 if (index >= 0 and index < ssize(_children)) {
200 return _children.begin() + index;
201 }
202
203 return _children.end();
204 }
205 [[nodiscard]] widget& selected_child() const noexcept
206 {
207 hi_axiom(loop::main().on_thread());
208 hi_assert(not _children.empty());
209
210 auto i = find_selected_child();
211 if (i != _children.cend()) {
212 return **i;
213 } else {
214 return *_children.front();
215 }
216 }
217};
218
219}} // namespace hi::v1
Defines widget.
Defines delegate_delegate and some default tab delegates.
Defines grid_widget.
@ window_reconstrain
Request that widget get constraint on the next frame.
Definition gui_event_type.hpp:48
@ window_resize
Request that the window resizes to desired constraints on the next frame.
Definition gui_event_type.hpp:49
std::shared_ptr< tab_delegate > make_default_tab_delegate(Value &&value) noexcept
Create a shared pointer to a default tab delegate.
Definition tab_delegate.hpp:108
@ partial
A widget is partially enabled.
Definition widget_state.hpp:73
@ invisible
The widget is invisible.
Definition widget_state.hpp:41
@ enabled
The widget is fully enabled.
Definition widget_state.hpp:81
The HikoGUI namespace.
Definition array_generic.hpp:21
The HikoGUI API version 1.
Definition array_generic.hpp:22
A delegate that controls the state of a tab_widget.
Definition tab_delegate.hpp:29
A graphical element that shows only one of a predefined set of mutually exclusive child widgets.
Definition tab_widget.hpp:40
tab_widget(std::shared_ptr< delegate_type > delegate) noexcept
Construct a tab widget with a delegate.
Definition tab_widget.hpp:58
tab_widget(Value &&value) noexcept
Construct a tab widget with an observer value.
Definition tab_widget.hpp:78
WidgetType & emplace(Key const &key, Args &&...args)
Make and add a child widget.
Definition tab_widget.hpp:105
widget() noexcept
Constructor for creating sub views.
Definition widget.hpp:50
box_constraints update_constraints() noexcept override
Update the constraints of the widget.
Definition widget.hpp:110
bool process_event(gui_event const &event) const noexcept override
Send a event to the window.
Definition widget.hpp:125
T forward(T... args)
T get(T... args)
T move(T... args)