HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
toolbar_widget.hpp
1// Copyright Take Vos 2020.
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 <memory>
9
10namespace tt {
11
13public:
15
17 {
18 if (parent) {
19 // The toolbar widget does draw itself.
20 ttlet lock = std::scoped_lock(gui_system_mutex);
21 _draw_layer = parent->draw_layer() + 1.0f;
22
23 // The toolbar is a top level widget, which draws its background as the next level.
24 _semantic_layer = 0;
25 }
26 }
27
29
33 std::shared_ptr<widget> add_widget(horizontal_alignment alignment, std::shared_ptr<widget> widget) noexcept
34 {
36 switch (alignment) {
37 using enum horizontal_alignment;
38 case left: _left_children.push_back(tmp); break;
39 case right: _right_children.push_back(tmp); break;
40 default: tt_no_default();
41 }
42
43 return tmp;
44 }
45
46 [[nodiscard]] bool update_constraints(hires_utc_clock::time_point display_time_point, bool need_reconstrain) noexcept
47 {
48 tt_axiom(gui_system_mutex.recurse_lock_count());
49
50 if (super::update_constraints(display_time_point, need_reconstrain)) {
51 auto shared_base_line = relative_base_line{vertical_alignment::middle, 0.0f, 100};
52 auto shared_height = 0.0f;
53
54 _layout.clear();
55 _layout.reserve(std::ssize(_left_children) + 1 + std::ssize(_right_children));
56
57 ssize_t index = 0;
58 for (ttlet &child : _left_children) {
59 update_constraints_for_child(*child, index++, shared_base_line, shared_height);
60 }
61
62 // Add a space between the left and right widgets.
63 _layout.update(
64 index++,
65 theme::global->width,
67 0.0f,
69
70 for (ttlet &child : std::views::reverse(_right_children)) {
71 update_constraints_for_child(*child, index++, shared_base_line, shared_height);
72 }
73
74 tt_axiom(index == std::ssize(_left_children) + 1 + std::ssize(_right_children));
75 _preferred_size = {f32x4{_layout.minimum_size(), shared_height}, f32x4{std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity()}};
76 _preferred_base_line = shared_base_line;
77 return true;
78 } else {
79 return false;
80 }
81 }
82
83 void update_layout(hires_utc_clock::time_point display_time_point, bool need_layout) noexcept
84 {
85 tt_axiom(gui_system_mutex.recurse_lock_count());
86
87 need_layout |= std::exchange(_request_relayout, false);
88 if (need_layout) {
89 _layout.set_size(rectangle().width());
90
91 ssize_t index = 0;
92 for (ttlet &child : _left_children) {
93 update_layout_for_child(*child, index++);
94 }
95
96 // Skip over the cell between left and right children.
97 index++;
98
99 for (ttlet &child : std::views::reverse(_right_children)) {
100 update_layout_for_child(*child, index++);
101 }
102
103 tt_axiom(index == std::ssize(_left_children) + 1 + std::ssize(_right_children));
104 }
105 abstract_container_widget::update_layout(display_time_point, need_layout);
106 }
107
108 void draw(draw_context context, hires_utc_clock::time_point display_time_point) noexcept
109 {
110 tt_axiom(gui_system_mutex.recurse_lock_count());
111
112 if (overlaps(context, this->window_clipping_rectangle())) {
113 context.fill_color = theme::global->fillColor(_semantic_layer + 1);
114 context.draw_filled_quad(rectangle());
115 }
116
117 abstract_container_widget::draw(std::move(context), display_time_point);
118 }
119
120 hit_box hitbox_test(f32x4 window_position) const noexcept
121 {
122 ttlet lock = std::scoped_lock(gui_system_mutex);
123
124 auto r = hit_box{};
125
126 if (_window_clipping_rectangle.contains(window_position)) {
127 r = hit_box{weak_from_this(), _draw_layer, hit_box::Type::MoveArea};
128 }
129
130 for (ttlet &child : _children) {
131 r = std::max(r, child->hitbox_test(window_position));
132 }
133 return r;
134 }
135
138 template<typename T, horizontal_alignment Alignment = horizontal_alignment::left, typename... Args>
140 {
141 auto widget = std::make_shared<T>(window, shared_from_this(), std::forward<Args>(args)...);
142 widget->init();
143 return std::static_pointer_cast<T>(add_widget(Alignment, std::move(widget)));
144 }
145
146 [[nodiscard]] bool is_toolbar() const noexcept override
147 {
148 return true;
149 }
150
151private:
154 flow_layout _layout;
155
156 void update_constraints_for_child(
157 widget const &child,
158 ssize_t index,
159 relative_base_line &shared_base_line,
160 float &shared_height) noexcept
161 {
162 tt_axiom(gui_system_mutex.recurse_lock_count());
163
164 _layout.update(index, child.preferred_size().minimum().width(), child.width_resistance(), child.margin(), relative_base_line{});
165
166 shared_base_line = std::max(shared_base_line, child.preferred_base_line());
167 shared_height = std::max(shared_height, child.preferred_size().minimum().height() + child.margin() * 2.0f);
168 }
169
170 void update_layout_for_child(widget &child, ssize_t index) const noexcept
171 {
172 tt_axiom(gui_system_mutex.recurse_lock_count());
173
174 ttlet[child_x, child_width] = _layout.get_offset_and_size(index++);
175
176 ttlet child_rectangle = aarect{
177 rectangle().x() + child_x,
178 rectangle().y() + child.margin(),
179 child_width,
180 rectangle().height() - child.margin() * 2.0f};
181
182 ttlet child_window_rectangle = translate2{_window_rectangle} * child_rectangle;
183
184 child.set_layout_parameters(child_window_rectangle, _window_clipping_rectangle, _window_base_line);
185 }
186};
187
188} // namespace tt
Definition alignment.hpp:104
void reserve(ssize_t new_size) noexcept
Grow layout to include upto new_size of items.
Definition flow_layout.hpp:112
void set_size(float total_size) noexcept
Update the layout of all items based on the total size.
Definition flow_layout.hpp:57
Draw context for drawing using the TTauri shaders.
Definition draw_context.hpp:33
Definition gui_window.hpp:39
Definition hit_box.hpp:15
A ranged integer.
Definition ranged_numeric.hpp:21
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
void draw(draw_context context, hires_utc_clock::time_point display_time_point) noexcept
Draw the widget.
Definition abstract_container_widget.hpp:125
std::shared_ptr< widget > add_widget(std::shared_ptr< widget > widget) noexcept
Add a widget directly to this widget.
Definition abstract_container_widget.hpp:39
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 toolbar_widget.hpp:12
hit_box hitbox_test(f32x4 window_position) const noexcept
Find the widget that is under the mouse cursor.
Definition toolbar_widget.hpp:120
bool update_constraints(hires_utc_clock::time_point display_time_point, bool need_reconstrain) noexcept
Update the constraints of the widget.
Definition toolbar_widget.hpp:46
void draw(draw_context context, hires_utc_clock::time_point display_time_point) noexcept
Draw the widget.
Definition toolbar_widget.hpp:108
std::shared_ptr< T > make_widget(Args &&... args)
Add a widget directly to this widget.
Definition toolbar_widget.hpp:139
void update_layout(hires_utc_clock::time_point display_time_point, bool need_layout) noexcept
Update the internal layout of the widget.
Definition toolbar_widget.hpp:83
std::shared_ptr< widget > add_widget(horizontal_alignment alignment, std::shared_ptr< widget > widget) noexcept
Add a widget directly to this widget.
Definition toolbar_widget.hpp:33
Definition widget.hpp:96
virtual void init() noexcept
Should be called right after allocating and constructing a widget.
Definition widget.hpp:119
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
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.
virtual aarect window_clipping_rectangle() const noexcept
Get the clipping-rectangle in window coordinates.
Definition widget.hpp:320
aarect rectangle() const noexcept
Get the rectangle in local coordinates.
Definition widget.hpp:340
T infinity(T... args)
T max(T... args)
T move(T... args)