mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2025-09-29 16:39:34 +08:00
Add clang-tidy. (#368)
This commit is contained in:
@@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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();
|
||||
|
@@ -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();
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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),
|
||||
|
@@ -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));
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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));
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user