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 "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(widget_intf const* parent, std::shared_ptr<delegate_type> delegate) noexcept : super(parent), 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(widget_intf const* parent, Value&& value) noexcept
79 requires requires { make_default_tab_delegate(std::forward<Value>(value)); }
80 : tab_widget(parent, make_default_tab_delegate(std::forward<Value>(value)))
81 {
82 }
83
92 template<typename WidgetType, typename Key, typename... Args>
93 WidgetType& emplace(Key const& key, Args&&...args)
94 {
95 hi_axiom(loop::main().on_thread());
96
97 auto tmp = std::make_unique<WidgetType>(this, std::forward<Args>(args)...);
98 auto& ref = *tmp;
99
100 hi_assert_not_null(delegate);
101 delegate->add_tab(*this, static_cast<std::size_t>(key), size(_children));
102 _children.push_back(std::move(tmp));
103 ++global_counter<"tab_widget:emplace:constrain">;
105 return ref;
106 }
107
109 [[nodiscard]] generator<widget_intf &> children(bool include_invisible) noexcept override
110 {
111 for (auto const& child : _children) {
112 co_yield *child;
113 }
114 }
115
116 [[nodiscard]] box_constraints update_constraints() noexcept override
117 {
118 _layout = {};
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");
126 }
127
128 for (auto const& child : _children) {
129 child->set_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 (auto const& child : _children) {
140 if (child->mode() > widget_mode::invisible) {
141 child->set_layout(context);
142 }
143 }
144 }
145
146 void draw(draw_context const& context) noexcept override
147 {
148 if (mode() > widget_mode::invisible) {
149 for (auto const& child : _children) {
150 child->draw(context);
151 }
152 }
153 }
154
155 [[nodiscard]] hitbox hitbox_test(point2 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 (auto const& 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 callback<void()> _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 [[nodiscard]] widget& selected_child() const noexcept
199 {
200 hi_axiom(loop::main().on_thread());
201 hi_assert(not _children.empty());
202
203 auto i = find_selected_child();
204 if (i != _children.cend()) {
205 return **i;
206 } else {
207 return *_children.front();
208 }
209 }
210};
211
212}} // namespace hi::v1
Defines widget.
Defines grid_widget.
Defines delegate_delegate and some default tab delegates.
@ 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(Value &&value) noexcept
Create a shared pointer to a default tab delegate.
Definition tab_delegate.hpp:108
widget_mode
The mode that the widget is operating at.
Definition widget_state.hpp:25
@ partial
A widget is partially enabled.
@ invisible
The widget is invisible.
@ enabled
The widget is fully enabled.
The HikoGUI namespace.
Definition array_generic.hpp:20
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Definition widget_intf.hpp:24
widget_intf * parent
Pointer to the parent widget.
Definition widget_intf.hpp:35
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(widget_intf const *parent, std::shared_ptr< delegate_type > delegate) noexcept
Construct a tab widget with a delegate.
Definition tab_widget.hpp:58
tab_widget(widget_intf const *parent, 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:93
An interactive graphical object as part of the user-interface.
Definition widget.hpp:37
virtual widget_id find_next_widget(widget_id current_keyboard_widget, keyboard_focus_group group, keyboard_focus_direction direction) const noexcept override
Find the next widget that handles keyboard focus.
Definition widget.hpp:265
widget() noexcept
Constructor for creating sub views.
Definition widget.hpp:55
bool process_event(gui_event const &event) const noexcept override
Send a event to the window.
Definition widget.hpp:130
T begin(T... args)
T empty(T... args)
T end(T... args)
T front(T... args)
T move(T... args)