FTXUI  5.0.0
C++ functional terminal UI.
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
7 #include <memory> // for shared_ptr
8 #include <utility> // for move
9 #include "ftxui/component/animation.hpp" // for Function, Duration
10 #include "ftxui/dom/direction.hpp"
11 #include "ftxui/dom/elements.hpp" // for operator|=, Element, text, bgcolor, inverted, bold, dim, operator|, color, borderEmpty, hbox, automerge, border, borderLight
12 
13 namespace ftxui {
14 
15 /// @brief A color option that can be animated.
16 /// @params _inactive The color when the component is inactive.
17 /// @params _active The color when the component is active.
18 /// @params _duration The duration of the animation.
19 /// @params _function The easing function of the animation.
20 /// @ingroup component
22  Color _active,
23  animation::Duration _duration,
24  animation::easing::Function _function) {
25  enabled = true;
26  inactive = _inactive;
27  active = _active;
28  duration = _duration;
29  function = std::move(_function);
30 }
31 
32 /// @brief Set how the underline should animate.
33 /// @param d The duration of the animation.
34 /// @param f The easing function of the animation.
35 /// @ingroup component
39  SetAnimationFunction(std::move(f));
40 }
41 
42 /// @brief Set how the underline should animate.
43 /// @param d The duration of the animation.
44 /// @ingroup component
46  leader_duration = d;
48 }
49 
50 /// @brief Set how the underline should animate.
51 /// @param f The easing function of the animation.
52 /// @ingroup component
54  leader_function = f;
55  follower_function = std::move(f);
56 }
57 
58 /// @brief Set how the underline should animate.
59 /// This is useful to desynchronize the animation of the leader and the
60 /// follower.
61 /// @param f_leader The duration of the animation for the leader.
62 /// @param f_follower The duration of the animation for the follower.
63 /// @ingroup component
66  animation::easing::Function f_follower) {
67  leader_function = std::move(f_leader);
68  follower_function = std::move(f_follower);
69 }
70 
71 /// @brief Standard options for an horizontal menu.
72 /// This can be useful to implement a tab bar.
73 /// @ingroup component
74 // static
76  MenuOption option;
77  option.direction = Direction::Right;
78  option.entries_option.transform = [](const EntryState& state) {
79  Element e = text(state.label);
80  if (state.focused) {
81  e |= inverted;
82  }
83  if (state.active) {
84  e |= bold;
85  }
86  if (!state.focused && !state.active) {
87  e |= dim;
88  }
89  return e;
90  };
91  option.elements_infix = [] { return text(" "); };
92 
93  return option;
94 }
95 
96 /// @brief Standard options for an animated horizontal menu.
97 /// This can be useful to implement a tab bar.
98 /// @ingroup component
99 // static
101  auto option = Horizontal();
102  option.underline.enabled = true;
103  return option;
104 }
105 
106 /// @brief Standard options for a vertical menu.
107 /// This can be useful to implement a list of selectable items.
108 /// @ingroup component
109 // static
111  MenuOption option;
112  option.entries_option.transform = [](const EntryState& state) {
113  Element e = text((state.active ? "> " : " ") + state.label); // NOLINT
114  if (state.focused) {
115  e |= inverted;
116  }
117  if (state.active) {
118  e |= bold;
119  }
120  if (!state.focused && !state.active) {
121  e |= dim;
122  }
123  return e;
124  };
125  return option;
126 }
127 
128 /// @brief Standard options for an animated vertical menu.
129 /// This can be useful to implement a list of selectable items.
130 /// @ingroup component
131 // static
133  auto option = MenuOption::Vertical();
134  option.entries_option.transform = [](const EntryState& state) {
135  Element e = text(state.label);
136  if (state.focused) {
137  e |= inverted;
138  }
139  if (state.active) {
140  e |= bold;
141  }
142  if (!state.focused && !state.active) {
143  e |= dim;
144  }
145  return e;
146  };
147  option.underline.enabled = true;
148  return option;
149 }
150 
151 /// @brief Standard options for a horitontal menu with some separator.
152 /// This can be useful to implement a tab bar.
153 /// @ingroup component
154 // static
156  auto option = MenuOption::Horizontal();
157  option.elements_infix = [] { return text("│") | automerge; };
158  return option;
159 }
160 
161 /// @brief Create a ButtonOption, highlighted using [] characters.
162 /// @ingroup component
163 // static
165  ButtonOption option;
166  option.transform = [](const EntryState& s) {
167  const std::string t = s.focused ? "[" + s.label + "]" //
168  : " " + s.label + " ";
169  return text(t);
170  };
171  return option;
172 }
173 
174 /// @brief Create a ButtonOption, inverted when focused.
175 /// @ingroup component
176 // static
178  ButtonOption option;
179  option.transform = [](const EntryState& s) {
180  auto element = text(s.label) | borderLight;
181  if (s.focused) {
182  element |= inverted;
183  }
184  return element;
185  };
186  return option;
187 }
188 
189 /// @brief Create a ButtonOption. The button is shown using a border, inverted
190 /// when focused. This is the current default.
191 /// @ingroup component
193  ButtonOption option;
194  option.transform = [](const EntryState& s) {
195  auto element = text(s.label) | border;
196  if (s.active) {
197  element |= bold;
198  }
199  if (s.focused) {
200  element |= inverted;
201  }
202  return element;
203  };
204  return option;
205 }
206 
207 /// @brief Create a ButtonOption, using animated colors.
208 /// @ingroup component
209 // static
213 }
214 
215 /// @brief Create a ButtonOption, using animated colors.
216 /// @ingroup component
217 // static
219  return ButtonOption::Animated(
220  Color::Interpolate(0.85F, color, Color::Black), // NOLINT
221  Color::Interpolate(0.10F, color, Color::White), // NOLINT
222  Color::Interpolate(0.10F, color, Color::Black), // NOLINT
223  Color::Interpolate(0.85F, color, Color::White)); // NOLINT
224 }
225 
226 /// @brief Create a ButtonOption, using animated colors.
227 /// @ingroup component
228 // static
230  // NOLINTBEGIN
231  return ButtonOption::Animated(
232  /*bakground=*/background,
233  /*foreground=*/foreground,
234  /*background_active=*/foreground,
235  /*foreground_active=*/background);
236  // NOLINTEND
237 }
238 
239 /// @brief Create a ButtonOption, using animated colors.
240 /// @ingroup component
241 // static
243  Color foreground,
244  Color background_active,
245  Color foreground_active) {
246  ButtonOption option;
247  option.transform = [](const EntryState& s) {
248  auto element = text(s.label) | borderEmpty;
249  if (s.focused) {
250  element |= bold;
251  }
252  return element;
253  };
254  option.animated_colors.foreground.Set(foreground, foreground_active);
255  option.animated_colors.background.Set(background, background_active);
256  return option;
257 }
258 
259 /// @brief Option for standard Checkbox.
260 /// @ingroup component
261 // static
263  auto option = CheckboxOption();
264  option.transform = [](const EntryState& s) {
265 #if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
266  // Microsoft terminal do not use fonts able to render properly the default
267  // radiobox glyph.
268  auto prefix = text(s.state ? "[X] " : "[ ] "); // NOLINT
269 #else
270  auto prefix = text(s.state ? "▣ " : "☐ "); // NOLINT
271 #endif
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 Option for standard Radiobox
285 /// @ingroup component
286 // static
288  auto option = RadioboxOption();
289  option.transform = [](const EntryState& s) {
290 #if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
291  // Microsoft terminal do not use fonts able to render properly the default
292  // radiobox glyph.
293  auto prefix = text(s.state ? "(*) " : "( ) "); // NOLINT
294 #else
295  auto prefix = text(s.state ? "◉ " : "○ "); // NOLINT
296 #endif
297  auto t = text(s.label);
298  if (s.active) {
299  t |= bold;
300  }
301  if (s.focused) {
302  t |= inverted;
303  }
304  return hbox({prefix, t});
305  };
306  return option;
307 }
308 
309 /// @brief Standard options for the input component.
310 /// @ingroup component
311 // static
313  InputOption option;
314  option.transform = [](InputState state) {
315  state.element |= color(Color::White);
316 
317  if (state.is_placeholder) {
318  state.element |= dim;
319  }
320 
321  if (state.focused) {
322  state.element |= inverted;
323  } else if (state.hovered) {
324  state.element |= bgcolor(Color::GrayDark);
325  }
326 
327  return state.element;
328  };
329  return option;
330 }
331 
332 /// @brief Standard options for a more beautiful input component.
333 /// @ingroup component
334 // static
336  InputOption option;
337  option.transform = [](InputState state) {
338  state.element |= borderEmpty;
339  state.element |= color(Color::White);
340 
341  if (state.is_placeholder) {
342  state.element |= dim;
343  }
344 
345  if (state.focused) {
346  state.element |= bgcolor(Color::Black);
347  }
348 
349  if (state.hovered) {
350  state.element |= bgcolor(Color::GrayDark);
351  }
352 
353  return state.element;
354  };
355  return option;
356 }
357 
358 } // namespace ftxui
A class representing terminal colors.
Definition: color.hpp:20
static Color Interpolate(float t, const Color &a, const Color &b)
Definition: color.cpp:212
std::function< float(float)> Function
Definition: animation.hpp:35
std::chrono::duration< float > Duration
Definition: animation.hpp:20
Decorator bgcolor(Color)
Decorate using a background color.
Definition: color.cpp:124
AnimatedColorOption foreground
std::shared_ptr< Node > Element
Definition: elements.hpp:22
Element bold(Element)
Use a bold font, for elements with more emphasis.
Definition: bold.cpp:33
AnimatedColorOption background
Element hbox(Elements)
A container displaying elements horizontally one by one.
Definition: hbox.cpp:83
std::function< Element(const EntryState &state)> transform
Element inverted(Element)
Add a filter that will invert the foreground and the background colors.
Definition: inverted.cpp:34
Element text(std::wstring text)
Display a piece of unicode text.
Definition: text.cpp:119
Element borderLight(Element)
Draw a light border around the element.
Definition: border.cpp:336
Element dim(Element)
Use a light font, for elements with less emphasis.
Definition: dim.cpp:33
Element automerge(Element child)
Enable character to be automatically merged with others nearby.
Definition: automerge.cpp:17
Element border(Element)
Draw a border around the element.
Definition: border.cpp:228
Element borderEmpty(Element)
Draw an empty border around the element.
Definition: border.cpp:476
Decorator color(Color)
Decorate using a foreground color.
Definition: color.cpp:110
arguments for |ButtonOption::transform|, |CheckboxOption::transform|, |Radiobox::transform|,...
Used to define style for the Input component.
animation::Duration duration
void Set(Color inactive, Color active, animation::Duration duration=std::chrono::milliseconds(250), animation::easing::Function function=animation::easing::QuadraticInOut)
A color option that can be animated. @params _inactive The color when the component is inactive....
Option for the AnimatedButton component.
static ButtonOption Animated()
Create a ButtonOption, using animated colors.
static ButtonOption Border()
Create a ButtonOption. The button is shown using a border, inverted when focused. This is the current...
static ButtonOption Simple()
Create a ButtonOption, inverted when focused.
static ButtonOption Ascii()
Create a ButtonOption, highlighted using [] characters.
AnimatedColorsOption animated_colors
std::function< Element(const EntryState &)> transform
Option for the Checkbox component.
static CheckboxOption Simple()
Option for standard Checkbox.
Option for the Input component.
static InputOption Default()
Create the default input style:
static InputOption Spacious()
A white on black style with high margins:
std::function< Element(InputState)> transform
Option for the Menu component.
static MenuOption Toggle()
Standard options for a horitontal menu with some separator. This can be useful to implement a tab bar...
MenuEntryOption entries_option
static MenuOption Horizontal()
Standard options for an horizontal menu. This can be useful to implement a tab bar.
static MenuOption VerticalAnimated()
Standard options for an animated vertical menu. This can be useful to implement a list of selectable ...
static MenuOption Vertical()
Standard options for a vertical menu. This can be useful to implement a list of selectable items.
std::function< Element()> elements_infix
static MenuOption HorizontalAnimated()
Standard options for an animated horizontal menu. This can be useful to implement a tab bar.
Option for the Radiobox component.
static RadioboxOption Simple()
Option for standard Radiobox.
animation::Duration follower_duration
animation::easing::Function leader_function
void SetAnimationFunction(animation::easing::Function f)
Set how the underline should animate.
animation::Duration leader_duration
void SetAnimation(animation::Duration d, animation::easing::Function f)
Set how the underline should animate.
void SetAnimationDuration(animation::Duration d)
Set how the underline should animate.
animation::easing::Function follower_function