diff --git a/include/ftxui/component/component_options.hpp b/include/ftxui/component/component_options.hpp index 4aa50d5..b9718c0 100644 --- a/include/ftxui/component/component_options.hpp +++ b/include/ftxui/component/component_options.hpp @@ -222,20 +222,7 @@ struct ResizableSplitOption { template struct SliderOption { Ref value; - ConstRef min = T(0); - ConstRef max = T(100); - ConstRef increment = (max() - min()) / 20; - Direction direction = Direction::Right; - Color color_active = Color::White; - Color color_inactive = Color::GrayDark; -}; - -// @brief Option for the `SliderWithCallback` component. -// @ingroup component -template -struct SliderWithCallbackOption { - std::function callback; - Ref value; + std::function callback = nullptr; ConstRef min = T(0); ConstRef max = T(100); ConstRef increment = (max() - min()) / 20; diff --git a/src/ftxui/component/slider.cpp b/src/ftxui/component/slider.cpp index 9a2052f..15c99e8 100644 --- a/src/ftxui/component/slider.cpp +++ b/src/ftxui/component/slider.cpp @@ -36,231 +36,8 @@ Decorator flexDirection(Direction direction) { template class SliderBase : public ComponentBase { - public: - explicit SliderBase(SliderOption options) - : value_(options.value), - min_(options.min), - max_(options.max), - increment_(options.increment), - options_(options) {} - - Element Render() override { - auto gauge_color = Focused() ? color(options_.color_active) - : color(options_.color_inactive); - const float percent = float(value_() - min_()) / float(max_() - min_()); - return gaugeDirection(percent, options_.direction) | - flexDirection(options_.direction) | reflect(gauge_box_) | - gauge_color; - } - - void OnLeft() { - switch (options_.direction) { - case Direction::Right: - value_() -= increment_(); - break; - case Direction::Left: - value_() += increment_(); - break; - case Direction::Up: - case Direction::Down: - break; - } - } - - void OnRight() { - switch (options_.direction) { - case Direction::Right: - value_() += increment_(); - break; - case Direction::Left: - value_() -= increment_(); - break; - case Direction::Up: - case Direction::Down: - break; - } - } - - void OnUp() { - switch (options_.direction) { - case Direction::Up: - value_() -= increment_(); - break; - case Direction::Down: - value_() += increment_(); - break; - case Direction::Left: - case Direction::Right: - break; - } - } - - void OnDown() { - switch (options_.direction) { - case Direction::Down: - value_() -= increment_(); - break; - case Direction::Up: - value_() += increment_(); - break; - case Direction::Left: - case Direction::Right: - break; - } - } - - bool OnEvent(Event event) final { - if (event.is_mouse()) { - return OnMouseEvent(event); - } - - T old_value = value_(); - if (event == Event::ArrowLeft || event == Event::Character('h')) { - OnLeft(); - } - if (event == Event::ArrowRight || event == Event::Character('l')) { - OnRight(); - } - if (event == Event::ArrowUp || event == Event::Character('k')) { - OnDown(); - } - if (event == Event::ArrowDown || event == Event::Character('j')) { - OnUp(); - } - - value_() = util::clamp(value_(), min_(), max_()); - if (old_value != value_()) { - return true; - } - - return ComponentBase::OnEvent(event); - } - - bool OnMouseEvent(Event event) { - if (captured_mouse_) { - if (event.mouse().motion == Mouse::Released) { - captured_mouse_ = nullptr; - return true; - } - - switch (options_.direction) { - case Direction::Right: { - value_() = min_() + (event.mouse().x - gauge_box_.x_min) * - (max_() - min_()) / - (gauge_box_.x_max - gauge_box_.x_min); - break; - } - case Direction::Left: { - value_() = max_() - (event.mouse().x - gauge_box_.x_min) * - (max_() - min_()) / - (gauge_box_.x_max - gauge_box_.x_min); - break; - } - case Direction::Down: { - value_() = min_() + (event.mouse().y - gauge_box_.y_min) * - (max_() - min_()) / - (gauge_box_.y_max - gauge_box_.y_min); - break; - } - case Direction::Up: { - value_() = max_() - (event.mouse().y - gauge_box_.y_min) * - (max_() - min_()) / - (gauge_box_.y_max - gauge_box_.y_min); - break; - } - } - value_() = std::max(min_(), std::min(max_(), value_())); - return true; - } - - if (event.mouse().button != Mouse::Left) { - return false; - } - if (event.mouse().motion != Mouse::Pressed) { - return false; - } - - if (!gauge_box_.Contain(event.mouse().x, event.mouse().y)) { - return false; - } - - captured_mouse_ = CaptureMouse(event); - - if (captured_mouse_) { - TakeFocus(); - return true; - } - - return false; - } - - bool Focusable() const final { return true; } - - private: - Ref value_; - ConstRef min_; - ConstRef max_; - ConstRef increment_; - SliderOption options_; - Box gauge_box_; - CapturedMouse captured_mouse_; -}; - -class SliderWithLabel : public ComponentBase { - public: - SliderWithLabel(ConstStringRef label, Component inner) - : label_(std::move(label)) { - Add(std::move(inner)); - SetActiveChild(ChildAt(0)); - } - - private: - bool OnEvent(Event event) final { - if (ComponentBase::OnEvent(event)) { - return true; - } - - if (!event.is_mouse()) { - return false; - } - - mouse_hover_ = box_.Contain(event.mouse().x, event.mouse().y); - - if (!mouse_hover_) { - return false; - } - - if (!CaptureMouse(event)) { - return false; - } - - return true; - } - - Element Render() override { - auto focus_management = Focused() ? focus : Active() ? select : nothing; - auto gauge_color = (Focused() || mouse_hover_) ? color(Color::White) - : color(Color::GrayDark); - return hbox({ - text(label_()) | dim | vcenter, - hbox({ - text("["), - ComponentBase::Render() | underlined, - text("]"), - }) | xflex, - }) | - gauge_color | xflex | reflect(box_) | focus_management; - } - - ConstStringRef label_; - Box box_; - bool mouse_hover_ = false; -}; - -template -class SliderWithCallback : public ComponentBase { public: - explicit SliderWithCallback(SliderWithCallbackOption options) + explicit SliderBase(SliderOption options) : callback_(options.callback), min_(options.min), max_(options.max), increment_(options.increment), options_(options) { SetValue(options.value()); @@ -422,7 +199,9 @@ public: void SetValue(Ref val) { value_() = util::clamp(val(), min_(), max_()); - callback_(value_()); + if (callback_ != nullptr) { + callback_(value_()); + } } private: @@ -431,10 +210,63 @@ private: ConstRef min_; ConstRef max_; ConstRef increment_; - SliderWithCallbackOption options_; + SliderOption options_; Box gauge_box_; CapturedMouse captured_mouse_; }; + + +class SliderWithLabel : public ComponentBase { + public: + SliderWithLabel(ConstStringRef label, Component inner) + : label_(std::move(label)) { + Add(std::move(inner)); + SetActiveChild(ChildAt(0)); + } + + private: + bool OnEvent(Event event) final { + if (ComponentBase::OnEvent(event)) { + return true; + } + + if (!event.is_mouse()) { + return false; + } + + mouse_hover_ = box_.Contain(event.mouse().x, event.mouse().y); + + if (!mouse_hover_) { + return false; + } + + if (!CaptureMouse(event)) { + return false; + } + + return true; + } + + Element Render() override { + auto focus_management = Focused() ? focus : Active() ? select : nothing; + auto gauge_color = (Focused() || mouse_hover_) ? color(Color::White) + : color(Color::GrayDark); + return hbox({ + text(label_()) | dim | vcenter, + hbox({ + text("["), + ComponentBase::Render() | underlined, + text("]"), + }) | xflex, + }) | + gauge_color | xflex | reflect(box_) | focus_management; + } + + ConstStringRef label_; + Box box_; + bool mouse_hover_ = false; +}; + } // namespace /// @brief An horizontal slider. @@ -520,11 +352,6 @@ Component Slider(SliderOption options) { return Make>(options); } -template -Component Slider(SliderWithCallbackOption options) { - return Make>(options); -}; - template Component Slider(SliderOption); template Component Slider(SliderOption); template Component Slider(SliderOption);