7#include <initializer_list>
17bool IsCell(
int x,
int y) {
18 return x % 2 == 1 &&
y % 2 == 1;
22static std::string table_charset[6][6] = {
23 {
"┌",
"┐",
"└",
"┘",
"─",
"│"},
24 {
"┏",
"┓",
"┗",
"┛",
"╍",
"╏"},
25 {
"┏",
"┓",
"┗",
"┛",
"━",
"┃"},
26 {
"╔",
"╗",
"╚",
"╝",
"═",
"║"},
27 {
"╭",
"╮",
"╰",
"╯",
"─",
"│"},
28 {
" ",
" ",
" ",
" ",
" ",
" "},
32int Wrap(
int input,
int modulo) {
33 return input < 0 ? input + modulo : input;
36bool InRange(
int input,
int modulo) {
37 return input >= 0 && input < modulo;
40void Order(
int& a,
int& b) {
55Table::Table(
const std::vector<std::vector<std::string>>& input) {
56 std::vector<std::vector<Element>> output;
57 output.reserve(input.size());
58 for (
const auto& row : input) {
59 output.emplace_back();
60 auto& output_row = output.back();
61 output_row.reserve(row.size());
62 for (
const auto& cell : row) {
63 output_row.push_back(text(std::move(cell)));
66 Initialize(std::move(output));
71Table::Table(std::vector<std::vector<Element>> input) {
72 Initialize(std::move(input));
77Table::Table(std::initializer_list<std::vector<std::string>> init) {
78 std::vector<std::vector<Element>> input;
79 for (
const auto& row : init) {
80 std::vector<Element> output_row;
81 output_row.reserve(row.size());
82 for (
const auto& cell : row) {
83 output_row.push_back(text(cell));
85 input.push_back(std::move(output_row));
87 Initialize(std::move(input));
91void Table::Initialize(std::vector<std::vector<Element>> input) {
92 input_dim_y_ =
static_cast<int>(input.size());
94 for (
auto& row : input) {
95 input_dim_x_ = std::max(input_dim_x_,
int(row.size()));
98 dim_y_ = 2 * input_dim_y_ + 1;
99 dim_x_ = 2 * input_dim_x_ + 1;
102 elements_.resize(dim_y_);
103 for (
int y = 0;
y < dim_y_; ++
y) {
104 elements_[
y].resize(dim_x_);
110 for (
auto& row : input) {
112 for (
auto& cell : row) {
113 elements_[
y][x] = std::move(cell);
121 for (
int y = 0;
y < dim_y_; ++
y) {
122 for (
int x = 0; x < dim_x_; ++x) {
140TableSelection Table::SelectRow(
int index) {
141 return SelectRectangle(0, -1, index, index);
148TableSelection Table::SelectRows(
int row_min,
int row_max) {
149 return SelectRectangle(0, -1, row_min, row_max);
155TableSelection Table::SelectColumn(
int index) {
156 return SelectRectangle(index, index, 0, -1);
163TableSelection Table::SelectColumns(
int column_min,
int column_max) {
164 return SelectRectangle(column_min, column_max, 0, -1);
171TableSelection Table::SelectCell(
int column,
int row) {
172 return SelectRectangle(column, column, row, row);
181TableSelection Table::SelectRectangle(
int column_min,
185 TableSelection output;
186 output.table_ =
this;
188 column_min =
Wrap(column_min, input_dim_x_);
189 column_max =
Wrap(column_max, input_dim_x_);
190 row_min =
Wrap(row_min, input_dim_y_);
191 row_max =
Wrap(row_max, input_dim_y_);
194 if (!InRange(column_min, input_dim_x_) ||
195 !InRange(column_max, input_dim_x_) || !InRange(row_min, input_dim_y_) ||
196 !InRange(row_max, input_dim_y_)) {
204 Order(column_min, column_max);
205 Order(row_min, row_max);
207 output.x_min_ = 2 * column_min;
208 output.x_max_ = 2 * column_max + 2;
209 output.y_min_ = 2 * row_min;
210 output.y_max_ = 2 * row_max + 2;
215TableSelection Table::SelectAll() {
216 TableSelection output;
217 output.table_ =
this;
219 output.x_max_ = dim_x_ - 1;
221 output.y_max_ = dim_y_ - 1;
228 for (
int y = 0;
y < dim_y_; ++
y) {
229 for (
int x = 0; x < dim_x_; ++x) {
230 auto& it = elements_[
y][x];
233 if ((x + y) % 2 == 1) {
234 it = std::move(it) | flex;
239 if ((x % 2) == 1 && (y % 2) == 1) {
240 it = std::move(it) | flex_shrink;
245 it = std::move(it) | size(WIDTH, EQUAL, 0) | size(HEIGHT, EQUAL, 0);
250 return gridbox(std::move(elements_));
257void TableSelection::Decorate(
const Decorator& decorator) {
258 for (
int y = y_min_;
y <= y_max_; ++
y) {
259 for (
int x = x_min_; x <= x_max_; ++x) {
260 Element& e = table_->elements_[
y][x];
261 e = std::move(e) | decorator;
270void TableSelection::DecorateCells(
const Decorator& decorator) {
271 for (
int y = y_min_;
y <= y_max_; ++
y) {
272 for (
int x = x_min_; x <= x_max_; ++x) {
273 if (y % 2 == 1 && x % 2 == 1) {
274 Element& e = table_->elements_[
y][x];
275 e = std::move(e) | decorator;
287void TableSelection::DecorateAlternateColumn(
const Decorator& decorator,
290 for (
int y = y_min_;
y <= y_max_; ++
y) {
291 for (
int x = x_min_; x <= x_max_; ++x) {
292 if (y % 2 == 1 && (x / 2) % modulo == shift) {
293 Element& e = table_->elements_[
y][x];
294 e = std::move(e) | decorator;
306void TableSelection::DecorateAlternateRow(
const Decorator& decorator,
309 for (
int y = y_min_ + 1;
y <= y_max_ - 1; ++
y) {
310 for (
int x = x_min_; x <= x_max_; ++x) {
311 if (y % 2 == 1 && (y / 2) % modulo == shift) {
312 Element& e = table_->elements_[
y][x];
313 e = std::move(e) | decorator;
325void TableSelection::DecorateCellsAlternateColumn(
const Decorator& decorator,
328 for (
int y = y_min_;
y <= y_max_; ++
y) {
329 for (
int x = x_min_; x <= x_max_; ++x) {
330 if (y % 2 == 1 && x % 2 == 1 && ((x / 2) % modulo == shift)) {
331 Element& e = table_->elements_[
y][x];
332 e = std::move(e) | decorator;
344void TableSelection::DecorateCellsAlternateRow(
const Decorator& decorator,
347 for (
int y = y_min_;
y <= y_max_; ++
y) {
348 for (
int x = x_min_; x <= x_max_; ++x) {
349 if (y % 2 == 1 && x % 2 == 1 && ((y / 2) % modulo == shift)) {
350 Element& e = table_->elements_[
y][x];
351 e = std::move(e) | decorator;
359void TableSelection::DecorateBorder(
const Decorator& decorator) {
360 for (
int x = x_min_; x <= x_max_; ++x) {
361 table_->elements_[y_min_][x] =
362 std::move(table_->elements_[y_min_][x]) | decorator;
363 table_->elements_[y_max_][x] =
364 std::move(table_->elements_[y_max_][x]) | decorator;
366 for (
int y = y_min_ + 1;
y <= y_max_ - 1; ++
y) {
367 table_->elements_[
y][x_min_] =
368 std::move(table_->elements_[y][x_min_]) | decorator;
369 table_->elements_[
y][x_max_] =
370 std::move(table_->elements_[y][x_max_]) | decorator;
376void TableSelection::DecorateBorderLeft(
const Decorator& decorator) {
377 for (
int y = y_min_;
y <= y_max_;
y++) {
378 table_->elements_[
y][x_min_] =
379 std::move(table_->elements_[y][x_min_]) | decorator;
385void TableSelection::DecorateBorderRight(
const Decorator& decorator) {
386 for (
int y = y_min_;
y <= y_max_;
y++) {
387 table_->elements_[
y][x_max_] =
388 std::move(table_->elements_[y][x_max_]) | decorator;
394void TableSelection::DecorateBorderTop(
const Decorator& decorator) {
395 for (
int x = x_min_; x <= x_max_; x++) {
396 table_->elements_[y_min_][x] =
397 std::move(table_->elements_[y_min_][x]) | decorator;
403void TableSelection::DecorateBorderBottom(
const Decorator& decorator) {
404 for (
int x = x_min_; x <= x_max_; x++) {
405 table_->elements_[y_max_][x] =
406 std::move(table_->elements_[y_max_][x]) | decorator;
412void TableSelection::DecorateSeparator(
const Decorator& decorator) {
413 for (
int y = y_min_ + 1;
y <= y_max_ - 1; ++
y) {
414 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
415 if (y % 2 == 0 || x % 2 == 0) {
416 table_->elements_[
y][x] =
417 std::move(table_->elements_[y][x]) | decorator;
425void TableSelection::DecorateSeparatorVertical(
const Decorator& decorator) {
426 for (
int y = y_min_ + 1;
y <= y_max_ - 1; ++
y) {
427 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
429 table_->elements_[
y][x] =
430 std::move(table_->elements_[y][x]) | decorator;
438void TableSelection::DecorateSeparatorHorizontal(
const Decorator& decorator) {
439 for (
int y = y_min_ + 1;
y <= y_max_ - 1; ++
y) {
440 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
442 table_->elements_[
y][x] =
443 std::move(table_->elements_[y][x]) | decorator;
452 if (x_min_ > x_max_ || y_min_ > y_max_) {
459 BorderBottom(border);
462 table_->elements_[y_min_][x_min_] =
463 text(table_charset[border][0]) | automerge;
465 table_->elements_[y_min_][x_max_] =
466 text(table_charset[border][1]) | automerge;
468 table_->elements_[y_max_][x_min_] =
469 text(table_charset[border][2]) | automerge;
471 table_->elements_[y_max_][x_max_] =
472 text(table_charset[border][3]) | automerge;
480 DecorateBorder(decorator);
485void TableSelection::Separator(
BorderStyle border) {
486 for (
int y = y_min_ + 1;
y <= y_max_ - 1; ++
y) {
487 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
488 if (y % 2 == 0 || x % 2 == 0) {
489 Element& e = table_->elements_[
y][x];
490 e = (
y % 2 == 1) ? separatorCharacter(table_charset[border][5]) |
492 : separatorCharacter(table_charset[border][4]) |
504 DecorateSeparator(decorator);
509void TableSelection::SeparatorVertical(
BorderStyle border) {
510 for (
int y = y_min_ + 1;
y <= y_max_ - 1; ++
y) {
511 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
513 table_->elements_[
y][x] =
514 separatorCharacter(table_charset[border][5]) | automerge;
523void TableSelection::SeparatorVertical(
BorderStyle border,
525 SeparatorVertical(border);
526 DecorateSeparatorVertical(decorator);
531void TableSelection::SeparatorHorizontal(
BorderStyle border) {
532 for (
int y = y_min_ + 1;
y <= y_max_ - 1; ++
y) {
533 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
535 table_->elements_[
y][x] =
536 separatorCharacter(table_charset[border][4]) | automerge;
545void TableSelection::SeparatorHorizontal(
BorderStyle border,
547 SeparatorHorizontal(border);
548 DecorateSeparatorHorizontal(decorator);
553void TableSelection::BorderLeft(
BorderStyle border) {
554 for (
int y = y_min_;
y <= y_max_;
y++) {
555 table_->elements_[
y][x_min_] =
556 separatorCharacter(table_charset[border][5]) | automerge;
566 DecorateBorderLeft(decorator);
571void TableSelection::BorderRight(
BorderStyle border) {
572 for (
int y = y_min_;
y <= y_max_;
y++) {
573 table_->elements_[
y][x_max_] =
574 separatorCharacter(table_charset[border][5]) | automerge;
581void TableSelection::BorderRight(
BorderStyle border,
584 DecorateBorderRight(decorator);
589void TableSelection::BorderTop(
BorderStyle border) {
590 for (
int x = x_min_; x <= x_max_; x++) {
591 table_->elements_[y_min_][x] =
592 separatorCharacter(table_charset[border][4]) | automerge;
601 DecorateBorderTop(decorator);
606void TableSelection::BorderBottom(
BorderStyle border) {
607 for (
int x = x_min_; x <= x_max_; x++) {
608 table_->elements_[y_max_][x] =
609 separatorCharacter(table_charset[border][4]) | automerge;
616void TableSelection::BorderBottom(
BorderStyle border,
618 BorderBottom(border);
619 DecorateBorderBottom(decorator);
Component Wrap(std::string name, Component component)
BorderStyle
BorderStyle is an enumeration that represents the different styles of borders that can be applied to ...
The FTXUI ftxui:: namespace.
std::shared_ptr< Node > Element
std::function< Element(Element)> Decorator