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))
149 : vbox(std::move(elements));
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);
584 option.
label = std::move(label);
620 const bool is_focused = Focused();
621 UpdateAnimationTarget();
624 label(),
false, hovered_, is_focused, Index(),
627 Element element = (transform ? transform : DefaultOptionTransform)
634 return element | AnimatedColorStyle() | reflect(box_);
637 void UpdateAnimationTarget() {
638 const bool focused = Focused();
639 float target = focused ? 1.F : hovered_ ? 0.5F : 0.F;
640 if (target == animator_background_.to()) {
644 &animation_background_, target, animated_colors.background.duration,
645 animated_colors.background.function);
647 &animation_foreground_, target, animated_colors.foreground.duration,
648 animated_colors.foreground.function);
653 if (animated_colors.foreground.enabled) {
655 color(Color::Interpolate(animation_foreground_,
656 animated_colors.foreground.inactive,
657 animated_colors.foreground.active));
660 if (animated_colors.background.enabled) {
662 bgcolor(Color::Interpolate(animation_background_,
663 animated_colors.background.inactive,
664 animated_colors.background.active));
669 bool Focusable()
const override {
return true; }
670 bool OnEvent(
Event event)
override {
675 hovered_ = box_.Contain(event.
mouse().
x, event.
mouse().
y);
691 animator_background_.OnAnimation(params);
692 animator_foreground_.OnAnimation(params);
696 bool hovered_ =
false;
698 float animation_background_ = 0.F;
699 float animation_foreground_ = 0.F;
一個適配器。擁有或引用一個常數字串。為方便起見,此類別將多個不可變字串轉換為共享表示。
void OnAnimation(Params &)
static const Event TabReverse
bool Focused() const
返回元素是否被使用者聚焦。 當 ComponentBase 被使用者聚焦時返回 true。當一個元素及其所有祖先都是其父項的 ActiveChild() 並且它是 Focusable() 時,該元素被聚...
std::function< Element()> elements_prefix
static MenuOption Toggle()
帶有分隔線的水平選單標準選項。 這對於實現一個標籤頁列很有用。
animation::Duration follower_duration
CapturedMouse CaptureMouse(const Event &event)
如果可用,則取得 CapturedMouse。它們只有一個組件。它代表一個優先於其他組件的組件。
animation::easing::Function leader_function
MenuEntryOption entries_option
static const Event PageUp
animation::easing::Function function
animation::Duration follower_delay
void TakeFocus()
配置所有祖先以將焦點給予此組件。
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
它將自己實作為 ftxui::Element 進行渲染。它透過回應 ftxui::Event 來實現鍵盤導航。
Component Menu(MenuOption options)
文字列表。選定的元素會被聚焦。
Component MenuEntry(MenuEntryOption options)
一個特定的菜單條目。它們可以放入 Container::Vertical 中以形成菜單。
Component Toggle(ConstStringListRef entries, int *selected)
元素的水平列表。使用者可以在其中導航。
代表一個事件。它可以是按鍵事件、終端機大小調整,或更多...
Decorator bgcolor(Color)
使用背景顏色進行裝飾。
Element xflex(Element)
在 X 軸上盡可能擴展/在需要時最小化。
Element nothing(Element element)
一個什麼都不做的裝飾器。
Direction
Direction 是一個列舉,表示四個主要方向。
Element bold(Element)
使用粗體字型,用於需要更多強調的元素。
Element yflex(Element)
在 Y 軸上盡可能擴展/在需要時最小化。
Element inverted(Element)
添加一個濾鏡,它將反轉前景和背景 顏色。
Element text(std::wstring text)
顯示一段 Unicode 文字。
Element focus(Element)
將 child 設置為其同級元素中被聚焦的元素。
Decorator color(Color)
使用前景顏色進行裝飾。
Element vbox(Elements)
一個垂直一個接一個顯示元素的容器。
bool Contain(int x, int y) const
static Color Interpolate(float t, const Color &a, const Color &b)
float Linear(float p)
模仿直線 y = x
constexpr const T & clamp(const T &v, const T &lo, const T &hi)
std::function< Element(Element)> Decorator
Element separatorVSelector(float up, float down, Color unselected_color, Color selected_color)
繪製一個垂直條,其中上方/下方之間的區域以不同顏色顯示。
std::shared_ptr< T > Make(Args &&... args)
std::shared_ptr< Node > Element
return Make< Impl >(option)
Element separatorHSelector(float left, float right, Color unselected_color, Color selected_color)
繪製一個水平條,其中左右兩側之間的區域以不同顏色顯示。
Element hbox(Elements)
一個逐一水平顯示元素的容器。
std::vector< Element > Elements
Decorator reflect(Box &box)
std::shared_ptr< ComponentBase > Component
AnimatedColorOption foreground
AnimatedColorOption background
來自 |ButtonOption|、|CheckboxOption|、 |RadioboxOption|、|MenuEntryOption|、|MenuOption| 的轉換參數。