diff --git a/include/ftxui/component/event.hpp b/include/ftxui/component/event.hpp index ec06272e..3bb00a76 100644 --- a/include/ftxui/component/event.hpp +++ b/include/ftxui/component/event.hpp @@ -33,6 +33,8 @@ struct Event { static Event Delete; static Event Return; static Event Escape; + static Event Tab; + static Event TabReverse; static Event F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12; // --- Custom --- diff --git a/src/ftxui/component/container.cpp b/src/ftxui/component/container.cpp index 4cbaabfe..dbbcd49d 100644 --- a/src/ftxui/component/container.cpp +++ b/src/ftxui/component/container.cpp @@ -44,45 +44,33 @@ Component* Container::ActiveChild() { } bool Container::VerticalEvent(Event event) { - selected_ %= children_.size(); - // Left pressed ? - if (event == Event::ArrowUp || event == Event::Character('k')) { - if (selected_ != 0) { - selected_--; - return true; - } - } + int old_selected = selected_; + if (event == Event::ArrowUp || event == Event::Character('k')) + selected_--; + if (event == Event::ArrowDown || event == Event::Character('j')) + selected_++; + if (event == Event::Tab && children_.size()) + selected_ = (selected_ + 1) % children_.size(); + if (event == Event::TabReverse && children_.size()) + selected_ = (selected_ + children_.size() - 1) % children_.size(); - // Left pressed ? - if (event == Event::ArrowDown || event == Event::Character('j')) { - if (selected_ != int(children_.size()) - 1) { - selected_++; - return true; - } - } - - return false; + selected_ = std::max(0, std::min(int(children_.size()) - 1, selected_)); + return old_selected != selected_; } bool Container::HorizontalEvent(Event event) { - selected_ %= children_.size(); - // Left pressed ? - if (event == Event::ArrowLeft || event == Event::Character('h')) { - if (selected_ != 0) { - selected_--; - return true; - } - } + int old_selected = selected_; + if (event == Event::ArrowLeft || event == Event::Character('h')) + selected_--; + if (event == Event::ArrowRight || event == Event::Character('l')) + selected_++; + if (event == Event::Tab && children_.size()) + selected_ = (selected_ + 1) % children_.size(); + if (event == Event::TabReverse && children_.size()) + selected_ = (selected_ + children_.size() - 1) % children_.size(); - // Left pressed ? - if (event == Event::ArrowRight || event == Event::Character('l')) { - if (selected_ != int(children_.size()) - 1) { - selected_++; - return true; - } - } - - return false; + selected_ = std::max(0, std::min(int(children_.size()) - 1, selected_)); + return old_selected != selected_; } Element Container::Render() { @@ -91,7 +79,7 @@ Element Container::Render() { Element Container::VerticalRender() { Elements elements; - for(auto& it : children_) + for (auto& it : children_) elements.push_back(it->Render()); if (elements.size() == 0) return text(L"Empty container"); @@ -100,7 +88,7 @@ Element Container::VerticalRender() { Element Container::HorizontalRender() { Elements elements; - for(auto& it : children_) + for (auto& it : children_) elements.push_back(it->Render()); if (elements.size() == 0) return text(L"Empty container"); diff --git a/src/ftxui/component/event.cpp b/src/ftxui/component/event.cpp index b23ba8e6..0c0ff4f0 100644 --- a/src/ftxui/component/event.cpp +++ b/src/ftxui/component/event.cpp @@ -137,6 +137,8 @@ Event Event::Backspace = Event::Special({127}); Event Event::Delete = Event::Special("\e[3~"); Event Event::Escape = Event::Special("\e"); Event Event::Return = Event::Special({10}); +Event Event::Tab = Event::Special({9}); +Event Event::TabReverse = Event::Special({27, 91, 90}); Event Event::F1 = Event::Special("\e[OP"); Event Event::F2 = Event::Special("\e[OQ"); Event Event::F3 = Event::Special("\e[OR"); diff --git a/src/ftxui/component/menu.cpp b/src/ftxui/component/menu.cpp index 93bf9881..3f751b6b 100644 --- a/src/ftxui/component/menu.cpp +++ b/src/ftxui/component/menu.cpp @@ -22,15 +22,19 @@ bool Menu::OnEvent(Event event) { if (!Focused()) return false; - int new_selected = selected; + int old_selected = selected; if (event == Event::ArrowUp || event == Event::Character('k')) - new_selected--; + selected--; if (event == Event::ArrowDown || event == Event::Character('j')) - new_selected++; - new_selected = std::max(0, std::min(int(entries.size()) - 1, new_selected)); + selected++; + if (event == Event::Tab && entries.size()) + selected = (selected + 1) % entries.size(); + if (event == Event::TabReverse && entries.size()) + selected = (selected + entries.size() - 1) % entries.size(); - if (selected != new_selected) { - selected = new_selected; + selected = std::max(0, std::min(int(entries.size()) - 1, selected)); + + if (selected != old_selected) { on_change(); return true; } diff --git a/src/ftxui/component/radiobox.cpp b/src/ftxui/component/radiobox.cpp index 226c98e4..17fc2645 100644 --- a/src/ftxui/component/radiobox.cpp +++ b/src/ftxui/component/radiobox.cpp @@ -28,7 +28,13 @@ bool RadioBox::OnEvent(Event event) { new_focused--; if (event == Event::ArrowDown || event == Event::Character('j')) new_focused++; + if (event == Event::Tab && entries.size()) + new_focused = (new_focused + 1) % entries.size(); + if (event == Event::TabReverse && entries.size()) + new_focused = (new_focused + entries.size() - 1) % entries.size(); + new_focused = std::max(0, std::min(int(entries.size()) - 1, new_focused)); + if (focused != new_focused) { focused = new_focused; return true; diff --git a/src/ftxui/component/toggle.cpp b/src/ftxui/component/toggle.cpp index 88f5df33..ec3812d1 100644 --- a/src/ftxui/component/toggle.cpp +++ b/src/ftxui/component/toggle.cpp @@ -6,7 +6,7 @@ Element Toggle::Render() { bool is_focused = Focused(); Elements children; - for(size_t i = 0; i 0 && - (event == Event::ArrowLeft || event == Event::Character('h'))) { + int old_selected = selected; + if (event == Event::ArrowLeft || event == Event::Character('h')) selected--; - on_change(); - return true; - } - - if (selected < int(entries.size()) - 1 && - (event == Event::ArrowRight || event == Event::Character('l'))) { + if (event == Event::ArrowRight || event == Event::Character('l')) selected++; - on_change(); - return true; - } + if (event == Event::Tab && entries.size()) + selected = (selected + 1) % entries.size(); + if (event == Event::TabReverse && entries.size()) + selected = (selected + entries.size() - 1) % entries.size(); - return false; + selected = std::max(0, std::min(int(entries.size()) - 1, selected)); + return old_selected != selected; } } // namespace ftxui