From 1a4b2c98b2b08710baf815aea5b24cba37e6dd1f Mon Sep 17 00:00:00 2001 From: Arthur Sonzogni Date: Fri, 12 Oct 2018 09:23:37 +0200 Subject: [PATCH] Add colors. + example. --- .clang-format | 4 -- examples/CMakeLists.txt | 3 +- examples/color/CMakeLists.txt | 4 ++ examples/color/main.cpp | 60 ++++++++++++++++++++++++ ftxui/CMakeLists.txt | 10 ++-- ftxui/include/ftxui/color.hpp | 40 ++++++++++++++++ ftxui/include/ftxui/dom/elements.hpp | 3 ++ ftxui/include/ftxui/screen.hpp | 4 ++ ftxui/src/ftxui/dom/bold.cpp | 16 ++----- ftxui/src/ftxui/dom/color.cpp | 51 ++++++++++++++++++++ ftxui/src/ftxui/dom/dim.cpp | 16 ++----- ftxui/src/ftxui/dom/inverted.cpp | 16 ++----- ftxui/src/ftxui/dom/node_decorator.cpp | 17 +++++++ ftxui/src/ftxui/dom/node_decorator.hpp | 22 +++++++++ ftxui/src/ftxui/dom/underlined.cpp | 18 ++----- ftxui/src/ftxui/screen.cpp | 14 +++++- tutorials/dom_elements.md => tutorial.md | 0 17 files changed, 234 insertions(+), 64 deletions(-) create mode 100644 examples/color/CMakeLists.txt create mode 100644 examples/color/main.cpp create mode 100644 ftxui/include/ftxui/color.hpp create mode 100644 ftxui/src/ftxui/dom/color.cpp create mode 100644 ftxui/src/ftxui/dom/node_decorator.cpp create mode 100644 ftxui/src/ftxui/dom/node_decorator.hpp rename tutorials/dom_elements.md => tutorial.md (100%) diff --git a/.clang-format b/.clang-format index 6fdf1dc..0f21d0b 100644 --- a/.clang-format +++ b/.clang-format @@ -1,8 +1,4 @@ # Defines the Chromium style for automatic reformatting. # http://clang.llvm.org/docs/ClangFormatStyleOptions.html BasedOnStyle: Chromium -# This defaults to 'Auto'. Explicitly set it for a while, so that -# 'vector >' in existing files gets formatted to -# 'vector>'. ('Auto' means that clang-format will only use -# 'int>>' if the file already contains at least one such instance.) Standard: Cpp11 diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 7637c65..53382c7 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,8 +1,9 @@ +add_subdirectory(color) add_subdirectory(frame) add_subdirectory(gauge) add_subdirectory(menu) add_subdirectory(menu2) add_subdirectory(print_key_press) add_subdirectory(separator) -add_subdirectory(vbox_hbox) add_subdirectory(toggle) +add_subdirectory(vbox_hbox) diff --git a/examples/color/CMakeLists.txt b/examples/color/CMakeLists.txt new file mode 100644 index 0000000..7818355 --- /dev/null +++ b/examples/color/CMakeLists.txt @@ -0,0 +1,4 @@ +add_executable(color_main + main.cpp +) +target_link_libraries(color_main PRIVATE ftxui) diff --git a/examples/color/main.cpp b/examples/color/main.cpp new file mode 100644 index 0000000..337da03 --- /dev/null +++ b/examples/color/main.cpp @@ -0,0 +1,60 @@ +#include "ftxui/screen.hpp" +#include "ftxui/dom/elements.hpp" +#include + +int main(int argc, const char *argv[]) +{ + using namespace ftxui; + using namespace ftxui::dom; + auto document = + hbox( + vbox( + color(Color::Default, text(L"Default")), + color(Color::Black, text(L"Black")), + color(Color::GrayDark, text(L"GrayDark")), + color(Color::GrayLight, text(L"GrayLight")), + color(Color::White, text(L"White")), + color(Color::Blue, text(L"Blue")), + color(Color::BlueLight, text(L"BlueLight")), + color(Color::Cyan, text(L"Cyan")), + color(Color::CyanLight, text(L"CyanLight")), + color(Color::Green, text(L"Green")), + color(Color::GreenLight, text(L"GreenLight")), + color(Color::Magenta, text(L"Magenta")), + color(Color::MagentaLight, text(L"MagentaLight")), + color(Color::Red, text(L"Red")), + color(Color::RedLight, text(L"RedLight")), + color(Color::Yellow, text(L"Yellow")), + color(Color::YellowLight, text(L"YellowLight")) + ), + vbox( + bgcolor(Color::Default, text(L"Default")), + bgcolor(Color::Black, text(L"Black")), + bgcolor(Color::GrayDark, text(L"GrayDark")), + bgcolor(Color::GrayLight, text(L"GrayLight")), + bgcolor(Color::White, text(L"White")), + bgcolor(Color::Blue, text(L"Blue")), + bgcolor(Color::BlueLight, text(L"BlueLight")), + bgcolor(Color::Cyan, text(L"Cyan")), + bgcolor(Color::CyanLight, text(L"CyanLight")), + bgcolor(Color::Green, text(L"Green")), + bgcolor(Color::GreenLight, text(L"GreenLight")), + bgcolor(Color::Magenta, text(L"Magenta")), + bgcolor(Color::MagentaLight, text(L"MagentaLight")), + bgcolor(Color::Red, text(L"Red")), + bgcolor(Color::RedLight, text(L"RedLight")), + bgcolor(Color::Yellow, text(L"Yellow")), + bgcolor(Color::YellowLight, text(L"YellowLight")) + ), + flex() + ); + + auto screen = ftxui::Screen::TerminalOutput(document); + Render(screen, document.get()); + + std::cout << screen.ToString(); + + getchar(); + + return 0; +} diff --git a/ftxui/CMakeLists.txt b/ftxui/CMakeLists.txt index dc5d1ff..7128aac 100644 --- a/ftxui/CMakeLists.txt +++ b/ftxui/CMakeLists.txt @@ -6,21 +6,23 @@ add_library(ftxui src/ftxui/component/component_direction.cpp src/ftxui/component/component_horizontal.cpp src/ftxui/component/component_vertical.cpp - src/ftxui/component/toggle.cpp src/ftxui/component/menu.cpp + src/ftxui/component/toggle.cpp src/ftxui/dom/bold.cpp - src/ftxui/dom/dim.cpp - src/ftxui/dom/underlined.cpp - src/ftxui/dom/inverted.cpp + src/ftxui/dom/color.cpp src/ftxui/dom/composite_decorator.cpp + src/ftxui/dom/dim.cpp src/ftxui/dom/flex.cpp src/ftxui/dom/frame.cpp src/ftxui/dom/frame.cpp src/ftxui/dom/gauge.cpp src/ftxui/dom/hbox.cpp + src/ftxui/dom/inverted.cpp src/ftxui/dom/node.cpp + src/ftxui/dom/node_decorator.cpp src/ftxui/dom/separator.cpp src/ftxui/dom/text.cpp + src/ftxui/dom/underlined.cpp src/ftxui/dom/vbox.cpp src/ftxui/screen.cpp src/ftxui/screen_interactive.cpp diff --git a/ftxui/include/ftxui/color.hpp b/ftxui/include/ftxui/color.hpp new file mode 100644 index 0000000..4853c5c --- /dev/null +++ b/ftxui/include/ftxui/color.hpp @@ -0,0 +1,40 @@ +#ifndef FTXUI_COLOR_H_ +#define FTXUI_COLOR_H_ + +#include + +namespace ftxui { + +enum class Color : uint8_t { + // --- Transparent ----- + Default = 39, + + // --- Grayscale ----- + Black = 30, + GrayDark = 90, + GrayLight = 37, + White = 97, + + // --- Hue ----- + Blue = 34, + BlueLight = 94, + + Cyan = 36, + CyanLight = 96, + + Green = 32, + GreenLight = 92, + + Magenta = 35, + MagentaLight = 95, + + Red = 31, + RedLight = 91, + + Yellow = 33, + YellowLight = 93, +}; + +}; // namespace ftxui + +#endif /* end of include guard: FTXUI_COLOR_H_ */ diff --git a/ftxui/include/ftxui/dom/elements.hpp b/ftxui/include/ftxui/dom/elements.hpp index 40c2dfe..37f2d30 100644 --- a/ftxui/include/ftxui/dom/elements.hpp +++ b/ftxui/include/ftxui/dom/elements.hpp @@ -1,6 +1,7 @@ #ifndef FTXUI_DOM_ELEMENTS_HPP #define FTXUI_DOM_ELEMENTS_HPP +#include "ftxui/color.hpp" #include "ftxui/dom/node.hpp" namespace ftxui { @@ -27,6 +28,8 @@ Element bold(Element); Element dim(Element); Element inverted(Element); Element underlined(Element); +Element color(Color, Element); +Element bgcolor(Color, Element); // --- Decorator --- Element hcenter(Element); diff --git a/ftxui/include/ftxui/screen.hpp b/ftxui/include/ftxui/screen.hpp index 2782271..3f6fcab 100644 --- a/ftxui/include/ftxui/screen.hpp +++ b/ftxui/include/ftxui/screen.hpp @@ -5,6 +5,8 @@ #include #include +#include + namespace ftxui { namespace dom { class Node; @@ -16,6 +18,8 @@ struct Pixel { bool inverted = false; bool underlined = false; bool dim = false; + Color background_color = Color::Default; + Color foreground_color = Color::Default; }; class Screen { diff --git a/ftxui/src/ftxui/dom/bold.cpp b/ftxui/src/ftxui/dom/bold.cpp index cee8d97..9025020 100644 --- a/ftxui/src/ftxui/dom/bold.cpp +++ b/ftxui/src/ftxui/dom/bold.cpp @@ -1,24 +1,14 @@ -#include "ftxui/dom/node.hpp" +#include "ftxui/dom/node_decorator.hpp" #include "ftxui/dom/elements.hpp" namespace ftxui { namespace dom { -class Bold : public Node { +class Bold : public NodeDecorator { public: - Bold(Children children) : Node(std::move(children)) {} + Bold(Children children) : NodeDecorator(std::move(children)) {} ~Bold() override {} - void ComputeRequirement() override { - Node::ComputeRequirement(); - requirement_ = children[0]->requirement(); - } - - void SetBox(Box box) override { - Node::SetBox(box); - children[0]->SetBox(box); - } - void Render(Screen& screen) override { Node::Render(screen); for (int y = box_.top; y <= box_.bottom; ++y) { diff --git a/ftxui/src/ftxui/dom/color.cpp b/ftxui/src/ftxui/dom/color.cpp new file mode 100644 index 0000000..e0c44c9 --- /dev/null +++ b/ftxui/src/ftxui/dom/color.cpp @@ -0,0 +1,51 @@ +#include "ftxui/dom/node_decorator.hpp" +#include "ftxui/dom/elements.hpp" + +namespace ftxui { +namespace dom { + +class BgColor : public NodeDecorator { + public: + BgColor(Children children, Color color) + : NodeDecorator(std::move(children)), color_(color) {} + + void Render(Screen& screen) override { + NodeDecorator::Render(screen); + for (int y = box_.top; y <= box_.bottom; ++y) { + for (int x = box_.left; x <= box_.right; ++x) { + screen.PixelAt(x, y).background_color = color_; + } + } + } + + Color color_; +}; + +class FgColor : public NodeDecorator { + public: + FgColor(Children children, Color color) + : NodeDecorator(std::move(children)), color_(color) {} + ~FgColor() override {} + + void Render(Screen& screen) override { + NodeDecorator::Render(screen); + for (int y = box_.top; y <= box_.bottom; ++y) { + for (int x = box_.left; x <= box_.right; ++x) { + screen.PixelAt(x, y).foreground_color = color_; + } + } + } + + Color color_; +}; + +std::unique_ptr color(Color c, Child child) { + return std::make_unique(unpack(std::move(child)), c); +} + +std::unique_ptr bgcolor(Color c, Child child) { + return std::make_unique(unpack(std::move(child)), c); +} + +}; // namespace dom +}; // namespace ftxui diff --git a/ftxui/src/ftxui/dom/dim.cpp b/ftxui/src/ftxui/dom/dim.cpp index 08283f9..ef7cdb9 100644 --- a/ftxui/src/ftxui/dom/dim.cpp +++ b/ftxui/src/ftxui/dom/dim.cpp @@ -1,24 +1,14 @@ -#include "ftxui/dom/node.hpp" +#include "ftxui/dom/node_decorator.hpp" #include "ftxui/dom/elements.hpp" namespace ftxui { namespace dom { -class Dim : public Node { +class Dim : public NodeDecorator { public: - Dim(Children children) : Node(std::move(children)) {} + Dim(Children children) : NodeDecorator(std::move(children)) {} ~Dim() override {} - void ComputeRequirement() override { - Node::ComputeRequirement(); - requirement_ = children[0]->requirement(); - } - - void SetBox(Box box) override { - Node::SetBox(box); - children[0]->SetBox(box); - } - void Render(Screen& screen) override { Node::Render(screen); for (int y = box_.top; y <= box_.bottom; ++y) { diff --git a/ftxui/src/ftxui/dom/inverted.cpp b/ftxui/src/ftxui/dom/inverted.cpp index 2f4afdb..2e231ee 100644 --- a/ftxui/src/ftxui/dom/inverted.cpp +++ b/ftxui/src/ftxui/dom/inverted.cpp @@ -1,24 +1,14 @@ -#include "ftxui/dom/node.hpp" +#include "ftxui/dom/node_decorator.hpp" #include "ftxui/dom/elements.hpp" namespace ftxui { namespace dom { -class Inverted : public Node { +class Inverted : public NodeDecorator { public: - Inverted(Children children) : Node(std::move(children)) {} + Inverted(Children children) : NodeDecorator(std::move(children)) {} ~Inverted() override {} - void ComputeRequirement() override { - Node::ComputeRequirement(); - requirement_ = children[0]->requirement(); - } - - void SetBox(Box box) override { - Node::SetBox(box); - children[0]->SetBox(box); - } - void Render(Screen& screen) override { Node::Render(screen); for (int y = box_.top; y <= box_.bottom; ++y) { diff --git a/ftxui/src/ftxui/dom/node_decorator.cpp b/ftxui/src/ftxui/dom/node_decorator.cpp new file mode 100644 index 0000000..8ba35a9 --- /dev/null +++ b/ftxui/src/ftxui/dom/node_decorator.cpp @@ -0,0 +1,17 @@ +#include "ftxui/dom/node_decorator.hpp" + +namespace ftxui { +namespace dom { + +void NodeDecorator::ComputeRequirement() { + Node::ComputeRequirement(); + requirement_ = children[0]->requirement(); +} + +void NodeDecorator::SetBox(Box box) { + Node::SetBox(box); + children[0]->SetBox(box); +} + +}; // namespace dom +}; // namespace ftxui diff --git a/ftxui/src/ftxui/dom/node_decorator.hpp b/ftxui/src/ftxui/dom/node_decorator.hpp new file mode 100644 index 0000000..cc53ef3 --- /dev/null +++ b/ftxui/src/ftxui/dom/node_decorator.hpp @@ -0,0 +1,22 @@ +#ifndef FTXUI_DOM_NODE_DECORATOR_H_ +#define FTXUI_DOM_NODE_DECORATOR_H_ + +#include "ftxui/dom/node.hpp" +#include "ftxui/dom/elements.hpp" + +namespace ftxui { +namespace dom { + +// Helper class. +class NodeDecorator : public Node { + public: + NodeDecorator(Children children) : Node(std::move(children)) {} + ~NodeDecorator() override {} + void ComputeRequirement() override; + void SetBox(Box box) override; +}; + +}; // namespace dom +}; // namespace ftxui + +#endif /* end of include guard: FTXUI_DOM_NODE_DECORATOR_H_ */ diff --git a/ftxui/src/ftxui/dom/underlined.cpp b/ftxui/src/ftxui/dom/underlined.cpp index 07f714f..b2cd7f9 100644 --- a/ftxui/src/ftxui/dom/underlined.cpp +++ b/ftxui/src/ftxui/dom/underlined.cpp @@ -1,29 +1,19 @@ -#include "ftxui/dom/node.hpp" +#include "ftxui/dom/node_decorator.hpp" #include "ftxui/dom/elements.hpp" namespace ftxui { namespace dom { -class Underlined : public Node { +class Underlined : public NodeDecorator { public: - Underlined(Children children) : Node(std::move(children)) {} + Underlined(Children children) : NodeDecorator(std::move(children)) {} ~Underlined() override {} - void ComputeRequirement() override { - Node::ComputeRequirement(); - requirement_ = children[0]->requirement(); - } - - void SetBox(Box box) override { - Node::SetBox(box); - children[0]->SetBox(box); - } - void Render(Screen& screen) override { Node::Render(screen); for (int y = box_.top; y <= box_.bottom; ++y) { for (int x = box_.left; x <= box_.right; ++x) { - screen.PixelAt(x,y).underlined = true; + screen.PixelAt(x, y).underlined = true; } } } diff --git a/ftxui/src/ftxui/screen.cpp b/ftxui/src/ftxui/screen.cpp index cbb5497..a3adeef 100644 --- a/ftxui/src/ftxui/screen.cpp +++ b/ftxui/src/ftxui/screen.cpp @@ -12,7 +12,7 @@ Screen::Screen(size_t dimx, size_t dimy) std::string Screen::ToString() { std::wstringstream ss; - + Pixel previous_pixel; for (size_t y = 0; y < dimy_; ++y) { @@ -45,6 +45,16 @@ std::string Screen::ToString() { ss << L"\e[22m"; } } + if (pixels_[y][x].foreground_color != previous_pixel.foreground_color) { + ss << L"\e[" + to_wstring(std::to_string( + (uint8_t)pixels_[y][x].foreground_color)) + + L"m"; + } + if (pixels_[y][x].background_color != previous_pixel.background_color) { + ss << L"\e[" + to_wstring(std::to_string( + 10 + (uint8_t)pixels_[y][x].background_color)) + + L"m"; + } ss << pixels_[y][x].character; previous_pixel = pixels_[y][x]; } @@ -77,7 +87,7 @@ Screen Screen::TerminalOutput(std::unique_ptr& element) { std::string Screen::ResetPosition() { std::stringstream ss; - for(size_t y = 1; y