12bool IsCell(
int x,
int y) {
13 return x % 2 == 1 && y % 2 == 1;
17static std::string charset[6][6] = {
18 {
"┌",
"┐",
"└",
"┘",
"─",
"│"},
19 {
"┏",
"┓",
"┗",
"┛",
"━",
"┃"},
20 {
"╔",
"╗",
"╚",
"╝",
"═",
"║"},
21 {
"╭",
"╮",
"╰",
"╯",
"─",
"│"},
22 {
" ",
" ",
" ",
" ",
" ",
" "},
25int Wrap(
int input,
int modulo) {
32void Order(
int& a,
int& b) {
45 std::vector<std::vector<Element>> output;
46 for (
auto& row : input) {
47 output.emplace_back();
48 auto& output_row = output.back();
49 for (
auto& cell : row) {
50 output_row.push_back(
text(std::move(cell)));
53 Initialize(std::move(output));
57 Initialize(std::move(input));
60void Table::Initialize(std::vector<std::vector<Element>> input) {
61 input_dim_y_ = (int)input.size();
63 for (
auto& row : input) {
64 input_dim_x_ = std::max(input_dim_x_, (
int)row.size());
67 dim_y_ = 2 * input_dim_y_ + 1;
68 dim_x_ = 2 * input_dim_x_ + 1;
71 elements_.resize(dim_y_);
72 for (
int y = 0; y < dim_y_; ++y) {
73 elements_[y].resize(dim_x_);
79 for (
auto& row : input) {
81 for (
auto& cell : row) {
82 elements_[y][x] = std::move(cell);
90 for (
int y = 0; y < dim_y_; ++y) {
91 for (
int x = 0; x < dim_x_; ++x) {
92 auto& element = elements_[y][x];
130 column_min = Wrap(column_min, input_dim_x_);
131 column_max = Wrap(column_max, input_dim_x_);
132 Order(column_min, column_max);
133 row_min = Wrap(row_min, input_dim_y_);
134 row_max = Wrap(row_max, input_dim_y_);
135 Order(row_min, row_max);
138 output.table_ =
this;
139 output.x_min_ = 2 * column_min;
140 output.x_max_ = 2 * column_max + 2;
141 output.y_min_ = 2 * row_min;
142 output.y_max_ = 2 * row_max + 2;
148 output.table_ =
this;
150 output.x_max_ = dim_x_ - 1;
152 output.y_max_ = dim_y_ - 1;
157 for (
int y = 0; y < dim_y_; ++y) {
158 for (
int x = 0; x < dim_x_; ++x) {
159 auto& it = elements_[y][x];
162 if ((x + y) % 2 == 1) {
163 it = std::move(it) |
flex;
168 if ((x % 2) == 1 && (y % 2) == 1) {
179 return gridbox(std::move(elements_));
184 for (
int y = y_min_; y <= y_max_; ++y) {
185 for (
int x = x_min_; x <= x_max_; ++x) {
186 Element& e = table_->elements_[y][x];
187 e = std::move(e) | decorator;
194 for (
int y = y_min_; y <= y_max_; ++y) {
195 for (
int x = x_min_; x <= x_max_; ++x) {
196 if (y % 2 == 1 && x % 2 == 1) {
197 Element& e = table_->elements_[y][x];
198 e = std::move(e) | decorator;
208 for (
int y = y_min_; y <= y_max_; ++y) {
209 for (
int x = x_min_; x <= x_max_; ++x) {
210 if (y % 2 == 1 && (x / 2) % modulo == shift) {
211 Element& e = table_->elements_[y][x];
212 e = std::move(e) | decorator;
222 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
223 for (
int x = x_min_; x <= x_max_; ++x) {
224 if (y % 2 == 1 && (y / 2) % modulo == shift) {
225 Element& e = table_->elements_[y][x];
226 e = std::move(e) | decorator;
236 for (
int y = y_min_; y <= y_max_; ++y) {
237 for (
int x = x_min_; x <= x_max_; ++x) {
238 if (y % 2 == 1 && x % 2 == 1 && ((x / 2) % modulo == shift)) {
239 Element& e = table_->elements_[y][x];
240 e = std::move(e) | decorator;
250 for (
int y = y_min_; y <= y_max_; ++y) {
251 for (
int x = x_min_; x <= x_max_; ++x) {
252 if (y % 2 == 1 && x % 2 == 1 && ((y / 2) % modulo == shift)) {
253 Element& e = table_->elements_[y][x];
254 e = std::move(e) | decorator;
277 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
278 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
279 if (y % 2 == 0 || x % 2 == 0) {
280 Element& e = table_->elements_[y][x];
290 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
291 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
293 table_->elements_[y][x] =
301 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
302 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
304 table_->elements_[y][x] =
312 for (
int y = y_min_; y <= y_max_; y++) {
313 table_->elements_[y][x_min_] =
319 for (
int y = y_min_; y <= y_max_; y++) {
320 table_->elements_[y][x_max_] =
326 for (
int x = x_min_; x <= x_max_; x++) {
327 table_->elements_[y_min_][x] =
333 for (
int x = x_min_; x <= x_max_; x++) {
334 table_->elements_[y_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.
Element automerge(Element child)
Enable character to be automatically merged with others nearby.
Decorator size(Direction, Constraint, int value)
Apply a constraint on the size of an element.
Element border(Element)
Draw a border around the element.