29Element DefaultOptionTransform(
const EntryState& state) {
30 std::string label = (state.active ?
"> " :
" ") + state.label;
69class MenuBase :
public ComponentBase,
public MenuOption {
71 explicit MenuBase(
const MenuOption& option) : MenuOption(option) {
75 bool IsHorizontal() {
return ftxui::IsHorizontal(
direction); }
89 if (
selected() != selected_previous_) {
92 boxes_.resize(size());
94 selected_previous_ =
util::clamp(selected_previous_, 0, size() - 1);
95 selected_focus_ =
util::clamp(selected_focus_, 0, size() - 1);
99 void OnAnimation(animation::Params& params)
override {
102 for (
auto& animator : animator_background_) {
103 animator.OnAnimation(params);
105 for (
auto& animator : animator_foreground_) {
106 animator.OnAnimation(params);
112 UpdateAnimationTarget();
115 const bool is_menu_focused =
Focused();
119 elements.reserve(size());
120 for (
int i = 0; i < size(); ++i) {
124 const bool is_focused = (
focused_entry() == i) && is_menu_focused;
125 const bool is_selected = (
selected() == i);
127 const EntryState state = {
128 std::string(
entries[i]),
false, is_selected, is_focused, i,
132 : DefaultOptionTransform)
134 if (selected_focus_ == i) {
137 element |= AnimatedColorStyle(i);
139 elements.push_back(element);
146 std::reverse(elements.begin(), elements.end());
150 IsHorizontal() ?
hbox(std::move(elements)) : vbox(std::move(elements));
153 return bar | reflect(box_);
156 if (IsHorizontal()) {
175 void SelectedTakeFocus() {
237 bool OnEvent(Event event)
override {
243 if (event.is_mouse()) {
244 return OnMouseEvent(event);
248 const int old_selected =
selected();
298 bool OnMouseEvent(Event event) {
301 return OnMouseWheel(event);
311 for (
int i = 0; i < size(); ++i) {
312 if (!boxes_[i].Contain(event.mouse().x, event.mouse().y)) {
332 bool OnMouseWheel(Event event) {
333 if (!box_.
Contain(event.mouse().x, event.mouse().y)) {
336 const int old_selected =
selected();
354 void UpdateAnimationTarget() {
356 UpdateUnderlineTarget();
359 void UpdateColorTarget() {
360 if (size() !=
int(animation_background_.size())) {
361 animation_background_.resize(size());
362 animation_foreground_.resize(size());
363 animator_background_.clear();
364 animator_foreground_.clear();
366 const int len = size();
367 animator_background_.reserve(len);
368 animator_foreground_.reserve(len);
369 for (
int i = 0; i < len; ++i) {
370 animation_background_[i] = 0.F;
371 animation_foreground_[i] = 0.F;
372 animator_background_.emplace_back(&animation_background_[i], 0.F,
373 std::chrono::milliseconds(0),
375 animator_foreground_.emplace_back(&animation_foreground_[i], 0.F,
376 std::chrono::milliseconds(0),
381 const bool is_menu_focused =
Focused();
382 for (
int i = 0; i < size(); ++i) {
383 const bool is_focused = (
focused_entry() == i) && is_menu_focused;
384 const bool is_selected = (
selected() == i);
385 float target = is_selected ? 1.F : is_focused ? 0.5F : 0.F;
386 if (animator_background_[i].to() != target) {
387 animator_background_[i] = animation::Animator(
388 &animation_background_[i], target,
391 animator_foreground_[i] = animation::Animator(
392 &animation_foreground_[i], target,
403 animation_foreground_[i],
410 animation_background_[i],
417 void UpdateUnderlineTarget() {
422 if (FirstTarget() == animator_first_.
to() &&
423 SecondTarget() == animator_second_.
to()) {
427 if (FirstTarget() >= animator_first_.
to()) {
428 animator_first_ = animation::Animator(
432 animator_second_ = animation::Animator(
436 animator_first_ = animation::Animator(
440 animator_second_ = animation::Animator(
446 bool Focusable() const final {
return entries.
size(); }
448 float FirstTarget() {
449 if (boxes_.empty()) {
452 const int value = IsHorizontal() ? boxes_[
selected()].x_min - box_.
x_min
456 float SecondTarget() {
457 if (boxes_.empty()) {
460 const int value = IsHorizontal() ? boxes_[
selected()].x_max - box_.
x_min
466 int selected_previous_ =
selected();
470 std::vector<Box> boxes_;
476 animation::Animator animator_first_ = animation::Animator(&first_, 0.F);
477 animation::Animator animator_second_ = animation::Animator(&second_, 0.F);
478 std::vector<animation::Animator> animator_background_;
479 std::vector<animation::Animator> animator_foreground_;
480 std::vector<float> animation_background_;
481 std::vector<float> animation_foreground_;
545 option.
entries = std::move(entries);
586 option.
label = std::move(label);
623 const bool is_focused = Focused();
624 UpdateAnimationTarget();
627 std::string(label()),
false, hovered_, is_focused, Index(),
630 Element element = (transform ? transform : DefaultOptionTransform)
637 return element | AnimatedColorStyle() | reflect(box_);
640 void UpdateAnimationTarget() {
641 const bool focused = Focused();
642 float target = focused ? 1.F : hovered_ ? 0.5F : 0.F;
643 if (target == animator_background_.to()) {
647 &animation_background_, target, animated_colors.background.duration,
648 animated_colors.background.function);
650 &animation_foreground_, target, animated_colors.foreground.duration,
651 animated_colors.foreground.function);
656 if (animated_colors.foreground.enabled) {
658 color(Color::Interpolate(animation_foreground_,
659 animated_colors.foreground.inactive,
660 animated_colors.foreground.active));
663 if (animated_colors.background.enabled) {
665 bgcolor(Color::Interpolate(animation_background_,
666 animated_colors.background.inactive,
667 animated_colors.background.active));
672 bool Focusable()
const override {
return true; }
673 bool OnEvent(
Event event)
override {
678 hovered_ = box_.Contain(event.
mouse().
x, event.
mouse().
y);
694 animator_background_.OnAnimation(params);
695 animator_foreground_.OnAnimation(params);
699 bool hovered_ =
false;
701 float animation_background_ = 0.F;
702 float animation_foreground_ = 0.F;
An adapter. Reference a list of strings.
An adapter. Own or reference a constant string. For convenience, this class convert multiple immutabl...
void OnAnimation(Params &)
static const Event TabReverse
bool Focused() const
Returns if the elements if focused by the user. True when the ComponentBase is focused by the user....
std::function< Element()> elements_prefix
static MenuOption Toggle()
Standard options for a horizontal menu with some separator. This can be useful to implement a tab bar...
animation::Duration follower_duration
CapturedMouse CaptureMouse(const Event &event)
Take the CapturedMouse if available. There is only one component of them. It represents a component t...
animation::easing::Function leader_function
MenuEntryOption entries_option
static const Event PageUp
animation::easing::Function function
animation::Duration follower_delay
void TakeFocus()
Configure all the ancestors to give focus to this component.
std::function< void()> on_enter
UnderlineOption underline
std::function< Element(const EntryState &state)> transform
animation::Duration leader_duration
animation::Duration duration
ConstStringListRef entries
animation::easing::Function follower_function
static const Event ArrowUp
std::function< Element()> elements_infix
static const Event ArrowDown
std::function< Element()> elements_postfix
AnimatedColorsOption animated_colors
std::function< void()> on_change
static const Event PageDown
static const Event Return
static const Event ArrowLeft
animation::Duration leader_delay
static const Event ArrowRight
It implement rendering itself as ftxui::Element. It implement keyboard navigation by responding to ft...
Component Menu(MenuOption options)
A list of text. The focused element is selected.
Component MenuEntry(MenuEntryOption options)
A specific menu entry. They can be put into a Container::Vertical to form a menu.
Component Toggle(ConstStringListRef entries, int *selected)
An horizontal list of elements. The user can navigate through them.
Represent an event. It can be key press event, a terminal resize, or more ...
Decorator bgcolor(Color)
Decorate using a background color.
Element xflex(Element)
Expand/Minimize if possible/needed on the X axis.
Element nothing(Element element)
A decoration doing absolutely nothing.
Direction
Direction is an enumeration that represents the four cardinal directions.
Element bold(Element)
Use a bold font, for elements with more emphasis.
Element yflex(Element)
Expand/Minimize if possible/needed on the Y axis.
Element inverted(Element)
Add a filter that will invert the foreground and the background colors.
Element focus(Element)
Set the child to be the one focused among its siblings.
Element text(std::wstring_view text)
Display a piece of unicode text.
Decorator color(Color)
Decorate using a foreground color.
Element vbox(Elements)
A container displaying elements vertically one by one.
bool Contain(int x, int y) const
static Color Interpolate(float t, const Color &a, const Color &b)
Box is a structure that represents a rectangular area in a 2D space.
float Linear(float p)
Modeled after the line y = x.
constexpr const T & clamp(const T &v, const T &lo, const T &hi)
The FTXUI ftxui:: namespace.
std::function< Element(Element)> Decorator
Element separatorVSelector(float up, float down, Color unselected_color, Color selected_color)
Draw an vertical bar, with the area in between up/downcolored differently.
std::shared_ptr< T > Make(Args &&... args)
std::shared_ptr< Node > Element
Element separatorHSelector(float left, float right, Color unselected_color, Color selected_color)
Draw a horizontal bar, with the area in between left/right colored differently.
Element hbox(Elements)
A container displaying elements horizontally one by one.
std::vector< Element > Elements
Decorator reflect(Box &box)
std::shared_ptr< ComponentBase > Component
AnimatedColorOption foreground
AnimatedColorOption background
arguments for transform from |ButtonOption|, |CheckboxOption|, |RadioboxOption|, |MenuEntryOption|,...