FTXUI 6.1.9
C++ functional terminal UI.
Loading...
Searching...
No Matches
src/ftxui/component/slider.cpp
Go to the documentation of this file.
1// Copyright 2020 Arthur Sonzogni. Todos los derechos reservados.
2// El uso de este código fuente se rige por la licencia MIT que se puede encontrar en
3// el archivo LICENSE.
4#include <algorithm> // for max, min
5#include <ftxui/component/component_options.hpp> // for SliderOption
6#include <ftxui/dom/direction.hpp> // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up
7#include <string> // for allocator
8#include <utility> // for move
9
10#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
11#include "ftxui/component/component.hpp" // for Make, Slider
12#include "ftxui/component/component_base.hpp" // for ComponentBase
13#include "ftxui/component/event.hpp" // for Event, Event::ArrowDown, Event::ArrowLeft, Event::ArrowRight, Event::ArrowUp
14#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed, Mouse::Released
15#include "ftxui/component/screen_interactive.hpp" // for Component
16#include "ftxui/dom/elements.hpp" // for operator|, text, Element, xflex, hbox, color, underlined, reflect, Decorator, dim, vcenter, focus, nothing, select, yflex, gaugeDirection
17#include "ftxui/screen/box.hpp" // for Box
18#include "ftxui/screen/color.hpp" // for Color, Color::GrayDark, Color::White
19#include "ftxui/util/ref.hpp" // for ConstRef, Ref, ConstStringRef
20
21namespace ftxui {
22
23namespace {
24Decorator flexDirection(Direction direction) {
25 switch (direction) {
26 case Direction::Up:
27 case Direction::Down:
28 return yflex;
29 case Direction::Left:
31 return xflex;
32 }
33 return xflex; // NOT_REACHED()
34}
35
36Direction Opposite(Direction d) {
37 switch (d) {
38 case Direction::Up:
39 return Direction::Down;
40 case Direction::Down:
41 return Direction::Up;
42 case Direction::Left:
43 return Direction::Right;
45 return Direction::Left;
46 }
47 return d; // NOT_REACHED()
48}
49
50template <class T>
51class SliderBase : public SliderOption<T>, public ComponentBase {
52 public:
53 explicit SliderBase(SliderOption<T> options) : SliderOption<T>(options) {}
54
55 Element OnRender() override {
56 auto gauge_color =
57 Focused() ? color(this->color_active) : color(this->color_inactive);
58 const float percent =
59 float(this->value() - this->min()) / float(this->max() - this->min());
60 return gaugeDirection(percent, this->direction) |
61 flexDirection(this->direction) | reflect(gauge_box_) | gauge_color;
62 }
63
64 void OnDirection(Direction pressed) {
65 if (pressed == this->direction) {
66 this->value() += this->increment();
67 return;
68 }
69
70 if (pressed == Opposite(this->direction)) {
71 this->value() -= this->increment();
72 return;
73 }
74 }
75
76 bool OnEvent(Event event) final {
77 if (event.is_mouse()) {
78 return OnMouseEvent(event);
79 }
80
81 T old_value = this->value();
82 if (event == Event::ArrowLeft || event == Event::Character('h')) {
83 OnDirection(Direction::Left);
84 }
85 if (event == Event::ArrowRight || event == Event::Character('l')) {
86 OnDirection(Direction::Right);
87 }
88 if (event == Event::ArrowUp || event == Event::Character('k')) {
89 OnDirection(Direction::Up);
90 }
91 if (event == Event::ArrowDown || event == Event::Character('j')) {
92 OnDirection(Direction::Down);
93 }
94
95 this->value() = std::max(this->min(), std::min(this->max(), this->value()));
96 if (old_value != this->value()) {
97 if (this->on_change) {
98 this->on_change();
99 }
100 return true;
101 }
102
103 return ComponentBase::OnEvent(event);
104 }
105
106 bool OnCapturedMouseEvent(Event event) {
107 if (event.mouse().motion == Mouse::Released) {
108 captured_mouse_ = nullptr;
109 return true;
110 }
111
112 T old_value = this->value();
113 switch (this->direction) {
114 case Direction::Right: {
115 this->value() = this->min() + (event.mouse().x - gauge_box_.x_min) *
116 (this->max() - this->min()) /
117 (gauge_box_.x_max - gauge_box_.x_min);
118
119 break;
120 }
121 case Direction::Left: {
122 this->value() = this->max() - (event.mouse().x - gauge_box_.x_min) *
123 (this->max() - this->min()) /
124 (gauge_box_.x_max - gauge_box_.x_min);
125 break;
126 }
127 case Direction::Down: {
128 this->value() = this->min() + (event.mouse().y - gauge_box_.y_min) *
129 (this->max() - this->min()) /
130 (gauge_box_.y_max - gauge_box_.y_min);
131 break;
132 }
133 case Direction::Up: {
134 this->value() = this->max() - (event.mouse().y - gauge_box_.y_min) *
135 (this->max() - this->min()) /
136 (gauge_box_.y_max - gauge_box_.y_min);
137 break;
138 }
139 }
140
141 this->value() = std::max(this->min(), std::min(this->max(), this->value()));
142
143 if (old_value != this->value() && this->on_change) {
144 this->on_change();
145 }
146 return true;
147 }
148
149 bool OnMouseEvent(Event event) {
150 if (captured_mouse_) {
151 return OnCapturedMouseEvent(event);
152 }
153
154 if (event.mouse().button != Mouse::Left) {
155 return false;
156 }
157 if (event.mouse().motion != Mouse::Pressed) {
158 return false;
159 }
160
161 if (!gauge_box_.Contain(event.mouse().x, event.mouse().y)) {
162 return false;
163 }
164
165 captured_mouse_ = CaptureMouse(event);
166
167 if (captured_mouse_) {
168 TakeFocus();
169 return OnCapturedMouseEvent(event);
170 }
171
172 return false;
173 }
174
175 bool Focusable() const final { return true; }
176
177 private:
178 Box gauge_box_;
179 CapturedMouse captured_mouse_;
180};
181
182class SliderWithLabel : public ComponentBase {
183 public:
184 SliderWithLabel(ConstStringRef label, Component inner)
185 : label_(std::move(label)) {
186 Add(std::move(inner));
187 SetActiveChild(ChildAt(0));
188 }
189
190 private:
191 bool OnEvent(Event event) final {
192 if (ComponentBase::OnEvent(event)) {
193 return true;
194 }
195
196 if (!event.is_mouse()) {
197 return false;
198 }
199
200 mouse_hover_ = box_.Contain(event.mouse().x, event.mouse().y);
201
202 if (!mouse_hover_) {
203 return false;
204 }
205
206 if (!CaptureMouse(event)) {
207 return false;
208 }
209
210 return true;
211 }
212
213 Element OnRender() override {
214 auto gauge_color = (Focused() || mouse_hover_) ? color(Color::White)
216 auto element = hbox({
217 text(label_()) | dim | vcenter,
218 hbox({
219 text("["),
221 text("]"),
222 }) | xflex,
223 }) |
224 gauge_color | xflex | reflect(box_);
225
226 element |= focus;
227 return element;
228 }
229
230 ConstStringRef label_;
231 Box box_;
232 bool mouse_hover_ = false;
233};
234
235} // namespace
236
237/// @brief Un deslizador horizontal.
238/// @param label El nombre del deslizador.
239/// @param value El valor actual del deslizador.
240/// @param min El valor mínimo.
241/// @param max El valor máximo.
242/// @param increment El incremento cuando se usa con el cursor.
243/// @ingroup component
244///
245/// ### Ejemplo
246///
247/// ```cpp
248/// auto screen = ScreenInteractive::TerminalOutput();
249/// int value = 50;
250/// auto slider = Slider("Value:", &value, 0, 100, 1);
251/// screen.Loop(slider);
252/// ```
253///
254/// ### Salida
255///
256/// ```bash
257/// Value:[██████████████████████████ ]
258/// ```
260 Ref<int> value,
261 ConstRef<int> min,
262 ConstRef<int> max,
263 ConstRef<int> increment) {
264 SliderOption<int> option;
265 option.value = value;
266 option.min = min;
267 option.max = max;
268 option.increment = increment;
269 auto slider = Make<SliderBase<int>>(option);
270 return Make<SliderWithLabel>(std::move(label), slider);
271}
272
274 Ref<float> value,
275 ConstRef<float> min,
276 ConstRef<float> max,
277 ConstRef<float> increment) {
278 SliderOption<float> option;
279 option.value = value;
280 option.min = min;
281 option.max = max;
282 option.increment = increment;
283 auto slider = Make<SliderBase<float>>(option);
284 return Make<SliderWithLabel>(std::move(label), slider);
285}
287 Ref<long> value,
288 ConstRef<long> min,
289 ConstRef<long> max,
290 ConstRef<long> increment) {
291 SliderOption<long> option;
292 option.value = value;
293 option.min = min;
294 option.max = max;
295 option.increment = increment;
296 auto slider = Make<SliderBase<long>>(option);
297 return Make<SliderWithLabel>(std::move(label), slider);
298}
299
300/// @brief Un deslizador en cualquier dirección.
301/// @param options Las opciones
302/// ### Ejemplo
303///
304/// ```cpp
305/// auto screen = ScreenInteractive::TerminalOutput();
306/// int value = 50;
307/// auto slider = Slider({
308/// .value = &value,
309/// .min = 0,
310/// .max = 100,
311/// .increment= 20,
312/// });
313/// screen.Loop(slider);
314/// ```
315template <typename T>
317 return Make<SliderBase<T>>(options);
318}
319
324
329
332
333} // namespace ftxui
Un adaptador. Posee o referencia un objeto inmutable.
Definition ref.hpp:17
Un adaptador. Posee o referencia una cadena constante. Para mayor comodidad, esta clase convierte múl...
Definition ref.hpp:94
Un adaptador. Posee o referencia un objeto mutable.
Definition ref.hpp:46
Element Render()
Dibuja el componente. Construye un ftxui::Element para ser dibujado en la ftxui::Screen representando...
static const Event ArrowUp
Definition event.hpp:42
static const Event ArrowDown
Definition event.hpp:43
virtual bool OnEvent(Event)
Llamado en respuesta a un evento.
static const Event ArrowLeft
Definition event.hpp:40
static const Event ArrowRight
Definition event.hpp:41
Element xflex(Element)
Expandir/Minimizar si es posible/necesario en el eje X.
Definition flex.cpp:129
Element gaugeDirection(float progress, Direction direction)
Dibuja una barra de progreso de alta definición que avanza en la dirección especificada.
Direction
Direction es una enumeración que representa las cuatro cardinales direcciones.
Definition direction.hpp:13
Element yflex(Element)
Expandir/Minimizar si es posible/necesario en el eje Y.
Definition flex.cpp:135
Element underlined(Element)
Subraya el elemento dado.
Element text(std::wstring text)
Muestra un fragmento de texto Unicode.
Definition text.cpp:160
Element focus(Element)
Establece que child sea el elemento enfocado entre sus hermanos.
Definition frame.cpp:101
Element vcenter(Element)
Centra un elemento verticalmente.
Decorator color(Color)
Decora usando un color de primer plano.
El espacio de nombres ftxui:: de FTXUI.
Definition animation.hpp:10
std::function< Element(Element)> Decorator
Definition elements.hpp:24
std::unique_ptr< CapturedMouseInterface > CapturedMouse
std::shared_ptr< T > Make(Args &&... args)
Definition component.hpp:27
std::shared_ptr< Node > Element
Definition elements.hpp:22
Element hbox(Elements)
Un contenedor que muestra elementos horizontalmente uno por uno.
Definition hbox.cpp:94
Component Slider(SliderOption< T > options)
Un deslizador en cualquier dirección.
Decorator reflect(Box &box)
Definition reflect.cpp:43
std::shared_ptr< ComponentBase > Component