From bead2134d6eb29bb719ac7fd0d6a73244c0eb5aa Mon Sep 17 00:00:00 2001 From: ArthurSonzogni Date: Sat, 10 Jul 2021 13:07:01 +0200 Subject: [PATCH] Remove radiobox.hpp --- CMakeLists.txt | 1 - include/ftxui/component/component_options.hpp | 2 + include/ftxui/component/radiobox.hpp | 52 ----- src/ftxui/component/radiobox.cpp | 213 ++++++++++-------- src/ftxui/component/radiobox_test.cpp | 4 +- 5 files changed, 119 insertions(+), 153 deletions(-) delete mode 100644 include/ftxui/component/radiobox.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b6e5d8b..00d70fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,7 +78,6 @@ add_library(component STATIC include/ftxui/component/component_base.hpp include/ftxui/component/event.hpp include/ftxui/component/mouse.hpp - include/ftxui/component/radiobox.hpp include/ftxui/component/receiver.hpp include/ftxui/component/screen_interactive.hpp include/ftxui/component/toggle.hpp diff --git a/include/ftxui/component/component_options.hpp b/include/ftxui/component/component_options.hpp index 61cdcb6..c88fbbc 100644 --- a/include/ftxui/component/component_options.hpp +++ b/include/ftxui/component/component_options.hpp @@ -58,6 +58,8 @@ struct RadioboxOption { /// Called when the selected entry changes. std::function on_change = []() {}; + + Ref focused_entry = 0; }; /// @brief Option for the Toggle component. diff --git a/include/ftxui/component/radiobox.hpp b/include/ftxui/component/radiobox.hpp deleted file mode 100644 index 181fc91..0000000 --- a/include/ftxui/component/radiobox.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef FTXUI_COMPONENT_RADIOBOX_HPP -#define FTXUI_COMPONENT_RADIOBOX_HPP - -#include // for function -#include // for wstring, allocator -#include // for vector - -#include "ftxui/component/component.hpp" // for Component -#include "ftxui/component/component_base.hpp" // for ComponentBase -#include "ftxui/dom/elements.hpp" // for Element, Decorator, inverted, nothing -#include "ftxui/screen/box.hpp" // for Box - -namespace ftxui { -struct Event; - -/// @brief A list of selectable element. One and only one can be selected at -/// the same time. -/// @ingroup component -class RadioboxBase : public ComponentBase { - public: - // Access this interface from a Component - static RadioboxBase* From(Component component); - - // Constructor. - RadioboxBase(const std::vector* entries, - int* selected, - Ref option = {}); - ~RadioboxBase() override = default; - - int focused = 0; - - // Component implementation. - Element Render() override; - bool OnEvent(Event) override; - - private: - const std::vector* const entries_; - int* const selected_; - - bool OnMouseEvent(Event event); - int cursor_position = 0; - std::vector boxes_; - Ref option_; -}; - -} // namespace ftxui - -#endif /* end of include guard: FTXUI_COMPONENT_RADIOBOX_HPP */ - -// Copyright 2020 Arthur Sonzogni. All rights reserved. -// Use of this source code is governed by the MIT license that can be found in -// the LICENSE file. diff --git a/src/ftxui/component/radiobox.cpp b/src/ftxui/component/radiobox.cpp index 81a3f84..b928d12 100644 --- a/src/ftxui/component/radiobox.cpp +++ b/src/ftxui/component/radiobox.cpp @@ -5,13 +5,127 @@ #include // for move #include "ftxui/component/captured_mouse.hpp" // for CapturedMouse +#include "ftxui/component/component.hpp" // for Component #include "ftxui/component/event.hpp" // for Event, Event::ArrowDown, Event::ArrowUp, Event::Return, Event::Tab, Event::TabReverse #include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed -#include "ftxui/component/radiobox.hpp" #include "ftxui/component/screen_interactive.hpp" // for Component namespace ftxui { +namespace { +/// @brief A list of selectable element. One and only one can be selected at +/// the same time. +/// @ingroup component +class RadioboxBase : public ComponentBase { + public: + RadioboxBase(const std::vector* entries, + int* selected, + Ref option) + : entries_(entries), selected_(selected), option_(std::move(option)) { +#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK) + // Microsoft terminal do not use fonts able to render properly the default + // radiobox glyph. + if (option_->checked == L"◉ ") + option_->checked = L"(*)"; + if (option_->unchecked == L"○ ") + option_->unchecked = L"( )"; +#endif + } + ~RadioboxBase() override = default; + + private: + + Element Render() override { + std::vector elements; + bool is_focused = Focused(); + boxes_.resize(entries_->size()); + for (size_t i = 0; i < entries_->size(); ++i) { + auto style = (focused_entry() == int(i) && is_focused) + ? option_->style_focused + : option_->style_unfocused; + auto focus_management = (focused_entry() != int(i)) ? nothing + : is_focused ? focus + : select; + + const std::wstring& symbol = *selected_ == int(i) + ? option_->style_checked + : option_->style_unchecked; + elements.push_back(hbox(text(symbol), text(entries_->at(i)) | style) | + focus_management | reflect(boxes_[i])); + } + return vbox(std::move(elements)); + } + + bool OnEvent(Event event) override { + if (!CaptureMouse(event)) + return false; + if (event.is_mouse()) + return OnMouseEvent(event); + + if (!Focused()) + return false; + + int new_focused = focused_entry(); + if (event == Event::ArrowUp || event == Event::Character('k')) + 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_entry() != new_focused) { + focused_entry() = new_focused; + return true; + } + + if (event == Event::Character(' ') || event == Event::Return) { + *selected_ = focused_entry(); + option_->on_change(); + } + + return false; + } + + bool OnMouseEvent(Event event) { + if (!CaptureMouse(event)) + return false; + for (int i = 0; i < int(boxes_.size()); ++i) { + if (!boxes_[i].Contain(event.mouse().x, event.mouse().y)) + continue; + + focused_entry() = i; + TakeFocus(); + + if (event.mouse().button == Mouse::Left && + event.mouse().motion == Mouse::Pressed) { + cursor_position = i; + TakeFocus(); + if (*selected_ != i) { + *selected_ = i; + option_->on_change(); + } + return true; + } + } + return false; + } + + int& focused_entry() { return option_->focused_entry(); } + + const std::vector* const entries_; + int* const selected_; + + int cursor_position = 0; + std::vector boxes_; + Ref option_; +}; + +} // namespace + /// @brief A list of element, where only one can be selected. /// @param entries The list of entries in the list. /// @param selected The index of the currently selected element. @@ -45,103 +159,6 @@ Component Radiobox(const std::vector* entries, return Make(entries, selected, std::move(option)); } -// static -RadioboxBase* RadioboxBase::From(Component component) { - return static_cast(component.get()); -} - -RadioboxBase::RadioboxBase(const std::vector* entries, - int* selected, - Ref option) - : entries_(entries), selected_(selected), option_(std::move(option)) { -#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK) - // Microsoft terminal do not use fonts able to render properly the default - // radiobox glyph. - if (option_->checked == L"◉ ") - option_->checked = L"(*)"; - if (option_->unchecked == L"○ ") - option_->unchecked = L"( )"; -#endif -} - -Element RadioboxBase::Render() { - std::vector elements; - bool is_focused = Focused(); - boxes_.resize(entries_->size()); - for (size_t i = 0; i < entries_->size(); ++i) { - auto style = (focused == int(i) && is_focused) ? option_->style_focused - : option_->style_unfocused; - auto focus_management = (focused != int(i)) ? nothing - : is_focused ? focus - : select; - - const std::wstring& symbol = *selected_ == int(i) - ? option_->style_checked - : option_->style_unchecked; - elements.push_back(hbox(text(symbol), text(entries_->at(i)) | style) | - focus_management | reflect(boxes_[i])); - } - return vbox(std::move(elements)); -} - -bool RadioboxBase::OnEvent(Event event) { - if (!CaptureMouse(event)) - return false; - if (event.is_mouse()) - return OnMouseEvent(event); - - if (!Focused()) - return false; - - int new_focused = focused; - if (event == Event::ArrowUp || event == Event::Character('k')) - 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; - } - - if (event == Event::Character(' ') || event == Event::Return) { - *selected_ = focused; - option_->on_change(); - } - - return false; -} - -bool RadioboxBase::OnMouseEvent(Event event) { - if (!CaptureMouse(event)) - return false; - for (int i = 0; i < int(boxes_.size()); ++i) { - if (!boxes_[i].Contain(event.mouse().x, event.mouse().y)) - continue; - - focused = i; - TakeFocus(); - - if (event.mouse().button == Mouse::Left && - event.mouse().motion == Mouse::Pressed) { - cursor_position = i; - TakeFocus(); - if (*selected_ != i) { - *selected_ = i; - option_->on_change(); - } - return true; - } - } - return false; -} - } // namespace ftxui // Copyright 2020 Arthur Sonzogni. All rights reserved. diff --git a/src/ftxui/component/radiobox_test.cpp b/src/ftxui/component/radiobox_test.cpp index 4e9a7fe..8900e98 100644 --- a/src/ftxui/component/radiobox_test.cpp +++ b/src/ftxui/component/radiobox_test.cpp @@ -2,10 +2,10 @@ #include // for TestPartResult, SuiteApiResolver, TestFactoryImpl #include // for __shared_ptr_access, shared_ptr +#include "ftxui/component/component.hpp" #include "ftxui/component/event.hpp" // for Event, Event::Return, Event::ArrowDown, Event::ArrowUp, Event::Tab, Event::TabReverse #include "ftxui/component/mouse.hpp" // for ftxui -#include "ftxui/component/radiobox.hpp" -#include "gtest/gtest_pred_impl.h" // for EXPECT_EQ, Test, TEST +#include "gtest/gtest_pred_impl.h" // for EXPECT_EQ, Test, TEST using namespace ftxui;