Loading...
Searching...
No Matches
dropdown.cpp
Go to the documentation of this file.
// Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
#include <ftxui/component/event.hpp>
#include <functional> // for function
#include <string> // for string
#include <utility>
#include "ftxui/component/component.hpp" // for Maybe, Checkbox, Make, Radiobox, Vertical, Dropdown
#include "ftxui/component/component_base.hpp" // for Component, ComponentBase
#include "ftxui/component/component_options.hpp" // for CheckboxOption, EntryState
#include "ftxui/dom/elements.hpp" // for operator|, Element, border, filler, operator|=, separator, size, text, vbox, frame, vscroll_indicator, hbox, HEIGHT, LESS_THAN, bold, inverted
#include "ftxui/screen/util.hpp" // for clamp
#include "ftxui/util/ref.hpp" // for ConstStringListRef
namespace ftxui {
/// @brief A dropdown menu.
/// @ingroup component
/// @param entries The list of entries to display.
/// @param selected The index of the selected entry.
Component Dropdown(ConstStringListRef entries, int* selected) {
DropdownOption option;
option.radiobox.entries = std::move(entries);
option.radiobox.selected = selected;
return Dropdown(option);
}
/// @brief A dropdown menu.
/// @ingroup component
/// @param option The options for the dropdown.
// NOLINTNEXTLINE
Component Dropdown(DropdownOption option) {
class Impl : public ComponentBase, public DropdownOption {
public:
explicit Impl(DropdownOption option) : DropdownOption(std::move(option)) {
FillDefault();
checkbox_ = Checkbox(checkbox);
radiobox_ = Radiobox(radiobox);
Add(Container::Vertical({
checkbox_,
Maybe(radiobox_, checkbox.checked),
}));
}
Element OnRender() override {
selected_ =
util::clamp(radiobox.selected(), 0, int(radiobox.entries.size()) - 1);
selected_ = util::clamp(selected_(), 0, int(radiobox.entries.size()) - 1);
if (selected_() >= 0 && selected_() < int(radiobox.entries.size())) {
title_ = radiobox.entries[selected_()];
}
return transform(*open_, checkbox_->Render(), radiobox_->Render());
}
// Switch focus in between the checkbox and the radiobox when selecting it.
bool OnEvent(ftxui::Event event) override {
const bool open_old = open_();
const int selected_old = selected_();
bool handled = ComponentBase::OnEvent(event);
// Transfer focus to the radiobox when the dropdown is opened.
if (!open_old && open_()) {
radiobox_->TakeFocus();
}
// Auto-close the dropdown when the user selects an item, even if the item
// it the same as the previous one.
if (open_old && open_()) {
const bool should_close =
(selected_() != selected_old) || //
(event == Event::Return) || //
(event == Event::Character(' ')) || //
(event == Event::Escape) || //
(event.is_mouse() && event.mouse().button == Mouse::Left &&
event.mouse().motion == Mouse::Pressed);
if (should_close) {
checkbox_->TakeFocus();
open_ = false;
handled = true;
}
}
return handled;
}
void FillDefault() {
open_ = checkbox.checked;
selected_ = radiobox.selected;
checkbox.checked = &*open_;
radiobox.selected = &*selected_;
checkbox.label = &title_;
if (!checkbox.transform) {
checkbox.transform = [](const EntryState& s) {
auto prefix = text(s.state ? "↓ " : "→ "); // NOLINT
auto t = text(s.label);
if (s.active) {
t |= bold;
}
if (s.focused) {
t |= inverted;
}
return hbox({prefix, t});
};
}
if (!transform) {
transform = [](bool is_open, Element checkbox_element,
Element radiobox_element) {
if (is_open) {
const int max_height = 12;
return vbox({
std::move(checkbox_element),
separator(),
std::move(radiobox_element) | vscroll_indicator | frame |
size(HEIGHT, LESS_THAN, max_height),
}) |
border;
}
return vbox({std::move(checkbox_element), filler()}) | border;
};
}
}
private:
Ref<bool> open_;
Ref<int> selected_;
Component checkbox_;
Component radiobox_;
std::string title_;
};
return Make<Impl>(option);
}
} // namespace ftxui
ftxui::ComponentBase
It implement rendering itself as ftxui::Element. It implement keyboard navigation by responding to ft...
Definition component_base.hpp:30
ftxui::ComponentBase::OnEvent
virtual bool OnEvent(Event)
Called in response to an event.
Definition component.cpp:161
ftxui::ConstStringListRef
An adapter. Reference a list of strings.
Definition ref.hpp:116
ftxui::Ref
An adapter. Own or reference an mutable object.
Definition ref.hpp:46
component.hpp
component_base.hpp
component_options.hpp
elements.hpp
event.hpp
ftxui::Container::Vertical
Component Vertical(Components children)
A list of components, drawn one by one vertically and navigated vertically using up/down arrow key or...
Definition container.cpp:317
ftxui::util::clamp
constexpr const T & clamp(const T &v, const T &lo, const T &hi)
Definition util.hpp:11
ftxui
Definition animation.hpp:10
ftxui::HEIGHT
@ HEIGHT
Definition elements.hpp:153
ftxui::vscroll_indicator
Element vscroll_indicator(Element)
Display a vertical scrollbar to the right. colors.
Definition scroll_indicator.cpp:21
ftxui::size
Decorator size(WidthOrHeight, Constraint, int value)
Apply a constraint on the size of an element.
Definition size.cpp:89
ftxui::Maybe
Component Maybe(Component, const bool *show)
Decorate a component |child|. It is shown only when |show| is true.
Definition maybe.cpp:74
ftxui::Element
std::shared_ptr< Node > Element
Definition elements.hpp:22
ftxui::Make
std::shared_ptr< T > Make(Args &&... args)
Definition component.hpp:26
ftxui::Component
std::shared_ptr< ComponentBase > Component
Definition component_base.hpp:24
ftxui::bold
Element bold(Element)
Use a bold font, for elements with more emphasis.
Definition bold.cpp:33
ftxui::Radiobox
Component Radiobox(RadioboxOption options)
A list of element, where only one can be selected.
Definition radiobox.cpp:204
ftxui::hbox
Element hbox(Elements)
A container displaying elements horizontally one by one.
Definition hbox.cpp:94
ftxui::inverted
Element inverted(Element)
Add a filter that will invert the foreground and the background colors.
Definition inverted.cpp:34
ftxui::text
Element text(std::wstring text)
Display a piece of unicode text.
Definition text.cpp:160
ftxui::DropdownOption::radiobox
RadioboxOption radiobox
Definition component_options.hpp:276
ftxui::Dropdown
Component Dropdown(ConstStringListRef entries, int *selected)
A dropdown menu.
Definition dropdown.cpp:22
ftxui::separator
Element separator()
Draw a vertical or horizontal separation in between two other elements.
Definition separator.cpp:134
ftxui::filler
Element filler()
An element that will take expand proportionally to the space left in a container.
Definition flex.cpp:98
ftxui::frame
Element frame(Element)
Allow an element to be displayed inside a 'virtual' area. It size can be larger than its container....
Definition frame.cpp:118
ftxui::LESS_THAN
@ LESS_THAN
Definition elements.hpp:154
ftxui::Checkbox
Component Checkbox(CheckboxOption options)
Draw checkable element.
Definition checkbox.cpp:108
ftxui::border
Element border(Element)
Draw a border around the element.
Definition border.cpp:227
ftxui::vbox
Element vbox(Elements)
A container displaying elements vertically one by one.
Definition vbox.cpp:96
ftxui::DropdownOption
Option for the Dropdown component.A dropdown menu is a checkbox opening/closing a radiobox.
Definition component_options.hpp:270
ftxui::EntryState
arguments for |ButtonOption::transform|, |CheckboxOption::transform|, |Radiobox::transform|,...
Definition component_options.hpp:23
ref.hpp
ftxui::Event
Represent an event. It can be key press event, a terminal resize, or more ...
Definition event.hpp:27
ftxui::Event::Escape
static const Event Escape
Definition event.hpp:52
ftxui::Event::Return
static const Event Return
Definition event.hpp:51
ftxui::Mouse::Left
@ Left
Definition mouse.hpp:13
ftxui::Mouse::Pressed
@ Pressed
Definition mouse.hpp:25
ftxui::RadioboxOption::entries
ConstStringListRef entries
Definition component_options.hpp:198
util.hpp