12bool IsCell(
int x,
int y) {
13 return x % 2 == 1 && y % 2 == 1;
16static std::string charset[6][6] = {
17 {
"┌",
"┐",
"└",
"┘",
"─",
"│"},
18 {
"┏",
"┓",
"┗",
"┛",
"━",
"┃"},
19 {
"╔",
"╗",
"╚",
"╝",
"═",
"║"},
20 {
"╭",
"╮",
"╰",
"╯",
"─",
"│"},
21 {
" ",
" ",
" ",
" ",
" ",
" "},
24int Wrap(
int input,
int modulo) {
31void Order(
int& a,
int& b) {
43 std::vector<std::vector<Element>> output;
44 for(
auto& row : input) {
46 auto& output_row = output.back();
47 for(
auto& cell : row) {
48 output_row.push_back(
text(cell));
51 Initialize(std::move(output));
55 Initialize(std::move(input));
58void Table::Initialize(std::vector<std::vector<Element>> input) {
59 input_dim_y_ = input.size();
61 for (
auto& row : input)
62 input_dim_x_ = std::max(input_dim_x_, (
int)row.size());
64 dim_y_ = 2 * input_dim_y_ + 1;
65 dim_x_ = 2 * input_dim_x_ + 1;
68 elements_.resize(dim_y_);
69 for (
int y = 0; y < dim_y_; ++y)
70 elements_[y].resize(dim_x_);
75 for (
auto& row : input) {
77 for (
auto& cell : row) {
78 elements_[y][x] = std::move(cell);
86 for (
int y = 0; y < dim_y_; ++y) {
87 for (
int x = 0; x < dim_x_; ++x) {
88 auto& element = elements_[y][x];
125 column_min = Wrap(column_min, input_dim_x_);
126 column_max = Wrap(column_max, input_dim_x_);
127 Order(column_min, column_max);
128 row_min = Wrap(row_min, input_dim_y_);
129 row_max = Wrap(row_max, input_dim_y_);
130 Order(row_min, row_max);
133 output.table_ =
this;
134 output.x_min_ = 2 * column_min;
135 output.x_max_ = 2 * column_max + 2;
136 output.y_min_ = 2 * row_min;
137 output.y_max_ = 2 * row_max + 2;
143 output.table_ =
this;
145 output.x_max_ = dim_x_ - 1;
147 output.y_max_ = dim_y_ - 1;
152 for (
int y = 0; y < dim_y_; ++y) {
153 for (
int x = 0; x < dim_x_; ++x) {
154 auto& it = elements_[y][x];
157 if ((x + y) % 2 == 1) {
158 it = std::move(it) |
flex;
163 if ((x % 2) == 1 && (y % 2) == 1) {
172 return gridbox(std::move(elements_));
176 for (
int y = y_min_; y <= y_max_; ++y) {
177 for (
int x = x_min_; x <= x_max_; ++x) {
178 Element& e = table_->elements_[y][x];
179 e = std::move(e) | decorator;
185 for (
int y = y_min_; y <= y_max_; ++y) {
186 for (
int x = x_min_; x <= x_max_; ++x) {
187 if (y % 2 && x % 2) {
188 Element& e = table_->elements_[y][x];
189 e = std::move(e) | decorator;
198 for (
int y = y_min_; y <= y_max_; ++y) {
199 for (
int x = x_min_; x <= x_max_; ++x) {
200 if (y % 2 && (x / 2) % modulo == shift) {
201 Element& e = table_->elements_[y][x];
202 e = std::move(e) | decorator;
211 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
212 for (
int x = x_min_; x <= x_max_; ++x) {
213 if (y % 2 && (y / 2) % modulo == shift) {
214 Element& e = table_->elements_[y][x];
215 e = std::move(e) | decorator;
224 for (
int y = y_min_; y <= y_max_; ++y) {
225 for (
int x = x_min_; x <= x_max_; ++x) {
226 if (y % 2 && x % 2 && ((x / 2) % modulo == shift)) {
227 Element& e = table_->elements_[y][x];
228 e = std::move(e) | decorator;
237 for (
int y = y_min_; y <= y_max_; ++y) {
238 for (
int x = x_min_; x <= x_max_; ++x) {
239 if (y % 2 && x % 2 && ((y / 2) % modulo == shift)) {
240 Element& e = table_->elements_[y][x];
241 e = std::move(e) | decorator;
253 table_->elements_[y_min_][x_min_] =
text(charset[style][0]);
254 table_->elements_[y_min_][x_max_] =
text(charset[style][1]);
255 table_->elements_[y_max_][x_min_] =
text(charset[style][2]);
256 table_->elements_[y_max_][x_max_] =
text(charset[style][3]);
260 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
261 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
262 if (y % 2 == 0 || x % 2 == 0) {
263 Element& e = table_->elements_[y][x];
272 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
273 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
282 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
283 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
292 for (
int y = y_min_; y <= y_max_; y++)
297 for (
int y = y_min_; y <= y_max_; y++)
302 for (
int x = x_min_; x <= x_max_; x++)
307 for (
int x = x_min_; x <= x_max_; x++)
void DecorateAlternateColumn(Decorator, int modulo=2, int shift=0)
void SeparatorVertical(BorderStyle border=LIGHT)
void DecorateCells(Decorator)
void BorderLeft(BorderStyle border=LIGHT)
void DecorateCellsAlternateColumn(Decorator, int modulo=2, int shift=0)
void DecorateAlternateRow(Decorator, int modulo=2, int shift=0)
void BorderTop(BorderStyle border=LIGHT)
void Separator(BorderStyle border=LIGHT)
void BorderBottom(BorderStyle border=LIGHT)
void DecorateCellsAlternateRow(Decorator, int modulo=2, int shift=0)
void BorderRight(BorderStyle border=LIGHT)
void Border(BorderStyle border=LIGHT)
void SeparatorHorizontal(BorderStyle border=LIGHT)
TableSelection SelectCell(int column, int row)
TableSelection SelectColumn(int column_index)
TableSelection SelectRow(int row_index)
TableSelection SelectColumns(int column_min, int column_max)
TableSelection SelectRows(int row_min, int row_max)
TableSelection SelectAll()
TableSelection SelectRectangle(int column_min, int column_max, int row_min, int row_max)
std::function< Element(Element)> Decorator
Element flex(Element)
Make a child element to expand proportionnally 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.
Decorator size(Direction, Constraint, int value)
Apply a constraint on the size of an element.