HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
grid_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 "../layout/layout.hpp"
13#include "../macros.hpp"
14#include <memory>
15#include <coroutine>
16
17hi_export_module(hikogui.widgets.grid_widget);
18
19hi_export namespace hi { inline namespace v1 {
20
43class grid_widget : public widget {
44public:
45 using super = widget;
46
47 ~grid_widget() {}
48
54 {
55 }
56
57 /* Add a widget to the grid.
58 */
59 widget& insert(
60 std::size_t first_column,
61 std::size_t first_row,
62 std::size_t last_column,
63 std::size_t last_row,
65 {
66 hi_axiom(loop::main().on_thread());
67 hi_axiom(first_column < last_column);
68 hi_axiom(first_row < last_row);
69
70 if (_grid.cell_in_use(first_column, first_row, last_column, last_row)) {
71 hi_log_fatal("cell ({},{}) of grid_widget is already in use", first_column, first_row);
72 }
73
74 auto& ref = *widget;
75 _grid.add_cell(first_column, first_row, last_column, last_row, std::move(widget));
76 hi_log_info("grid_widget::insert({}, {}, {}, {})", first_column, first_row, last_column, last_row);
77
78 ++global_counter<"grid_widget:insert:constrain">;
80 return ref;
81 }
82
94 {
95 for (auto &cell: _grid) {
96 ++cell.first_column;
97 ++cell.last_column;
98 }
99 return insert(0, 0, 1, 1, std::move(widget));
100 }
101
112 {
113 auto it = std::max_element(_grid.begin(), _grid.end(), [](auto const &a, auto const &b) {
114 return a.last_column < b.last_column;
115 });
116
117 if (it == _grid.end()) {
118 return insert(0, 0, 1, 1, std::move(widget));
119 } else {
120 return insert(it->last_column, 0, it->last_column + 1, 1, std::move(widget));
121 }
122 }
123
133 {
134 for (auto &cell: _grid) {
135 ++cell.first_row;
136 ++cell.last_row;
137 }
138 return insert(0, 0, 1, 1, std::move(widget));
139 }
140
149 {
150 auto it = std::max_element(_grid.begin(), _grid.end(), [](auto const &a, auto const &b) {
151 return a.last_row < b.last_row;
152 });
153
154 if (it == _grid.end()) {
155 return insert(0, 0, 1, 1, std::move(widget));
156 } else {
157 return insert(0, it->last_row, 1, it->last_row + 1, std::move(widget));
158 }
159 }
160
171 template<typename Widget, typename... Args>
172 Widget&
173 emplace(std::size_t first_column, std::size_t first_row, std::size_t last_column, std::size_t last_row, Args&&...args)
174 {
175 hi_axiom(first_column < last_column);
176 hi_axiom(first_row < last_row);
177 auto tmp = std::make_unique<Widget>(this, std::forward<Args>(args)...);
178 return static_cast<Widget&>(insert(first_column, first_row, last_column, last_row, std::move(tmp)));
179 }
180
189 template<typename Widget, typename... Args>
190 Widget& emplace(std::size_t column, std::size_t row, Args&&...args)
191 {
192 return emplace<Widget>(column, row, column + 1, row + 1, std::forward<Args>(args)...);
193 }
194
203 template<typename Widget, typename... Args>
204 Widget& emplace(std::string_view address, Args&&...args)
205 {
206 auto const[column_first, row_first, column_last, row_last] = parse_spreadsheet_range(address);
207 return emplace<Widget>(column_first, row_first, column_last, row_last, std::forward<Args>(args)...);
208 }
209
221 template<typename Widget, typename... Args>
222 Widget& emplace_front(Args&&...args)
223 {
224 return static_cast<Widget&>(push_front(std::make_unique<Widget>(this, std::forward<Args>(args)...)));
225 }
226
237 template<typename Widget, typename... Args>
238 Widget& emplace_back(Args&&...args)
239 {
240 return static_cast<Widget&>(push_back(std::make_unique<Widget>(this, std::forward<Args>(args)...)));
241 }
242
252 template<typename Widget, typename... Args>
253 Widget& emplace_top(Args&&...args)
254 {
255 return static_cast<Widget&>(push_top(std::make_unique<Widget>(this, std::forward<Args>(args)...)));
256 }
257
266 template<typename Widget, typename... Args>
267 Widget& emplace_bottom(Args&&...args)
268 {
269 return static_cast<Widget&>(push_bottom(std::make_unique<Widget>(this, std::forward<Args>(args)...)));
270 }
271
274 void clear() noexcept
275 {
276 _grid.clear();
277 }
278
280 [[nodiscard]] generator<widget_intf &> children(bool include_invisible) noexcept override
281 {
282 for (auto const& cell : _grid) {
283 co_yield *cell.value;
284 }
285 }
286
287 [[nodiscard]] box_constraints update_constraints() noexcept override
288 {
289 _layout = {};
290
291 for (auto& cell : _grid) {
292 cell.set_constraints(cell.value->update_constraints());
293 }
294
295 return _grid.constraints(os_settings::left_to_right());
296 }
297
298 void set_layout(widget_layout const& context) noexcept override
299 {
300 if (compare_store(_layout, context)) {
301 _grid.set_layout(context.shape, theme().baseline_adjustment());
302 }
303
304 for (auto const& cell : _grid) {
305 cell.value->set_layout(context.transform(cell.shape, transform_command::level));
306 }
307 }
308
309 void draw(draw_context const& context) noexcept override
310 {
311 if (mode() > widget_mode::invisible) {
312 for (auto const& cell : _grid) {
313 cell.value->draw(context);
314 }
315 }
316 }
317
318 [[nodiscard]] hitbox hitbox_test(point2 position) const noexcept override
319 {
320 hi_axiom(loop::main().on_thread());
321
322 if (mode() >= widget_mode::partial) {
323 auto r = hitbox{};
324 for (auto const& cell : _grid) {
325 r = cell.value->hitbox_test_from_parent(position, r);
326 }
327 return r;
328 } else {
329 return {};
330 }
331 }
333private:
334 grid_layout<std::unique_ptr<widget>> _grid;
335};
336
337}} // namespace hi::v1
Defines widget.
@ window_reconstrain
Request that widget get constraint on the next frame.
@ partial
A widget is partially enabled.
@ invisible
The widget is invisible.
The HikoGUI namespace.
Definition array_generic.hpp:20
bool compare_store(T &lhs, U &&rhs) noexcept
Compare then store if there was a change.
Definition misc.hpp:53
@ level
The child widget stays at the same elevation and layer.
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 GUI widget that lays out child-widgets in a grid with variable sized cells.
Definition grid_widget.hpp:43
widget & push_back(std::unique_ptr< widget > widget) noexcept
Insert a widget to the back of the grid.
Definition grid_widget.hpp:111
Widget & emplace(std::size_t column, std::size_t row, Args &&...args)
Add a widget directly to this grid-widget.
Definition grid_widget.hpp:190
Widget & emplace_bottom(Args &&...args)
Emplace a widget to the back.
Definition grid_widget.hpp:267
grid_widget(widget_intf const *parent) noexcept
Constructs an empty grid widget.
Definition grid_widget.hpp:53
Widget & emplace(std::string_view address, Args &&...args)
Add a widget directly to this grid-widget.
Definition grid_widget.hpp:204
widget & push_bottom(std::unique_ptr< widget > widget) noexcept
Insert a widget to the bottom of the grid.
Definition grid_widget.hpp:148
Widget & emplace_back(Args &&...args)
Emplace a widget to the back.
Definition grid_widget.hpp:238
widget & push_top(std::unique_ptr< widget > widget) noexcept
Insert a widget to the top of the grid.
Definition grid_widget.hpp:132
void clear() noexcept
Remove all child widgets.
Definition grid_widget.hpp:274
widget & push_front(std::unique_ptr< widget > widget) noexcept
Insert a widget to the front of the grid.
Definition grid_widget.hpp:93
Widget & emplace_top(Args &&...args)
Emplace a widget to the back.
Definition grid_widget.hpp:253
Widget & emplace(std::size_t first_column, std::size_t first_row, std::size_t last_column, std::size_t last_row, Args &&...args)
Add a widget directly to this grid-widget.
Definition grid_widget.hpp:173
Widget & emplace_front(Args &&...args)
Emplace a widget to the front.
Definition grid_widget.hpp:222
An interactive graphical object as part of the user-interface.
Definition widget.hpp:37
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 max_element(T... args)
T move(T... args)