FTXUI 6.1.9
C++ functional terminal UI.
Loading...
Searching...
No Matches
src/ftxui/component/button.cpp
Go to the documentation of this file.
1// Copyright 2020 Arthur Sonzogni. All rights reserved.
2// Use of this source code is governed by the MIT license that can be found in
3// the LICENSE file.
4
5#include <functional> // for function
6#include <string> // for string
7#include <utility> // for move
8
9#include "ftxui/component/animation.hpp" // for Animator, Params (ptr only)
10#include "ftxui/component/app.hpp" // for Component
11#include "ftxui/component/component.hpp" // for Make, Button
12#include "ftxui/component/component_base.hpp" // for ComponentBase
13#include "ftxui/component/component_options.hpp" // for ButtonOption, AnimatedColorOption, AnimatedColorsOption, EntryState
14#include "ftxui/component/event.hpp" // for Event, Event::Return
15#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed
16#include "ftxui/dom/elements.hpp" // for operator|, Decorator, Element, operator|=, bgcolor, color, reflect, text, bold, border, inverted, nothing
17#include "ftxui/screen/box.hpp" // for Box
18#include "ftxui/screen/color.hpp" // for Color
19#include "ftxui/util/ref.hpp" // for Ref, ConstStringRef
20
21namespace ftxui {
22
23namespace {
24
25Element DefaultTransform(EntryState params) { // NOLINT
26 auto element = text(params.label) | border;
27 if (params.active) {
28 element |= bold;
29 }
30 if (params.focused) {
31 element |= inverted;
32 }
33 return element;
34}
35
36class ButtonBase : public ComponentBase, public ButtonOption {
37 public:
38 explicit ButtonBase(ButtonOption option) : ButtonOption(std::move(option)) {}
39
40 // Component implementation:
41 Element OnRender() override {
42 const bool active = Active();
43 const bool focused = Focused();
44 const bool focused_or_hover = focused || mouse_hover_;
45
46 float target = focused_or_hover ? 1.f : 0.f; // NOLINT
47 if (target != animator_background_.to()) {
48 SetAnimationTarget(target);
49 }
50
51 const EntryState state{
52 std::string(*label), false, active, focused_or_hover, Index(),
53 };
54
55 auto element = (transform ? transform : DefaultTransform) //
56 (state);
57 element |= AnimatedColorStyle();
58 element |= focus;
59 element |= reflect(box_);
60 return element;
61 }
62
63 Decorator AnimatedColorStyle() {
64 Decorator style = nothing;
65 if (animated_colors.background.enabled) {
66 style = style |
67 bgcolor(Color::Interpolate(animation_foreground_, //
68 animated_colors.background.inactive,
69 animated_colors.background.active));
70 }
71 if (animated_colors.foreground.enabled) {
72 style =
73 style | color(Color::Interpolate(animation_foreground_, //
74 animated_colors.foreground.inactive,
75 animated_colors.foreground.active));
76 }
77 return style;
78 }
79
80 void SetAnimationTarget(float target) {
81 if (animated_colors.foreground.enabled) {
82 animator_foreground_ = animation::Animator(
83 &animation_foreground_, target, animated_colors.foreground.duration,
84 animated_colors.foreground.function);
85 }
86 if (animated_colors.background.enabled) {
87 animator_background_ = animation::Animator(
88 &animation_background_, target, animated_colors.background.duration,
89 animated_colors.background.function);
90 }
91 }
92
93 void OnAnimation(animation::Params& p) override {
94 animator_background_.OnAnimation(p);
95 animator_foreground_.OnAnimation(p);
96 }
97
98 void OnClick() {
99 animation_background_ = 0.5F; // NOLINT
100 animation_foreground_ = 0.5F; // NOLINT
101 SetAnimationTarget(1.F); // NOLINT
102
103 // TODO(arthursonzogni): Consider posting the task to the main loop, instead
104 // of invoking it immediately.
105 on_click(); // May delete this.
106 }
107
108 bool OnEvent(Event event) override {
109 if (event.is_mouse()) {
110 return OnMouseEvent(event);
111 }
112
113 if (event == Event::Return) {
114 OnClick(); // May delete this.
115 return true;
116 }
117 return false;
118 }
119
120 bool OnMouseEvent(Event event) {
121 mouse_hover_ =
122 box_.Contain(event.mouse().x, event.mouse().y) && CaptureMouse(event);
123
124 if (!mouse_hover_) {
125 return false;
126 }
127
128 if (event.mouse().button == Mouse::Left &&
129 event.mouse().motion == Mouse::Pressed) {
130 TakeFocus();
131 OnClick(); // May delete this.
132 return true;
133 }
134
135 return false;
136 }
137
138 bool Focusable() const final { return true; }
139
140 private:
141 bool mouse_hover_ = false;
142 Box box_;
143 float animation_background_ = 0;
144 float animation_foreground_ = 0;
145 animation::Animator animator_background_ =
146 animation::Animator(&animation_background_);
147 animation::Animator animator_foreground_ =
148 animation::Animator(&animation_foreground_);
149};
150
151} // namespace
152
153/// @brief Draw a button. Execute a function when clicked.
154/// @param option Additional optional parameters.
155/// @ingroup component
156/// @see ButtonBase
157///
158/// ### Example
159///
160/// ```cpp
161/// auto screen = App::FitComponent();
162/// Component button = Button({
163/// .label = "Click to quit",
164/// .on_click = screen.ExitLoopClosure(),
165/// });
166/// screen.Loop(button)
167/// ```
168///
169/// ### Output
170///
171/// ```bash
172/// ┌─────────────┐
173/// │Click to quit│
174/// └─────────────┘
175/// ```
177 return Make<ButtonBase>(std::move(option));
178}
179
180/// @brief Draw a button. Execute a function when clicked.
181/// @param label The label of the button.
182/// @param on_click The action to execute when clicked.
183/// @param option Additional optional parameters.
184/// @ingroup component
185/// @see ButtonBase
186///
187/// ### Example
188///
189/// ```cpp
190/// auto screen = App::FitComponent();
191/// std::string label = "Click to quit";
192/// Component button = Button(&label, screen.ExitLoopClosure());
193/// screen.Loop(button)
194/// ```
195///
196/// ### Output
197///
198/// ```bash
199/// ┌─────────────┐
200/// │Click to quit│
201/// └─────────────┘
202/// ```
203// NOLINTNEXTLINE
205 std::function<void()> on_click,
206 ButtonOption option) {
207 option.label = std::move(label);
208 option.on_click = std::move(on_click);
209 return Make<ButtonBase>(std::move(option));
210}
211
212} // namespace ftxui
An adapter. Own or reference a constant string. For convenience, this class convert multiple immutabl...
Definition ref.hpp:112
std::function< void()> on_click
static const Event Return
Definition event.hpp:65
Component Button(ButtonOption options)
Draw a button. Execute a function when clicked.
Option for the AnimatedButton component.
Decorator bgcolor(Color)
Decorate using a background color.
Element nothing(Element element)
A decoration doing absolutely nothing.
Definition dom/util.cpp:28
Element text(std::wstring_view text)
Display a piece of unicode text.
Element bold(Element)
Use a bold font, for elements with more emphasis.
Definition bold.cpp:33
Element inverted(Element)
Add a filter that will invert the foreground and the background colors.
Definition inverted.cpp:34
Element focus(Element)
Set the child to be the one focused among its siblings.
Definition frame.cpp:101
Element border(Element)
Draw a border around the element.
Decorator color(Color)
Decorate using a foreground color.
static Color Interpolate(float t, const Color &a, const Color &b)
The FTXUI ftxui:: namespace.
Definition animation.hpp:10
std::function< Element(Element)> Decorator
Definition elements.hpp:25
std::shared_ptr< T > Make(Args &&... args)
Definition component.hpp:27
std::shared_ptr< Node > Element
Definition elements.hpp:23
Decorator reflect(Box &box)
Definition reflect.cpp:43
std::shared_ptr< ComponentBase > Component
Definition app.hpp:24