6#include <initializer_list>
16bool IsCell(
int x,
int y) {
17 return x % 2 == 1 && y % 2 == 1;
21static std::string charset[6][6] = {
22 {
"┌",
"┐",
"└",
"┘",
"─",
"│"},
23 {
"┏",
"┓",
"┗",
"┛",
"╍",
"╏"},
24 {
"┏",
"┓",
"┗",
"┛",
"━",
"┃"},
25 {
"╔",
"╗",
"╚",
"╝",
"═",
"║"},
26 {
"╭",
"╮",
"╰",
"╯",
"─",
"│"},
27 {
" ",
" ",
" ",
" ",
" ",
" "},
30int Wrap(
int input,
int modulo) {
37void Order(
int& a,
int& b) {
53 std::vector<std::vector<Element>> output;
54 output.reserve(input.size());
55 for (
auto& row : input) {
56 output.emplace_back();
57 auto& output_row = output.back();
58 output_row.reserve(row.size());
59 for (
auto& cell : row) {
60 output_row.push_back(
text(std::move(cell)));
63 Initialize(std::move(output));
69 Initialize(std::move(input));
74Table::Table(std::initializer_list<std::vector<std::string>> init) {
75 std::vector<std::vector<Element>> input;
76 for (
const auto& row : init) {
77 std::vector<Element> output_row;
78 output_row.reserve(row.size());
79 for (
const auto& cell : row) {
80 output_row.push_back(
text(cell));
82 input.push_back(std::move(output_row));
84 Initialize(std::move(input));
88void Table::Initialize(std::vector<std::vector<Element>> input) {
89 input_dim_y_ =
static_cast<int>(input.size());
91 for (
auto& row : input) {
92 input_dim_x_ = std::max(input_dim_x_,
int(row.size()));
95 dim_y_ = 2 * input_dim_y_ + 1;
96 dim_x_ = 2 * input_dim_x_ + 1;
99 elements_.resize(dim_y_);
100 for (
int y = 0; y < dim_y_; ++y) {
101 elements_[y].resize(dim_x_);
107 for (
auto& row : input) {
109 for (
auto& cell : row) {
110 elements_[y][x] = std::move(cell);
118 for (
int y = 0; y < dim_y_; ++y) {
119 for (
int x = 0; x < dim_x_; ++x) {
120 auto& element = elements_[y][x];
182 column_min =
Wrap(column_min, input_dim_x_);
183 column_max =
Wrap(column_max, input_dim_x_);
184 Order(column_min, column_max);
185 row_min =
Wrap(row_min, input_dim_y_);
186 row_max =
Wrap(row_max, input_dim_y_);
187 Order(row_min, row_max);
190 output.table_ =
this;
191 output.x_min_ = 2 * column_min;
192 output.x_max_ = 2 * column_max + 2;
193 output.y_min_ = 2 * row_min;
194 output.y_max_ = 2 * row_max + 2;
201 output.table_ =
this;
203 output.x_max_ = dim_x_ - 1;
205 output.y_max_ = dim_y_ - 1;
212 for (
int y = 0; y < dim_y_; ++y) {
213 for (
int x = 0; x < dim_x_; ++x) {
214 auto& it = elements_[y][x];
217 if ((x + y) % 2 == 1) {
218 it = std::move(it) |
flex;
223 if ((x % 2) == 1 && (y % 2) == 1) {
234 return gridbox(std::move(elements_));
242 for (
int y = y_min_; y <= y_max_; ++y) {
243 for (
int x = x_min_; x <= x_max_; ++x) {
244 Element& e = table_->elements_[y][x];
245 e = std::move(e) | decorator;
255 for (
int y = y_min_; y <= y_max_; ++y) {
256 for (
int x = x_min_; x <= x_max_; ++x) {
257 if (y % 2 == 1 && x % 2 == 1) {
258 Element& e = table_->elements_[y][x];
259 e = std::move(e) | decorator;
274 for (
int y = y_min_; y <= y_max_; ++y) {
275 for (
int x = x_min_; x <= x_max_; ++x) {
276 if (y % 2 == 1 && (x / 2) % modulo == shift) {
277 Element& e = table_->elements_[y][x];
278 e = std::move(e) | decorator;
293 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
294 for (
int x = x_min_; x <= x_max_; ++x) {
295 if (y % 2 == 1 && (y / 2) % modulo == shift) {
296 Element& e = table_->elements_[y][x];
297 e = std::move(e) | decorator;
312 for (
int y = y_min_; y <= y_max_; ++y) {
313 for (
int x = x_min_; x <= x_max_; ++x) {
314 if (y % 2 == 1 && x % 2 == 1 && ((x / 2) % modulo == shift)) {
315 Element& e = table_->elements_[y][x];
316 e = std::move(e) | decorator;
331 for (
int y = y_min_; y <= y_max_; ++y) {
332 for (
int x = x_min_; x <= x_max_; ++x) {
333 if (y % 2 == 1 && x % 2 == 1 && ((y / 2) % modulo == shift)) {
334 Element& e = table_->elements_[y][x];
335 e = std::move(e) | decorator;
350 table_->elements_[y_min_][x_min_] =
text(charset[border][0]) |
automerge;
352 table_->elements_[y_min_][x_max_] =
text(charset[border][1]) |
automerge;
354 table_->elements_[y_max_][x_min_] =
text(charset[border][2]) |
automerge;
356 table_->elements_[y_max_][x_max_] =
text(charset[border][3]) |
automerge;
362 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
363 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
364 if (y % 2 == 0 || x % 2 == 0) {
365 Element& e = table_->elements_[y][x];
377 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
378 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
380 table_->elements_[y][x] =
390 for (
int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
391 for (
int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
393 table_->elements_[y][x] =
403 for (
int y = y_min_; y <= y_max_; y++) {
404 table_->elements_[y][x_min_] =
412 for (
int y = y_min_; y <= y_max_; y++) {
413 table_->elements_[y][x_max_] =
421 for (
int x = x_min_; x <= x_max_; x++) {
422 table_->elements_[y_min_][x] =
430 for (
int x = x_min_; x <= x_max_; x++) {
431 table_->elements_[y_max_][x] =
void DecorateAlternateColumn(Decorator, int modulo=2, int shift=0)
選択範囲に decorator を適用します。 これは、modulo でモジュロ化され、shift でシフトされた線のみを装飾します。
void SeparatorVertical(BorderStyle border=LIGHT)
選択範囲に垂直の区切り線を描画します。
void DecorateCells(Decorator)
選択範囲に decorator を適用します。
void BorderLeft(BorderStyle border=LIGHT)
選択範囲の左側に区切り線を描画します。
void DecorateCellsAlternateColumn(Decorator, int modulo=2, int shift=0)
選択範囲に decorator を適用します。 これは、modulo でモジュロ化され、shift でシフトされた角のみを装飾します。
void Decorate(Decorator)
選択範囲に decorator を適用します。 これはセル、線、角の両方を装飾します。
void DecorateAlternateRow(Decorator, int modulo=2, int shift=0)
選択範囲に decorator を適用します。 これは、modulo でモジュロ化され、shift でシフトされた線のみを装飾します。
void BorderTop(BorderStyle border=LIGHT)
選択範囲の上側に区切り線を描画します。
void Separator(BorderStyle border=LIGHT)
選択範囲に区切り線を描画します。
void BorderBottom(BorderStyle border=LIGHT)
選択範囲の下側に区切り線を描画します。
void DecorateCellsAlternateRow(Decorator, int modulo=2, int shift=0)
選択範囲に decorator を適用します。 これは、modulo でモジュロ化され、shift でシフトされた角のみを装飾します。
void BorderRight(BorderStyle border=LIGHT)
選択範囲の右側に区切り線を描画します。
void Border(BorderStyle border=LIGHT)
選択範囲に border を適用します。
void SeparatorHorizontal(BorderStyle border=LIGHT)
選択範囲に水平の区切り線を描画します。
Component Wrap(std::string name, Component component)
Element Render()
テーブルをレンダリングします。
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)
テーブルの矩形を選択します。
Element flex(Element)
子要素をコンテナに残されたスペースに比例して拡大させます。
Element flex_shrink(Element)
必要であれば最小化します。
Element text(std::wstring text)
ユニコードテキストを表示します。
Element automerge(Element child)
文字が近くの他の文字と自動的にマージされるようにします。
BorderStyle
BorderStyleは、ターミナルUIの要素に適用できる様々なボーダースタイルを表す列挙型です。
std::function< Element(Element)> Decorator
std::shared_ptr< Node > Element
Element separatorCharacter(std::string)
Element gridbox(std::vector< Elements > lines)
要素のグリッドを表示するコンテナ。