FTXUI 7.0.3
C++ functional terminal UI.
Loading...
Searching...
No Matches
node.cpp
Go to the documentation of this file.
1// Copyright 2020 Arthur Sonzogni. All rights reserved.
2// Use of this source code is governed by the MIT license that can be found in
3// the LICENSE file.
4#include <ftxui/screen/box.hpp> // for Box
5#include <string>
6#include <utility> // for move
7
8#include <cstddef>
9#include "ftxui/dom/node.hpp"
10#include "ftxui/dom/selection.hpp" // for Selection
11#include "ftxui/screen/screen.hpp" // for Screen
12#include "ftxui/screen/terminal.hpp" // for GetQuirks
13
14namespace ftxui {
15
16Node::Node() = default;
17Node::Node(Elements children) : children_(std::move(children)) {}
18Node::~Node() = default;
19
20/// @brief Calcule l'espace nécessaire à un élément.
21void Node::ComputeRequirement() {
22 if (children_.empty()) {
23 return;
24 }
25 for (auto& child : children_) {
26 child->ComputeRequirement();
27 }
28
29 // Par défaut, l'exigence est celle du premier enfant.
30 requirement_ = children_[0]->requirement();
31
32 // Propager l'exigence de focus.
33 for (size_t i = 1; i < children_.size(); ++i) {
34 if (requirement_.focused.Prefer(children_[i]->requirement().focused)) {
35 requirement_.focused = children_[i]->requirement().focused;
36 }
37 }
38}
39
40/// @brief Assigne une position et une dimension à un élément pour le dessin.
41void Node::SetBox(Box box) {
42 box_ = box;
43}
44
45/// @brief Calcule la sélection d'un élément.
46void Node::Select(Selection& selection) {
47 // Si la boîte de ce nœud n'intersecte pas la sélection, alors pas de sélection.
48 if (Box::Intersection(selection.GetBox(), box_).IsEmpty()) {
49 return;
50 }
51
52 // Par défaut, nous déléguons la sélection aux enfants.
53 for (auto& child : children_) {
54 child->Select(selection);
55 }
56}
57
58/// @brief Affiche un élément sur un ftxui::Screen.
59void Node::Render(Screen& screen) {
60 for (auto& child : children_) {
61 child->Render(screen);
62 }
63}
64
65void Node::Check(Status* status) {
66 for (auto& child : children_) {
67 child->Check(status);
68 }
69 status->need_iteration |= (status->iteration == 0);
70}
71
72std::string Node::GetSelectedContent(Selection& selection) {
73 std::string content;
74
75 for (auto& child : children_) {
76 content += child->GetSelectedContent(selection);
77 }
78
79 return content;
80}
81
82void Node::Reserved1() {}
83void Node::Reserved2() {}
84void Node::Reserved3() {}
85void Node::Reserved4() {}
86void Node::Reserved5() {}
87void Node::Reserved6() {}
88void Node::Reserved7() {}
89void Node::Reserved8() {}
90
91/// @brief Affiche un élément sur un ftxui::Screen.
92/// @ingroup dom
93void Render(Screen& screen, const Element& element) {
94 Selection selection;
95 Render(screen, element.get(), selection);
96}
97
98/// @brief Affiche un élément sur un ftxui::Screen.
99/// @ingroup dom
100void Render(Screen& screen, Node* node) {
101 Selection selection;
102 Render(screen, node, selection);
103}
104
105void Render(Screen& screen, Node* node, Selection& selection) {
106 Box box;
107 box.x_min = 0;
108 box.y_min = 0;
109 box.x_max = screen.dimx() - 1;
110 box.y_max = screen.dimy() - 1;
111
112 Node::Status status;
113 node->Check(&status);
114 const int max_iterations = 20;
115 while (status.need_iteration && status.iteration < max_iterations) {
116 // Étape 1 : Détermine la dimension souhaitée par cet élément.
117 node->ComputeRequirement();
118
119 // Étape 2 : Assigne une dimension à l'élément.
120 node->SetBox(box);
121
122 // Vérifie si l'élément nécessite une autre itération de l'algorithme de mise en page.
123 status.need_iteration = false;
124 status.iteration++;
125 node->Check(&status);
126 }
127
128 // Étape 3 : Sélection
129 if (!selection.IsEmpty()) {
130 node->Select(selection);
131 }
132
133 bool use_cursor = node->requirement().focused.enabled;
134 if (!Terminal::GetQuirks().CursorHiding() &&
135 node->requirement().focused.cursor_shape ==
136 Screen::Cursor::Shape::Hidden) {
137 // Placer le curseur à la bonne position permet aux personnes utilisant des caractères CJK (Chine,
138 // Japon, Corée, ...) de voir leur [éditeur de méthode de saisie]
139 // affiché au bon endroit. Voir [issue].
140 //
141 // [éditeur de méthode de saisie]:
142 // https://en.wikipedia.org/wiki/Input_method
143 //
144 // [issue]:
145 // https://github.com/ArthurSonzogni/FTXUI/issues/2#issuecomment-505282355
146 //
147 // Malheureusement, Microsoft terminal ne gère pas correctement le fait de cacher le
148 // curseur. À la place, le caractère sous le curseur est caché, ce qui est un
149 // gros problème. En conséquence, on ne peut pas activer le positionnement du curseur au bon
150 // endroit. Il sera affiché dans le coin inférieur droit.
151 // Voir :
152 // https://github.com/microsoft/terminal/issues/1203
153 // https://github.com/microsoft/terminal/issues/3093
154 use_cursor = false;
155 }
156
157 if (use_cursor) {
158 screen.SetCursor(Screen::Cursor{
159 node->requirement().focused.node->box_.x_min,
160 node->requirement().focused.node->box_.y_min,
161 node->requirement().focused.cursor_shape,
162 });
163 } else {
164 screen.SetCursor(Screen::Cursor{
165 screen.dimx() - 1,
166 screen.dimy() - 1,
167 Screen::Cursor::Shape::Hidden,
168 });
169 }
170
171 // Étape 4 : Dessine l'élément.
172 screen.stencil = box;
173 node->Render(screen);
174
175 // Étape 5 : Applique les shaders.
176 screen.ApplyShader();
177}
178
179std::string GetNodeSelectedContent(Screen& screen,
180 Node* node,
181 Selection& selection) {
182 Box box;
183 box.x_min = 0;
184 box.y_min = 0;
185 box.x_max = screen.dimx() - 1;
186 box.y_max = screen.dimy() - 1;
187
188 Node::Status status;
189 node->Check(&status);
190 const int max_iterations = 20;
191 while (status.need_iteration && status.iteration < max_iterations) {
192 // Étape 1 : Détermine la dimension souhaitée par cet élément.
193 node->ComputeRequirement();
194
195 // Étape 2 : Assigne une dimension à l'élément.
196 node->SetBox(box);
197
198 // Vérifie si l'élément nécessite une autre itération de l'algorithme de mise en page.
199 status.need_iteration = false;
200 status.iteration++;
201 node->Check(&status);
202 }
203
204 // Étape 3 : Sélection
205 node->Select(selection);
206
207 // Étape 4 : Récupère le contenu sélectionné.
208 return node->GetSelectedContent(selection);
209}
210
211} // namespace ftxui
L'espace de noms FTXUI ftxui::
Definition animation.hpp:11
std::string GetNodeSelectedContent(Screen &screen, Node *node, Selection &selection)
Definition node.cpp:179
std::shared_ptr< Node > Element
Definition elements.hpp:25
std::vector< Element > Elements
Definition elements.hpp:26
const Element & element
Definition node.hpp:94
void Render(Screen &screen, Node *node, Selection &selection)
Definition node.cpp:105
Node * node
Definition node.hpp:95