Loading...
Searching...
No Matches
button.cpp
Go to the documentation of this file.
// 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.
#include <functional> // for function
#include <utility> // for move
#include "ftxui/component/animation.hpp" // for Animator, Params (ptr only)
#include "ftxui/component/component.hpp" // for Make, Button
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for ButtonOption, AnimatedColorOption, AnimatedColorsOption, EntryState
#include "ftxui/component/event.hpp" // for Event, Event::Return
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed
#include "ftxui/component/screen_interactive.hpp" // for Component
#include "ftxui/dom/elements.hpp" // for operator|, Decorator, Element, operator|=, bgcolor, color, reflect, text, bold, border, inverted, nothing
#include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/color.hpp" // for Color
#include "ftxui/util/ref.hpp" // for Ref, ConstStringRef
namespace ftxui {
namespace {
Element DefaultTransform(EntryState params) { // NOLINT
auto element = text(params.label) | border;
if (params.active) {
element |= bold;
}
if (params.focused) {
element |= inverted;
}
return element;
}
class ButtonBase : public ComponentBase, public ButtonOption {
public:
explicit ButtonBase(ButtonOption option) : ButtonOption(std::move(option)) {}
// Component implementation:
Element OnRender() override {
const bool active = Active();
const bool focused = Focused();
const bool focused_or_hover = focused || mouse_hover_;
float target = focused_or_hover ? 1.f : 0.f; // NOLINT
if (target != animator_background_.to()) {
SetAnimationTarget(target);
}
const EntryState state{
*label, false, active, focused_or_hover, Index(),
};
auto element = (transform ? transform : DefaultTransform) //
(state);
element |= AnimatedColorStyle();
element |= focus;
element |= reflect(box_);
return element;
}
Decorator AnimatedColorStyle() {
Decorator style = nothing;
if (animated_colors.background.enabled) {
style = style |
bgcolor(Color::Interpolate(animation_foreground_, //
animated_colors.background.inactive,
animated_colors.background.active));
}
if (animated_colors.foreground.enabled) {
style =
style | color(Color::Interpolate(animation_foreground_, //
animated_colors.foreground.inactive,
animated_colors.foreground.active));
}
return style;
}
void SetAnimationTarget(float target) {
if (animated_colors.foreground.enabled) {
animator_foreground_ = animation::Animator(
&animation_foreground_, target, animated_colors.foreground.duration,
animated_colors.foreground.function);
}
if (animated_colors.background.enabled) {
animator_background_ = animation::Animator(
&animation_background_, target, animated_colors.background.duration,
animated_colors.background.function);
}
}
void OnAnimation(animation::Params& p) override {
animator_background_.OnAnimation(p);
animator_foreground_.OnAnimation(p);
}
void OnClick() {
animation_background_ = 0.5F; // NOLINT
animation_foreground_ = 0.5F; // NOLINT
SetAnimationTarget(1.F); // NOLINT
// TODO(arthursonzogni): Consider posting the task to the main loop, instead
// of invoking it immediately.
on_click(); // May delete this.
}
bool OnEvent(Event event) override {
if (event.is_mouse()) {
return OnMouseEvent(event);
}
if (event == Event::Return) {
OnClick(); // May delete this.
return true;
}
return false;
}
bool OnMouseEvent(Event event) {
mouse_hover_ =
box_.Contain(event.mouse().x, event.mouse().y) && CaptureMouse(event);
if (!mouse_hover_) {
return false;
}
if (event.mouse().button == Mouse::Left &&
event.mouse().motion == Mouse::Pressed) {
TakeFocus();
OnClick(); // May delete this.
return true;
}
return false;
}
bool Focusable() const final { return true; }
private:
bool mouse_hover_ = false;
Box box_;
ButtonOption option_;
float animation_background_ = 0;
float animation_foreground_ = 0;
animation::Animator animator_background_ =
animation::Animator(&animation_background_);
animation::Animator animator_foreground_ =
animation::Animator(&animation_foreground_);
};
} // namespace
/// @brief Draw a button. Execute a function when clicked.
/// @param option Additional optional parameters.
/// @ingroup component
/// @see ButtonBase
///
/// ### Example
///
/// ```cpp
/// auto screen = ScreenInteractive::FitComponent();
/// Component button = Button({
/// .label = "Click to quit",
/// .on_click = screen.ExitLoopClosure(),
/// });
/// screen.Loop(button)
/// ```
///
/// ### Output
///
/// ```bash
/// ┌─────────────┐
/// │Click to quit│
/// └─────────────┘
/// ```
Component Button(ButtonOption option) {
return Make<ButtonBase>(std::move(option));
}
/// @brief Draw a button. Execute a function when clicked.
/// @param label The label of the button.
/// @param on_click The action to execute when clicked.
/// @param option Additional optional parameters.
/// @ingroup component
/// @see ButtonBase
///
/// ### Example
///
/// ```cpp
/// auto screen = ScreenInteractive::FitComponent();
/// std::string label = "Click to quit";
/// Component button = Button(&label, screen.ExitLoopClosure());
/// screen.Loop(button)
/// ```
///
/// ### Output
///
/// ```bash
/// ┌─────────────┐
/// │Click to quit│
/// └─────────────┘
/// ```
// NOLINTNEXTLINE
Component Button(ConstStringRef label,
std::function<void()> on_click,
ButtonOption option) {
option.label = std::move(label);
option.on_click = std::move(on_click);
return Make<ButtonBase>(std::move(option));
}
} // namespace ftxui
animation.hpp
box.hpp
ftxui::Color::Interpolate
static Color Interpolate(float t, const Color &a, const Color &b)
Definition color.cpp:212
ftxui::ConstStringRef
An adapter. Own or reference a constant string. For convenience, this class convert multiple immutabl...
Definition ref.hpp:94
color.hpp
component.hpp
component_base.hpp
component_options.hpp
elements.hpp
event.hpp
mouse.hpp
ftxui
Definition animation.hpp:10
ftxui::bgcolor
Decorator bgcolor(Color)
Decorate using a background color.
Definition color.cpp:124
ftxui::Decorator
std::function< Element(Element)> Decorator
Definition elements.hpp:24
ftxui::nothing
Element nothing(Element element)
A decoration doing absolutely nothing.
Definition util.cpp:28
ftxui::Element
std::shared_ptr< Node > Element
Definition elements.hpp:22
ftxui::Make
std::shared_ptr< T > Make(Args &&... args)
Definition component.hpp:26
ftxui::Component
std::shared_ptr< ComponentBase > Component
Definition component_base.hpp:24
ftxui::bold
Element bold(Element)
Use a bold font, for elements with more emphasis.
Definition bold.cpp:33
ftxui::Button
Component Button(ButtonOption options)
Draw a button. Execute a function when clicked.
Definition button.cpp:176
ftxui::inverted
Element inverted(Element)
Add a filter that will invert the foreground and the background colors.
Definition inverted.cpp:34
ftxui::text
Element text(std::wstring text)
Display a piece of unicode text.
Definition text.cpp:160
ftxui::focus
Element focus(Element)
Set the child to be the one focused among its siblings.
Definition frame.cpp:101
ftxui::reflect
Decorator reflect(Box &box)
Definition reflect.cpp:43
ftxui::border
Element border(Element)
Draw a border around the element.
Definition border.cpp:227
ftxui::color
Decorator color(Color)
Decorate using a foreground color.
Definition color.cpp:110
ref.hpp
screen_interactive.hpp
ftxui::ButtonOption
Option for the AnimatedButton component.
Definition component_options.hpp:112
ftxui::Event::Return
static const Event Return
Definition event.hpp:51
ftxui::Mouse::Left
@ Left
Definition mouse.hpp:13
ftxui::Mouse::Pressed
@ Pressed
Definition mouse.hpp:25