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