Add clang-tidy. (#368)

This commit is contained in:
Arthur Sonzogni
2022-03-31 02:17:43 +02:00
committed by GitHub
parent 62fb6298be
commit aebde94352
80 changed files with 1958 additions and 1376 deletions

View File

@@ -1,9 +1,9 @@
#include <algorithm> // for max
#include <iterator> // for begin, end
#include <array> // for array
#include <memory> // for allocator, make_shared, __shared_ptr_access
#include <string> // for string, basic_string
#include <string> // for basic_string, string
#include <utility> // for move
#include <vector> // for vector, __alloc_traits<>::value_type
#include <vector> // for __alloc_traits<>::value_type
#include "ftxui/dom/elements.hpp" // for unpack, Element, Decorator, BorderStyle, ROUNDED, Elements, DOUBLE, EMPTY, HEAVY, LIGHT, border, borderDouble, borderEmpty, borderHeavy, borderLight, borderRounded, borderStyled, borderWith, window
#include "ftxui/dom/node.hpp" // for Node, Elements
@@ -13,30 +13,25 @@
namespace ftxui {
static std::string simple_border_charset[6][6] = {
{"", "", "", "", "", ""}, //
{"", "", "", "", "", ""}, //
{"", "", "", "", "", ""}, //
{"", "", "", "", "", ""}, //
{" ", " ", " ", " ", " ", " "}, //
using Charset = std::array<std::string, 6>; // NOLINT
using Charsets = std::array<Charset, 6>; // NOLINT
static Charsets simple_border_charset = // NOLINT
{
Charset{"", "", "", "", "", ""},
Charset{"", "", "", "", "", ""},
Charset{"", "", "", "", "", ""},
Charset{"", "", "", "", "", ""},
Charset{" ", " ", " ", " ", " ", " "},
};
// For reference, here is the charset for normal border:
// {"┌", "┐", "└", "┘", "─", "│", "┬", "┴", "┤", "├"};
// TODO(arthursonzogni): Consider adding options to choose the kind of borders
// to use.
class Border : public Node {
public:
Border(Elements children, BorderStyle style)
: Node(std::move(children)),
charset(std::begin(simple_border_charset[style]),
std::end(simple_border_charset[style])) {}
Border(Elements children, Pixel pixel)
: Node(std::move(children)), charset_pixel(10, pixel) {}
charset_(simple_border_charset[style]) {} // NOLINT
std::vector<Pixel> charset_pixel;
std::vector<std::string> charset;
const Charset& charset_; // NOLINT
void ComputeRequirement() override {
Node::ComputeRequirement();
@@ -75,63 +70,101 @@ class Border : public Node {
children_[0]->Render(screen);
// Draw the border.
if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max)
if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max) {
return;
}
if (!charset.empty())
RenderPixel(screen);
else
RenderChar(screen);
}
screen.at(box_.x_min, box_.y_min) = charset_[0]; // NOLINT
screen.at(box_.x_max, box_.y_min) = charset_[1]; // NOLINT
screen.at(box_.x_min, box_.y_max) = charset_[2]; // NOLINT
screen.at(box_.x_max, box_.y_max) = charset_[3]; // NOLINT
void RenderPixel(Screen& screen) {
screen.at(box_.x_min, box_.y_min) = charset[0];
screen.at(box_.x_max, box_.y_min) = charset[1];
screen.at(box_.x_min, box_.y_max) = charset[2];
screen.at(box_.x_max, box_.y_max) = charset[3];
for (float x = box_.x_min + 1; x < box_.x_max; ++x) {
for (int x = box_.x_min + 1; x < box_.x_max; ++x) {
Pixel& p1 = screen.PixelAt(x, box_.y_min);
Pixel& p2 = screen.PixelAt(x, box_.y_max);
p1.character = charset[4];
p2.character = charset[4];
p1.character = charset_[4]; // NOLINT
p2.character = charset_[4]; // NOLINT
p1.automerge = true;
p2.automerge = true;
}
for (float y = box_.y_min + 1; y < box_.y_max; ++y) {
for (int y = box_.y_min + 1; y < box_.y_max; ++y) {
Pixel& p3 = screen.PixelAt(box_.x_min, y);
Pixel& p4 = screen.PixelAt(box_.x_max, y);
p3.character = charset[5];
p4.character = charset[5];
p3.character = charset_[5]; // NOLINT
p4.character = charset_[5]; // NOLINT
p3.automerge = true;
p4.automerge = true;
}
// Draw title.
if (children_.size() == 2)
if (children_.size() == 2) {
children_[1]->Render(screen);
}
}
};
// For reference, here is the charset for normal border:
class BorderPixel : public Node {
public:
BorderPixel(Elements children, Pixel pixel)
: Node(std::move(children)), pixel_(std::move(pixel)) {}
private:
Pixel pixel_;
void ComputeRequirement() override {
Node::ComputeRequirement();
requirement_ = children_[0]->requirement();
requirement_.min_x += 2;
requirement_.min_y += 2;
if (children_.size() == 2) {
requirement_.min_x =
std::max(requirement_.min_x, children_[1]->requirement().min_x + 2);
}
requirement_.selected_box.x_min++;
requirement_.selected_box.x_max++;
requirement_.selected_box.y_min++;
requirement_.selected_box.y_max++;
}
void RenderChar(Screen& screen) {
screen.PixelAt(box_.x_min, box_.y_min) = charset_pixel[0];
screen.PixelAt(box_.x_max, box_.y_min) = charset_pixel[1];
screen.PixelAt(box_.x_min, box_.y_max) = charset_pixel[2];
screen.PixelAt(box_.x_max, box_.y_max) = charset_pixel[3];
for (float x = box_.x_min + 1; x < box_.x_max; ++x) {
Pixel& p1 = screen.PixelAt(x, box_.y_min);
Pixel& p2 = screen.PixelAt(x, box_.y_max);
p1 = charset_pixel[5];
p2 = charset_pixel[5];
p1.automerge = true;
p2.automerge = true;
void SetBox(Box box) override {
Node::SetBox(box);
if (children_.size() == 2) {
Box title_box;
title_box.x_min = box.x_min + 1;
title_box.x_max = box.x_max - 1;
title_box.y_min = box.y_min;
title_box.y_max = box.y_min;
children_[1]->SetBox(title_box);
}
for (float y = box_.y_min + 1; y < box_.y_max; ++y) {
Pixel& p3 = screen.PixelAt(box_.x_min, y);
Pixel& p4 = screen.PixelAt(box_.x_max, y);
p3 = charset_pixel[5];
p4 = charset_pixel[5];
p3.automerge = true;
p4.automerge = true;
box.x_min++;
box.x_max--;
box.y_min++;
box.y_max--;
children_[0]->SetBox(box);
}
void Render(Screen& screen) override {
// Draw content.
children_[0]->Render(screen);
// Draw the border.
if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max) {
return;
}
screen.PixelAt(box_.x_min, box_.y_min) = pixel_;
screen.PixelAt(box_.x_max, box_.y_min) = pixel_;
screen.PixelAt(box_.x_min, box_.y_max) = pixel_;
screen.PixelAt(box_.x_max, box_.y_max) = pixel_;
for (int x = box_.x_min + 1; x < box_.x_max; ++x) {
screen.PixelAt(x, box_.y_min) = pixel_;
screen.PixelAt(x, box_.y_max) = pixel_;
}
for (int y = box_.y_min + 1; y < box_.y_max; ++y) {
screen.PixelAt(box_.x_min, y) = pixel_;
screen.PixelAt(box_.x_max, y) = pixel_;
}
}
};
@@ -171,9 +204,9 @@ Element border(Element child) {
/// @brief Same as border but with a constant Pixel around the element.
/// @ingroup dom
/// @see border
Decorator borderWith(Pixel pixel) {
Decorator borderWith(const Pixel& pixel) {
return [pixel](Element child) {
return std::make_shared<Border>(unpack(std::move(child)), pixel);
return std::make_shared<BorderPixel>(unpack(std::move(child)), pixel);
};
}

View File

@@ -2,8 +2,7 @@
#include <algorithm> // for max
namespace ftxui {
namespace box_helper {
namespace ftxui::box_helper {
namespace {
// Called when the size allowed is greater than the requested size. This
@@ -44,7 +43,7 @@ void ComputeShrinkHard(std::vector<Element>* elements,
int extra_space,
int size) {
for (Element& element : *elements) {
if (element.flex_shrink) {
if (element.flex_shrink != 0) {
element.size = 0;
continue;
}
@@ -68,23 +67,25 @@ void Compute(std::vector<Element>* elements, int target_size) {
for (auto& element : *elements) {
flex_grow_sum += element.flex_grow;
flex_shrink_sum += element.min_size * element.flex_shrink;
if (element.flex_shrink)
if (element.flex_shrink != 0) {
flex_shrink_size += element.min_size;
}
size += element.min_size;
}
int extra_space = target_size - size;
if (extra_space >= 0)
if (extra_space >= 0) {
ComputeGrow(elements, extra_space, flex_grow_sum);
else if (flex_shrink_size + extra_space >= 0)
} else if (flex_shrink_size + extra_space >= 0) {
ComputeShrinkEasy(elements, extra_space, flex_shrink_sum);
else
} else {
ComputeShrinkHard(elements, extra_space + flex_shrink_size,
size - flex_shrink_size);
}
}
} // namespace box_helper
} // namespace ftxui
} // namespace ftxui::box_helper
// Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in

View File

@@ -1,8 +1,8 @@
#include "ftxui/dom/canvas.hpp"
#include <stdlib.h> // for abs
#include <algorithm> // for max, min
#include <cstdint> // for uint8_t
#include <cstdlib> // for abs
#include <map> // for allocator, map
#include <memory> // for make_shared
#include <utility> // for move, pair
@@ -42,26 +42,29 @@ namespace {
// 11100010 10100000 10100000 // dot6
// 11100010 10100010 10000000 // dot0-2
// NOLINTNEXTLINE
uint8_t g_map_braille[2][4][2] = {
{
{0b00000000, 0b00000001}, // dot1
{0b00000000, 0b00000010}, // dot2
{0b00000000, 0b00000100}, // dot3
{0b00000001, 0b00000000}, // dot0-1
{0b00000000, 0b00000001}, // NOLINT | dot1
{0b00000000, 0b00000010}, // NOLINT | dot2
{0b00000000, 0b00000100}, // NOLINT | dot3
{0b00000001, 0b00000000}, // NOLINT | dot0-1
},
{
{0b00000000, 0b00001000}, // dot4
{0b00000000, 0b00010000}, // dot5
{0b00000000, 0b00100000}, // dot6
{0b00000010, 0b00000000}, // dot0-2
{0b00000000, 0b00001000}, // NOLINT | dot4
{0b00000000, 0b00010000}, // NOLINT | dot5
{0b00000000, 0b00100000}, // NOLINT | dot6
{0b00000010, 0b00000000}, // NOLINT | dot0-2
},
};
// NOLINTNEXTLINE
std::vector<std::string> g_map_block = {
" ", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
};
// NOLINTNEXTLINE
const std::map<std::string, uint8_t> g_map_block_inversed = {
{" ", 0b0000}, {"", 0b0001}, {"", 0b0010}, {"", 0b0011},
{"", 0b0100}, {"", 0b0101}, {"", 0b0110}, {"", 0b0111},
@@ -69,13 +72,17 @@ const std::map<std::string, uint8_t> g_map_block_inversed = {
{"", 0b1100}, {"", 0b1101}, {"", 0b1110}, {"", 0b1111},
};
constexpr auto nostyle = [](Pixel& /*pixel*/) {};
} // namespace
/// @brief Constructor.
/// @param width the width of the canvas. A cell is a 2x8 braille dot.
/// @param height the height of the canvas. A cell is a 2x8 braille dot.
Canvas::Canvas(int width, int height)
: width_(width), height_(height), storage_(width_ * height_ / 8) {}
: width_(width),
height_(height),
storage_(width_ * height_ / 8 /* NOLINT */) {}
/// @brief Get the content of a cell.
/// @param x the x coordinate of the cell.
@@ -90,7 +97,7 @@ Pixel Canvas::GetPixel(int x, int y) const {
/// @param y the y coordinate of the dot.
/// @param value whether the dot is filled or not.
void Canvas::DrawPoint(int x, int y, bool value) {
DrawPoint(x, y, value, [](Pixel&) {});
DrawPoint(x, y, value, [](Pixel& /*pixel*/) {});
}
/// @brief Draw a braille dot.
@@ -109,42 +116,45 @@ void Canvas::DrawPoint(int x, int y, bool value, const Color& color) {
/// @param style the style of the cell.
void Canvas::DrawPoint(int x, int y, bool value, const Stylizer& style) {
Style(x, y, style);
if (value)
if (value) {
DrawPointOn(x, y);
else
} else {
DrawPointOff(x, y);
}
}
/// @brief Draw a braille dot.
/// @param x the x coordinate of the dot.
/// @param y the y coordinate of the dot.
void Canvas::DrawPointOn(int x, int y) {
if (!IsIn(x, y))
if (!IsIn(x, y)) {
return;
}
Cell& cell = storage_[XY{x / 2, y / 4}];
if (cell.type != CellType::kBraille) {
cell.content.character = ""; // 3 bytes.
cell.type = CellType::kBraille;
}
cell.content.character[1] |= g_map_braille[x % 2][y % 4][0];
cell.content.character[2] |= g_map_braille[x % 2][y % 4][1];
cell.content.character[1] |= g_map_braille[x % 2][y % 4][0]; // NOLINT
cell.content.character[2] |= g_map_braille[x % 2][y % 4][1]; // NOLINT
}
/// @brief Erase a braille dot.
/// @param x the x coordinate of the dot.
/// @param y the y coordinate of the dot.
void Canvas::DrawPointOff(int x, int y) {
if (!IsIn(x, y))
if (!IsIn(x, y)) {
return;
}
Cell& cell = storage_[XY{x / 2, y / 4}];
if (cell.type != CellType::kBraille) {
cell.content.character = ""; // 3 byt
cell.type = CellType::kBraille;
}
cell.content.character[1] &= ~(g_map_braille[x % 2][y % 4][0]);
cell.content.character[2] &= ~(g_map_braille[x % 2][y % 4][1]);
cell.content.character[1] &= ~(g_map_braille[x % 2][y % 4][0]); // NOLINT
cell.content.character[2] &= ~(g_map_braille[x % 2][y % 4][1]); // NOLINT
}
/// @brief Toggle a braille dot. A filled one will be erased, and the other will
@@ -152,16 +162,17 @@ void Canvas::DrawPointOff(int x, int y) {
/// @param x the x coordinate of the dot.
/// @param y the y coordinate of the dot.
void Canvas::DrawPointToggle(int x, int y) {
if (!IsIn(x, y))
if (!IsIn(x, y)) {
return;
}
Cell& cell = storage_[XY{x / 2, y / 4}];
if (cell.type != CellType::kBraille) {
cell.content.character = ""; // 3 byt
cell.type = CellType::kBraille;
}
cell.content.character[1] ^= g_map_braille[x % 2][y % 4][0];
cell.content.character[2] ^= g_map_braille[x % 2][y % 4][1];
cell.content.character[1] ^= g_map_braille[x % 2][y % 4][0]; // NOLINT
cell.content.character[2] ^= g_map_braille[x % 2][y % 4][1]; // NOLINT
}
/// @brief Draw a line made of braille dots.
@@ -170,7 +181,7 @@ void Canvas::DrawPointToggle(int x, int y) {
/// @param x2 the x coordinate of the second dot.
/// @param y2 the y coordinate of the second dot.
void Canvas::DrawPointLine(int x1, int y1, int x2, int y2) {
DrawPointLine(x1, y1, x2, y2, [](Pixel&) {});
DrawPointLine(x1, y1, x2, y2, [](Pixel& /*pixel*/) {});
}
/// @brief Draw a line made of braille dots.
@@ -201,10 +212,12 @@ void Canvas::DrawPointLine(int x1,
const int sy = y1 < y2 ? 1 : -1;
const int length = std::max(dx, dy);
if (!IsIn(x1, y1) && !IsIn(x2, y2))
if (!IsIn(x1, y1) && !IsIn(x2, y2)) {
return;
if (dx + dx > width_ * height_)
}
if (dx + dx > width_ * height_) {
return;
}
int error = dx - dy;
for (int i = 0; i < length; ++i) {
@@ -226,7 +239,7 @@ void Canvas::DrawPointLine(int x1,
/// @param y the y coordinate of the center of the circle.
/// @param radius the radius of the circle.
void Canvas::DrawPointCircle(int x, int y, int radius) {
DrawPointCircle(x, y, radius, [](Pixel&) {});
DrawPointCircle(x, y, radius, [](Pixel& /*pixel*/) {});
}
/// @brief Draw a circle made of braille dots.
@@ -253,7 +266,7 @@ void Canvas::DrawPointCircle(int x, int y, int radius, const Stylizer& style) {
/// @param y the y coordinate of the center of the circle.
/// @param radius the radius of the circle.
void Canvas::DrawPointCircleFilled(int x, int y, int radius) {
DrawPointCircleFilled(x, y, radius, [](Pixel&) {});
DrawPointCircleFilled(x, y, radius, [](Pixel& /*pixel*/) {});
}
/// @brief Draw a filled circle made of braille dots.
@@ -287,7 +300,7 @@ void Canvas::DrawPointCircleFilled(int x,
/// @param r1 the radius of the ellipse along the x axis.
/// @param r2 the radius of the ellipse along the y axis.
void Canvas::DrawPointEllipse(int x, int y, int r1, int r2) {
DrawPointEllipse(x, y, r1, r2, [](Pixel&) {});
DrawPointEllipse(x, y, r1, r2, [](Pixel& /*pixel*/) {});
}
/// @brief Draw an ellipse made of braille dots.
@@ -351,7 +364,7 @@ void Canvas::DrawPointEllipse(int x1,
/// @param r1 the radius of the ellipse along the x axis.
/// @param r2 the radius of the ellipse along the y axis.
void Canvas::DrawPointEllipseFilled(int x1, int y1, int r1, int r2) {
DrawPointEllipseFilled(x1, y1, r1, r2, [](Pixel&) {});
DrawPointEllipseFilled(x1, y1, r1, r2, [](Pixel& /*pixel*/) {});
}
/// @brief Draw a filled ellipse made of braille dots.
@@ -395,11 +408,11 @@ void Canvas::DrawPointEllipseFilled(int x1,
e2 = 2 * err;
if (e2 >= dx) {
x++;
err += dx += 2 * (long)r2 * r2;
err += dx += 2 * (long)r2 * r2; // NOLINT
}
if (e2 <= dy) {
y++;
err += dy += 2 * (long)r1 * r1;
err += dy += 2 * (long)r1 * r1; // NOLINT
}
} while (x <= 0);
@@ -415,7 +428,7 @@ void Canvas::DrawPointEllipseFilled(int x1,
/// @param y the y coordinate of the block.
/// @param value whether the block is filled or not.
void Canvas::DrawBlock(int x, int y, bool value) {
DrawBlock(x, y, value, [](Pixel&) {});
DrawBlock(x, y, value, [](Pixel& /*pixel*/) {});
}
/// @brief Draw a block.
@@ -434,18 +447,20 @@ void Canvas::DrawBlock(int x, int y, bool value, const Color& color) {
/// @param style the style of the block.
void Canvas::DrawBlock(int x, int y, bool value, const Stylizer& style) {
Style(x, y, style);
if (value)
if (value) {
DrawBlockOn(x, y);
else
} else {
DrawBlockOff(x, y);
}
}
/// @brief Draw a block.
/// @param x the x coordinate of the block.
/// @param y the y coordinate of the block.
void Canvas::DrawBlockOn(int x, int y) {
if (!IsIn(x, y))
if (!IsIn(x, y)) {
return;
}
y /= 2;
Cell& cell = storage_[XY{x / 2, y / 2}];
if (cell.type != CellType::kBlock) {
@@ -453,9 +468,9 @@ void Canvas::DrawBlockOn(int x, int y) {
cell.type = CellType::kBlock;
}
int bit = (x % 2) * 2 + y % 2;
uint8_t bit = (x % 2) * 2 + y % 2;
uint8_t value = g_map_block_inversed.at(cell.content.character);
value |= 1 << bit;
value |= 1U << bit;
cell.content.character = g_map_block[value];
}
@@ -463,8 +478,9 @@ void Canvas::DrawBlockOn(int x, int y) {
/// @param x the x coordinate of the block.
/// @param y the y coordinate of the block.
void Canvas::DrawBlockOff(int x, int y) {
if (!IsIn(x, y))
if (!IsIn(x, y)) {
return;
}
Cell& cell = storage_[XY{x / 2, y / 4}];
if (cell.type != CellType::kBlock) {
cell.content.character = " ";
@@ -472,9 +488,9 @@ void Canvas::DrawBlockOff(int x, int y) {
}
y /= 2;
int bit = (y % 2) * 2 + x % 2;
uint8_t bit = (y % 2) * 2 + x % 2;
uint8_t value = g_map_block_inversed.at(cell.content.character);
value &= ~(1 << bit);
value &= ~(1U << bit);
cell.content.character = g_map_block[value];
}
@@ -483,8 +499,9 @@ void Canvas::DrawBlockOff(int x, int y) {
/// @param x the x coordinate of the block.
/// @param y the y coordinate of the block.
void Canvas::DrawBlockToggle(int x, int y) {
if (!IsIn(x, y))
if (!IsIn(x, y)) {
return;
}
Cell& cell = storage_[XY{x / 2, y / 4}];
if (cell.type != CellType::kBlock) {
cell.content.character = " ";
@@ -492,9 +509,9 @@ void Canvas::DrawBlockToggle(int x, int y) {
}
y /= 2;
int bit = (y % 2) * 2 + x % 2;
uint8_t bit = (y % 2) * 2 + x % 2;
uint8_t value = g_map_block_inversed.at(cell.content.character);
value ^= 1 << bit;
value ^= 1U << bit;
cell.content.character = g_map_block[value];
}
@@ -504,7 +521,7 @@ void Canvas::DrawBlockToggle(int x, int y) {
/// @param x2 the x coordinate of the second point of the line.
/// @param y2 the y coordinate of the second point of the line.
void Canvas::DrawBlockLine(int x1, int y1, int x2, int y2) {
DrawBlockLine(x1, y1, x2, y2, [](Pixel&) {});
DrawBlockLine(x1, y1, x2, y2, [](Pixel& /*pixel*/) {});
}
/// @brief Draw a line made of block characters.
@@ -538,10 +555,12 @@ void Canvas::DrawBlockLine(int x1,
const int sy = y1 < y2 ? 1 : -1;
const int length = std::max(dx, dy);
if (!IsIn(x1, y1) && !IsIn(x2, y2))
if (!IsIn(x1, y1) && !IsIn(x2, y2)) {
return;
if (dx + dx > width_ * height_)
}
if (dx + dx > width_ * height_) {
return;
}
int error = dx - dy;
for (int i = 0; i < length; ++i) {
@@ -563,7 +582,7 @@ void Canvas::DrawBlockLine(int x1,
/// @param y the y coordinate of the center of the circle.
/// @param radius the radius of the circle.
void Canvas::DrawBlockCircle(int x, int y, int radius) {
DrawBlockCircle(x, y, radius, [](Pixel&) {});
DrawBlockCircle(x, y, radius, nostyle);
}
/// @brief Draw a circle made of block characters.
@@ -590,7 +609,7 @@ void Canvas::DrawBlockCircle(int x, int y, int radius, const Stylizer& style) {
/// @param y the y coordinate of the center of the circle.
/// @param radius the radius of the circle.
void Canvas::DrawBlockCircleFilled(int x, int y, int radius) {
DrawBlockCircleFilled(x, y, radius, [](Pixel&) {});
DrawBlockCircleFilled(x, y, radius, nostyle);
}
/// @brief Draw a filled circle made of block characters.
@@ -624,7 +643,7 @@ void Canvas::DrawBlockCircleFilled(int x,
/// @param r1 the radius of the ellipse along the x axis.
/// @param r2 the radius of the ellipse along the y axis.
void Canvas::DrawBlockEllipse(int x, int y, int r1, int r2) {
DrawBlockEllipse(x, y, r1, r2, [](Pixel&) {});
DrawBlockEllipse(x, y, r1, r2, nostyle);
}
/// @brief Draw an ellipse made of block characters.
@@ -690,7 +709,7 @@ void Canvas::DrawBlockEllipse(int x1,
/// @param r1 the radius of the ellipse along the x axis.
/// @param r2 the radius of the ellipse along the y axis.
void Canvas::DrawBlockEllipseFilled(int x, int y, int r1, int r2) {
DrawBlockEllipseFilled(x, y, r1, r2, [](Pixel&) {});
DrawBlockEllipseFilled(x, y, r1, r2, nostyle);
}
/// @brief Draw a filled ellipse made of block characters.
@@ -756,7 +775,7 @@ void Canvas::DrawBlockEllipseFilled(int x1,
/// @param y the y coordinate of the text.
/// @param value the text to draw.
void Canvas::DrawText(int x, int y, const std::string& value) {
DrawText(x, y, value, [](Pixel&) {});
DrawText(x, y, value, nostyle);
}
/// @brief Draw a piece of text.
@@ -781,8 +800,9 @@ void Canvas::DrawText(int x,
const std::string& value,
const Stylizer& style) {
for (const auto& it : Utf8ToGlyphs(value)) {
if (!IsIn(x, y))
if (!IsIn(x, y)) {
continue;
}
Cell& cell = storage_[XY{x / 2, y / 4}];
cell.type = CellType::kText;
cell.content.character = it;
@@ -794,15 +814,16 @@ void Canvas::DrawText(int x,
/// @brief Modify a pixel at a given location.
/// @param style a function that modifies the pixel.
void Canvas::Style(int x, int y, const Stylizer& style) {
if (IsIn(x, y))
if (IsIn(x, y)) {
style(storage_[XY{x / 2, y / 4}].content);
}
}
namespace {
class CanvasNodeBase : public Node {
public:
CanvasNodeBase() {}
CanvasNodeBase() = default;
void Render(Screen& screen) override {
const Canvas& c = canvas();
@@ -824,7 +845,7 @@ class CanvasNodeBase : public Node {
Element canvas(ConstRef<Canvas> canvas) {
class Impl : public CanvasNodeBase {
public:
Impl(ConstRef<Canvas> canvas) : canvas_(canvas) {
explicit Impl(ConstRef<Canvas> canvas) : canvas_(std::move(canvas)) {
requirement_.min_x = (canvas_->width() + 1) / 2;
requirement_.min_y = (canvas_->height() + 3) / 4;
}
@@ -869,7 +890,8 @@ Element canvas(int width, int height, std::function<void(Canvas&)> fn) {
/// @brief Produce an element drawing a canvas.
/// @param fn a function drawing the canvas.
Element canvas(std::function<void(Canvas&)> fn) {
return canvas(12, 12, std::move(fn));
const int default_dim = 12;
return canvas(default_dim, default_dim, std::move(fn));
}
} // namespace ftxui

View File

@@ -29,8 +29,8 @@ class ClearUnder : public NodeDecorator {
// combinaison with dbox.
/// @see ftxui::dbox
/// @ingroup dom
Element clear_under(Element child) {
return std::make_shared<ClearUnder>(std::move(child));
Element clear_under(Element element) {
return std::make_shared<ClearUnder>(std::move(element));
}
} // namespace ftxui

View File

@@ -12,7 +12,7 @@ namespace ftxui {
class DBox : public Node {
public:
DBox(Elements children) : Node(std::move(children)) {}
explicit DBox(Elements children) : Node(std::move(children)) {}
void ComputeRequirement() override {
requirement_.min_x = 0;
@@ -38,8 +38,9 @@ class DBox : public Node {
void SetBox(Box box) override {
Node::SetBox(box);
for (auto& child : children_)
for (auto& child : children_) {
child->SetBox(box);
}
}
};

View File

@@ -67,7 +67,7 @@ void function_not_flex(Requirement& r) {
class Flex : public Node {
public:
Flex(FlexFunction f) : f_(f) {}
explicit Flex(FlexFunction f) : f_(f) {}
Flex(FlexFunction f, Element child) : Node(unpack(std::move(child))), f_(f) {}
void ComputeRequirement() override {
requirement_.min_x = 0;
@@ -80,8 +80,9 @@ class Flex : public Node {
}
void SetBox(Box box) override {
if (children_.empty())
if (children_.empty()) {
return;
}
children_[0]->SetBox(box);
}

View File

@@ -1,5 +1,5 @@
#include <stddef.h> // for size_t
#include <algorithm> // for min, max
#include <cstddef> // for size_t
#include <memory> // for __shared_ptr_access, shared_ptr, allocator_traits<>::value_type, make_shared
#include <utility> // for move, swap
#include <vector> // for vector
@@ -56,11 +56,12 @@ class Flexbox : public Node {
requirement_.flex_grow_x = 1;
requirement_.flex_grow_y = 0;
if (IsColumnOriented())
if (IsColumnOriented()) {
std::swap(requirement_.flex_grow_x, requirement_.flex_grow_y);
}
}
bool IsColumnOriented() {
bool IsColumnOriented() const {
return config_.direction == FlexboxConfig::Direction::Column ||
config_.direction == FlexboxConfig::Direction::ColumnInversed;
}
@@ -84,20 +85,21 @@ class Flexbox : public Node {
}
void ComputeRequirement() override {
for (auto& child : children_)
for (auto& child : children_) {
child->ComputeRequirement();
}
flexbox_helper::Global global;
global.config = config_normalized_;
if (IsColumnOriented()) {
global.size_x = 100000;
global.size_x = 100000; // NOLINT
global.size_y = asked_;
} else {
global.size_x = asked_;
global.size_y = 100000;
global.size_y = 100000; // NOLINT
}
Layout(global, true);
if (global.blocks.size() == 0) {
if (global.blocks.empty()) {
requirement_.min_x = 0;
requirement_.min_y = 0;
return;
@@ -150,18 +152,19 @@ class Flexbox : public Node {
}
void Check(Status* status) override {
for (auto& child : children_)
for (auto& child : children_) {
child->Check(status);
}
if (status->iteration == 0) {
asked_ = 6000;
asked_ = 6000; // NOLINT
need_iteration_ = true;
}
status->need_iteration |= need_iteration_;
}
int asked_ = 6000;
int asked_ = 6000; // NOLINT
bool need_iteration_ = true;
const FlexboxConfig config_;
const FlexboxConfig config_normalized_;
@@ -190,7 +193,7 @@ class Flexbox : public Node {
// )
/// ```
Element flexbox(Elements children, FlexboxConfig config) {
return std::make_shared<Flexbox>(std::move(children), std::move(config));
return std::make_shared<Flexbox>(std::move(children), config);
}
/// @brief A container displaying elements in rows from left to right. When

View File

@@ -1,14 +1,13 @@
#include "ftxui/dom/flexbox_helper.hpp"
#include <stddef.h> // for size_t
#include <algorithm> // for min, max
#include <cstddef> // for size_t
#include <memory> // for allocator_traits<>::value_type
#include <utility> // for swap, move
#include "ftxui/dom/box_helper.hpp" // for Element, Compute
namespace ftxui {
namespace flexbox_helper {
namespace ftxui::flexbox_helper {
namespace {
void SymmetryXY(FlexboxConfig& c) {
@@ -92,15 +91,17 @@ void SetX(Global& global, std::vector<Line> lines) {
box_helper::Element element;
element.min_size = block->min_size_x;
element.flex_grow =
block->flex_grow_x || global.config.justify_content ==
FlexboxConfig::JustifyContent::Stretch;
block->flex_grow_x != 0 || global.config.justify_content ==
FlexboxConfig::JustifyContent::Stretch
? 1
: 0;
element.flex_shrink = block->flex_shrink_x;
elements.push_back(element);
}
box_helper::Compute(
&elements,
global.size_x - global.config.gap_x * (line.blocks.size() - 1));
global.size_x - global.config.gap_x * (int(line.blocks.size()) - 1));
int x = 0;
for (size_t i = 0; i < line.blocks.size(); ++i) {
@@ -112,6 +113,7 @@ void SetX(Global& global, std::vector<Line> lines) {
}
}
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
void SetY(Global& g, std::vector<Line> lines) {
std::vector<box_helper::Element> elements;
for (auto& line : lines) {
@@ -127,7 +129,7 @@ void SetY(Global& g, std::vector<Line> lines) {
}
// box_helper::Compute(&elements, g.size_y);
box_helper::Compute(&elements, 10000);
box_helper::Compute(&elements, 10000); // NOLINT
// [Align-content]
std::vector<int> ys(elements.size());
@@ -140,48 +142,57 @@ void SetY(Global& g, std::vector<Line> lines) {
int remaining_space = std::max(0, g.size_y - y);
switch (g.config.align_content) {
case FlexboxConfig::AlignContent::FlexStart: {
} break;
break;
}
case FlexboxConfig::AlignContent::FlexEnd: {
for (size_t i = 0; i < ys.size(); ++i)
for (size_t i = 0; i < ys.size(); ++i) { // NOLINT
ys[i] += remaining_space;
} break;
}
break;
}
case FlexboxConfig::AlignContent::Center: {
for (size_t i = 0; i < ys.size(); ++i)
for (size_t i = 0; i < ys.size(); ++i) { // NOLINT
ys[i] += remaining_space / 2;
} break;
}
break;
}
case FlexboxConfig::AlignContent::Stretch: {
for (int i = ys.size() - 1; i >= 0; --i) {
for (int i = ys.size() - 1; i >= 0; --i) { // NOLINT
int shifted = remaining_space * (i + 0) / (i + 1);
ys[i] += shifted;
int consumed = remaining_space - shifted;
elements[i].size += consumed;
remaining_space -= consumed;
}
} break;
break;
}
case FlexboxConfig::AlignContent::SpaceBetween: {
for (int i = ys.size() - 1; i >= 1; --i) {
for (int i = ys.size() - 1; i >= 1; --i) { // NOLINT
ys[i] += remaining_space;
remaining_space = remaining_space * (i - 1) / i;
}
} break;
break;
}
case FlexboxConfig::AlignContent::SpaceAround: {
for (int i = ys.size() - 1; i >= 0; --i) {
for (int i = ys.size() - 1; i >= 0; --i) { // NOLINT
ys[i] += remaining_space * (2 * i + 1) / (2 * i + 2);
remaining_space = remaining_space * (2 * i) / (2 * i + 2);
}
} break;
break;
}
case FlexboxConfig::AlignContent::SpaceEvenly: {
for (int i = ys.size() - 1; i >= 0; --i) {
for (int i = ys.size() - 1; i >= 0; --i) { // NOLINT
ys[i] += remaining_space * (i + 1) / (i + 2);
remaining_space = remaining_space * (i + 1) / (i + 2);
}
} break;
break;
}
}
// [Align items]
@@ -189,7 +200,7 @@ void SetY(Global& g, std::vector<Line> lines) {
auto& element = elements[i];
for (auto* block : lines[i].blocks) {
bool stretch =
block->flex_grow_y ||
block->flex_grow_y != 0 ||
g.config.align_content == FlexboxConfig::AlignContent::Stretch;
int size =
stretch ? element.size : std::min(element.size, block->min_size_y);
@@ -197,22 +208,26 @@ void SetY(Global& g, std::vector<Line> lines) {
case FlexboxConfig::AlignItems::FlexStart: {
block->y = ys[i];
block->dim_y = size;
} break;
break;
}
case FlexboxConfig::AlignItems::Center: {
block->y = ys[i] + (element.size - size) / 2;
block->dim_y = size;
} break;
break;
}
case FlexboxConfig::AlignItems::FlexEnd: {
block->y = ys[i] + element.size - size;
block->dim_y = size;
} break;
break;
}
case FlexboxConfig::AlignItems::Stretch: {
block->y = ys[i];
block->dim_y = element.size;
} break;
break;
}
}
}
}
@@ -228,63 +243,74 @@ void JustifyContent(Global& g, std::vector<Line> lines) {
break;
case FlexboxConfig::JustifyContent::FlexEnd: {
for (auto* block : line.blocks)
for (auto* block : line.blocks) {
block->x += remaining_space;
} break;
}
break;
}
case FlexboxConfig::JustifyContent::Center: {
for (auto* block : line.blocks)
for (auto* block : line.blocks) {
block->x += remaining_space / 2;
} break;
}
break;
}
case FlexboxConfig::JustifyContent::SpaceBetween: {
for (int i = line.blocks.size() - 1; i >= 1; --i) {
for (int i = (int)line.blocks.size() - 1; i >= 1; --i) {
line.blocks[i]->x += remaining_space;
remaining_space = remaining_space * (i - 1) / i;
}
} break;
break;
}
case FlexboxConfig::JustifyContent::SpaceAround: {
for (int i = line.blocks.size() - 1; i >= 0; --i) {
for (int i = (int)line.blocks.size() - 1; i >= 0; --i) {
line.blocks[i]->x += remaining_space * (2 * i + 1) / (2 * i + 2);
remaining_space = remaining_space * (2 * i) / (2 * i + 2);
}
} break;
break;
}
case FlexboxConfig::JustifyContent::SpaceEvenly: {
for (int i = line.blocks.size() - 1; i >= 0; --i) {
for (int i = (int)line.blocks.size() - 1; i >= 0; --i) {
line.blocks[i]->x += remaining_space * (i + 1) / (i + 2);
remaining_space = remaining_space * (i + 1) / (i + 2);
}
} break;
break;
}
}
}
}
} // namespace
void Compute(Global& global) {
if (global.config.direction == FlexboxConfig::Direction::Column ||
global.config.direction == FlexboxConfig::Direction::ColumnInversed) {
SymmetryXY(global);
Compute(global);
SymmetryXY(global);
return;
}
namespace {
void Compute1(Global& global);
void Compute2(Global& global);
void Compute3(Global& global);
void Compute1(Global& global) {
if (global.config.direction == FlexboxConfig::Direction::RowInversed) {
SymmetryX(global);
Compute(global);
Compute2(global);
SymmetryX(global);
return;
}
Compute2(global);
}
void Compute2(Global& global) {
if (global.config.wrap == FlexboxConfig::Wrap::WrapInversed) {
SymmetryY(global);
Compute(global);
Compute3(global);
SymmetryY(global);
return;
}
Compute3(global);
}
void Compute3(Global& global) {
// Step 1: Lay out every elements into rows:
std::vector<Line> lines;
{
@@ -295,18 +321,20 @@ void Compute(Global& global) {
// No? Then we need to start a new one:
if (x + block.min_size_x > global.size_x) {
x = 0;
if (!line.blocks.empty())
if (!line.blocks.empty()) {
lines.push_back(std::move(line));
}
line = Line();
}
block.line = lines.size();
block.line_position = line.blocks.size();
block.line = (int)lines.size();
block.line_position = (int)line.blocks.size();
line.blocks.push_back(&block);
x += block.min_size_x + global.config.gap_x;
}
if (!line.blocks.empty())
if (!line.blocks.empty()) {
lines.push_back(std::move(line));
}
}
// Step 2: Set positions on the X axis.
@@ -317,8 +345,21 @@ void Compute(Global& global) {
SetY(global, lines);
}
} // namespace flexbox_helper
} // namespace ftxui
} // namespace
void Compute(Global& global) {
if (global.config.direction == FlexboxConfig::Direction::Column ||
global.config.direction == FlexboxConfig::Direction::ColumnInversed) {
SymmetryXY(global);
Compute1(global);
SymmetryXY(global);
return;
}
Compute1(global);
}
} // namespace ftxui::flexbox_helper
// Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in

View File

@@ -29,17 +29,17 @@ Decorator focusPositionRelative(float x, float y) {
class Impl : public NodeDecorator {
public:
Impl(Element child, float x, float y)
: NodeDecorator(child), x_(x), y_(y) {}
: NodeDecorator(std::move(child)), x_(x), y_(y) {}
void ComputeRequirement() override {
NodeDecorator::ComputeRequirement();
requirement_.selection = Requirement::Selection::NORMAL;
Box& box = requirement_.selected_box;
box.x_min = requirement_.min_x * x_;
box.y_min = requirement_.min_y * y_;
box.x_max = requirement_.min_x * x_;
box.y_max = requirement_.min_y * y_;
box.x_min = (int)((float)requirement_.min_x * x_);
box.y_min = (int)((float)requirement_.min_y * y_);
box.x_max = (int)((float)requirement_.min_x * x_);
box.y_max = (int)((float)requirement_.min_y * y_);
}
private:
@@ -67,8 +67,8 @@ Decorator focusPositionRelative(float x, float y) {
Decorator focusPosition(int x, int y) {
class Impl : public NodeDecorator {
public:
Impl(Element child, float x, float y)
: NodeDecorator(child), x_(x), y_(y) {}
Impl(Element child, int x, int y)
: NodeDecorator(std::move(child)), x_(x), y_(y) {}
void ComputeRequirement() override {
NodeDecorator::ComputeRequirement();

View File

@@ -16,7 +16,7 @@ namespace ftxui {
class Select : public Node {
public:
Select(Elements children) : Node(std::move(children)) {}
explicit Select(Elements children) : Node(std::move(children)) {}
void ComputeRequirement() override {
Node::ComputeRequirement();

View File

@@ -1,17 +1,16 @@
#include <iostream>
#include <algorithm> // for max, min
#include <memory> // for allocator, make_shared
#include <string> // for string
#include <memory> // for allocator, make_shared
#include <string> // for string
#include "ftxui/dom/elements.hpp" // for Element, gauge
#include "ftxui/dom/node.hpp" // for Node
#include "ftxui/dom/elements.hpp" // for GaugeDirection, Element, GaugeDirection::Down, GaugeDirection::Left, GaugeDirection::Right, GaugeDirection::Up, gauge, gaugeDirection, gaugeDown, gaugeLeft, gaugeRight, gaugeUp
#include "ftxui/dom/node.hpp" // for Node
#include "ftxui/dom/requirement.hpp" // for Requirement
#include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/screen.hpp" // for Screen
#include "ftxui/screen/screen.hpp" // for Screen, Pixel
namespace ftxui {
static std::string charset_horizontal[11] = {
// NOLINTNEXTLINE
static const std::string charset_horizontal[11] = {
#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
// Microsoft's terminals often use fonts not handling the 8 unicode
// characters for representing the whole gauge. Fallback with less.
@@ -23,7 +22,8 @@ static std::string charset_horizontal[11] = {
// int(9 * (limit - limit_int) = 9
""};
static std::string charset_vertical[10] = {
// NOLINTNEXTLINE
static const std::string charset_vertical[10] = {
"",
"",
"",
@@ -43,10 +43,12 @@ class Gauge : public Node {
Gauge(float progress, GaugeDirection direction)
: progress_(progress), direction_(direction) {
// This handle NAN correctly:
if (!(progress_ > 0.f))
progress_ = 0.f;
if (!(progress_ < 1.f))
progress_ = 1.f;
if (!(progress_ > 0.F)) {
progress_ = 0.F;
}
if (!(progress_ < 1.F)) {
progress_ = 1.F;
}
}
void ComputeRequirement() override {
@@ -89,49 +91,61 @@ class Gauge : public Node {
void RenderHorizontal(Screen& screen, bool invert) {
int y = box_.y_min;
if (y > box_.y_max)
if (y > box_.y_max) {
return;
}
// Draw the progress bar horizontally.
{
float progress = invert ? 1.f - progress_ : progress_;
float limit = box_.x_min + progress * (box_.x_max - box_.x_min + 1);
int limit_int = limit;
float progress = invert ? 1.F - progress_ : progress_;
float limit =
(float)box_.x_min + progress * (float)(box_.x_max - box_.x_min + 1);
int limit_int = (int)limit;
int x = box_.x_min;
while (x < limit_int)
screen.at(x++, y) = charset_horizontal[9];
while (x < limit_int) {
screen.at(x++, y) = charset_horizontal[9]; // NOLINT
}
// NOLINTNEXTLINE
screen.at(x++, y) = charset_horizontal[int(9 * (limit - limit_int))];
while (x <= box_.x_max)
while (x <= box_.x_max) {
screen.at(x++, y) = charset_horizontal[0];
}
}
if (invert) {
for (int x = box_.x_min; x <= box_.x_max; x++)
for (int x = box_.x_min; x <= box_.x_max; x++) {
screen.PixelAt(x, y).inverted ^= true;
}
}
}
void RenderVertical(Screen& screen, bool invert) {
int x = box_.x_min;
if (x > box_.x_max)
if (x > box_.x_max) {
return;
}
// Draw the progress bar vertically:
{
float progress = invert ? progress_ : 1.f - progress_;
float limit = box_.y_min + progress * (box_.y_max - box_.y_min + 1);
int limit_int = limit;
float progress = invert ? progress_ : 1.F - progress_;
float limit =
(float)box_.y_min + progress * (float)(box_.y_max - box_.y_min + 1);
int limit_int = (int)limit;
int y = box_.y_min;
while (y < limit_int)
screen.at(x, y++) = charset_vertical[8];
while (y < limit_int) {
screen.at(x, y++) = charset_vertical[8]; // NOLINT
}
// NOLINTNEXTLINE
screen.at(x, y++) = charset_vertical[int(8 * (limit - limit_int))];
while (y <= box_.y_max)
while (y <= box_.y_max) {
screen.at(x, y++) = charset_vertical[0];
}
}
if (invert) {
for (int y = box_.y_min; y <= box_.y_max; y++)
for (int y = box_.y_min; y <= box_.y_max; y++) {
screen.PixelAt(x, y).inverted ^= true;
}
}
}

View File

@@ -1,6 +1,7 @@
#include <functional> // for function
#include <memory> // for allocator, make_shared
#include <string> // for string
#include <utility> // for move
#include <vector> // for vector
#include "ftxui/dom/elements.hpp" // for GraphFunction, Element, graph
@@ -11,6 +12,7 @@
namespace ftxui {
// NOLINTNEXTLINE
static std::string charset[] =
#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
// Microsoft's terminals often use fonts not handling the 8 unicode
@@ -22,7 +24,8 @@ static std::string charset[] =
class Graph : public Node {
public:
Graph(GraphFunction graph_function) : graph_function_(graph_function) {}
explicit Graph(GraphFunction graph_function)
: graph_function_(std::move(graph_function)) {}
void ComputeRequirement() override {
requirement_.flex_grow_x = 1;
@@ -43,9 +46,9 @@ class Graph : public Node {
int height_2 = 2 * box_.y_max - data[i++];
for (int y = box_.y_min; y <= box_.y_max; ++y) {
int yy = 2 * y;
int i_1 = yy < height_1 ? 0 : yy == height_1 ? 3 : 6;
int i_2 = yy < height_2 ? 0 : yy == height_2 ? 1 : 2;
screen.at(x, y) = charset[i_1 + i_2];
int i_1 = yy < height_1 ? 0 : yy == height_1 ? 3 : 6; // NOLINT
int i_2 = yy < height_2 ? 0 : yy == height_2 ? 1 : 2; // NOLINT
screen.at(x, y) = charset[i_1 + i_2]; // NOLINT
}
}
}
@@ -57,7 +60,7 @@ class Graph : public Node {
/// @brief Draw a graph using a GraphFunction.
/// @param graph_function the function to be called to get the data.
Element graph(GraphFunction graph_function) {
return std::make_shared<Graph>(graph_function);
return std::make_shared<Graph>(std::move(graph_function));
}
} // namespace ftxui

View File

@@ -1,5 +1,5 @@
#include <stddef.h> // for size_t
#include <algorithm> // for max, min
#include <cstddef> // for size_t
#include <memory> // for __shared_ptr_access, shared_ptr, make_shared, allocator_traits<>::value_type
#include <utility> // for move
#include <vector> // for vector, __alloc_traits<>::value_type
@@ -15,10 +15,11 @@ class Screen;
class GridBox : public Node {
public:
GridBox(std::vector<Elements> lines) : Node(), lines_(std::move(lines)) {
y_size = lines_.size();
for (const auto& line : lines_)
explicit GridBox(std::vector<Elements> lines) : lines_(std::move(lines)) {
y_size = (int)lines_.size();
for (const auto& line : lines_) {
x_size = std::max(x_size, (int)line.size());
}
for (auto& line : lines_) {
while (line.size() < (size_t)x_size) {
line.push_back(filler());
@@ -39,8 +40,9 @@ class GridBox : public Node {
cell->ComputeRequirement();
// Determine focus based on the focused child.
if (requirement_.selection >= cell->requirement().selection)
if (requirement_.selection >= cell->requirement().selection) {
continue;
}
requirement_.selection = cell->requirement().selection;
requirement_.selected_box = cell->requirement().selected_box;
requirement_.selected_box.x_min += requirement_.min_x;
@@ -51,16 +53,18 @@ class GridBox : public Node {
// Work on the x-axis.
for (int x = 0; x < x_size; ++x) {
int min_x = 0;
for (int y = 0; y < y_size; ++y)
for (int y = 0; y < y_size; ++y) {
min_x = std::max(min_x, lines_[y][x]->requirement().min_x);
}
requirement_.min_x += min_x;
}
// Work on the y-axis.
for (int y = 0; y < y_size; ++y) {
int min_y = 0;
for (int x = 0; x < x_size; ++x)
for (int x = 0; x < x_size; ++x) {
min_y = std::max(min_y, lines_[y][x]->requirement().min_y);
}
requirement_.min_y += min_y;
}
}
@@ -70,8 +74,8 @@ class GridBox : public Node {
box_helper::Element init;
init.min_size = 0;
init.flex_grow = 1024;
init.flex_shrink = 1024;
init.flex_grow = 1024; // NOLINT
init.flex_shrink = 1024; // NOLINT
std::vector<box_helper::Element> elements_x(x_size, init);
std::vector<box_helper::Element> elements_y(y_size, init);
@@ -115,8 +119,9 @@ class GridBox : public Node {
void Render(Screen& screen) override {
for (auto& line : lines_) {
for (auto& cell : line)
for (auto& cell : line) {
cell->Render(screen);
}
}
}

View File

@@ -1,5 +1,5 @@
#include <stddef.h> // for size_t
#include <algorithm> // for max
#include <cstddef> // for size_t
#include <memory> // for __shared_ptr_access, shared_ptr, make_shared, allocator_traits<>::value_type
#include <utility> // for move
#include <vector> // for vector, __alloc_traits<>::value_type
@@ -14,7 +14,7 @@ namespace ftxui {
class HBox : public Node {
public:
HBox(Elements children) : Node(std::move(children)) {}
explicit HBox(Elements children) : Node(std::move(children)) {}
void ComputeRequirement() override {
requirement_.min_x = 0;

View File

@@ -5,15 +5,16 @@
namespace ftxui {
Node::Node() {}
Node::Node() = default;
Node::Node(Elements children) : children_(std::move(children)) {}
Node::~Node() {}
Node::~Node() = default;
/// @brief Compute how much space an elements needs.
/// @ingroup dom
void Node::ComputeRequirement() {
for (auto& child : children_)
for (auto& child : children_) {
child->ComputeRequirement();
}
}
/// @brief Assign a position and a dimension to an element for drawing.
@@ -25,13 +26,15 @@ void Node::SetBox(Box box) {
/// @brief Display an element on a ftxui::Screen.
/// @ingroup dom
void Node::Render(Screen& screen) {
for (auto& child : children_)
for (auto& child : children_) {
child->Render(screen);
}
}
void Node::Check(Status* status) {
for (auto& child : children_)
for (auto& child : children_) {
child->Check(status);
}
status->need_iteration |= (status->iteration == 0);
}
@@ -52,7 +55,8 @@ void Render(Screen& screen, Node* node) {
Node::Status status;
node->Check(&status);
while (status.need_iteration && status.iteration < 20) {
const int max_iterations = 20;
while (status.need_iteration && status.iteration < max_iterations) {
// Step 1: Find what dimension this elements wants to be.
node->ComputeRequirement();

View File

@@ -8,12 +8,13 @@
namespace ftxui {
namespace {
Elements Split(std::string the_text) {
Elements Split(const std::string& the_text) {
Elements output;
std::stringstream ss(the_text);
std::string word;
while (std::getline(ss, word, ' '))
while (std::getline(ss, word, ' ')) {
output.push_back(text(word));
}
return output;
}
} // namespace
@@ -21,37 +22,37 @@ Elements Split(std::string the_text) {
/// @brief Return an element drawing the paragraph on multiple lines.
/// @ingroup dom
/// @see flexbox.
Element paragraph(std::string the_text) {
return paragraphAlignLeft(std::move(the_text));
Element paragraph(const std::string& the_text) {
return paragraphAlignLeft(the_text);
}
/// @brief Return an element drawing the paragraph on multiple lines, aligned on
/// the left.
/// @ingroup dom
/// @see flexbox.
Element paragraphAlignLeft(std::string the_text) {
Element paragraphAlignLeft(const std::string& the_text) {
static const auto config = FlexboxConfig().SetGap(1, 0);
return flexbox(Split(std::move(the_text)), config);
return flexbox(Split(the_text), config);
}
/// @brief Return an element drawing the paragraph on multiple lines, aligned on
/// the right.
/// @ingroup dom
/// @see flexbox.
Element paragraphAlignRight(std::string the_text) {
Element paragraphAlignRight(const std::string& the_text) {
static const auto config =
FlexboxConfig().SetGap(1, 0).Set(FlexboxConfig::JustifyContent::FlexEnd);
return flexbox(Split(std::move(the_text)), config);
return flexbox(Split(the_text), config);
}
/// @brief Return an element drawing the paragraph on multiple lines, aligned on
/// the center.
/// @ingroup dom
/// @see flexbox.
Element paragraphAlignCenter(std::string the_text) {
Element paragraphAlignCenter(const std::string& the_text) {
static const auto config =
FlexboxConfig().SetGap(1, 0).Set(FlexboxConfig::JustifyContent::Center);
return flexbox(Split(std::move(the_text)), config);
return flexbox(Split(the_text), config);
}
/// @brief Return an element drawing the paragraph on multiple lines, aligned
@@ -59,10 +60,10 @@ Element paragraphAlignCenter(std::string the_text) {
/// the center.
/// @ingroup dom
/// @see flexbox.
Element paragraphAlignJustify(std::string the_text) {
Element paragraphAlignJustify(const std::string& the_text) {
static const auto config = FlexboxConfig().SetGap(1, 0).Set(
FlexboxConfig::JustifyContent::SpaceBetween);
Elements words = Split(std::move(the_text));
Elements words = Split(the_text);
words.push_back(text("") | xflex);
return flexbox(std::move(words), config);
}

View File

@@ -21,27 +21,29 @@ Element vscroll_indicator(Element child) {
using NodeDecorator::NodeDecorator;
void ComputeRequirement() override {
Node::ComputeRequirement();
NodeDecorator::ComputeRequirement();
requirement_ = children_[0]->requirement();
requirement_.min_x++;
}
void SetBox(Box box) override {
Node::SetBox(box);
if (box_.x_min > box_.x_max)
NodeDecorator::SetBox(box);
if (box_.x_min > box_.x_max) {
box_.x_max--;
}
children_[0]->SetBox(box);
}
void Render(Screen& screen) final {
Node::Render(screen);
NodeDecorator::Render(screen);
const Box& stencil = screen.stencil;
int size_inner = box_.y_max - box_.y_min;
int size_outter = stencil.y_max - stencil.y_min + 1;
if (size_outter >= size_inner)
if (size_outter >= size_inner) {
return;
}
int size = 2 * size_outter * size_outter / size_inner;
size = std::max(size, 1);
@@ -56,7 +58,7 @@ Element vscroll_indicator(Element child) {
bool up = (start_y <= y_up) && (y_up <= start_y + size);
bool down = (start_y <= y_down) && (y_down <= start_y + size);
const char* c = up ? (down ? "" : "") : (down ? "" : " ");
const char* c = up ? (down ? "" : "") : (down ? "" : " "); // NOLINT
screen.PixelAt(x, y) = Pixel();
screen.PixelAt(x, y).character = c;
}

View File

@@ -1,5 +1,7 @@
#include <memory> // for make_shared, allocator
#include <string> // for string
#include <array> // for array, array<>::value_type
#include <memory> // for make_shared, allocator
#include <string> // for basic_string, string
#include <utility> // for move
#include "ftxui/dom/elements.hpp" // for Element, BorderStyle, LIGHT, separator, DOUBLE, EMPTY, HEAVY, separatorCharacter, separatorDouble, separatorEmpty, separatorHSelector, separatorHeavy, separatorLight, separatorStyled, separatorVSelector
#include "ftxui/dom/node.hpp" // for Node
@@ -10,19 +12,25 @@
namespace ftxui {
namespace {
using ftxui::Screen;
const std::string charset[][2] = {
{"", ""}, //
{"", ""}, //
{"", ""}, //
{"", ""}, //
{" ", " "}, //
using Charset = std::array<std::string, 2>; // NOLINT
using Charsets = std::array<Charset, 5>; // NOLINT
const Charsets charsets = // NOLINT
{
Charset{"", ""}, //
Charset{"", ""}, //
Charset{"", ""}, //
Charset{"", ""}, //
Charset{" ", " "}, //
};
} // namespace
class Separator : public Node {
public:
Separator(std::string value) : value_(value) {}
explicit Separator(std::string value) : value_(std::move(value)) {}
void ComputeRequirement() override {
requirement_.min_x = 1;
@@ -44,7 +52,7 @@ class Separator : public Node {
class SeparatorAuto : public Node {
public:
SeparatorAuto(BorderStyle style) : style_(style) {}
explicit SeparatorAuto(BorderStyle style) : style_(style) {}
void ComputeRequirement() override {
requirement_.min_x = 1;
@@ -55,7 +63,7 @@ class SeparatorAuto : public Node {
bool is_column = (box_.x_max == box_.x_min);
bool is_line = (box_.y_min == box_.y_max);
const std::string c = charset[style_][is_line && !is_column];
const std::string c = charsets[style_][int(is_line && !is_column)];
for (int y = box_.y_min; y <= box_.y_max; ++y) {
for (int x = box_.x_min; x <= box_.x_max; ++x) {
@@ -71,7 +79,8 @@ class SeparatorAuto : public Node {
class SeparatorWithPixel : public SeparatorAuto {
public:
SeparatorWithPixel(Pixel pixel) : SeparatorAuto(LIGHT), pixel_(pixel) {
explicit SeparatorWithPixel(Pixel pixel)
: SeparatorAuto(LIGHT), pixel_(std::move(pixel)) {
pixel_.automerge = true;
}
void Render(Screen& screen) override {
@@ -337,7 +346,7 @@ Element separatorEmpty() {
/// down
/// ```
Element separatorCharacter(std::string value) {
return std::make_shared<Separator>(value);
return std::make_shared<Separator>(std::move(value));
}
/// @brief Draw a separator in between two element filled with a given pixel.
@@ -367,7 +376,7 @@ Element separatorCharacter(std::string value) {
/// Down
/// ```
Element separator(Pixel pixel) {
return std::make_shared<SeparatorWithPixel>(pixel);
return std::make_shared<SeparatorWithPixel>(std::move(pixel));
}
/// @brief Draw an horizontal bar, with the area in between left/right colored
@@ -384,27 +393,28 @@ Element separator(Pixel pixel) {
/// ```
Element separatorHSelector(float left,
float right,
Color selected_color,
Color unselected_color) {
Color unselected_color,
Color selected_color) {
class Impl : public Node {
public:
Impl(float left, float right, Color selected_color, Color unselected_color)
: left_(left),
right_(right),
selected_color_(selected_color),
unselected_color_(unselected_color) {}
unselected_color_(unselected_color),
selected_color_(selected_color) {}
void ComputeRequirement() override {
requirement_.min_x = 1;
requirement_.min_y = 1;
}
void Render(Screen& screen) override {
if (box_.y_max < box_.y_min)
if (box_.y_max < box_.y_min) {
return;
}
// This are the two location with an empty demi-cell.
int demi_cell_left = left_ * 2 - 1;
int demi_cell_right = right_ * 2 + 2;
int demi_cell_left = int(left_ * 2.F - 1.F); // NOLINT
int demi_cell_right = int(right_ * 2.F + 2.F); // NOLINT
int y = box_.y_min;
for (int x = box_.x_min; x <= box_.x_max; ++x) {
@@ -419,23 +429,24 @@ Element separatorHSelector(float left,
pixel.character = "";
pixel.automerge = true;
} else {
pixel.character = a_empty ? "" : "";
pixel.character = a_empty ? "" : ""; // NOLINT
pixel.automerge = false;
}
if (demi_cell_left <= a && b <= demi_cell_right)
if (demi_cell_left <= a && b <= demi_cell_right) {
pixel.foreground_color = selected_color_;
else
} else {
pixel.foreground_color = unselected_color_;
}
}
}
float left_;
float right_;
Color selected_color_;
Color unselected_color_;
Color selected_color_;
};
return std::make_shared<Impl>(left, right, selected_color, unselected_color);
return std::make_shared<Impl>(left, right, unselected_color, selected_color);
}
/// @brief Draw an vertical bar, with the area in between up/downcolored
@@ -452,27 +463,28 @@ Element separatorHSelector(float left,
/// ```
Element separatorVSelector(float up,
float down,
Color selected_color,
Color unselected_color) {
Color unselected_color,
Color selected_color) {
class Impl : public Node {
public:
Impl(float up, float down, Color selected_color, Color unselected_color)
Impl(float up, float down, Color unselected_color, Color selected_color)
: up_(up),
down_(down),
selected_color_(selected_color),
unselected_color_(unselected_color) {}
unselected_color_(unselected_color),
selected_color_(selected_color) {}
void ComputeRequirement() override {
requirement_.min_x = 1;
requirement_.min_y = 1;
}
void Render(Screen& screen) override {
if (box_.x_max < box_.x_min)
if (box_.x_max < box_.x_min) {
return;
}
// This are the two location with an empty demi-cell.
int demi_cell_up = up_ * 2 - 1;
int demi_cell_down = down_ * 2 + 2;
int demi_cell_up = int(up_ * 2 - 1);
int demi_cell_down = int(down_ * 2 + 2);
int x = box_.x_min;
for (int y = box_.y_min; y <= box_.y_max; ++y) {
@@ -487,23 +499,24 @@ Element separatorVSelector(float up,
pixel.character = "";
pixel.automerge = true;
} else {
pixel.character = a_empty ? "" : "";
pixel.character = a_empty ? "" : ""; // NOLINT
pixel.automerge = false;
}
if (demi_cell_up <= a && b <= demi_cell_down)
if (demi_cell_up <= a && b <= demi_cell_down) {
pixel.foreground_color = selected_color_;
else
} else {
pixel.foreground_color = unselected_color_;
}
}
}
float up_;
float down_;
Color selected_color_;
Color unselected_color_;
Color selected_color_;
};
return std::make_shared<Impl>(up, down, selected_color, unselected_color);
return std::make_shared<Impl>(up, down, unselected_color, selected_color);
}
} // namespace ftxui

View File

@@ -1,4 +1,3 @@
#include <stddef.h> // for size_t
#include <algorithm> // for min, max
#include <memory> // for make_shared, __shared_ptr_access
#include <utility> // for move
@@ -13,7 +12,7 @@ namespace ftxui {
class Size : public Node {
public:
Size(Element child, Direction direction, Constraint constraint, size_t value)
Size(Element child, Direction direction, Constraint constraint, int value)
: Node(unpack(std::move(child))),
direction_(direction),
constraint_(constraint),

View File

@@ -1,14 +1,16 @@
#include <stddef.h> // for size_t
#include <memory> // for allocator, allocator_traits<>::value_type
#include <string> // for basic_string, string
#include <utility> // for move
#include <vector> // for vector, __alloc_traits<>::value_type
#include <cstddef> // for size_t
#include <memory> // for allocator, allocator_traits<>::value_type
#include <string> // for basic_string, string
#include <utility> // for move
#include <vector> // for vector, __alloc_traits<>::value_type
#include "ftxui/dom/elements.hpp" // for Element, gauge, text, vbox, spinner
namespace ftxui {
static const std::vector<std::vector<std::vector<std::string>>> elements = {
namespace {
// NOLINTNEXTLINE
const std::vector<std::vector<std::vector<std::string>>> elements = {
{
{"Replaced by the gauge"},
},
@@ -246,6 +248,8 @@ static const std::vector<std::vector<std::vector<std::string>>> elements = {
" LOLLOL ",
}}};
} // namespace
/// @brief Useful to represent the effect of time and/or events. This display an
/// ASCII art "video".
/// @param charset_index The type of "video".
@@ -254,16 +258,19 @@ static const std::vector<std::vector<std::vector<std::string>>> elements = {
/// @ingroup dom
Element spinner(int charset_index, size_t image_index) {
if (charset_index == 0) {
image_index %= 40;
if (image_index > 20)
image_index = 40 - image_index;
return gauge(image_index * 0.05);
const int progress_size = 40;
image_index %= progress_size;
if (image_index > progress_size / 2) {
image_index = progress_size - image_index;
}
return gauge(float(image_index) * 0.05F); // NOLINT
}
charset_index %= elements.size();
image_index %= elements[charset_index].size();
charset_index %= (int)elements.size();
image_index %= (int)elements[charset_index].size();
std::vector<Element> lines;
for (const auto& it : elements[charset_index][image_index])
for (const auto& it : elements[charset_index][image_index]) {
lines.push_back(text(it));
}
return vbox(std::move(lines));
}

View File

@@ -13,6 +13,7 @@ bool IsCell(int x, int y) {
return x % 2 == 1 && y % 2 == 1;
}
// NOLINTNEXTLINE
static std::string charset[6][6] = {
{"", "", "", "", "", ""}, //
{"", "", "", "", "", ""}, //
@@ -29,8 +30,9 @@ int Wrap(int input, int modulo) {
}
void Order(int& a, int& b) {
if (a >= b)
if (a >= b) {
std::swap(a, b);
}
}
} // namespace
@@ -42,10 +44,10 @@ Table::Table() {
Table::Table(std::vector<std::vector<std::string>> input) {
std::vector<std::vector<Element>> output;
for (auto& row : input) {
output.push_back({});
output.emplace_back();
auto& output_row = output.back();
for (auto& cell : row) {
output_row.push_back(text(cell));
output_row.push_back(text(std::move(cell)));
}
}
Initialize(std::move(output));
@@ -56,18 +58,20 @@ Table::Table(std::vector<std::vector<Element>> input) {
}
void Table::Initialize(std::vector<std::vector<Element>> input) {
input_dim_y_ = input.size();
input_dim_y_ = (int)input.size();
input_dim_x_ = 0;
for (auto& row : input)
for (auto& row : input) {
input_dim_x_ = std::max(input_dim_x_, (int)row.size());
}
dim_y_ = 2 * input_dim_y_ + 1;
dim_x_ = 2 * input_dim_x_ + 1;
// Reserve space.
elements_.resize(dim_y_);
for (int y = 0; y < dim_y_; ++y)
for (int y = 0; y < dim_y_; ++y) {
elements_[y].resize(dim_x_);
}
// Transfert elements_ from |input| toward |elements_|.
{
@@ -88,8 +92,9 @@ void Table::Initialize(std::vector<std::vector<Element>> input) {
auto& element = elements_[y][x];
if (IsCell(x, y)) {
if (!element)
if (!element) {
element = emptyElement();
}
continue;
}
@@ -129,7 +134,7 @@ TableSelection Table::SelectRectangle(int column_min,
row_max = Wrap(row_max, input_dim_y_);
Order(row_min, row_max);
TableSelection output;
TableSelection output; // NOLINT
output.table_ = this;
output.x_min_ = 2 * column_min;
output.x_max_ = 2 * column_max + 2;
@@ -139,7 +144,7 @@ TableSelection Table::SelectRectangle(int column_min,
}
TableSelection Table::SelectAll() {
TableSelection output;
TableSelection output; // NOLINT
output.table_ = this;
output.x_min_ = 0;
output.x_max_ = dim_x_ - 1;
@@ -172,6 +177,7 @@ Element Table::Render() {
return gridbox(std::move(elements_));
}
// NOLINTNEXTLINE
void TableSelection::Decorate(Decorator decorator) {
for (int y = y_min_; y <= y_max_; ++y) {
for (int x = x_min_; x <= x_max_; ++x) {
@@ -181,10 +187,11 @@ void TableSelection::Decorate(Decorator decorator) {
}
}
// NOLINTNEXTLINE
void TableSelection::DecorateCells(Decorator decorator) {
for (int y = y_min_; y <= y_max_; ++y) {
for (int x = x_min_; x <= x_max_; ++x) {
if (y % 2 && x % 2) {
if (y % 2 == 1 && x % 2 == 1) {
Element& e = table_->elements_[y][x];
e = std::move(e) | decorator;
}
@@ -192,12 +199,13 @@ void TableSelection::DecorateCells(Decorator decorator) {
}
}
// NOLINTNEXTLINE
void TableSelection::DecorateAlternateColumn(Decorator decorator,
int modulo,
int shift) {
for (int y = y_min_; y <= y_max_; ++y) {
for (int x = x_min_; x <= x_max_; ++x) {
if (y % 2 && (x / 2) % modulo == shift) {
if (y % 2 == 1 && (x / 2) % modulo == shift) {
Element& e = table_->elements_[y][x];
e = std::move(e) | decorator;
}
@@ -205,12 +213,13 @@ void TableSelection::DecorateAlternateColumn(Decorator decorator,
}
}
// NOLINTNEXTLINE
void TableSelection::DecorateAlternateRow(Decorator decorator,
int modulo,
int shift) {
for (int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
for (int x = x_min_; x <= x_max_; ++x) {
if (y % 2 && (y / 2) % modulo == shift) {
if (y % 2 == 1 && (y / 2) % modulo == shift) {
Element& e = table_->elements_[y][x];
e = std::move(e) | decorator;
}
@@ -218,12 +227,13 @@ void TableSelection::DecorateAlternateRow(Decorator decorator,
}
}
// NOLINTNEXTLINE
void TableSelection::DecorateCellsAlternateColumn(Decorator decorator,
int modulo,
int shift) {
for (int y = y_min_; y <= y_max_; ++y) {
for (int x = x_min_; x <= x_max_; ++x) {
if (y % 2 && x % 2 && ((x / 2) % modulo == shift)) {
if (y % 2 == 1 && x % 2 == 1 && ((x / 2) % modulo == shift)) {
Element& e = table_->elements_[y][x];
e = std::move(e) | decorator;
}
@@ -231,12 +241,13 @@ void TableSelection::DecorateCellsAlternateColumn(Decorator decorator,
}
}
// NOLINTNEXTLINE
void TableSelection::DecorateCellsAlternateRow(Decorator decorator,
int modulo,
int shift) {
for (int y = y_min_; y <= y_max_; ++y) {
for (int x = x_min_; x <= x_max_; ++x) {
if (y % 2 && x % 2 && ((y / 2) % modulo == shift)) {
if (y % 2 == 1 && x % 2 == 1 && ((y / 2) % modulo == shift)) {
Element& e = table_->elements_[y][x];
e = std::move(e) | decorator;
}
@@ -244,77 +255,82 @@ void TableSelection::DecorateCellsAlternateRow(Decorator decorator,
}
}
void TableSelection::Border(BorderStyle style) {
BorderLeft(style);
BorderRight(style);
BorderTop(style);
BorderBottom(style);
void TableSelection::Border(BorderStyle border) {
BorderLeft(border);
BorderRight(border);
BorderTop(border);
BorderBottom(border);
table_->elements_[y_min_][x_min_] = text(charset[style][0]) | automerge;
table_->elements_[y_min_][x_max_] = text(charset[style][1]) | automerge;
table_->elements_[y_max_][x_min_] = text(charset[style][2]) | automerge;
table_->elements_[y_max_][x_max_] = text(charset[style][3]) | automerge;
// NOLINTNEXTLINE
table_->elements_[y_min_][x_min_] = text(charset[border][0]) | automerge;
// NOLINTNEXTLINE
table_->elements_[y_min_][x_max_] = text(charset[border][1]) | automerge;
// NOLINTNEXTLINE
table_->elements_[y_max_][x_min_] = text(charset[border][2]) | automerge;
// NOLINTNEXTLINE
table_->elements_[y_max_][x_max_] = text(charset[border][3]) | automerge;
}
void TableSelection::Separator(BorderStyle style) {
void TableSelection::Separator(BorderStyle border) {
for (int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
for (int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
if (y % 2 == 0 || x % 2 == 0) {
Element& e = table_->elements_[y][x];
e = (y % 2) ? separatorCharacter(charset[style][5]) | automerge
: separatorCharacter(charset[style][4]) | automerge;
e = (y % 2 == 1)
? separatorCharacter(charset[border][5]) | automerge // NOLINT
: separatorCharacter(charset[border][4]) | automerge; // NOLINT
}
}
}
}
void TableSelection::SeparatorVertical(BorderStyle style) {
void TableSelection::SeparatorVertical(BorderStyle border) {
for (int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
for (int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
if (x % 2 == 0) {
table_->elements_[y][x] =
separatorCharacter(charset[style][5]) | automerge;
separatorCharacter(charset[border][5]) | automerge; // NOLINT
}
}
}
}
void TableSelection::SeparatorHorizontal(BorderStyle style) {
void TableSelection::SeparatorHorizontal(BorderStyle border) {
for (int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
for (int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
if (y % 2 == 0) {
table_->elements_[y][x] =
separatorCharacter(charset[style][4]) | automerge;
separatorCharacter(charset[border][4]) | automerge; // NOLINT
}
}
}
}
void TableSelection::BorderLeft(BorderStyle style) {
void TableSelection::BorderLeft(BorderStyle border) {
for (int y = y_min_; y <= y_max_; y++) {
table_->elements_[y][x_min_] =
separatorCharacter(charset[style][5]) | automerge;
separatorCharacter(charset[border][5]) | automerge; // NOLINT
}
}
void TableSelection::BorderRight(BorderStyle style) {
void TableSelection::BorderRight(BorderStyle border) {
for (int y = y_min_; y <= y_max_; y++) {
table_->elements_[y][x_max_] =
separatorCharacter(charset[style][5]) | automerge;
separatorCharacter(charset[border][5]) | automerge; // NOLINT
}
}
void TableSelection::BorderTop(BorderStyle style) {
void TableSelection::BorderTop(BorderStyle border) {
for (int x = x_min_; x <= x_max_; x++) {
table_->elements_[y_min_][x] =
separatorCharacter(charset[style][4]) | automerge;
separatorCharacter(charset[border][4]) | automerge; // NOLINT
}
}
void TableSelection::BorderBottom(BorderStyle style) {
void TableSelection::BorderBottom(BorderStyle border) {
for (int x = x_min_; x <= x_max_; x++) {
table_->elements_[y_max_][x] =
separatorCharacter(charset[style][4]) | automerge;
separatorCharacter(charset[border][4]) | automerge; // NOLINT
}
}

View File

@@ -1,6 +1,7 @@
#include <algorithm> // for min
#include <memory> // for make_shared
#include <string> // for string, wstring
#include <utility> // for move
#include <vector> // for vector
#include "ftxui/dom/deprecated.hpp" // for text, vtext
@@ -17,7 +18,7 @@ using ftxui::Screen;
class Text : public Node {
public:
Text(std::string text) : text_(text) {}
explicit Text(std::string text) : text_(std::move(text)) {}
void ComputeRequirement() override {
requirement_.min_x = string_width(text_);
@@ -27,11 +28,13 @@ class Text : public Node {
void Render(Screen& screen) override {
int x = box_.x_min;
int y = box_.y_min;
if (y > box_.y_max)
if (y > box_.y_max) {
return;
}
for (const auto& cell : Utf8ToGlyphs(text_)) {
if (x > box_.x_max)
if (x > box_.x_max) {
return;
}
screen.PixelAt(x, y).character = cell;
++x;
}
@@ -43,8 +46,8 @@ class Text : public Node {
class VText : public Node {
public:
VText(std::string text)
: text_(text), width_{std::min(string_width(text_), 1)} {}
explicit VText(std::string text)
: text_(std::move(text)), width_{std::min(string_width(text_), 1)} {}
void ComputeRequirement() override {
requirement_.min_x = width_;
@@ -54,11 +57,13 @@ class VText : public Node {
void Render(Screen& screen) override {
int x = box_.x_min;
int y = box_.y_min;
if (x + width_ - 1 > box_.x_max)
if (x + width_ - 1 > box_.x_max) {
return;
}
for (const auto& it : Utf8ToGlyphs(text_)) {
if (y > box_.y_max)
if (y > box_.y_max) {
return;
}
screen.PixelAt(x, y).character = it;
y += 1;
}
@@ -85,7 +90,7 @@ class VText : public Node {
/// Hello world!
/// ```
Element text(std::string text) {
return std::make_shared<Text>(text);
return std::make_shared<Text>(std::move(text));
}
/// @brief Display a piece of unicode text.
@@ -103,7 +108,7 @@ Element text(std::string text) {
/// ```bash
/// Hello world!
/// ```
Element text(std::wstring text) {
Element text(std::wstring text) { // NOLINT
return std::make_shared<Text>(to_string(text));
}
@@ -134,7 +139,7 @@ Element text(std::wstring text) {
/// !
/// ```
Element vtext(std::string text) {
return std::make_shared<VText>(text);
return std::make_shared<VText>(std::move(text));
}
/// @brief Display a piece unicode text vertically.
@@ -163,7 +168,7 @@ Element vtext(std::string text) {
/// d
/// !
/// ```
Element vtext(std::wstring text) {
Element vtext(std::wstring text) { // NOLINT
return std::make_shared<VText>(to_string(text));
}

View File

@@ -36,16 +36,18 @@ Element nothing(Element element) {
/// auto decorator = bold | blink;
/// ```
Decorator operator|(Decorator a, Decorator b) {
return compose(a, b);
return compose(std::move(a), //
std::move(b));
}
/// @brief From a set of element, apply a decorator to every elements.
/// @return the set of decorated element.
/// @ingroup dom
Elements operator|(Elements elements, Decorator decorator) {
Elements operator|(Elements elements, Decorator decorator) { // NOLINT
Elements output;
for (auto& it : elements)
for (auto& it : elements) {
output.push_back(std::move(it) | decorator);
}
return output;
}
@@ -62,7 +64,7 @@ Elements operator|(Elements elements, Decorator decorator) {
/// ```cpp
/// text("Hello") | bold;
/// ```
Element operator|(Element element, Decorator decorator) {
Element operator|(Element element, Decorator decorator) { // NOLINT
return decorator(std::move(element));
}
@@ -78,7 +80,7 @@ Element operator|(Element element, Decorator decorator) {
/// element |= bold;
/// ```
Element& operator|=(Element& e, Decorator d) {
e = e | d;
e = e | std::move(d);
return e;
}
@@ -95,7 +97,8 @@ Dimensions Dimension::Fit(Element& e) {
Node::Status status;
e->Check(&status);
while (status.need_iteration && status.iteration < 20) {
const int max_iteration = 20;
while (status.need_iteration && status.iteration < max_iteration) {
e->ComputeRequirement();
// Don't give the element more space than it needs:
@@ -107,8 +110,9 @@ Dimensions Dimension::Fit(Element& e) {
status.iteration++;
e->Check(&status);
if (!status.need_iteration)
if (!status.need_iteration) {
break;
}
// Increase the size of the box until it fits, but not more than the with of
// the terminal emulator:
box.x_max = std::min(e->requirement().min_x, fullsize.dimx);

View File

@@ -1,5 +1,5 @@
#include <stddef.h> // for size_t
#include <algorithm> // for max
#include <cstddef> // for size_t
#include <memory> // for __shared_ptr_access, shared_ptr, make_shared, allocator_traits<>::value_type
#include <utility> // for move
#include <vector> // for vector, __alloc_traits<>::value_type
@@ -14,7 +14,7 @@ namespace ftxui {
class VBox : public Node {
public:
VBox(Elements children) : Node(std::move(children)) {}
explicit VBox(Elements children) : Node(std::move(children)) {}
void ComputeRequirement() override {
requirement_.min_x = 0;