FTXUI 6.1.9
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
13namespace ftxui {
14
15Node::Node() = default;
16Node::Node(Elements children) : children_(std::move(children)) {}
17Node::~Node() = default;
18
19/// @brief Compute how much space an element needs.
21 if (children_.empty()) {
22 return;
23 }
24 for (auto& child : children_) {
25 child->ComputeRequirement();
26 }
27
28 // By default, the requirement is the one of the first child.
29 requirement_ = children_[0]->requirement();
30
31 // Propagate the focused requirement.
32 for (size_t i = 1; i < children_.size(); ++i) {
33 if (requirement_.focused.Prefer(children_[i]->requirement().focused)) {
34 requirement_.focused = children_[i]->requirement().focused;
35 }
36 }
37}
38
39/// @brief Assign a position and a dimension to an element for drawing.
40void Node::SetBox(Box box) {
41 box_ = box;
42}
43
44/// @brief Compute the selection of an element.
45void Node::Select(Selection& selection) {
46 // If this Node box_ doesn't intersect with the selection, then no selection.
47 if (Box::Intersection(selection.GetBox(), box_).IsEmpty()) {
48 return;
49 }
50
51 // By default we defer the selection to the children.
52 for (auto& child : children_) {
53 child->Select(selection);
54 }
55}
56
57/// @brief Display an element on a ftxui::Screen.
58void Node::Render(Screen& screen) {
59 for (auto& child : children_) {
60 child->Render(screen);
61 }
62}
63
64void Node::Check(Status* status) {
65 for (auto& child : children_) {
66 child->Check(status);
67 }
68 status->need_iteration |= (status->iteration == 0);
69}
70
71std::string Node::GetSelectedContent(Selection& selection) {
72 std::string content;
73
74 for (auto& child : children_) {
75 content += child->GetSelectedContent(selection);
76 }
77
78 return content;
79}
80
81/// @brief Display an element on a ftxui::Screen.
82/// @ingroup dom
83void Render(Screen& screen, const Element& element) {
84 Selection selection;
85 Render(screen, element.get(), selection);
86}
87
88/// @brief Display an element on a ftxui::Screen.
89/// @ingroup dom
90void Render(Screen& screen, Node* node) {
91 Selection selection;
92 Render(screen, node, selection);
93}
94
95void Render(Screen& screen, Node* node, Selection& selection) {
96 Box box;
97 box.x_min = 0;
98 box.y_min = 0;
99 box.x_max = screen.dimx() - 1;
100 box.y_max = screen.dimy() - 1;
101
102 Node::Status status;
103 node->Check(&status);
104 const int max_iterations = 20;
105 while (status.need_iteration && status.iteration < max_iterations) {
106 // Step 1: Find what dimension this elements wants to be.
107 node->ComputeRequirement();
108
109 // Step 2: Assign a dimension to the element.
110 node->SetBox(box);
111
112 // Check if the element needs another iteration of the layout algorithm.
113 status.need_iteration = false;
114 status.iteration++;
115 node->Check(&status);
116 }
117
118 // Step 3: Selection
119 if (!selection.IsEmpty()) {
120 node->Select(selection);
121 }
122
123 if (node->requirement().focused.enabled
124#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
125 // Setting the cursor to the right position allow folks using CJK (China,
126 // Japanese, Korean, ...) characters to see their [input method editor]
127 // displayed at the right location. See [issue].
128 //
129 // [input method editor]:
130 // https://en.wikipedia.org/wiki/Input_method
131 //
132 // [issue]:
133 // https://github.com/ArthurSonzogni/FTXUI/issues/2#issuecomment-505282355
134 //
135 // Unfortunately, Microsoft terminal do not handle properly hiding the
136 // cursor. Instead the character under the cursor is hidden, which is a
137 // big problem. As a result, we can't enable setting cursor to the right
138 // location. It will be displayed at the bottom right corner.
139 // See:
140 // https://github.com/microsoft/terminal/issues/1203
141 // https://github.com/microsoft/terminal/issues/3093
142 &&
144#endif
145 ) {
150 });
151 } else {
153 screen.dimx() - 1,
154 screen.dimy() - 1,
156 });
157 }
158
159 // Step 4: Draw the element.
160 screen.stencil = box;
161 node->Render(screen);
162
163 // Step 5: Apply shaders
164 screen.ApplyShader();
165}
166
167std::string GetNodeSelectedContent(Screen& screen,
168 Node* node,
169 Selection& selection) {
170 Box box;
171 box.x_min = 0;
172 box.y_min = 0;
173 box.x_max = screen.dimx() - 1;
174 box.y_max = screen.dimy() - 1;
175
176 Node::Status status;
177 node->Check(&status);
178 const int max_iterations = 20;
179 while (status.need_iteration && status.iteration < max_iterations) {
180 // Step 1: Find what dimension this elements wants to be.
181 node->ComputeRequirement();
182
183 // Step 2: Assign a dimension to the element.
184 node->SetBox(box);
185
186 // Check if the element needs another iteration of the layout algorithm.
187 status.need_iteration = false;
188 status.iteration++;
189 node->Check(&status);
190 }
191
192 // Step 3: Selection
193 node->Select(selection);
194
195 // Step 4: get the selected content.
196 return node->GetSelectedContent(selection);
197}
198
199} // namespace ftxui
const Box & GetBox() const
Get the box of the selection.
virtual void Select(Selection &selection)
Compute the selection of an element.
Definition node.cpp:45
Elements children_
Definition node.hpp:79
virtual std::string GetSelectedContent(Selection &selection)
Definition node.cpp:71
virtual void SetBox(Box box)
Assign a position and a dimension to an element for drawing.
Definition node.cpp:40
Requirement requirement_
Definition node.hpp:80
Requirement requirement()
Definition node.hpp:52
virtual void ComputeRequirement()
Compute how much space an element needs.
Definition node.cpp:20
virtual void Check(Status *status)
Definition node.cpp:64
virtual ~Node()
virtual void Render(Screen &screen)
Display an element on a ftxui::Screen.
Definition node.cpp:58
bool IsEmpty() const
Definition selection.hpp:31
Box box_
Definition node.hpp:81
friend void Render(Screen &screen, Node *node, Selection &selection)
Definition node.cpp:95
Node is the base class for all elements in the DOM tree.
Definition node.hpp:37
Represents a selection in a terminal user interface.
Definition selection.hpp:22
void Render(Screen &screen, const Element &element)
Display an element on a ftxui::Screen.
Definition node.cpp:83
void ApplyShader()
Definition screen.cpp:537
int dimy() const
Definition surface.hpp:43
void SetCursor(Cursor cursor)
Definition screen.hpp:69
int x_max
Definition box.hpp:18
int y_min
Definition box.hpp:19
static auto Intersection(Box a, Box b) -> Box
Definition box.cpp:11
int y_max
Definition box.hpp:20
int x_min
Definition box.hpp:17
int dimx() const
Definition surface.hpp:42
A rectangular grid of Cell.
Definition screen.hpp:26
Box is a structure that represents a rectangular area in a 2D space.
Definition box.hpp:16
The FTXUI ftxui:: namespace.
Definition animation.hpp:10
std::string GetNodeSelectedContent(Screen &screen, Node *node, Selection &selection)
Definition node.cpp:167
std::shared_ptr< Node > Element
Definition elements.hpp:23
std::vector< Element > Elements
Definition elements.hpp:24
Screen::Cursor::Shape cursor_shape
bool Prefer(const Focused &other) const