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) {
56 std::vector<std::vector<Element>> output;
57 output.reserve(input.size());
58 for (
auto& row : input) {
59 output.emplace_back();
60 auto& output_row = output.back();
61 output_row.reserve(row.size());
62 for (
auto& cell : row) {
63 output_row.push_back(
text(std::move(cell)));
66 Initialize(std::move(output));
73 Initialize(std::move(input));
79Table::Table(std::initializer_list<std::vector<std::string>> init) {
80 std::vector<std::vector<Element>> input;
81 for (
const auto& row : init) {
82 std::vector<Element> output_row;
83 output_row.reserve(row.size());
84 for (
const auto& cell : row) {
85 output_row.push_back(
text(cell));
87 input.push_back(std::move(output_row));
89 Initialize(std::move(input));
93void Table::Initialize(std::vector<std::vector<Element>> input) {
94 input_dim_y_ =
static_cast<int>(input.size());
96 for (
auto& row : input) {
97 input_dim_x_ = std::max(input_dim_x_,
int(row.size()));
100 dim_y_ = 2 * input_dim_y_ + 1;
101 dim_x_ = 2 * input_dim_x_ + 1;
104 elements_.resize(dim_y_);
105 for (
int y = 0; y < dim_y_; ++y) {
106 elements_[y].resize(dim_x_);
112 for (
auto& row : input) {
114 for (
auto& cell : row) {
115 elements_[y][x] = std::move(cell);
123 for (
int y = 0; y < dim_y_; ++y) {
124 for (
int x = 0; x < dim_x_; ++x) {
125 auto& element = elements_[y][x];
193 column_min = Wrap(column_min, input_dim_x_);
194 column_max = Wrap(column_max, input_dim_x_);
195 Order(column_min, column_max);
196 row_min = Wrap(row_min, input_dim_y_);
197 row_max = Wrap(row_max, input_dim_y_);
198 Order(row_min, row_max);
201 output.table_ =
this;
202 output.x_min_ = 2 * column_min;
203 output.x_max_ = 2 * column_max + 2;
204 output.y_min_ = 2 * row_min;
205 output.y_max_ = 2 * row_max + 2;
213 output.table_ =
this;
215 output.x_max_ = dim_x_ - 1;
217 output.y_max_ = dim_y_ - 1;
225 for (
int y = 0; y < dim_y_; ++y) {
226 for (
int x = 0; x < dim_x_; ++x) {
227 auto& it = elements_[y][x];
230 if ((x + y) % 2 == 1) {
231 it = std::move(it) |
flex;
236 if ((x % 2) == 1 && (y % 2) == 1) {
247 return gridbox(std::move(elements_));
256 for (
int y = y_min_; y <= y_max_; ++y) {
257 for (
int x = x_min_; x <= x_max_; ++x) {
258 Element& e = table_->elements_[y][x];
259 e = std::move(e) | decorator;
270 for (
int y = y_min_; y <= y_max_; ++y) {
271 for (
int x = x_min_; x <= x_max_; ++x) {
272 if (y % 2 == 1 && x % 2 == 1) {
273 Element& e = table_->elements_[y][x];
274 e = std::move(e) | 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;
310 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
311 for (
int x = x_min_; x <= x_max_; ++x) {
312 if (y % 2 == 1 && (y / 2) % modulo == shift) {
313 Element& e = table_->elements_[y][x];
314 e = std::move(e) | decorator;
330 for (
int y = y_min_; y <= y_max_; ++y) {
331 for (
int x = x_min_; x <= x_max_; ++x) {
332 if (y % 2 == 1 && x % 2 == 1 && ((x / 2) % modulo == shift)) {
333 Element& e = table_->elements_[y][x];
334 e = std::move(e) | decorator;
350 for (
int y = y_min_; y <= y_max_; ++y) {
351 for (
int x = x_min_; x <= x_max_; ++x) {
352 if (y % 2 == 1 && x % 2 == 1 && ((y / 2) % modulo == shift)) {
353 Element& e = table_->elements_[y][x];
354 e = std::move(e) | decorator;
383 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
384 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
385 if (y % 2 == 0 || x % 2 == 0) {
386 Element& e = table_->elements_[y][x];
399 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
400 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
402 table_->elements_[y][x] =
413 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
414 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
416 table_->elements_[y][x] =
427 for (
int y = y_min_; y <= y_max_; y++) {
428 table_->elements_[y][x_min_] =
437 for (
int y = y_min_; y <= y_max_; y++) {
438 table_->elements_[y][x_max_] =
447 for (
int x = x_min_; x <= x_max_; x++) {
448 table_->elements_[y_min_][x] =
457 for (
int x = x_min_; x <= x_max_; x++) {
458 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.
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.
std::function< Element(Element)> Decorator
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.
std::shared_ptr< Node > Element
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 gridbox(std::vector< Elements > lines)
A container displaying a grid of elements.
Element automerge(Element child)
Enable character to be automatically merged with others nearby.
Element border(Element)
Draw a border around the element.