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