7#include <initializer_list>
17bool IsCell(
int x,
int y) {
18 return x % 2 == 1 && y % 2 == 1;
22static std::string charset[6][6] = {
23 {
"┌",
"┐",
"└",
"┘",
"─",
"│"},
24 {
"┏",
"┓",
"┗",
"┛",
"╍",
"╏"},
25 {
"┏",
"┓",
"┗",
"┛",
"━",
"┃"},
26 {
"╔",
"╗",
"╚",
"╝",
"═",
"║"},
27 {
"╭",
"╮",
"╰",
"╯",
"─",
"│"},
28 {
" ",
" ",
" ",
" ",
" ",
" "},
31int Wrap(
int input,
int modulo) {
38void Order(
int& a,
int& b) {
54 std::vector<std::vector<Element>> output;
55 output.reserve(input.size());
56 for (
auto& row : input) {
57 output.emplace_back();
58 auto& output_row = output.back();
59 output_row.reserve(row.size());
60 for (
auto& cell : row) {
61 output_row.push_back(
text(std::move(cell)));
64 Initialize(std::move(output));
70 Initialize(std::move(input));
75Table::Table(std::initializer_list<std::vector<std::string>> init) {
76 std::vector<std::vector<Element>> input;
77 for (
const auto& row : init) {
78 std::vector<Element> output_row;
79 output_row.reserve(row.size());
80 for (
const auto& cell : row) {
81 output_row.push_back(
text(cell));
83 input.push_back(std::move(output_row));
85 Initialize(std::move(input));
89void Table::Initialize(std::vector<std::vector<Element>> input) {
90 input_dim_y_ =
static_cast<int>(input.size());
92 for (
auto& row : input) {
93 input_dim_x_ = std::max(input_dim_x_,
int(row.size()));
96 dim_y_ = 2 * input_dim_y_ + 1;
97 dim_x_ = 2 * input_dim_x_ + 1;
100 elements_.resize(dim_y_);
101 for (
int y = 0; y < dim_y_; ++y) {
102 elements_[y].resize(dim_x_);
108 for (
auto& row : input) {
110 for (
auto& cell : row) {
111 elements_[y][x] = std::move(cell);
119 for (
int y = 0; y < dim_y_; ++y) {
120 for (
int x = 0; x < dim_x_; ++x) {
121 auto& element = elements_[y][x];
183 column_min =
Wrap(column_min, input_dim_x_);
184 column_max =
Wrap(column_max, input_dim_x_);
185 Order(column_min, column_max);
186 row_min =
Wrap(row_min, input_dim_y_);
187 row_max =
Wrap(row_max, input_dim_y_);
188 Order(row_min, row_max);
191 output.table_ =
this;
192 output.x_min_ = 2 * column_min;
193 output.x_max_ = 2 * column_max + 2;
194 output.y_min_ = 2 * row_min;
195 output.y_max_ = 2 * row_max + 2;
202 output.table_ =
this;
204 output.x_max_ = dim_x_ - 1;
206 output.y_max_ = dim_y_ - 1;
213 for (
int y = 0; y < dim_y_; ++y) {
214 for (
int x = 0; x < dim_x_; ++x) {
215 auto& it = elements_[y][x];
218 if ((x + y) % 2 == 1) {
219 it = std::move(it) |
flex;
224 if ((x % 2) == 1 && (y % 2) == 1) {
235 return gridbox(std::move(elements_));
243 for (
int y = y_min_; y <= y_max_; ++y) {
244 for (
int x = x_min_; x <= x_max_; ++x) {
245 Element& e = table_->elements_[y][x];
246 e = std::move(e) | decorator;
256 for (
int y = y_min_; y <= y_max_; ++y) {
257 for (
int x = x_min_; x <= x_max_; ++x) {
258 if (y % 2 == 1 && x % 2 == 1) {
259 Element& e = table_->elements_[y][x];
260 e = std::move(e) | decorator;
275 for (
int y = y_min_; y <= y_max_; ++y) {
276 for (
int x = x_min_; x <= x_max_; ++x) {
277 if (y % 2 == 1 && (x / 2) % modulo == shift) {
278 Element& e = table_->elements_[y][x];
279 e = std::move(e) | decorator;
294 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
295 for (
int x = x_min_; x <= x_max_; ++x) {
296 if (y % 2 == 1 && (y / 2) % modulo == shift) {
297 Element& e = table_->elements_[y][x];
298 e = std::move(e) | decorator;
313 for (
int y = y_min_; y <= y_max_; ++y) {
314 for (
int x = x_min_; x <= x_max_; ++x) {
315 if (y % 2 == 1 && x % 2 == 1 && ((x / 2) % modulo == shift)) {
316 Element& e = table_->elements_[y][x];
317 e = std::move(e) | decorator;
332 for (
int y = y_min_; y <= y_max_; ++y) {
333 for (
int x = x_min_; x <= x_max_; ++x) {
334 if (y % 2 == 1 && x % 2 == 1 && ((y / 2) % modulo == shift)) {
335 Element& e = table_->elements_[y][x];
336 e = std::move(e) | decorator;
351 table_->elements_[y_min_][x_min_] =
text(charset[border][0]) |
automerge;
353 table_->elements_[y_min_][x_max_] =
text(charset[border][1]) |
automerge;
355 table_->elements_[y_max_][x_min_] =
text(charset[border][2]) |
automerge;
357 table_->elements_[y_max_][x_max_] =
text(charset[border][3]) |
automerge;
363 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
364 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
365 if (y % 2 == 0 || x % 2 == 0) {
366 Element& e = table_->elements_[y][x];
378 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
379 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
381 table_->elements_[y][x] =
391 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
392 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
394 table_->elements_[y][x] =
404 for (
int y = y_min_; y <= y_max_; y++) {
405 table_->elements_[y][x_min_] =
413 for (
int y = y_min_; y <= y_max_; y++) {
414 table_->elements_[y][x_max_] =
422 for (
int x = x_min_; x <= x_max_; x++) {
423 table_->elements_[y_min_][x] =
431 for (
int x = x_min_; x <= x_max_; x++) {
432 table_->elements_[y_max_][x] =
void DecorateAlternateColumn(Decorator, int modulo=2, int shift=0)
Apply the decorator to the selection. This decorate only the lines modulo modulo with a shift of shif...
void SeparatorVertical(BorderStyle border=LIGHT)
Draw some vertical separator lines in the selection.
void DecorateCells(Decorator)
Apply the decorator to the selection.
void BorderLeft(BorderStyle border=LIGHT)
Draw some separator lines to the left side of the selection.
void DecorateCellsAlternateColumn(Decorator, int modulo=2, int shift=0)
Apply the decorator to the selection. This decorate only the corners modulo modulo with a shift of sh...
void Decorate(Decorator)
Apply the decorator to the selection. This decorate both the cells, the lines and the corners.
void DecorateAlternateRow(Decorator, int modulo=2, int shift=0)
Apply the decorator to the selection. This decorate only the lines modulo modulo with a shift of shif...
void BorderTop(BorderStyle border=LIGHT)
Draw some separator lines to the top side of the selection.
void Separator(BorderStyle border=LIGHT)
Draw some separator lines in the selection.
void BorderBottom(BorderStyle border=LIGHT)
Draw some separator lines to the bottom side of the selection.
void DecorateCellsAlternateRow(Decorator, int modulo=2, int shift=0)
Apply the decorator to the selection. This decorate only the corners modulo modulo with a shift of sh...
void BorderRight(BorderStyle border=LIGHT)
Draw some separator lines to the right side of the selection.
void Border(BorderStyle border=LIGHT)
Apply a border around the selection.
void SeparatorHorizontal(BorderStyle border=LIGHT)
Draw some horizontal separator lines in the selection.
Component Wrap(std::string name, Component component)
Element Render()
Render the table.
Table()
Create an empty table.
TableSelection SelectCell(int column, int row)
Select a cell of the table.
TableSelection SelectColumn(int column_index)
Select a column of the table.
TableSelection SelectRow(int row_index)
Select a row of the table.
TableSelection SelectColumns(int column_min, int column_max)
Select a range of columns of the table.
TableSelection SelectRows(int row_min, int row_max)
Select a range of rows of the table.
TableSelection SelectAll()
Select all the table.
TableSelection SelectRectangle(int column_min, int column_max, int row_min, int row_max)
Select a rectangle of the table.
Decorator size(WidthOrHeight, Constraint, int value)
Apply a constraint on the size of an element.
Element flex(Element)
Make a child element to expand proportionally to the space left in a container.
Element flex_shrink(Element)
Minimize if needed.
Element text(std::wstring text)
Display a piece of unicode text.
Element separatorCharacter(std::string)
Draw a vertical or horizontal separation in between two other elements.
Element automerge(Element child)
Enable character to be automatically merged with others nearby.
BorderStyle
BorderStyle is an enumeration that represents the different styles of borders that can be applied to ...
The FTXUI ftxui:: namespace.
std::function< Element(Element)> Decorator
std::shared_ptr< Node > Element
Element gridbox(std::vector< Elements > lines)
A container displaying a grid of elements.