From 0af8201023eab435d13ef9cb210844a3bf8bf46e Mon Sep 17 00:00:00 2001 From: ArthurSonzogni Date: Thu, 29 Apr 2021 00:18:58 +0200 Subject: [PATCH] Add the slider component. --- CMakeLists.txt | 4 +- examples/component/CMakeLists.txt | 3 +- examples/component/slider.cpp | 79 ++++++++++++++++++++++++++ include/ftxui/component/component.hpp | 3 + include/ftxui/component/slider.hpp | 25 +++++++++ src/ftxui/component/slider.cpp | 80 +++++++++++++++++++++++++++ 6 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 examples/component/slider.cpp create mode 100644 include/ftxui/component/slider.hpp create mode 100644 src/ftxui/component/slider.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 24214cf..3b79204 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,6 +87,7 @@ add_library(component include/ftxui/component/radiobox.hpp include/ftxui/component/receiver.hpp include/ftxui/component/screen_interactive.hpp + include/ftxui/component/slider.hpp include/ftxui/component/toggle.hpp src/ftxui/component/button.cpp src/ftxui/component/checkbox.cpp @@ -98,9 +99,10 @@ add_library(component src/ftxui/component/radiobox.cpp src/ftxui/component/radiobox.cpp src/ftxui/component/screen_interactive.cpp - src/ftxui/component/toggle.cpp + src/ftxui/component/slider.cpp src/ftxui/component/terminal_input_parser.cpp src/ftxui/component/terminal_input_parser.hpp + src/ftxui/component/toggle.cpp ) add_library(ftxui::screen ALIAS screen) diff --git a/examples/component/CMakeLists.txt b/examples/component/CMakeLists.txt index d20f899..07dc0b3 100644 --- a/examples/component/CMakeLists.txt +++ b/examples/component/CMakeLists.txt @@ -13,9 +13,10 @@ example(input) example(menu) example(menu2) example(menu_style) +example(modal_dialog) example(radiobox) example(radiobox_in_frame) +example(slider) example(tab_horizontal) example(tab_vertical) example(toggle) -example(modal_dialog) diff --git a/examples/component/slider.cpp b/examples/component/slider.cpp new file mode 100644 index 0000000..65cb068 --- /dev/null +++ b/examples/component/slider.cpp @@ -0,0 +1,79 @@ +#include "ftxui/component/slider.hpp" +#include "ftxui/component/container.hpp" +#include "ftxui/component/screen_interactive.hpp" +#include "ftxui/component/toggle.hpp" +#include "ftxui/screen/string.hpp" + +using namespace ftxui; + +Element ColorTile(int red, int green, int blue) { + return text(L"") + | size(WIDTH, GREATER_THAN, 14) + | size(HEIGHT, GREATER_THAN, 7) + | bgcolor(Color::RGB(red, green, blue)); +} + +Element ColorString(int red, int green, int blue) { + return text(L"RGB = (" + // + std::to_wstring(red) + L"," + // + std::to_wstring(green) + L"," + // + std::to_wstring(blue) + L")" // + ); +} + +class MyComponent : public Component { + public: + MyComponent(int* red, int* green, int* blue, std::function quit) + : red_(red), green_(green), blue_(blue), quit_(quit) { + Add(&container_); + container_.Add(slider_red_.get()); + container_.Add(slider_green_.get()); + container_.Add(slider_blue_.get()); + } + + Element Render() { + return hbox({ + ColorTile(*red_, *green_, *blue_), + separator(), + vbox({ + slider_red_->Render(), + separator(), + slider_green_->Render(), + separator(), + slider_blue_->Render(), + separator(), + ColorString(*red_, *green_, *blue_), + }) | xflex, + }) | + border | size(WIDTH, LESS_THAN, 80); + } + + bool OnEvent(Event event) { + if (event == Event::Return || event == Event::Escape) + quit_(); + return Component::OnEvent(event); + } + + private: + int* red_; + int* green_; + int* blue_; + Container container_ = Container::Vertical(); + ComponentPtr slider_red_ = Slider(L"Red :", red_, 0, 255, 1); + ComponentPtr slider_green_ = Slider(L"Green:", green_, 0, 255, 1); + ComponentPtr slider_blue_ = Slider(L"Blue :", blue_, 0, 255, 1); + std::function quit_; +}; + +int main(int argc, const char* argv[]) { + auto screen = ScreenInteractive::TerminalOutput(); + int red = 128; + int green = 25; + int blue = 100; + auto component = MyComponent(&red, &green, &blue, screen.ExitLoopClosure()); + screen.Loop(&component); +} + +// 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/include/ftxui/component/component.hpp b/include/ftxui/component/component.hpp index 2b7af38..fcaf3f9 100644 --- a/include/ftxui/component/component.hpp +++ b/include/ftxui/component/component.hpp @@ -1,6 +1,7 @@ #ifndef FTXUI_COMPONENT_COMPONENT_HPP #define FTXUI_COMPONENT_COMPONENT_HPP +#include #include "ftxui/component/event.hpp" #include "ftxui/dom/elements.hpp" @@ -60,6 +61,8 @@ class Component { std::vector children_; }; +using ComponentPtr = std::unique_ptr; + } // namespace ftxui #endif /* end of include guard: FTXUI_COMPONENT_COMPONENT_HPP */ diff --git a/include/ftxui/component/slider.hpp b/include/ftxui/component/slider.hpp new file mode 100644 index 0000000..35a139d --- /dev/null +++ b/include/ftxui/component/slider.hpp @@ -0,0 +1,25 @@ +#ifndef FTXUI_COMPONENT_SLIDER_HPP +#define FTXUI_COMPONENT_SLIDER_HPP + +#include +#include "ftxui/component/component.hpp" + +namespace ftxui { +// ComponentPtr Slider(std::string label, +// float* value, +// float min = 0.f, +// float max = 100.f, +// float increment = (max - min) * 0.05f); + +ComponentPtr Slider(std::wstring label, + int* value, + int min, + int max, + int increment); +} // namespace ftxui + +#endif /* end of include guard: FTXUI_COMPONENT_SLIDER_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/slider.cpp b/src/ftxui/component/slider.cpp new file mode 100644 index 0000000..894f9ee --- /dev/null +++ b/src/ftxui/component/slider.cpp @@ -0,0 +1,80 @@ +#include "ftxui/component/slider.hpp" + +namespace ftxui { +class SliderInt : public Component { + public: + SliderInt(std::wstring label, int* value, int min, int max, int increment) + : label_(label), + value_(value), + min_(min), + max_(max), + increment_(increment) {} + + Element Render() { + auto gauge_color = + Focused() ? color(Color::GrayLight) : color(Color::GrayDark); + float percent = float(*value_ - min_) / float(max_ - min_); + return hbox({ + text(label_) | dim | vcenter, + hbox({ + text(L"["), + gauge(percent) | underlined | xflex | reflect(gauge_box_), + text(L"]"), + }) | xflex, + }) | + gauge_color | xflex | reflect(box_); + } + + bool OnEvent(Event event) final { + if (event.is_mouse()) + return OnMouseEvent(event); + + if (event == Event::ArrowLeft || event == Event::Character('h')) { + *value_ -= increment_; + *value_ = std::max(*value_, min_); + return true; + } + + if (event == Event::ArrowRight || event == Event::Character('l')) { + *value_ += increment_; + *value_ = std::min(*value_, max_); + return true; + } + + return Component::OnEvent(event); + } + + bool OnMouseEvent(Event event) { + if (!box_.Contain(event.mouse().x, event.mouse().y)) + return false; + TakeFocus(); + if (!gauge_box_.Contain(event.mouse().x, event.mouse().y)) + return false; + if (event.mouse().button == Mouse::Left && + event.mouse().motion == Mouse::Pressed) { + *value_ = min_ + (event.mouse().x - gauge_box_.x_min) * (max_ - min_) / + (gauge_box_.x_max - gauge_box_.x_min); + } + return true; + } + + private: + std::wstring label_; + int* value_; + int min_; + int max_; + int increment_ = 1; + Box box_; + Box gauge_box_; +}; + +ComponentPtr Slider(std::wstring label, + int* value, + int min, + int max, + int increment) { + return std::make_unique(std::move(label), value, min, max, + increment); +} + +} // namespace ftxui