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/dom/linear_gradient.hpp> // for LinearGradient
7 #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 <utility> // for move
10 
11 #include "ftxui/component/animation.hpp" // for Function, Duration
12 #include "ftxui/dom/elements.hpp" // for operator|=, Element, text, bgcolor, inverted, bold, dim, operator|, color, borderEmpty, hbox, automerge, border, borderLight
13 
14 namespace ftxui {
15 
16 /// @brief A color option that can be animated.
17 /// @params _inactive The color when the component is inactive.
18 /// @params _active The color when the component is active.
19 /// @params _duration The duration of the animation.
20 /// @params _function The easing function of the animation.
21 /// @ingroup component
23  Color _active,
24  animation::Duration _duration,
25  animation::easing::Function _function) {
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.
36 /// @ingroup component
40  SetAnimationFunction(std::move(f));
41 }
42 
43 /// @brief Set how the underline should animate.
44 /// @param d The duration of the animation.
45 /// @ingroup component
47  leader_duration = d;
49 }
50 
51 /// @brief Set how the underline should animate.
52 /// @param f The easing function of the animation.
53 /// @ingroup component
55  leader_function = f;
56  follower_function = std::move(f);
57 }
58 
59 /// @brief Set how the underline should animate.
60 /// This is useful to desynchronize the animation of the leader and the
61 /// follower.
62 /// @param f_leader The duration of the animation for the leader.
63 /// @param f_follower The duration of the animation for the follower.
64 /// @ingroup component
67  animation::easing::Function f_follower) {
68  leader_function = std::move(f_leader);
69  follower_function = std::move(f_follower);
70 }
71 
72 /// @brief Standard options for an horizontal menu.
73 /// This can be useful to implement a tab bar.
74 /// @ingroup component
75 // static
77  MenuOption option;
78  option.direction = Direction::Right;
79  option.entries_option.transform = [](const EntryState& state) {
80  Element e = text(state.label);
81  if (state.focused) {
82  e |= inverted;
83  }
84  if (state.active) {
85  e |= bold;
86  }
87  if (!state.focused && !state.active) {
88  e |= dim;
89  }
90  return e;
91  };
92  option.elements_infix = [] { return text(" "); };
93 
94  return option;
95 }
96 
97 /// @brief Standard options for an animated horizontal menu.
98 /// This can be useful to implement a tab bar.
99 /// @ingroup component
100 // static
102  auto option = Horizontal();
103  option.underline.enabled = true;
104  return option;
105 }
106 
107 /// @brief Standard options for a vertical menu.
108 /// This can be useful to implement a list of selectable items.
109 /// @ingroup component
110 // static
112  MenuOption option;
113  option.entries_option.transform = [](const EntryState& state) {
114  Element e = text((state.active ? "> " : " ") + state.label); // NOLINT
115  if (state.focused) {
116  e |= inverted;
117  }
118  if (state.active) {
119  e |= bold;
120  }
121  if (!state.focused && !state.active) {
122  e |= dim;
123  }
124  return e;
125  };
126  return option;
127 }
128 
129 /// @brief Standard options for an animated vertical menu.
130 /// This can be useful to implement a list of selectable items.
131 /// @ingroup component
132 // static
134  auto option = MenuOption::Vertical();
135  option.entries_option.transform = [](const EntryState& state) {
136  Element e = text(state.label);
137  if (state.focused) {
138  e |= inverted;
139  }
140  if (state.active) {
141  e |= bold;
142  }
143  if (!state.focused && !state.active) {
144  e |= dim;
145  }
146  return e;
147  };
148  option.underline.enabled = true;
149  return option;
150 }
151 
152 /// @brief Standard options for a horitontal menu with some separator.
153 /// This can be useful to implement a tab bar.
154 /// @ingroup component
155 // static
157  auto option = MenuOption::Horizontal();
158  option.elements_infix = [] { return text("│") | automerge; };
159  return option;
160 }
161 
162 /// @brief Create a ButtonOption, highlighted using [] characters.
163 /// @ingroup component
164 // static
166  ButtonOption option;
167  option.transform = [](const EntryState& s) {
168  const std::string t = s.focused ? "[" + s.label + "]" //
169  : " " + s.label + " ";
170  return text(t);
171  };
172  return option;
173 }
174 
175 /// @brief Create a ButtonOption, inverted when focused.
176 /// @ingroup component
177 // static
179  ButtonOption option;
180  option.transform = [](const EntryState& s) {
181  auto element = text(s.label) | borderLight;
182  if (s.focused) {
183  element |= inverted;
184  }
185  return element;
186  };
187  return option;
188 }
189 
190 /// @brief Create a ButtonOption. The button is shown using a border, inverted
191 /// when focused. This is the current default.
192 /// @ingroup component
194  ButtonOption option;
195  option.transform = [](const EntryState& s) {
196  auto element = text(s.label) | border;
197  if (s.active) {
198  element |= bold;
199  }
200  if (s.focused) {
201  element |= inverted;
202  }
203  return element;
204  };
205  return option;
206 }
207 
208 /// @brief Create a ButtonOption, using animated colors.
209 /// @ingroup component
210 // static
214 }
215 
216 /// @brief Create a ButtonOption, using animated colors.
217 /// @ingroup component
218 // static
220  return ButtonOption::Animated(
221  Color::Interpolate(0.85F, color, Color::Black), // NOLINT
222  Color::Interpolate(0.10F, color, Color::White), // NOLINT
223  Color::Interpolate(0.10F, color, Color::Black), // NOLINT
224  Color::Interpolate(0.85F, color, Color::White)); // NOLINT
225 }
226 
227 /// @brief Create a ButtonOption, using animated colors.
228 /// @ingroup component
229 // static
231  // NOLINTBEGIN
232  return ButtonOption::Animated(
233  /*bakground=*/background,
234  /*foreground=*/foreground,
235  /*background_active=*/foreground,
236  /*foreground_active=*/background);
237  // NOLINTEND
238 }
239 
240 /// @brief Create a ButtonOption, using animated colors.
241 /// @ingroup component
242 // static
244  Color foreground,
245  Color background_active,
246  Color foreground_active) {
247  ButtonOption option;
248  option.transform = [](const EntryState& s) {
249  auto element = text(s.label) | borderEmpty;
250  if (s.focused) {
251  element |= bold;
252  }
253  return element;
254  };
255  option.animated_colors.foreground.Set(foreground, foreground_active);
256  option.animated_colors.background.Set(background, background_active);
257  return option;
258 }
259 
260 /// @brief Option for standard Checkbox.
261 /// @ingroup component
262 // static
264  auto option = CheckboxOption();
265  option.transform = [](const EntryState& s) {
266 #if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
267  // Microsoft terminal do not use fonts able to render properly the default
268  // radiobox glyph.
269  auto prefix = text(s.state ? "[X] " : "[ ] "); // NOLINT
270 #else
271  auto prefix = text(s.state ? "▣ " : "☐ "); // NOLINT
272 #endif
273  auto t = text(s.label);
274  if (s.active) {
275  t |= bold;
276  }
277  if (s.focused) {
278  t |= inverted;
279  }
280  return hbox({prefix, t});
281  };
282  return option;
283 }
284 
285 /// @brief Option for standard Radiobox
286 /// @ingroup component
287 // static
289  auto option = RadioboxOption();
290  option.transform = [](const EntryState& s) {
291 #if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
292  // Microsoft terminal do not use fonts able to render properly the default
293  // radiobox glyph.
294  auto prefix = text(s.state ? "(*) " : "( ) "); // NOLINT
295 #else
296  auto prefix = text(s.state ? "◉ " : "○ "); // NOLINT
297 #endif
298  auto t = text(s.label);
299  if (s.active) {
300  t |= bold;
301  }
302  if (s.focused) {
303  t |= inverted;
304  }
305  return hbox({prefix, t});
306  };
307  return option;
308 }
309 
310 /// @brief Standard options for the input component.
311 /// @ingroup component
312 // static
314  InputOption option;
315  option.transform = [](InputState state) {
316  state.element |= color(Color::White);
317 
318  if (state.is_placeholder) {
319  state.element |= dim;
320  }
321 
322  if (state.focused) {
323  state.element |= inverted;
324  } else if (state.hovered) {
325  state.element |= bgcolor(Color::GrayDark);
326  }
327 
328  return state.element;
329  };
330  return option;
331 }
332 
333 /// @brief Standard options for a more beautiful input component.
334 /// @ingroup component
335 // static
337  InputOption option;
338  option.transform = [](InputState state) {
339  state.element |= borderEmpty;
340  state.element |= color(Color::White);
341 
342  if (state.is_placeholder) {
343  state.element |= dim;
344  }
345 
346  if (state.focused) {
347  state.element |= bgcolor(Color::Black);
348  }
349 
350  if (state.hovered) {
351  state.element |= bgcolor(Color::GrayDark);
352  }
353 
354  return state.element;
355  };
356  return option;
357 }
358 
359 } // namespace ftxui
A class representing terminal colors.
Definition: color.hpp:21
static Color Interpolate(float t, const Color &a, const Color &b)
Definition: color.cpp:176
std::function< float(float)> Function
Definition: animation.hpp:39
std::chrono::duration< float > Duration
Definition: animation.hpp:24
Decorator bgcolor(Color)
Decorate using a background color.
Definition: color.cpp:105
AnimatedColorOption foreground
std::shared_ptr< Node > Element
Definition: elements.hpp:23
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:120
Element borderLight(Element)
Draw a dashed border around the element.
Definition: border.cpp:335
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:227
Element borderEmpty(Element)
Draw an empty border around the element.
Definition: border.cpp:475
Decorator color(Color)
Decorate using a foreground color.
Definition: color.cpp:91
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