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 "../GUI/module.hpp"
12#include "../layout/grid_layout.hpp"
13#include "../log.hpp"
14#include <memory>
15
16namespace hi { inline namespace v1 {
17
40template<fixed_string Name = "">
41class grid_widget : public widget {
42public:
43 using super = widget;
44 constexpr static auto prefix = Name / "grid";
45
46 ~grid_widget() {};
47
53 {
54 hi_axiom(loop::main().on_thread());
55
56 if (parent) {
58 }
59 }
60
71 template<typename Widget, typename... Args>
72 Widget&
73 make_widget(std::size_t first_column, std::size_t first_row, std::size_t last_column, std::size_t last_row, Args&&...args)
74 {
75 hi_axiom(first_column < last_column);
76 hi_axiom(first_row < last_row);
77 auto tmp = std::make_unique<Widget>(this, std::forward<Args>(args)...);
78 return static_cast<Widget&>(add_widget(first_column, first_row, last_column, last_row, std::move(tmp)));
79 }
80
89 template<typename Widget, typename... Args>
90 Widget& make_widget(std::size_t column, std::size_t row, Args&&...args)
91 {
92 return make_widget<Widget>(column, row, column + 1, row + 1, std::forward<Args>(args)...);
93 }
94
103 template<typename Widget, typename... Args>
104 Widget& make_widget(std::string_view address, Args&&...args)
105 {
106 hilet[column_first, row_first, column_last, row_last] = parse_spreadsheet_range(address);
107 return make_widget<Widget>(column_first, row_first, column_last, row_last, std::forward<Args>(args)...);
108 }
109
111 [[nodiscard]] generator<widget const&> children(bool include_invisible) const noexcept override
112 {
113 for (hilet& cell : _grid) {
114 co_yield *cell.value;
115 }
116 }
117
118 [[nodiscard]] box_constraints update_constraints() noexcept override
119 {
120 for (auto& cell : _grid) {
121 cell.set_constraints(cell.value->update_constraints());
122 }
123
124 return _grid.constraints(os_settings::left_to_right());
125 }
126
127 void set_layout(widget_layout const& context) noexcept override
128 {
129 if (compare_store(layout, context)) {
130 _grid.set_layout(context.shape, theme<prefix>.cap_height(this));
131 }
132
133 for (hilet& cell : _grid) {
134 cell.value->set_layout(context.transform(cell.shape, 0.0f));
135 }
136 }
137
138 void draw(widget_draw_context& context) noexcept override
139 {
140 // Don't check for overlap, since children can have overlays.
142 for (hilet& cell : _grid) {
143 cell.value->draw(context);
144 }
145 }
146 }
147
148 [[nodiscard]] hitbox hitbox_test(point2i position) const noexcept override
149 {
150 hi_axiom(loop::main().on_thread());
151
152 if (*mode >= widget_mode::partial) {
153 auto r = hitbox{};
154 for (hilet& cell : _grid) {
155 r = cell.value->hitbox_test_from_parent(position, r);
156 }
157 return r;
158 } else {
159 return {};
160 }
161 }
162
164private:
165 grid_layout<std::unique_ptr<widget>> _grid;
166
167 /* Add a widget to the grid.
168 */
169 widget& add_widget(
170 std::size_t first_column,
171 std::size_t first_row,
172 std::size_t last_column,
173 std::size_t last_row,
174 std::unique_ptr<widget> child_widget) noexcept
175 {
176 hi_axiom(loop::main().on_thread());
177 hi_axiom(first_column < last_column);
178 hi_axiom(first_row < last_row);
179
180 if (_grid.cell_in_use(first_column, first_row, last_column, last_row)) {
181 hi_log_fatal("cell ({},{}) of grid_widget is already in use", first_column, first_row);
182 }
183
184 auto& ref = *child_widget;
185 _grid.add_cell(first_column, first_row, last_column, last_row, std::move(child_widget));
186 hi_log_info("grid_widget::add_widget({}, {}, {}, {})", first_column, first_row, last_column, last_row);
187
188 ++global_counter<"grid_widget:add_widget:constrain">;
189 process_event({gui_event_type::window_reconstrain});
190 return ref;
191 }
192};
193
194}} // namespace hi::v1
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:253
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
@ window_reconstrain
Request that widget get constraint on the next frame.
@ partial
A widget is partially enabled.
@ invisible
The widget is invisible.
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11
bool compare_store(T &lhs, U &&rhs) noexcept
Compare then store if there was a change.
Definition utility.hpp:212
Definition widget.hpp:26
widget * parent
Pointer to the parent widget.
Definition widget.hpp:40
observer< widget_mode > mode
The widget mode.
Definition widget.hpp:49
size_t semantic_layer
The draw layer of the widget.
Definition widget.hpp:81
A GUI widget that lays out child-widgets in a grid with variable sized cells.
Definition grid_widget.hpp:41
Widget & make_widget(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:73
Widget & make_widget(std::size_t column, std::size_t row, Args &&...args)
Add a widget directly to this grid-widget.
Definition grid_widget.hpp:90
Widget & make_widget(std::string_view address, Args &&...args)
Add a widget directly to this grid-widget.
Definition grid_widget.hpp:104
grid_widget(widget *parent) noexcept
Constructs an empty grid widget.
Definition grid_widget.hpp:52
T move(T... args)
T ref(T... args)