FTXUI 6.1.9
C++ functional terminal UI.
载入中...
搜索中...
未找到
node.cpp
浏览该文件的文档.
1// 版权所有 2020 Arthur Sonzogni. 保留所有权利。
2// 本源代码的使用受 MIT 许可协议的约束,该协议可在
3// LICENSE 文件中找到。
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 计算元素所需的空间。
21 if (children_.empty()) {
22 return;
23 }
24 for (auto& child : children_) {
25 child->ComputeRequirement();
26 }
27
28 // 默认情况下,需求是第一个子元素的需求。
29 requirement_ = children_[0]->requirement();
30
31 // 传播焦点需求。
32 for (size_t i = 1; i < children_.size(); ++i) {
34 children_[i]->requirement().focused.enabled) {
35 requirement_.focused = children_[i]->requirement().focused;
36 }
37 }
38}
39
40/// @brief 为绘图元素分配位置和尺寸。
41void Node::SetBox(Box box) {
42 box_ = box;
43}
44
45/// @brief 计算元素的选区。
46void Node::Select(Selection& selection) {
47 // 如果此节点 box_ 不与选区相交,则不进行选区。
48 if (Box::Intersection(selection.GetBox(), box_).IsEmpty()) {
49 return;
50 }
51
52 // 默认情况下,我们将选择推迟到子元素。
53 for (auto& child : children_) {
54 child->Select(selection);
55 }
56}
57
58/// @brief 在 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
82/// @brief 在 ftxui::Screen 上显示元素。
83/// @ingroup dom
84void Render(Screen& screen, const Element& element) {
85 Selection selection;
86 Render(screen, element.get(), selection);
87}
88
89/// @brief 在 ftxui::Screen 上显示元素。
90/// @ingroup dom
91void Render(Screen& screen, Node* node) {
92 Selection selection;
93 Render(screen, node, selection);
94}
95
96void 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 // 步骤 1:查找此元素所需的尺寸。
108 node->ComputeRequirement();
109
110 // 步骤 2:为元素分配尺寸。
111 node->SetBox(box);
112
113 // 检查元素是否需要布局算法的另一次迭代。
114 status.need_iteration = false;
115 status.iteration++;
116 node->Check(&status);
117 }
118
119 // 步骤 3:选区
120 if (!selection.IsEmpty()) {
121 node->Select(selection);
122 }
123
124 if (node->requirement().focused.enabled
125#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
126 // 将光标设置到正确的位置,可以让使用 CJK(中文、日文、韩文等)
127 // 字符的用户在正确的位置看到他们的[输入法编辑器]显示。参见[问题]。
128 //
129 // [输入法编辑器]:
130 // https://en.wikipedia.org/wiki/Input_method
131 //
132 // [问题]:
133 // https://github.com/ArthurSonzogni/FTXUI/issues/2#issuecomment-505282355
134 //
135 // 不幸的是,Microsoft 终端无法正确处理隐藏光标。
136 // 相反,光标下的字符被隐藏,这是一个大问题。
137 // 因此,我们无法启用将光标设置到正确位置的功能。
138 // 它将显示在右下角。
139 // 参见:
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 // 步骤 4:绘制元素。
160 screen.stencil = box;
161 node->Render(screen);
162
163 // 步骤 5:应用着色器
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 // 步骤 1:查找此元素所需的尺寸。
181 node->ComputeRequirement();
182
183 // 步骤 2:为元素分配尺寸。
184 node->SetBox(box);
185
186 // 检查元素是否需要布局算法的另一次迭代。
187 status.need_iteration = false;
188 status.iteration++;
189 node->Check(&status);
190 }
191
192 // 步骤 3:选区
193 node->Select(selection);
194
195 // 步骤 4:获取选定的内容。
196 return node->GetSelectedContent(selection);
197}
198
199} // namespace ftxui
const Box & GetBox() const
获取选择框。
virtual void Select(Selection &selection)
计算元素的选区。
Elements children_
virtual std::string GetSelectedContent(Selection &selection)
virtual void SetBox(Box box)
为绘图元素分配位置和尺寸。
Requirement requirement_
Requirement requirement()
virtual void ComputeRequirement()
计算元素所需的空间。
virtual void Check(Status *status)
virtual ~Node()
virtual void Render(Screen &screen)
在 ftxui::Screen 上显示元素。
friend void Render(Screen &screen, Node *node, Selection &selection)
Node 是 DOM 树中所有元素的基类。
代表终端用户界面中的选择。
void Render(Screen &screen, const Element &element)
在 ftxui::Screen 上显示元素。
int dimy() const
void SetCursor(Cursor cursor)
static auto Intersection(Box a, Box b) -> Box
定义 box.cpp:11
int dimx() const
像素的矩形网格。
Box是一个表示2D空间中矩形区域的结构体。
定义 box.hpp:15
#include "ftxui/component/component_base.hpp" // 用于 ComponentBase
std::string GetNodeSelectedContent(Screen &screen, Node *node, Selection &selection)
std::shared_ptr< Node > Element
std::vector< Element > Elements
Screen::Cursor::Shape cursor_shape