diff --git a/examples/input/main.cpp b/examples/input/main.cpp index fa4e0be..d4688c8 100644 --- a/examples/input/main.cpp +++ b/examples/input/main.cpp @@ -17,6 +17,10 @@ class MyComponent : ComponentVertical { input_1(delegate->NewChild()), input_2(delegate->NewChild()), input_3(delegate->NewChild()) { + + input_1.placeholder = L"input1"; + input_2.placeholder = L"input2"; + input_3.placeholder = L"input3"; Focus(&input_1); } diff --git a/ftxui/CMakeLists.txt b/ftxui/CMakeLists.txt index 6991e40..b877ae9 100644 --- a/ftxui/CMakeLists.txt +++ b/ftxui/CMakeLists.txt @@ -9,6 +9,7 @@ add_library(ftxui src/ftxui/component/input.cpp src/ftxui/component/menu.cpp src/ftxui/component/toggle.cpp + src/ftxui/dom/blink.cpp src/ftxui/dom/bold.cpp src/ftxui/dom/color.cpp src/ftxui/dom/composite_decorator.cpp @@ -23,6 +24,7 @@ add_library(ftxui src/ftxui/dom/separator.cpp src/ftxui/dom/text.cpp src/ftxui/dom/underlined.cpp + src/ftxui/dom/util.cpp src/ftxui/dom/vbox.cpp src/ftxui/event.cpp src/ftxui/screen.cpp diff --git a/ftxui/include/ftxui/README.md b/ftxui/include/ftxui/README.md index 74e2a21..0ad8ad1 100644 --- a/ftxui/include/ftxui/README.md +++ b/ftxui/include/ftxui/README.md @@ -28,4 +28,4 @@ * mouse * terminal event - You can make implement your own. + Implement your own! diff --git a/ftxui/include/ftxui/component/input.hpp b/ftxui/include/ftxui/component/input.hpp index b45256d..232d88e 100644 --- a/ftxui/include/ftxui/component/input.hpp +++ b/ftxui/include/ftxui/component/input.hpp @@ -14,8 +14,8 @@ class Input : public Component { ~Input() override; // State. - std::wstring content = L"input"; - std::wstring placeholder = L"placeholder"; + std::wstring content; + std::wstring placeholder; // State update callback. std::function on_change = [](){}; diff --git a/ftxui/include/ftxui/dom/elements.hpp b/ftxui/include/ftxui/dom/elements.hpp index 37f2d30..c24a1f6 100644 --- a/ftxui/include/ftxui/dom/elements.hpp +++ b/ftxui/include/ftxui/dom/elements.hpp @@ -28,6 +28,7 @@ Element bold(Element); Element dim(Element); Element inverted(Element); Element underlined(Element); +Element blink(Element); Element color(Color, Element); Element bgcolor(Color, Element); @@ -37,6 +38,9 @@ Element vcenter(Element); Element center(Element); Element flex(Element); +// --- Util --- +Element nothing(Element element); + template Children unpack(Args... args) { Children vec; diff --git a/ftxui/include/ftxui/event.hpp b/ftxui/include/ftxui/event.hpp index 15410d7..c276c24 100644 --- a/ftxui/include/ftxui/event.hpp +++ b/ftxui/include/ftxui/event.hpp @@ -9,7 +9,7 @@ namespace ftxui { struct Event{ public: // --- Character --- - static Event Character(char); + static Event Character(int); // --- Arrow --- static Event ArrowLeft; @@ -27,7 +27,7 @@ struct Event{ bool operator==(const Event& other) { return values == other.values; } // Internal representation. - std::array values = {0, 0, 0, 0, 0}; + std::array values = {0, 0, 0, 0, 0}; }; diff --git a/ftxui/include/ftxui/screen.hpp b/ftxui/include/ftxui/screen.hpp index 3f6fcab..f01e410 100644 --- a/ftxui/include/ftxui/screen.hpp +++ b/ftxui/include/ftxui/screen.hpp @@ -14,10 +14,11 @@ namespace dom { struct Pixel { wchar_t character = U' '; + bool blink = false; bool bold = false; + bool dim = false; bool inverted = false; bool underlined = false; - bool dim = false; Color background_color = Color::Default; Color foreground_color = Color::Default; }; diff --git a/ftxui/src/ftxui/component/input.cpp b/ftxui/src/ftxui/component/input.cpp index 3ed3add..77e53d6 100644 --- a/ftxui/src/ftxui/component/input.cpp +++ b/ftxui/src/ftxui/component/input.cpp @@ -9,36 +9,69 @@ Input::~Input() {} // Component implementation. dom::Element Input::Render() { - bool is_place_ho - std::wstring& displayed_text = content.size() ? content : placeholder; - using namespace dom; - if (Focused()) - return flex(inverted(text(displayed_text))); - else - return flex(text(displayed_text)); + bool is_focused = Focused(); + + // Placeholder. + if (content.size() == 0) { + if (is_focused) + return flex(inverted(dim(text(placeholder)))); + else + return flex(dim(text(placeholder))); + } + + // Not focused. + if (!is_focused) + return flex(text(content)); + + 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) + : L" "; + std::wstring part_after_cursor = cursor_position < (int)content.size() - 1 + ? content.substr(cursor_position + 1) + : L""; + return flex(inverted(hbox( // + text(part_before_cursor), // + underlined(text(part_at_cursor)), // + text(part_after_cursor) // + ))); // } bool Input::OnEvent(Event event) { std::wstring c; - // Backspace + // Backspace. if (event == Event::Backspace) { - if (content.size() != 0) - content = content.substr(0, content.size()-1); + if (cursor_position == 0) + return false; + content.erase(cursor_position - 1, 1); + cursor_position--; return true; } - // Enter + // Enter. if (event == Event::Return) { return true; } - constexpr char ESC = char(27); - if (event.values[0] != ESC) { - content += event.values[0]; + if (event == Event::ArrowLeft && cursor_position > 0) { + cursor_position--; return true; } + if (event == Event::ArrowRight && cursor_position < (int)content.size()) { + cursor_position++; + return true; + } + + // Content + constexpr char ESC = char(27); + if (event.values[0] != ESC) { + wchar_t v = (char)event.values[0]; + content.insert(cursor_position, 1, v); + cursor_position++; + return true; + } return false; } diff --git a/ftxui/src/ftxui/event.cpp b/ftxui/src/ftxui/event.cpp index f4fe123..ed232f2 100644 --- a/ftxui/src/ftxui/event.cpp +++ b/ftxui/src/ftxui/event.cpp @@ -2,10 +2,10 @@ namespace ftxui { -constexpr char ESC = char(27); +constexpr int ESC = int(27); // --- Character --- -Event Event::Character(char c) { +Event Event::Character(int c) { return Event{c}; } @@ -16,10 +16,10 @@ Event Event::ArrowUp{ESC, '[', 'A'}; Event Event::ArrowDown{ESC, '[', 'B'}; // --- Other --- -Event Event::Backspace{char(127)}; +Event Event::Backspace{127}; Event Event::Delete{ESC, '[', '3', '~'}; Event Event::Escape{ESC}; -Event Event::Return{char(10)}; +Event Event::Return{10}; Event Event::F1{ESC, '[', 'O', 'P'}; Event Event::F2{ESC, '[', 'O', 'Q'}; diff --git a/ftxui/src/ftxui/screen.cpp b/ftxui/src/ftxui/screen.cpp index a3adeef..79cc866 100644 --- a/ftxui/src/ftxui/screen.cpp +++ b/ftxui/src/ftxui/screen.cpp @@ -45,6 +45,13 @@ std::string Screen::ToString() { 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)) + diff --git a/ftxui/src/ftxui/screen_interactive.cpp b/ftxui/src/ftxui/screen_interactive.cpp index 3b2d49d..7e157e3 100644 --- a/ftxui/src/ftxui/screen_interactive.cpp +++ b/ftxui/src/ftxui/screen_interactive.cpp @@ -9,16 +9,30 @@ namespace ftxui { namespace { - constexpr char ESC = char(27); + constexpr int ESC = 27; + constexpr int WAT = 195; + constexpr int WATWAIT = 91; Event GetEvent() { - char v1 = char(getchar()); - if (v1 != ESC) - return Event{v1}; + int v1 = getchar(); + if (v1 == ESC) { + int v2 = getchar(); + int v3 = getchar(); - char v2 = char(getchar()); - char v3 = char(getchar()); - return Event{v1,v2,v3}; + //if (v2 == WATWAIT) { + //int v4 = getchar(); + //int v5 = getchar(); + //return Event{v1, v2, v3, v4, v5}; + //} + return Event{v1, v2, v3}; + } + + if (v1 == WAT) { + int v2 = getchar(); + return Event{v1, v2}; + } + + return Event{v1}; }; };