GitHub - ArthurSonzogni/FTXUI: :computer: C++ Functional Terminal User Interface. :heart:
cpp
#include <stdlib.h> // for EXIT_SUCCESS
#include <ftxui/dom/elements.hpp> // for text, operator|, vbox, border, Element, Fit, hbox
#include <ftxui/screen/screen.hpp> // for Full, Screen
#include <memory> // for allocator
#include <chrono> // for operator""s, chrono_literals
#include <thread> // for sleep_for
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/color.hpp" // for ftxui
#include "ftxui/dom/canvas.hpp" // for Canvas
#include <ftxui/dom/table.hpp> // for Table, TableSelection
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Button, Horizontal, Renderer
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for separator, gauge, text, Element, operator|, vbox, border
using namespace ftxui;
ButtonOption Style() {
auto option = ButtonOption::Animated();
option.transform = [](const EntryState& s) {
auto element = text(s.label);
if (s.focused) {
element |= bold;
}
return element | center | borderEmpty | flex;
};
return option;
}
class Graph {
public:
std::vector<int> operator()(int width, int height) const {
std::vector<int> output(width);
for (int i = 0; i < width; ++i) {
float v = 0;
v += 0.1f * sin((i + shift) * 0.1f); // NOLINT
v += 0.2f * sin((i + shift + 10) * 0.15f); // NOLINT
v += 0.1f * sin((i + shift) * 0.03f); // NOLINT
v *= height; // NOLINT
v += 0.5f * height; // NOLINT
output[i] = static_cast<int>(v);
}
return output;
}
int shift = 0;
};
auto testBorder() {
using namespace ftxui;
auto make_boxed = [] {
return vbox({
text("borderLight") | borderStyled(LIGHT, Color::Red),
text("borderDashed") | borderStyled(DASHED, Color::Green),
text("borderHeavy") | borderStyled(HEAVY, Color::Blue),
text("borderDouble") | borderStyled(DOUBLE, Color::Yellow),
text("borderRounded") | borderStyled(ROUNDED, Color::Cyan),
text("borderLight") | borderLight,
});
};
auto make_box = [](int dimx, int dimy) {
std::string title = std::to_string(dimx) + "x" + std::to_string(dimy);
return window(text(title) | hcenter | bold,
text("content") | hcenter | dim) |
size(WIDTH, EQUAL, dimx) | size(HEIGHT, EQUAL, dimy);
};
auto style = size(WIDTH, GREATER_THAN, 20) | border |
size(HEIGHT, GREATER_THAN, 30) | size(WIDTH, LESS_THAN, 50);
Graph my_graph;
return
hbox({
vbox({
text("Line 1"),
filler(),
text("Line 2"),
text("Line 3"),
}) | border,
make_boxed() | color(Color::Red) | border,
separatorDashed() | color(Color::Red),
dbox({
vbox({
text("line_1"),
text("line_2"),
text("strikethrough") | strikethrough,
text("inverted") | inverted,
text("hyperlink") | hyperlink("https://www.google.com"),
}) | border,
text("overlay") | border | center,
}),
graph(std::ref(my_graph)) | color(Color::YellowLight) | bgcolor(LinearGradient()
.Angle(45)
.Stop(Color::DeepPink1)
.Stop(Color::DeepSkyBlue1)),
hflow({
make_box(7, 7),
make_box(7, 5),
}) | style,
hflow(
paragraph(" Here is a text "), text("underlined ") | underlined,
paragraph(" Here is a text "), text("bold ") | bold,
paragraph(" Here is a text "), text("dim ") | dim,
paragraph(" Here is a text "), text("red ") | color(Color::Red),
paragraph(" A spinner "), spinner(6, 5 / 10)) | border,
}) | flex;
}
auto testTable() {
using namespace ftxui;
auto table = Table({
{"Version", "Marketing name", "Release date", "API level", "Runtime"},
{"2.3", "Gingerbread", "February 9 2011", "10", "Dalvik 1.4.0"},
{"4.0", "Ice Cream Sandwich", "October 19 2011", "15", "Dalvik"},
{"4.1", "Jelly Bean", "July 9 2012", "16", "Dalvik"},
{"4.2", "Jelly Bean", "November 13 2012", "17", "Dalvik"},
{"4.3", "Jelly Bean", "July 24 2013", "18", "Dalvik"},
{"4.4", "KitKat", "October 31 2013", "19", "Dalvik and ART"},
{"5.0", "Lollipop", "November 3 2014", "21", "ART"},
{"5.1", "Lollipop", "March 9 2015", "22", "ART"},
{"6.0", "Marshmallow", "October 5 2015", "23", "ART"},
{"7.0", "Nougat", "August 22 2016", "24", "ART"},
{"7.1", "Nougat", "October 4 2016", "25", "ART"},
{"8.0", "Oreo", "August 21 2017", "26", "ART"},
{"8.1", "Oreo", "December 5 2017", "27", "ART"},
{"9", "Pie", "August 6 2018", "28", "ART"},
{"10", "10", "September 3 2019", "29", "ART"},
{"11", "11", "September 8 2020", "30", "ART"},
});
table.SelectAll().Border(LIGHT);
// Add border around the first column.
table.SelectColumn(0).Border(LIGHT);
// Make first row bold with a double border.
table.SelectRow(0).Decorate(bold);
table.SelectRow(0).SeparatorVertical(LIGHT);
table.SelectRow(0).Border(DOUBLE);
// Align right the "Release date" column.
table.SelectColumn(2).DecorateCells(align_right);
// Select row from the second to the last.
auto content = table.SelectRows(1, -1);
// Alternate in between 3 colors.
content.DecorateCellsAlternateRow(color(Color::Blue), 3, 0);
content.DecorateCellsAlternateRow(color(Color::Cyan), 3, 1);
content.DecorateCellsAlternateRow(color(Color::White), 3, 2);
return table.Render();
}
auto testCanvas(ftxui::Canvas& c) {
using namespace ftxui;
c.DrawText(0, 0, "This is a canvas", [](Pixel& p) {
p.foreground_color = Color::Red;
p.underlined = true;
});
// Triangle:
c.DrawPointLine(10, 10, 80, 10, Color::Red);
c.DrawPointLine(80, 10, 80, 40, Color::Blue);
c.DrawPointLine(80, 40, 10, 10, Color::Green);
// Circle, not filled and filled:
c.DrawPointCircle(30, 50, 20);
c.DrawPointCircleFilled(40, 40, 10);
// Plot a function:
std::vector<int> ys(100);
for (int x = 0; x < 100; x++)
ys[x] = int(80 + 20 * cos(x * 0.2));
for (int x = 0; x < 99; x++)
c.DrawPointLine(x, ys[x], x + 1, ys[x + 1], Color::Red);
return canvas(&c) | border;
}
void testDom() {
using namespace ftxui;
//auto c = Canvas(100, 100);
//auto document = testCanvas(c);
auto document = testBorder();
//auto document = testTable();
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
Render(screen, document);
screen.Print();
getchar();
}
int test() {
int value = 50;
auto style = ButtonOption::Animated(Color::Default, Color::GrayDark,
Color::Default, Color::White);
// clang-format off
auto btn_dec_01 = Button("-1", [&] { value += 1; }, style);
auto btn_inc_01 = Button("+1", [&] { value -= 1; }, ButtonOption::Animated());
auto btn_dec_10 = Button("-10", [&] { value -= 10; }, Style());
auto btn_inc_10 = Button("+10", [&] { value += 10; }, Style());
auto input = Input("1", "placeholder " + std::to_string(1));
// clang-format on
// The tree of components. This defines how to navigate using the keyboard.
// The selected `row` is shared to get a grid layout.
int row = 0;
auto container = Container::Vertical({});
auto buttons = Container::Vertical({
Container::Horizontal({btn_dec_01, btn_inc_01}, &row) | flex,
Container::Horizontal({btn_dec_10, btn_inc_10}, &row) | flex,
});
//container.Add(input);
//container.Add(Checkbox("Checkbox" + std::to_string(1)));
// Modify the way to render them on screen:
auto component = Renderer(buttons, [&] {
return vbox({
text("value = " + std::to_string(value)),
separator(),
buttons->Render() | flex,
}) |
flex | border;
});
auto screen = ScreenInteractive::FitComponent();
screen.Loop(component);
return EXIT_SUCCESS;
}