HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
row_column_widget.hpp
Go to the documentation of this file.
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
6
7#pragma once
8
9#include "widget.hpp"
10#include "row_column_delegate.hpp"
11#include "../GUI/theme.hpp"
12#include "../flow_layout.hpp"
13#include "../geometry/axis.hpp"
14#include <memory>
15
16namespace tt {
17
36template<axis Axis>
37class row_column_widget final : public widget {
38public:
39 static_assert(Axis == axis::horizontal or Axis == axis::vertical);
40
41 using super = widget;
43 static constexpr tt::axis axis = Axis;
44
53 super(window, parent), _delegate(std::move(delegate))
54 {
55 tt_axiom(is_gui_thread());
56
57 if (parent) {
59 }
60 }
61
74 template<typename Widget, typename... Args>
75 Widget &make_widget(Args &&...args)
76 {
77 return super::make_widget<Widget>(std::forward<Args>(args)...);
78 }
79
81 void init() noexcept override
82 {
84 if (auto delegate = _delegate.lock()) {
85 delegate->init(*this);
86 }
87 }
88
89 void deinit() noexcept override
90 {
91 if (auto delegate = _delegate.lock()) {
92 delegate->deinit(*this);
93 }
94 }
95
96 [[nodiscard]] float margin() const noexcept override
97 {
98 return 0.0f;
99 }
100
101 [[nodiscard]] bool constrain(utc_nanoseconds display_time_point, bool need_reconstrain) noexcept override
102 {
103 tt_axiom(is_gui_thread());
104
105 if (super::constrain(display_time_point, need_reconstrain)) {
106 _layout.clear();
107 _layout.reserve(std::ssize(_children));
108
109 ssize_t index = 0;
110
111 auto minimum_thickness = 0.0f;
112 auto preferred_thickness = 0.0f;
113 auto maximum_thickness = 0.0f;
114 for (ttlet &child : _children) {
115 update_constraints_for_child(*child, index++, minimum_thickness, preferred_thickness, maximum_thickness);
116 }
117
118 tt_axiom(index == std::ssize(_children));
119
120 if constexpr (axis == axis::row) {
121 _minimum_size = {_layout.minimum_size(), minimum_thickness};
122 _preferred_size = {_layout.preferred_size(), preferred_thickness};
123 _maximum_size = {_layout.maximum_size(), maximum_thickness};
124 } else {
125 _minimum_size = {minimum_thickness, _layout.minimum_size()};
126 _preferred_size = {preferred_thickness, _layout.preferred_size()};
127 _maximum_size = {maximum_thickness, _layout.maximum_size()};
128 }
129 tt_axiom(_minimum_size <= _preferred_size && _preferred_size <= _maximum_size);
130 return true;
131 } else {
132 return false;
133 }
134 }
135
136 [[nodiscard]] void layout(utc_nanoseconds display_time_point, bool need_layout) noexcept override
137 {
138 tt_axiom(is_gui_thread());
139
140 need_layout |= _request_layout.exchange(false);
141 if (need_layout) {
142 _layout.set_size(axis == axis::row ? rectangle().width() : rectangle().height());
143
144 ssize_t index = 0;
145 for (ttlet &child : _children) {
146 update_layout_for_child(*child, index++);
147 }
148
149 tt_axiom(index == std::ssize(_children));
150 }
151 super::layout(display_time_point, need_layout);
152 }
154private:
156 flow_layout _layout;
157
158 void update_constraints_for_child(
159 widget const &child,
160 ssize_t index,
161 float &minimum_thickness,
162 float &preferred_thickness,
163 float &maximum_thickness) noexcept
164 {
165 tt_axiom(is_gui_thread());
166
167 if (axis == axis::row) {
168 ttlet minimum_length = child.minimum_size().width();
169 ttlet preferred_length = child.preferred_size().width();
170 ttlet maximum_length = child.maximum_size().width();
171 _layout.update(index, minimum_length, preferred_length, maximum_length, child.margin());
172
173 minimum_thickness = std::max(minimum_thickness, child.minimum_size().height() + child.margin() * 2.0f);
174 preferred_thickness = std::max(preferred_thickness, child.preferred_size().height() + child.margin() * 2.0f);
175 maximum_thickness = std::max(maximum_thickness, child.maximum_size().height() + child.margin() * 2.0f);
176
177 } else {
178 ttlet minimum_length = child.minimum_size().height();
179 ttlet preferred_length = child.preferred_size().height();
180 ttlet maximum_length = child.maximum_size().height();
181 _layout.update(index, minimum_length, preferred_length, maximum_length, child.margin());
182
183 minimum_thickness = std::max(minimum_thickness, child.minimum_size().width() + child.margin() * 2.0f);
184 preferred_thickness = std::max(preferred_thickness, child.preferred_size().width() + child.margin() * 2.0f);
185 maximum_thickness = std::max(maximum_thickness, child.maximum_size().width() + child.margin() * 2.0f);
186 }
187 }
188
189 void update_layout_for_child(widget &child, ssize_t index) const noexcept
190 {
191 tt_axiom(is_gui_thread());
192
193 ttlet[child_offset, child_length] = _layout.get_offset_and_size(index++);
194
195 ttlet child_rectangle = axis == axis::row ?
196 aarectangle{
197 rectangle().left() + child_offset,
198 rectangle().bottom() + child.margin(),
199 child_length,
200 rectangle().height() - child.margin() * 2.0f} :
201 aarectangle{
202 rectangle().left() + child.margin(),
203 rectangle().top() - child_offset - child_length,
204 rectangle().width() - child.margin() * 2.0f,
205 child_length};
206
207 child.set_layout_parameters_from_parent(child_rectangle);
208 }
209};
210
214
218
219} // namespace tt
STL namespace.
void reserve(ssize_t new_size) noexcept
Grow layout to include upto new_size of items.
Definition flow_layout.hpp:151
void set_size(float total_size) noexcept
Update the layout of all items based on the total size.
Definition flow_layout.hpp:118
Definition gui_window.hpp:39
A row/column widget lays out child widgets along a row or column.
Definition row_column_widget.hpp:37
row_column_widget(gui_window &window, widget *parent, std::weak_ptr< delegate_type > delegate={}) noexcept
Constructs an empty row/column widget.
Definition row_column_widget.hpp:52
Widget & make_widget(Args &&...args)
Add a widget directly to this grid-widget.
Definition row_column_widget.hpp:75
Definition row_column_delegate.hpp:16
An interactive graphical object as part of the user-interface.
Definition widget.hpp:37
widget *const parent
Pointer to the parent widget.
Definition widget.hpp:46
virtual bool constrain(utc_nanoseconds display_time_point, bool need_reconstrain) noexcept
Update the constraints of the widget.
virtual void init() noexcept
Should be called right after allocating and constructing a widget.
int semantic_layer
The draw layer of the widget.
Definition widget.hpp:90
aarectangle rectangle() const noexcept
Get the rectangle in local coordinates.
gui_window & window
Convenient reference to the Window.
Definition widget.hpp:41
virtual void layout(utc_nanoseconds display_time_point, bool need_layout) noexcept
Update the internal layout of the widget.
widget(gui_window &window, widget *parent) noexcept
T max(T... args)