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) {}
73 bool IsHorizontal() {
return ftxui::IsHorizontal(
direction); }
87 if (
selected() != selected_previous_) {
90 boxes_.resize(size());
92 selected_previous_ =
util::clamp(selected_previous_, 0, size() - 1);
93 selected_focus_ =
util::clamp(selected_focus_, 0, size() - 1);
97 void OnAnimation(animation::Params& params)
override {
100 for (
auto& animator : animator_background_) {
101 animator.OnAnimation(params);
103 for (
auto& animator : animator_foreground_) {
104 animator.OnAnimation(params);
110 UpdateAnimationTarget();
113 const bool is_menu_focused =
Focused();
117 elements.reserve(size());
118 for (
int i = 0; i < size(); ++i) {
122 const bool is_focused = (
focused_entry() == i) && is_menu_focused;
123 const bool is_selected = (
selected() == i);
125 const EntryState state = {
126 entries[i],
false, is_selected, is_focused, i,
130 : DefaultOptionTransform)
132 if (selected_focus_ == i) {
135 element |= AnimatedColorStyle(i);
137 elements.push_back(element);
144 std::reverse(elements.begin(), elements.end());
147 const Element bar = IsHorizontal()
148 ?
hbox(std::move(elements), selected_focus_)
149 : vbox(std::move(elements), selected_focus_);
152 return bar | reflect(box_);
155 if (IsHorizontal()) {
174 void SelectedTakeFocus() {
236 bool OnEvent(Event event)
override {
242 if (event.is_mouse()) {
243 return OnMouseEvent(event);
247 const int old_selected =
selected();
297 bool OnMouseEvent(Event event) {
300 return OnMouseWheel(event);
310 for (
int i = 0; i < size(); ++i) {
311 if (!boxes_[i].Contain(event.mouse().x, event.mouse().y)) {
331 bool OnMouseWheel(Event event) {
332 if (!box_.
Contain(event.mouse().x, event.mouse().y)) {
335 const int old_selected =
selected();
353 void UpdateAnimationTarget() {
355 UpdateUnderlineTarget();
358 void UpdateColorTarget() {
359 if (size() !=
int(animation_background_.size())) {
360 animation_background_.resize(size());
361 animation_foreground_.resize(size());
362 animator_background_.clear();
363 animator_foreground_.clear();
365 const int len = size();
366 animator_background_.reserve(len);
367 animator_foreground_.reserve(len);
368 for (
int i = 0; i < len; ++i) {
369 animation_background_[i] = 0.F;
370 animation_foreground_[i] = 0.F;
371 animator_background_.emplace_back(&animation_background_[i], 0.F,
372 std::chrono::milliseconds(0),
374 animator_foreground_.emplace_back(&animation_foreground_[i], 0.F,
375 std::chrono::milliseconds(0),
380 const bool is_menu_focused =
Focused();
381 for (
int i = 0; i < size(); ++i) {
382 const bool is_focused = (
focused_entry() == i) && is_menu_focused;
383 const bool is_selected = (
selected() == i);
384 float target = is_selected ? 1.F : is_focused ? 0.5F : 0.F;
385 if (animator_background_[i].to() != target) {
386 animator_background_[i] = animation::Animator(
387 &animation_background_[i], target,
390 animator_foreground_[i] = animation::Animator(
391 &animation_foreground_[i], target,
402 animation_foreground_[i],
409 animation_background_[i],
416 void UpdateUnderlineTarget() {
421 if (FirstTarget() == animator_first_.
to() &&
422 SecondTarget() == animator_second_.
to()) {
426 if (FirstTarget() >= animator_first_.
to()) {
427 animator_first_ = animation::Animator(
431 animator_second_ = animation::Animator(
435 animator_first_ = animation::Animator(
439 animator_second_ = animation::Animator(
445 bool Focusable() const final {
return entries.
size(); }
447 float FirstTarget() {
448 if (boxes_.empty()) {
451 const int value = IsHorizontal() ? boxes_[
selected()].x_min - box_.
x_min
455 float SecondTarget() {
456 if (boxes_.empty()) {
459 const int value = IsHorizontal() ? boxes_[
selected()].x_max - box_.
x_min
465 int selected_previous_ =
selected();
469 std::vector<Box> boxes_;
475 animation::Animator animator_first_ = animation::Animator(&first_, 0.F);
476 animation::Animator animator_second_ = animation::Animator(&second_, 0.F);
477 std::vector<animation::Animator> animator_background_;
478 std::vector<animation::Animator> animator_foreground_;
479 std::vector<float> animation_background_;
480 std::vector<float> animation_foreground_;
544 option.
entries = std::move(entries);
585 option.
label = std::move(label);
622 const bool is_focused = Focused();
623 UpdateAnimationTarget();
626 label(),
false, hovered_, is_focused, Index(),
629 Element element = (transform ? transform : DefaultOptionTransform)
636 return element | AnimatedColorStyle() | reflect(box_);
639 void UpdateAnimationTarget() {
640 const bool focused = Focused();
641 float target = focused ? 1.F : hovered_ ? 0.5F : 0.F;
642 if (target == animator_background_.to()) {
646 &animation_background_, target, animated_colors.background.duration,
647 animated_colors.background.function);
649 &animation_foreground_, target, animated_colors.foreground.duration,
650 animated_colors.foreground.function);
655 if (animated_colors.foreground.enabled) {
657 color(Color::Interpolate(animation_foreground_,
658 animated_colors.foreground.inactive,
659 animated_colors.foreground.active));
662 if (animated_colors.background.enabled) {
664 bgcolor(Color::Interpolate(animation_background_,
665 animated_colors.background.inactive,
666 animated_colors.background.active));
671 bool Focusable()
const override {
return true; }
672 bool OnEvent(
Event event)
override {
677 hovered_ = box_.Contain(event.
mouse().
x, event.
mouse().
y);
693 animator_background_.OnAnimation(params);
694 animator_foreground_.OnAnimation(params);
698 bool hovered_ =
false;
700 float animation_background_ = 0.F;
701 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 text(std::wstring text)
Display a piece of unicode text.
Element focus(Element)
Set the child to be the one focused among its siblings.
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|,...