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
8
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
53 grid_widget() noexcept : widget()
54 {
55 }
56
57 /* Add a widget to the grid.
58 */
59 void 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 widget->set_parent(this);
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 }
81
93 {
94 for (auto &cell: _grid) {
95 ++cell.first_column;
96 ++cell.last_column;
97 }
98 insert(0, 0, 1, 1, std::move(widget));
99 }
100
111 {
112 auto it = std::max_element(_grid.begin(), _grid.end(), [](auto const &a, auto const &b) {
113 return a.last_column < b.last_column;
114 });
115
116 if (it == _grid.end()) {
117 insert(0, 0, 1, 1, std::move(widget));
118 } else {
119 insert(it->last_column, 0, it->last_column + 1, 1, std::move(widget));
120 }
121 }
122
132 {
133 for (auto &cell: _grid) {
134 ++cell.first_row;
135 ++cell.last_row;
136 }
137 insert(0, 0, 1, 1, std::move(widget));
138 }
139
148 {
149 auto it = std::max_element(_grid.begin(), _grid.end(), [](auto const &a, auto const &b) {
150 return a.last_row < b.last_row;
151 });
152
153 if (it == _grid.end()) {
154 insert(0, 0, 1, 1, std::move(widget));
155 } else {
156 insert(0, it->last_row, 1, it->last_row + 1, std::move(widget));
157 }
158 }
159
170 template<typename Widget, typename... Args>
171 Widget&
172 emplace(std::size_t first_column, std::size_t first_row, std::size_t last_column, std::size_t last_row, Args&&...args)
173 {
174 hi_axiom(first_column < last_column);
175 hi_axiom(first_row < last_row);
176 auto tmp = std::make_unique<Widget>(std::forward<Args>(args)...);
177 auto &ref = *tmp;
178 insert(first_column, first_row, last_column, last_row, std::move(tmp));
179 return ref;
180 }
181
190 template<typename Widget, typename... Args>
191 Widget& emplace(std::size_t column, std::size_t row, Args&&...args)
192 {
193 return emplace<Widget>(column, row, column + 1, row + 1, std::forward<Args>(args)...);
194 }
195
204 template<typename Widget, typename... Args>
205 Widget& emplace(std::string_view address, Args&&...args)
206 {
207 auto const[column_first, row_first, column_last, row_last] = parse_spreadsheet_range(address);
208 return emplace<Widget>(column_first, row_first, column_last, row_last, std::forward<Args>(args)...);
209 }
210
222 template<typename Widget, typename... Args>
223 Widget& emplace_front(Args&&...args)
224 {
225 return static_cast<Widget&>(push_front(std::make_unique<Widget>(this, std::forward<Args>(args)...)));
226 }
227
238 template<typename Widget, typename... Args>
239 Widget& emplace_back(Args&&...args)
240 {
241 return static_cast<Widget&>(push_back(std::make_unique<Widget>(this, std::forward<Args>(args)...)));
242 }
243
253 template<typename Widget, typename... Args>
254 Widget& emplace_top(Args&&...args)
255 {
256 return static_cast<Widget&>(push_top(std::make_unique<Widget>(this, std::forward<Args>(args)...)));
257 }
258
267 template<typename Widget, typename... Args>
268 Widget& emplace_bottom(Args&&...args)
269 {
270 auto tmp = std::make_unique<Widget>(std::forward<Args>(args)...);
271 auto &ref = *tmp;
273 return ref;
274 }
275
278 void clear() noexcept
279 {
280 _grid.clear();
281 }
282
284 [[nodiscard]] generator<widget_intf &> children(bool include_invisible) noexcept override
285 {
286 for (auto const& cell : _grid) {
287 co_yield *cell.value;
288 }
289 }
290
291 [[nodiscard]] box_constraints update_constraints() noexcept override
292 {
293 _layout = {};
294
295 for (auto& cell : _grid) {
296 cell.set_constraints(cell.value->update_constraints());
297 }
298
299 return _grid.constraints(os_settings::left_to_right());
300 }
301
302 void set_layout(widget_layout const& context) noexcept override
303 {
304 if (compare_store(_layout, context)) {
305 _grid.set_layout(context.shape, theme().baseline_adjustment());
306 }
307
308 for (auto const& cell : _grid) {
309 cell.value->set_layout(context.transform(cell.shape, transform_command::level));
310 }
311 }
312
313 void draw(draw_context const& context) noexcept override
314 {
315 if (mode() > widget_mode::invisible) {
316 for (auto const& cell : _grid) {
317 cell.value->draw(context);
318 }
319 }
320 }
321
322 [[nodiscard]] hitbox hitbox_test(point2 position) const noexcept override
323 {
324 hi_axiom(loop::main().on_thread());
325
326 if (mode() >= widget_mode::partial) {
327 auto r = hitbox{};
328 for (auto const& cell : _grid) {
329 r = cell.value->hitbox_test_from_parent(position, r);
330 }
331 return r;
332 } else {
333 return {};
334 }
335 }
337private:
338 grid_layout<std::unique_ptr<widget>> _grid;
339};
340
341}} // namespace hi::v1
Defines widget.
@ window_reconstrain
Request that widget get constraint on the next frame.
Definition gui_event_type.hpp:48
@ partial
A widget is partially enabled.
Definition widget_state.hpp:73
@ invisible
The widget is invisible.
Definition widget_state.hpp:41
The HikoGUI namespace.
Definition array_generic.hpp:21
The HikoGUI API version 1.
Definition array_generic.hpp:22
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.
Definition widget_layout.hpp:26
virtual void set_parent(widget_intf *new_parent) noexcept
Set the parent widget.
Definition widget_intf.hpp:411
A GUI widget that lays out child-widgets in a grid with variable sized cells.
Definition grid_widget.hpp:43
void push_top(std::unique_ptr< widget > widget) noexcept
Insert a widget to the top of the grid.
Definition grid_widget.hpp:131
Widget & emplace(std::size_t column, std::size_t row, Args &&...args)
Add a widget directly to this grid-widget.
Definition grid_widget.hpp:191
grid_widget() noexcept
Constructs an empty grid widget.
Definition grid_widget.hpp:53
void push_front(std::unique_ptr< widget > widget) noexcept
Insert a widget to the front of the grid.
Definition grid_widget.hpp:92
Widget & emplace_bottom(Args &&...args)
Emplace a widget to the back.
Definition grid_widget.hpp:268
Widget & emplace(std::string_view address, Args &&...args)
Add a widget directly to this grid-widget.
Definition grid_widget.hpp:205
Widget & emplace_back(Args &&...args)
Emplace a widget to the back.
Definition grid_widget.hpp:239
void push_back(std::unique_ptr< widget > widget) noexcept
Insert a widget to the back of the grid.
Definition grid_widget.hpp:110
void clear() noexcept
Remove all child widgets.
Definition grid_widget.hpp:278
Widget & emplace_top(Args &&...args)
Emplace a widget to the back.
Definition grid_widget.hpp:254
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:172
Widget & emplace_front(Args &&...args)
Emplace a widget to the front.
Definition grid_widget.hpp:223
void push_bottom(std::unique_ptr< widget > widget) noexcept
Insert a widget to the bottom of the grid.
Definition grid_widget.hpp:147
An interactive graphical object as part of the user-interface.
Definition widget.hpp:38
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 max_element(T... args)
T move(T... args)