28 grid& operator=(
grid const&) =
delete;
31 constexpr grid()
noexcept =
default;
53 if (state != grid_state::done) {
54 [[unlikely]] _update();
59 constexpr void remove_cell(
size_t id)
noexcept
61 _cells[id].make_free(std::exchange(_first_free,
id));
64 [[nodiscard]]
constexpr size_t add_cell() noexcept
68 hilet next_free = _cells[_first_free].parent;
69 return std::exchange(_first_free, next_free);
72 hilet id = _cells.size();
73 _cells.emplace_back();
82 [[nodiscard]]
constexpr detail::grid_cell_data& operator[](
size_t id)
noexcept
88 [[nodiscard]]
constexpr detail::grid_cell_data
const& operator[](
size_t id)
const noexcept
101 int32_t _first_free = -1;
112 decltype(_indices)::iterator _grid_begin = {};
116 decltype(_indices)::iterator _root_begin = {};
120 grid_axis _rows = {};
124 grid_axis _columns = {};
128 grid_state _state = grid_state::need_constrain;
130 constexpr auto row_begin(detail::grid_cell_data
const& cell)
noexcept
132 return _rows.begin() + cell.row_offset;
135 constexpr auto col_end(detail::grid_cell_data
const& cell)
noexcept
137 return _cols.begin() + cell.col_offset;
140 constexpr auto row_pair(detail::grid_cell_data
const& parent, detail::grid_cell_data
const& child)
noexcept
142 return std::make_tuple(row_begin(parent) + cell.row_begin, row_begin(parent) + cell.row_end);
145 constexpr auto col_pair(detail::grid_cell_data
const& parent, detail::grid_cell_data
const& child)
noexcept
147 return std::make_tuple(col_begin(parent) + cell.col_begin, col_begin(parent) + cell.col_end);
150 constexpr void update_indices_visit(int32_t i, detail::grid_cell_data& n)
noexcept
154 if (n.permanent_mark) {
157 if (n.temporary_mark) {
161 n.temporary_mark = 1;
162 if (n.parent != -1) {
163 auto& p = _cells[n.parent];
165 make_tree_visit(n.parent, p);
168 n.temporary_mark = 0;
169 n.permanent_mark = 1;
175 constexpr void update_indices() noexcept
179 for (
auto& cell : _cells) {
181 cell.perminant_mark = 0;
182 cell.temporary_mark = 0;
187 for (int32_t i = 0; i != std::ssize(_cells); ++i) {
190 update_indices_visit(i, n);
199 return _cells[a].leaf;
204 return _cells[a].parent != -1;
208 constexpr void calculate_row_col_count_and_margins() noexcept
211 for (
auto& cell : _cells) {
214 cell.row_before_margin = cell.top_margin;
215 cell.col_before_margin = _left_to_right ? cell.left_margin : cell.right_margin;
216 cell.row_after_margin = cell.bottom_margin;
217 cell.col_after_margin = _left_to_right ? cell.right_margin : cell.left_margin;
221 for (
hilet& cell : _cells) {
222 if (cell.parent == -1) {
226 inplace_max(_cells[cell.parent].num_cols, cell.col_end);
227 inplace_max(_cells[cell.parent].num_rows, cell.row_end);
233 for (
hilet i : _indices) {
234 hilet& cell : _cells[i];
236 auto& parent = _cells[cell.parent];
237 if (cell.col_begin == 0) {
238 inplace_max(parent.col_before_margin, cell.col_before_margin);
240 if (cell.row_begin == 0) {
241 inplace_max(parent.row_before_margin, cell.row_before_margin);
243 if (cell.col_end == parent.num_cols) {
244 inplace_max(parent.col_after_margin, cell.col_after_margin);
246 if (cell.row_end == parent.num_row) {
247 inplace_max(parent.row_after_margin, cell.row_after_margin);
252 constexpr void setup_row_col_tables() noexcept
256 for (
auto it = _indices_split; it != _indices.
end(); ++it) {
257 auto& cell = _cells[*it];
261 cell.col_offset = num_cols;
262 cell.row_offset = num_rows;
263 num_cols += cell.num_cols;
264 num_rows += cell.num_rows;
266 _cols.clear(num_cols);
267 _rows.clear(num_rows);
270 constexpr void populate_row_col_tables() noexcept
276 for (
hilet& cell : _cells) {
277 if (cell.parent != -1 and cell.in_use) {
278 hilet& parent = _cells[cell.parent];
280 hilet[first_row, last_row] = row_pair(parent, cell);
281 set_priority(first_row, last_row, cell.row_priority);
282 set_margins(first_row, last_row, cell.row_before_margin, cell.row_after_margin);
285 set_minimum(first_row, last_row, cell.minimum_height);
286 set_preferred(first_row, last_row, cell.minimum_height);
287 set_maximum(first_row, last_row, cell.maximum_height);
290 hilet[first_col, last_col] = col_pair(parent, cell);
291 set_priority(first_col, last_col, cell.row_priority);
292 set_margins(first_col, last_col, cell.col_before_margin, cell.col_after_margin);
296 set_preferred(first_col, last_col, cell.minimum_width);
297 set_maximum(first_col, last_col, cell.maximum_width);
304 for (
hilet& cell : _cells) {
305 if (cell.parent != -1 and cell.in_use) {
306 hilet& parent = _cells[cell.parent];
308 hilet[first_row, last_row] = row_pair(parent, cell);
310 set_minimum(first_row, last_row, cell.minimum_height);
311 set_preferred(first_row, last_row, cell.minimum_height);
312 set_maximum(first_row, last_row, cell.maximum_height);
315 hilet[first_col, last_col] = col_pair(parent, cell);
318 set_preferred(first_col, last_col, cell.minimum_width);
319 set_maximum(first_col, last_col, cell.maximum_width);
327 for (
hilet& cell : _cells) {
328 if (cell.parent != -1 and cell.in_use) {
329 hilet[first_row, last_row] = row_pair(parent, cell);
330 hilet minimum_height = get_minimum(first_row, last_row);
332 hilet[first_col, last_col] = col_pair(parent, cell);
333 hilet minimum_width = cell.wrapped_height <= minimum_height ? cell.wrapped_width : cell.minimum_width);
334 set_minimum(first_col, last_col, minimum_width);
339 constexpr void constrain() noexcept
342 calculate_row_col_count_and_margins();
343 setup_row_col_tables();
344 populate_row_col_tables();
347 constexpr void layout() noexcept
351 for (
auto it = _indices.
rbegin(); it != _indices.
rend(); ++it) {
352 auto& cell = _cells[*it];
354 if (cell.parent != -1) {
357 hilet &parent = _cells[cell.parent];
358 hilet row_first = row_begin(parent) + cell.row_begin;
359 hilet row_last = row_begin(parent) + cell.row_end;
360 hilet col_first = col_begin(parent) + cell.col_begin;
361 hilet col_last = col_begin(parent) + cell.col_end;
362 cell.height = get_size(row_first, row_last);
363 cell.width = get_size(col_first, col_last);
369 hilet [row_first, row_last] = row_pair(grid);
370 update_size(row_first, row_last, grid.height);
371 update_position(row_first, row_last);
373 hilet[col_first, col_last] = col_pair(grid);
374 update_size(col_first, col_last, grid.width);
375 update_position(col_first, col_last);
380 hi_no_inline
constexpr void _update() noexcept
382 if (to_bool(state & grid_state::need_constrain)) {