diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 9ffb08e..c733e2d 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,10 +1,8 @@ -add_subdirectory(color) -add_subdirectory(frame) -add_subdirectory(gauge) -add_subdirectory(input) -add_subdirectory(menu) -add_subdirectory(menu2) -add_subdirectory(print_key_press) -add_subdirectory(separator) -add_subdirectory(toggle) -add_subdirectory(vbox_hbox) +function(example name) + add_executable(${name} ${name}.cpp) + target_link_libraries(${name} PUBLIC ftxui) +endfunction(example) + +add_subdirectory(component) +add_subdirectory(dom) +example(print_key_press) diff --git a/examples/color/CMakeLists.txt b/examples/color/CMakeLists.txt deleted file mode 100644 index 7818355..0000000 --- a/examples/color/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_executable(color_main - main.cpp -) -target_link_libraries(color_main PRIVATE ftxui) diff --git a/examples/component/CMakeLists.txt b/examples/component/CMakeLists.txt new file mode 100644 index 0000000..b6b9615 --- /dev/null +++ b/examples/component/CMakeLists.txt @@ -0,0 +1,6 @@ +example(color) +example(gauge) +example(input) +example(menu) +example(menu2) +example(toggle) diff --git a/examples/color/main.cpp b/examples/component/color.cpp similarity index 99% rename from examples/color/main.cpp rename to examples/component/color.cpp index 337da03..5eb429c 100644 --- a/examples/color/main.cpp +++ b/examples/component/color.cpp @@ -54,7 +54,5 @@ int main(int argc, const char *argv[]) std::cout << screen.ToString(); - getchar(); - return 0; } diff --git a/examples/gauge/main.cpp b/examples/component/gauge.cpp similarity index 100% rename from examples/gauge/main.cpp rename to examples/component/gauge.cpp diff --git a/examples/input/main.cpp b/examples/component/input.cpp similarity index 94% rename from examples/input/main.cpp rename to examples/component/input.cpp index d4688c8..72ea012 100644 --- a/examples/input/main.cpp +++ b/examples/component/input.cpp @@ -9,6 +9,7 @@ using namespace ftxui::component; using namespace ftxui::dom; +using namespace ftxui; class MyComponent : ComponentVertical { public: @@ -44,7 +45,7 @@ class MyComponent : ComponentVertical { }; int main(int argc, const char* argv[]) { - ftxui::ScreenInteractive screen(60, 17); + ftxui::ScreenInteractive screen(60, 5); MyComponent component(screen.delegate()); component.on_enter = screen.ExitLoopClosure(); screen.Loop(); diff --git a/examples/menu/main.cpp b/examples/component/menu.cpp similarity index 100% rename from examples/menu/main.cpp rename to examples/component/menu.cpp diff --git a/examples/menu2/main.cpp b/examples/component/menu2.cpp similarity index 97% rename from examples/menu2/main.cpp rename to examples/component/menu2.cpp index 80accaf..f2244af 100644 --- a/examples/menu2/main.cpp +++ b/examples/component/menu2.cpp @@ -43,6 +43,7 @@ class MyComponent : ComponentHorizontal { flex( vbox( hcenter(bold(text(L"Percentage by 10%"))), + separator(), left_menu.Render() ) ), @@ -50,6 +51,7 @@ class MyComponent : ComponentHorizontal { flex( vbox( hcenter(bold(text(L"Percentage by 1%"))), + separator(), right_menu.Render() ) ), diff --git a/examples/toggle/main.cpp b/examples/component/toggle.cpp similarity index 100% rename from examples/toggle/main.cpp rename to examples/component/toggle.cpp diff --git a/examples/dom/CMakeLists.txt b/examples/dom/CMakeLists.txt new file mode 100644 index 0000000..6aeb8a5 --- /dev/null +++ b/examples/dom/CMakeLists.txt @@ -0,0 +1,3 @@ +example(frame) +example(separator) +example(vbox_hbox) diff --git a/examples/frame/main.cpp b/examples/dom/frame.cpp similarity index 100% rename from examples/frame/main.cpp rename to examples/dom/frame.cpp diff --git a/examples/separator/main.cpp b/examples/dom/separator.cpp similarity index 99% rename from examples/separator/main.cpp rename to examples/dom/separator.cpp index e3426d8..79f1f9a 100644 --- a/examples/separator/main.cpp +++ b/examples/dom/separator.cpp @@ -19,7 +19,6 @@ int main(int argc, const char *argv[]) Render(screen, document.get()); std::cout << screen.ToString(); - getchar(); return 0; diff --git a/examples/vbox_hbox/main.cpp b/examples/dom/vbox_hbox.cpp similarity index 97% rename from examples/vbox_hbox/main.cpp rename to examples/dom/vbox_hbox.cpp index f4efb41..77bdc35 100644 --- a/examples/vbox_hbox/main.cpp +++ b/examples/dom/vbox_hbox.cpp @@ -32,7 +32,5 @@ int main(int argc, const char *argv[]) std::cout << screen.ToString(); - getchar(); - return 0; } diff --git a/examples/frame/CMakeLists.txt b/examples/frame/CMakeLists.txt deleted file mode 100644 index cef99a5..0000000 --- a/examples/frame/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_executable(frame_example - main.cpp -) -target_link_libraries(frame_example PRIVATE ftxui) diff --git a/examples/gauge/CMakeLists.txt b/examples/gauge/CMakeLists.txt deleted file mode 100644 index ea0a964..0000000 --- a/examples/gauge/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_executable(gauge_example - main.cpp -) -target_link_libraries(gauge_example PRIVATE ftxui) diff --git a/examples/input/CMakeLists.txt b/examples/input/CMakeLists.txt deleted file mode 100644 index 1e37595..0000000 --- a/examples/input/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_executable(input_main - main.cpp -) -target_link_libraries(input_main PRIVATE ftxui) diff --git a/examples/menu/CMakeLists.txt b/examples/menu/CMakeLists.txt deleted file mode 100644 index 3b5e420..0000000 --- a/examples/menu/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_executable(menu_main - main.cpp -) -target_link_libraries(menu_main PRIVATE ftxui) diff --git a/examples/menu2/CMakeLists.txt b/examples/menu2/CMakeLists.txt deleted file mode 100644 index 719d9bc..0000000 --- a/examples/menu2/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_executable(menu2_main - main.cpp -) -target_link_libraries(menu2_main PRIVATE ftxui) diff --git a/examples/print_key_press/main.cpp b/examples/print_key_press.cpp similarity index 100% rename from examples/print_key_press/main.cpp rename to examples/print_key_press.cpp diff --git a/examples/print_key_press/CMakeLists.txt b/examples/print_key_press/CMakeLists.txt deleted file mode 100644 index 8245f94..0000000 --- a/examples/print_key_press/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_executable(print_key_press - main.cpp -) -target_link_libraries(print_key_press PRIVATE ftxui) diff --git a/examples/separator/CMakeLists.txt b/examples/separator/CMakeLists.txt deleted file mode 100644 index f292211..0000000 --- a/examples/separator/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_executable(separator_example - main.cpp -) -target_link_libraries(separator_example PRIVATE ftxui) diff --git a/examples/toggle/CMakeLists.txt b/examples/toggle/CMakeLists.txt deleted file mode 100644 index a1784e2..0000000 --- a/examples/toggle/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_executable(toogle_main - main.cpp -) -target_link_libraries(toogle_main PRIVATE ftxui) diff --git a/examples/vbox_hbox/CMakeLists.txt b/examples/vbox_hbox/CMakeLists.txt deleted file mode 100644 index 4db6ff6..0000000 --- a/examples/vbox_hbox/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_executable(vbox_hbox_example - main.cpp -) -target_link_libraries(vbox_hbox_example PRIVATE ftxui) diff --git a/ftxui/include/ftxui/component/component_direction.hpp b/ftxui/include/ftxui/component/component_direction.hpp index 55b99ef..1b7c6a2 100644 --- a/ftxui/include/ftxui/component/component_direction.hpp +++ b/ftxui/include/ftxui/component/component_direction.hpp @@ -7,6 +7,7 @@ namespace ftxui { namespace component { // A component where focus and events are automatically handled for you. +// Please use ComponentVertical or ComponentHorizontal. class ComponentDirection : public Component { public: ComponentDirection(Delegate* delegate); diff --git a/ftxui/include/ftxui/dom/elements.hpp b/ftxui/include/ftxui/dom/elements.hpp index c24a1f6..c2a7c73 100644 --- a/ftxui/include/ftxui/dom/elements.hpp +++ b/ftxui/include/ftxui/dom/elements.hpp @@ -15,6 +15,7 @@ using Children = std::vector; Element vbox(Children); Element hbox(Children); Element flex(); +Element flex(Element); // --- Widget -- Element text(std::wstring text); @@ -23,7 +24,7 @@ Element gauge(float ratio); Element frame(Child); Element frame(Child title, Child content); -// -- Decorator (Style) --- +// -- Style --- Element bold(Element); Element dim(Element); Element inverted(Element); @@ -32,11 +33,10 @@ Element blink(Element); Element color(Color, Element); Element bgcolor(Color, Element); -// --- Decorator --- +// --- Util --- Element hcenter(Element); Element vcenter(Element); Element center(Element); -Element flex(Element); // --- Util --- Element nothing(Element element); diff --git a/ftxui/include/ftxui/dom/node.hpp b/ftxui/include/ftxui/dom/node.hpp index 6a5f7be..7f92be7 100644 --- a/ftxui/include/ftxui/dom/node.hpp +++ b/ftxui/include/ftxui/dom/node.hpp @@ -17,14 +17,14 @@ class Node { Node(std::vector> children); virtual ~Node(); - // Step 1: Direction parent <= children. - // Compute layout requirement. Tell parent what dimensions this + // Step 1: Compute layout requirement. Tell parent what dimensions this // element wants to be. + // Propagated from Children to Parents. virtual void ComputeRequirement(); Requirement requirement() { return requirement_; } - // Step 2: Direction parent => children. - // Assign this element its final dimensions. + // Step 2: Assign this element its final dimensions. + // Propagated from Parents to Children. virtual void SetBox(Box box); // Step 3: Draw this element. diff --git a/ftxui/src/ftxui/component/input.cpp b/ftxui/src/ftxui/component/input.cpp index 77e53d6..3da91e4 100644 --- a/ftxui/src/ftxui/component/input.cpp +++ b/ftxui/src/ftxui/component/input.cpp @@ -24,6 +24,9 @@ dom::Element Input::Render() { if (!is_focused) return flex(text(content)); + std::wstring sub_content = content; + size_t sub_cursor_position = cursor_position; + std::wstring part_before_cursor = content.substr(0,cursor_position); std::wstring part_at_cursor = cursor_position < (int)content.size() ? content.substr(cursor_position, 1) diff --git a/ftxui/src/ftxui/dom/blink.cpp b/ftxui/src/ftxui/dom/blink.cpp new file mode 100644 index 0000000..a24f20a --- /dev/null +++ b/ftxui/src/ftxui/dom/blink.cpp @@ -0,0 +1,27 @@ +#include "ftxui/dom/node_decorator.hpp" +#include "ftxui/dom/elements.hpp" + +namespace ftxui { +namespace dom { + +class Blink : public NodeDecorator { + public: + Blink(Children children) : NodeDecorator(std::move(children)) {} + ~Blink() override {} + + 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).blink = true; + } + } + } +}; + +std::unique_ptr blink(Child child) { + return std::make_unique(unpack(std::move(child))); +} + +}; // namespace dom +}; // namespace ftxui diff --git a/ftxui/src/ftxui/dom/util.cpp b/ftxui/src/ftxui/dom/util.cpp new file mode 100644 index 0000000..b4dc76f --- /dev/null +++ b/ftxui/src/ftxui/dom/util.cpp @@ -0,0 +1,11 @@ +#include "ftxui/dom/elements.hpp" + +namespace ftxui { +namespace dom { + +Element nothing(Element element) { + return std::move(element); +} + +}; // namespace dom +}; // namespace ftxui diff --git a/ftxui/src/ftxui/screen.cpp b/ftxui/src/ftxui/screen.cpp index 79cc866..c2e0516 100644 --- a/ftxui/src/ftxui/screen.cpp +++ b/ftxui/src/ftxui/screen.cpp @@ -1,5 +1,5 @@ -#include "ftxui/dom/node.hpp" #include "ftxui/screen.hpp" +#include "ftxui/dom/node.hpp" #include "ftxui/terminal.hpp" #include "ftxui/util/string.hpp" @@ -10,6 +10,35 @@ namespace ftxui { Screen::Screen(size_t dimx, size_t dimy) : dimx_(dimx), dimy_(dimy), pixels_(dimy, std::vector(dimx)) {} +void UpdatePixelStyle(std::wstringstream& ss, Pixel& previous, Pixel& next) { + if (next.bold != previous.bold) + ss << (next.bold ? L"\e[1m" : L"\e[0m"); + + if (next.inverted != previous.inverted) + ss << (next.inverted ? L"\e[7m" : L"\e[27m"); + + if (next.underlined != previous.underlined) + ss << (next.underlined ? L"\e[4m" : L"\e[24m"); + + if (next.dim != previous.dim) + ss << (next.dim ? L"\e[2m" : L"\e[22m"); + + if (next.blink != previous.blink) + ss << (next.blink ? L"\e[5m" : L"\e[25m"); + + if (next.foreground_color != previous.foreground_color) { + ss << L"\e[" + to_wstring(std::to_string((uint8_t)next.foreground_color)) + + L"m"; + } + if (next.background_color != previous.background_color) { + ss << L"\e[" + + to_wstring(std::to_string(10 + (uint8_t)next.background_color)) + + L"m"; + } + + previous = next; +} + std::string Screen::ToString() { std::wstringstream ss; @@ -17,57 +46,13 @@ std::string Screen::ToString() { for (size_t y = 0; y < dimy_; ++y) { for (size_t x = 0; x < dimx_; ++x) { - if (pixels_[y][x].bold != previous_pixel.bold) { - if (pixels_[y][x].bold) { - ss << L"\e[1m"; - } else { - ss << L"\e[0m"; - } - } - if (pixels_[y][x].inverted != previous_pixel.inverted) { - if (pixels_[y][x].inverted) { - ss << L"\e[7m"; - } else { - ss << L"\e[27m"; - } - } - if (pixels_[y][x].underlined != previous_pixel.underlined) { - if (pixels_[y][x].underlined) { - ss << L"\e[4m"; - } else { - ss << L"\e[24m"; - } - } - if (pixels_[y][x].dim != previous_pixel.dim) { - if (pixels_[y][x].dim) { - ss << L"\e[2m"; - } else { - ss << L"\e[22m"; - } - } - if (pixels_[y][x].blink != previous_pixel.blink) { - if (pixels_[y][x].blink) { - ss << L"\e[5m"; - } else { - ss << L"\e[25m"; - } - } - 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"; - } + UpdatePixelStyle(ss, previous_pixel, pixels_[y][x]); ss << pixels_[y][x].character; - previous_pixel = pixels_[y][x]; } if (y + 1 < dimy_) ss << '\n'; } + return to_string(ss.str()); } diff --git a/ftxui/src/ftxui/screen_interactive.cpp b/ftxui/src/ftxui/screen_interactive.cpp index 7e157e3..0ffd1fd 100644 --- a/ftxui/src/ftxui/screen_interactive.cpp +++ b/ftxui/src/ftxui/screen_interactive.cpp @@ -11,6 +11,7 @@ namespace ftxui { namespace { constexpr int ESC = 27; constexpr int WAT = 195; + constexpr int WAT2 = 194; constexpr int WATWAIT = 91; Event GetEvent() { @@ -32,6 +33,11 @@ namespace { return Event{v1, v2}; } + if (v1 == WAT2) { + int v2 = getchar(); + return Event{v1, v2}; + } + return Event{v1}; }; }; diff --git a/tutorial.md b/tutorial.md index f392094..955c6ba 100644 --- a/tutorial.md +++ b/tutorial.md @@ -25,6 +25,7 @@ It declares the following set of elements: Element vbox(Children); Element hbox(Children); Element flex(); +Element flex(Element); // --- Widget -- Element text(std::wstring text); @@ -33,24 +34,28 @@ Element gauge(float ratio); Element frame(Child); Element frame(Child title, Child content); -// -- Decorator (Style) --- +// -- Style --- Element bold(Element); Element dim(Element); Element inverted(Element); Element underlined(Element); -Element color(Color,Element); -Element bgcolor(Element); +Element blink(Element); +Element color(Color, Element); +Element bgcolor(Color, Element); -// --- Decorator --- +// --- Util --- Element hcenter(Element); Element vcenter(Element); Element center(Element); -Element flex(Element); + +// --- Util --- +Element nothing(Element element); ~~~ ### Style A terminal console can usually display colored text and colored background. -The text can also have different effects: bold, dim, underlined, inverted. +The text can also have different effects: bold, dim, underlined, inverted, +blink. ~~~cpp Element bold(Element); @@ -164,5 +169,8 @@ frame(gauge(0.5)) ## Components. ### Input + TODO(arthursonzogni): Add Video ### Menu + TODO(arthursonzogni): Add Video ### Toggle. + TODO(arthursonzogni): Add video