FTXUI 6.1.9
C++ functional terminal UI.
Chargement...
Recherche...
Aucune correspondance
src/ftxui/component/radiobox.cpp
Aller à la documentation de ce fichier.
1// Copyright 2020 Arthur Sonzogni. Tous droits réservés.
2// L'utilisation de ce code source est régie par la licence MIT que l'on peut trouver dans
3// le fichier LICENSE.
4#include <functional> // for function
5#include <utility> // for move
6#include <vector> // for vector
7
8#include "ftxui/component/component.hpp" // for Make, Radiobox
9#include "ftxui/component/component_base.hpp" // for ComponentBase
10#include "ftxui/component/component_options.hpp" // for RadioboxOption, EntryState
11#include "ftxui/component/event.hpp" // for Event, Event::ArrowDown, Event::ArrowUp, Event::End, Event::Home, Event::PageDown, Event::PageUp, Event::Return, Event::Tab, Event::TabReverse
12#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::WheelDown, Mouse::WheelUp, Mouse::Left, Mouse::Released
13#include "ftxui/component/screen_interactive.hpp" // for Component
14#include "ftxui/dom/elements.hpp" // for operator|, reflect, Element, vbox, Elements, focus, nothing, select
15#include "ftxui/screen/box.hpp" // for Box
16#include "ftxui/screen/util.hpp" // for clamp
17#include "ftxui/util/ref.hpp" // for Ref, ConstStringListRef
18
19namespace ftxui {
20
21namespace {
22/// @brief Une liste d'éléments sélectionnables. Un seul et unique peut être sélectionné à
23/// la fois.
24/// @ingroup component
25class RadioboxBase : public ComponentBase, public RadioboxOption {
26 public:
27 explicit RadioboxBase(const RadioboxOption& option)
28 : RadioboxOption(option) {}
29
30 private:
31 Element OnRender() override {
32 Clamp();
33 Elements elements;
34 const bool is_menu_focused = Focused();
35 elements.reserve(size());
36 for (int i = 0; i < size(); ++i) {
37 const bool is_focused = (focused_entry() == i) && is_menu_focused;
38 const bool is_selected = (hovered_ == i);
39 auto state = EntryState{
40 entries[i], selected() == i, is_selected, is_focused, i,
41 };
42 auto element =
43 (transform ? transform : RadioboxOption::Simple().transform)(state);
44 if (is_selected) {
45 element |= focus;
46 }
47 elements.push_back(element | reflect(boxes_[i]));
48 }
49 return vbox(std::move(elements)) | reflect(box_);
50 }
51
52 // NOLINTNEXTLINE(readability-function-cognitive-complexity)
53 bool OnEvent(Event event) override {
54 Clamp();
55 if (!CaptureMouse(event)) {
56 return false;
57 }
58
59 if (event.is_mouse()) {
60 return OnMouseEvent(event);
61 }
62
63 if (Focused()) {
64 const int old_hovered = hovered_;
65 if (event == Event::ArrowUp || event == Event::Character('k')) {
66 (hovered_)--;
67 }
68 if (event == Event::ArrowDown || event == Event::Character('j')) {
69 (hovered_)++;
70 }
71 if (event == Event::PageUp) {
72 (hovered_) -= box_.y_max - box_.y_min;
73 }
74 if (event == Event::PageDown) {
75 (hovered_) += box_.y_max - box_.y_min;
76 }
77 if (event == Event::Home) {
78 (hovered_) = 0;
79 }
80 if (event == Event::End) {
81 (hovered_) = size() - 1;
82 }
83 if (event == Event::Tab && size()) {
84 hovered_ = (hovered_ + 1) % size();
85 }
86 if (event == Event::TabReverse && size()) {
87 hovered_ = (hovered_ + size() - 1) % size();
88 }
89
90 hovered_ = util::clamp(hovered_, 0, size() - 1);
91
92 if (hovered_ != old_hovered) {
93 focused_entry() = hovered_;
94 on_change();
95 return true;
96 }
97 }
98
99 if (event == Event::Character(' ') || event == Event::Return) {
100 selected() = hovered_;
101 on_change();
102 return true;
103 }
104
105 return false;
106 }
107
108 bool OnMouseEvent(Event event) {
109 if (event.mouse().button == Mouse::WheelDown ||
110 event.mouse().button == Mouse::WheelUp) {
111 return OnMouseWheel(event);
112 }
113
114 for (int i = 0; i < size(); ++i) {
115 if (!boxes_[i].Contain(event.mouse().x, event.mouse().y)) {
116 continue;
117 }
118
119 TakeFocus();
120 focused_entry() = i;
121 if (event.mouse().button == Mouse::Left &&
122 event.mouse().motion == Mouse::Pressed) {
123 if (selected() != i) {
124 selected() = i;
125 on_change();
126 }
127
128 return true;
129 }
130 }
131 return false;
132 }
133
134 bool OnMouseWheel(Event event) {
135 if (!box_.Contain(event.mouse().x, event.mouse().y)) {
136 return false;
137 }
138
139 const int old_hovered = hovered_;
140
141 if (event.mouse().button == Mouse::WheelUp) {
142 (hovered_)--;
143 }
144 if (event.mouse().button == Mouse::WheelDown) {
145 (hovered_)++;
146 }
147
148 hovered_ = util::clamp(hovered_, 0, size() - 1);
149
150 if (hovered_ != old_hovered) {
151 on_change();
152 }
153
154 return true;
155 }
156
157 void Clamp() {
158 boxes_.resize(size());
159 selected() = util::clamp(selected(), 0, size() - 1);
160 focused_entry() = util::clamp(focused_entry(), 0, size() - 1);
161 hovered_ = util::clamp(hovered_, 0, size() - 1);
162 }
163
164 bool Focusable() const final { return entries.size(); }
165 int size() const { return int(entries.size()); }
166
167 int hovered_ = selected();
168 std::vector<Box> boxes_;
169 Box box_;
170};
171
172} // namespace
173
174/// @brief Une liste d'éléments, où un seul peut être sélectionné.
175/// @param option Les paramètres
176/// @ingroup component
177/// @see RadioboxBase
178///
179/// ### Exemple
180///
181/// ```cpp
182/// auto screen = ScreenInteractive::TerminalOutput();
183/// std::vector<std::string> entries = {
184/// "entry 1",
185/// "entry 2",
186/// "entry 3",
187/// };
188/// int selected = 0;
189/// auto menu = Radiobox({
190/// .entries = entries,
191/// .selected = &selected,
192/// });
193/// screen.Loop(menu);
194/// ```
195///
196/// ### Sortie
197///
198/// ```bash
199/// ◉ entry 1
200/// ○ entry 2
201/// ○ entry 3
202/// ```
203/// NOLINTNEXTLINE
205 return Make<RadioboxBase>(std::move(option));
206}
207
208/// @brief Une liste d'éléments, où un seul peut être sélectionné.
209/// @param entries La liste des entrées.
210/// @param selected L'index de l'élément actuellement sélectionné.
211/// @param option Paramètres optionnels supplémentaires.
212/// @ingroup component
213/// @see RadioboxBase
214///
215/// ### Exemple
216///
217/// ```cpp
218/// auto screen = ScreenInteractive::TerminalOutput();
219/// std::vector<std::string> entries = {
220/// "entry 1",
221/// "entry 2",
222/// "entry 3",
223/// };
224/// int selected = 0;
225/// auto menu = Radiobox(&entries, &selected);
226/// screen.Loop(menu);
227/// ```
228///
229/// ### Sortie
230///
231/// ```bash
232/// ◉ entry 1
233/// ○ entry 2
234/// ○ entry 3
235/// ```
237 int* selected,
238 RadioboxOption option) {
239 option.entries = std::move(entries);
240 option.selected = selected;
241 return Make<RadioboxBase>(std::move(option));
242}
243
244} // namespace ftxui
Un adaptateur. Référence une liste de chaînes de caractères.
Definition ref.hpp:116
static const Event TabReverse
Definition event.hpp:55
static const Event PageUp
Definition event.hpp:61
ConstStringListRef entries
static const Event ArrowUp
Definition event.hpp:41
static const Event Tab
Definition event.hpp:54
static const Event ArrowDown
Definition event.hpp:42
static const Event End
Definition event.hpp:60
static const Event Home
Definition event.hpp:59
static const Event PageDown
Definition event.hpp:62
static const Event Return
Definition event.hpp:52
static RadioboxOption Simple()
Option pour un bouton radio standard.
std::function< Element(const EntryState &)> transform
Component Radiobox(RadioboxOption options)
Une liste d'éléments, où un seul peut être sélectionné.
Option pour le composant Radiobox.
Decorator size(WidthOrHeight, Constraint, int value)
Applique une contrainte sur la taille d'un élément.
Element focus(Element)
Définit l'élément child comme étant celui qui est focalisé parmi ses frères.
Definition frame.cpp:101
Element vbox(Elements)
Un conteneur affichant les éléments verticalement un par un.
Definition vbox.cpp:96
constexpr const T & clamp(const T &v, const T &lo, const T &hi)
Definition util.hpp:11
L'espace de noms FTXUI ftxui::
Definition animation.hpp:10
std::shared_ptr< T > Make(Args &&... args)
Definition component.hpp:27
std::shared_ptr< Node > Element
Definition elements.hpp:22
std::vector< Element > Elements
Definition elements.hpp:23
Decorator reflect(Box &box)
Definition reflect.cpp:43
std::shared_ptr< ComponentBase > Component