FTXUI 6.1.9
C++ functional terminal UI.
Loading...
Searching...
No Matches
component_options.cpp
Go to the documentation of this file.
1// Copyright 2022 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.
5
6#include <ftxui/screen/color.hpp> // for Color, Color::White, Color::Black, Color::GrayDark, Color::Blue, Color::GrayLight, Color::Red
8#include <memory> // for shared_ptr
9#include <string>
10#include <utility> // for move
11#include "ftxui/component/animation.hpp" // for Function, Duration
13#include "ftxui/dom/elements.hpp" // for operator|=, Element, text, bgcolor, inverted, bold, dim, operator|, color, borderEmpty, hbox, automerge, border, borderLight
14
15namespace ftxui {
16
17/// @brief A color option that can be animated.
18/// @param _inactive The color when the component is inactive.
19/// @param _active The color when the component is active.
20/// @param _duration The duration of the animation.
21/// @param _function The easing function of the animation.
22void AnimatedColorOption::Set(Color _inactive,
23 Color _active,
24 animation::Duration _duration,
26 enabled = true;
27 inactive = _inactive;
28 active = _active;
29 duration = _duration;
30 function = std::move(_function);
31}
32
33/// @brief Set how the underline should animate.
34/// @param d The duration of the animation.
35/// @param f The easing function of the animation.
36void UnderlineOption::SetAnimation(animation::Duration d,
38 SetAnimationDuration(d);
39 SetAnimationFunction(std::move(f));
40}
41
42/// @brief Set how the underline should animate.
43/// @param d The duration of the animation.
44void UnderlineOption::SetAnimationDuration(animation::Duration d) {
45 leader_duration = d;
46 follower_duration = d;
47}
48
49/// @brief Set how the underline should animate.
50/// @param f The easing function of the animation.
51void UnderlineOption::SetAnimationFunction(animation::easing::Function f) {
52 leader_function = f;
53 follower_function = std::move(f);
54}
55
56/// @brief Set how the underline should animate.
57/// This is useful to desynchronize the animation of the leader and the
58/// follower.
59/// @param f_leader The duration of the animation for the leader.
60/// @param f_follower The duration of the animation for the follower.
61void UnderlineOption::SetAnimationFunction(
63 animation::easing::Function f_follower) {
64 leader_function = std::move(f_leader);
65 follower_function = std::move(f_follower);
66}
67
68/// @brief Standard options for a horizontal menu.
69/// This can be useful to implement a tab bar.
70// static
71MenuOption MenuOption::Horizontal() {
72 MenuOption option;
73 option.direction = Direction::Right;
74 option.entries_option.transform = [](const EntryState& state) {
75 Element e = text(state.label);
76 if (state.focused) {
77 e |= inverted;
78 }
79 if (state.active) {
80 e |= bold;
81 }
82 if (!state.focused && !state.active) {
83 e |= dim;
84 }
85 return e;
86 };
87 option.elements_infix = [] { return text(" "); };
88
89 return option;
90}
91
92/// @brief Standard options for an animated horizontal menu.
93/// This can be useful to implement a tab bar.
94// static
95MenuOption MenuOption::HorizontalAnimated() {
96 auto option = Horizontal();
97 option.underline.enabled = true;
98 return option;
99}
100
101/// @brief Standard options for a vertical menu.
102/// This can be useful to implement a list of selectable items.
103// static
104MenuOption MenuOption::Vertical() {
105 MenuOption option;
106 option.entries_option.transform = [](const EntryState& state) {
107 Element e = text((state.active ? "> " : " ") + state.label); // NOLINT
108 if (state.focused) {
109 e |= inverted;
110 }
111 if (state.active) {
112 e |= bold;
113 }
114 if (!state.focused && !state.active) {
115 e |= dim;
116 }
117 return e;
118 };
119 return option;
120}
121
122/// @brief Standard options for an animated vertical menu.
123/// This can be useful to implement a list of selectable items.
124// static
125MenuOption MenuOption::VerticalAnimated() {
126 auto option = MenuOption::Vertical();
127 option.entries_option.transform = [](const EntryState& state) {
128 Element e = text(state.label);
129 if (state.focused) {
130 e |= inverted;
131 }
132 if (state.active) {
133 e |= bold;
134 }
135 if (!state.focused && !state.active) {
136 e |= dim;
137 }
138 return e;
139 };
140 option.underline.enabled = true;
141 return option;
142}
143
144/// @brief Standard options for a horizontal menu with some separator.
145/// This can be useful to implement a tab bar.
146// static
147MenuOption MenuOption::Toggle() {
148 auto option = MenuOption::Horizontal();
149 option.elements_infix = [] { return text("│") | automerge; };
150 return option;
151}
152
153/// @brief Create a ButtonOption, highlighted using [] characters.
154// static
155ButtonOption ButtonOption::Ascii() {
156 ButtonOption option;
157 option.transform = [](const EntryState& s) {
158 const std::string t = s.focused ? "[" + s.label + "]" //
159 : " " + s.label + " ";
160 return text(t);
161 };
162 return option;
163}
164
165/// @brief Create a ButtonOption, inverted when focused.
166// static
167ButtonOption ButtonOption::Simple() {
168 ButtonOption option;
169 option.transform = [](const EntryState& s) {
170 auto element = text(s.label) | borderLight;
171 if (s.focused) {
172 element |= inverted;
173 }
174 return element;
175 };
176 return option;
177}
178
179/// @brief Create a ButtonOption. The button is shown using a border, inverted
180/// when focused. This is the current default.
181ButtonOption ButtonOption::Border() {
182 ButtonOption option;
183 option.transform = [](const EntryState& s) {
184 auto element = text(s.label) | border;
185 if (s.active) {
186 element |= bold;
187 }
188 if (s.focused) {
189 element |= inverted;
190 }
191 return element;
192 };
193 return option;
194}
195
196/// @brief Create a ButtonOption, using animated colors.
197// static
198ButtonOption ButtonOption::Animated() {
199 return Animated(Color::Black, Color::GrayLight, //
200 Color::GrayDark, Color::White);
201}
202
203/// @brief Create a ButtonOption, using animated colors.
204// static
205ButtonOption ButtonOption::Animated(Color color) {
206 return ButtonOption::Animated(
207 Color::Interpolate(0.85F, color, Color::Black), // NOLINT
208 Color::Interpolate(0.10F, color, Color::White), // NOLINT
209 Color::Interpolate(0.10F, color, Color::Black), // NOLINT
210 Color::Interpolate(0.85F, color, Color::White)); // NOLINT
211}
212
213/// @brief Create a ButtonOption, using animated colors.
214// static
215ButtonOption ButtonOption::Animated(Color background, Color foreground) {
216 // NOLINTBEGIN
217 return ButtonOption::Animated(
218 /*background=*/background,
219 /*foreground=*/foreground,
220 /*background_active=*/foreground,
221 /*foreground_active=*/background);
222 // NOLINTEND
223}
224
225/// @brief Create a ButtonOption, using animated colors.
226// static
227ButtonOption ButtonOption::Animated(Color background,
228 Color foreground,
229 Color background_active,
230 Color foreground_active) {
231 ButtonOption option;
232 option.transform = [](const EntryState& s) {
233 auto element = text(s.label) | borderEmpty;
234 if (s.focused) {
235 element |= bold;
236 }
237 return element;
238 };
239 option.animated_colors.foreground.Set(foreground, foreground_active);
240 option.animated_colors.background.Set(background, background_active);
241 return option;
242}
243
244/// @brief Option for standard Checkbox.
245// static
246CheckboxOption CheckboxOption::Simple() {
247 auto option = CheckboxOption();
248 option.transform = [](const EntryState& s) {
249 auto prefix = (Terminal::GetQuirks().ComponentAscii())
250 ? text(s.state ? "[X] " : "[ ] ") // NOLINT
251 : text(s.state ? "▣ " : "☐ "); // NOLINT
252 auto t = text(s.label);
253 if (s.active) {
254 t |= bold;
255 }
256 if (s.focused) {
257 t |= inverted;
258 }
259 return hbox({prefix, t});
260 };
261 return option;
262}
263
264/// @brief Option for standard Radiobox
265// static
266RadioboxOption RadioboxOption::Simple() {
267 auto option = RadioboxOption();
268 option.transform = [](const EntryState& s) {
269 auto prefix = (Terminal::GetQuirks().ComponentAscii())
270 ? text(s.state ? "(*) " : "( ) ") // NOLINT
271 : text(s.state ? "◉ " : "○ "); // NOLINT
272 auto t = text(s.label);
273 if (s.active) {
274 t |= bold;
275 }
276 if (s.focused) {
277 t |= inverted;
278 }
279 return hbox({prefix, t});
280 };
281 return option;
282}
283
284/// @brief Standard options for the input component.
285// static
286InputOption InputOption::Default() {
287 InputOption option;
288 option.transform = [](InputState state) {
289 if (state.is_placeholder) {
290 state.element |= dim;
291 }
292
293 if (state.focused) {
294 state.element |= inverted;
295 } else if (state.hovered) {
296 state.element |= underlined;
297 }
298
299 return state.element;
300 };
301 return option;
302}
303
304/// @brief Standard options for a more beautiful input component.
305// static
306InputOption InputOption::Spacious() {
307 InputOption option;
308 option.transform = [](InputState state) {
309 state.element |= borderEmpty;
310
311 if (state.is_placeholder) {
312 state.element |= dim;
313 }
314
315 if (state.focused) {
316 state.element |= inverted;
317 } else if (state.hovered) {
318 state.element |= bold;
319 }
320
321 return state.element;
322 };
323 return option;
324}
325
326} // namespace ftxui
std::function< float(float)> Function
Definition animation.hpp:46
std::chrono::duration< float > Duration
Definition animation.hpp:31
The FTXUI ftxui:: namespace.
Definition animation.hpp:11
std::shared_ptr< Node > Element
Definition elements.hpp:24
const Element & element
Definition node.hpp:95