FTXUI  0.10.0
C++ functional terminal UI.
Loading...
Searching...
No Matches
toggle.cpp
Go to the documentation of this file.
1#include <stddef.h> // for size_t
2#include <algorithm> // for max, min
3#include <functional> // for function
4#include <memory> // for shared_ptr, allocator_traits<>::value_type
5#include <utility> // for move
6#include <vector> // for vector
7
8#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
9#include "ftxui/component/component.hpp" // for Make, Toggle
10#include "ftxui/component/component_base.hpp" // for Component, ComponentBase
11#include "ftxui/component/component_options.hpp" // for ToggleOption
12#include "ftxui/component/event.hpp" // for Event, Event::ArrowLeft, Event::ArrowRight, Event::Return, Event::Tab, Event::TabReverse
13#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed
14#include "ftxui/dom/elements.hpp" // for operator|, Element, Elements, hbox, reflect, separator, text, focus, nothing, select
15#include "ftxui/screen/box.hpp" // for Box
16#include "ftxui/util/ref.hpp" // for ConstStringListRef, Ref
17
18namespace ftxui {
19
20namespace {
21
22/// @brief An horizontal list of elements. The user can navigate through them.
23/// @ingroup component
24class ToggleBase : public ComponentBase {
25 public:
26 ToggleBase(ConstStringListRef entries,
27 int* selected,
28 Ref<ToggleOption> option)
29 : entries_(entries), selected_(selected), option_(std::move(option)) {}
30
31 private:
32 Element Render() override {
33 Elements children;
34 bool is_toggle_focused = Focused();
35 boxes_.resize(entries_.size());
36 for (size_t i = 0; i < entries_.size(); ++i) {
37 // Separator.
38 if (i != 0)
39 children.push_back(separator());
40
41 bool is_focused = (focused_entry() == int(i)) && is_toggle_focused;
42 bool is_selected = (*selected_ == int(i));
43
44 auto style = is_selected ? (is_focused ? option_->style_selected_focused
45 : option_->style_selected)
46 : (is_focused ? option_->style_focused
47 : option_->style_normal);
48 auto focus_management = !is_selected ? nothing
49 : is_toggle_focused ? focus
50 : select;
51 children.push_back(text(entries_[i]) | style | focus_management |
52 reflect(boxes_[i]));
53 }
54 return hbox(std::move(children));
55 }
56
57 bool OnEvent(Event event) override {
58 if (event.is_mouse())
59 return OnMouseEvent(event);
60
61 int old_selected = *selected_;
62 if (event == Event::ArrowLeft || event == Event::Character('h'))
63 (*selected_)--;
64 if (event == Event::ArrowRight || event == Event::Character('l'))
65 (*selected_)++;
66 if (event == Event::Tab && entries_.size())
67 *selected_ = (*selected_ + 1) % entries_.size();
68 if (event == Event::TabReverse && entries_.size())
69 *selected_ = (*selected_ + entries_.size() - 1) % entries_.size();
70
71 *selected_ = std::max(0, std::min(int(entries_.size()) - 1, *selected_));
72
73 if (old_selected != *selected_) {
74 focused_entry() = *selected_;
75 option_->on_change();
76 return true;
77 }
78
79 if (event == Event::Return) {
80 option_->on_enter();
81 return true;
82 }
83
84 return false;
85 }
86
87 bool OnMouseEvent(Event event) {
88 if (!CaptureMouse(event))
89 return false;
90 for (int i = 0; i < int(boxes_.size()); ++i) {
91 if (!boxes_[i].Contain(event.mouse().x, event.mouse().y))
92 continue;
93
94 TakeFocus();
95 focused_entry() = i;
96 if (event.mouse().button == Mouse::Left &&
97 event.mouse().motion == Mouse::Pressed) {
98 TakeFocus();
99 if (*selected_ != i) {
100 *selected_ = i;
101 option_->on_change();
102 }
103 return true;
104 }
105 }
106 return false;
107 }
108
109 bool Focusable() const final { return entries_.size(); }
110 int& focused_entry() { return option_->focused_entry(); }
111
112 ConstStringListRef entries_;
113 int* selected_ = 0;
114
115 std::vector<Box> boxes_;
116 Ref<ToggleOption> option_;
117};
118
119} // namespace
120
121/// @brief An horizontal list of elements. The user can navigate through them.
122/// @param entries The list of selectable entries to display.
123/// @param selected Reference the selected entry.
124/// @param option Additional optional parameters.
125/// @ingroup component
127 int* selected,
128 Ref<ToggleOption> option) {
129 return Make<ToggleBase>(entries, selected, std::move(option));
130}
131
132} // namespace ftxui
133
134// Copyright 2020 Arthur Sonzogni. All rights reserved.
135// Use of this source code is governed by the MIT license that can be found in
136// the LICENSE file.
An adapter. Reference a list of strings.
Definition ref.hpp:94
An adapter. Own or reference an mutable object.
Definition ref.hpp:27
Element nothing(Element element)
A decoration doing absolutely nothing.
Definition util.cpp:25
Component Toggle(ConstStringListRef entries, int *selected, Ref< ToggleOption > option={})
An horizontal list of elements. The user can navigate through them.
Definition toggle.cpp:126
std::shared_ptr< T > Make(Args &&... args)
Definition component.hpp:25
std::shared_ptr< Node > Element
Definition elements.hpp:15
Element separator(void)
Definition separator.cpp:61
Element focus(Element)
Definition frame.cpp:79
Element hbox(Elements)
A container displaying elements horizontally one by one.
Definition hbox.cpp:76
std::vector< Element > Elements
Definition elements.hpp:16
Element text(std::wstring text)
Display a piece of unicode text.
Definition text.cpp:106
Decorator reflect(Box &box)
Definition reflect.cpp:39
void Render(Screen &screen, const Element &node)
Display an element on a ftxui::Screen.
Definition node.cpp:34
Element select(Element)
Definition frame.cpp:38
std::shared_ptr< ComponentBase > Component
static const Event TabReverse
Definition event.hpp:46
static const Event Tab
Definition event.hpp:45
static const Event Return
Definition event.hpp:43
static const Event ArrowLeft
Definition event.hpp:35
static const Event ArrowRight
Definition event.hpp:36