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// 本原始碼的使用受 MIT 授權條款約束,詳情請參閱 LICENSE 檔案。
3#include <ftxui/screen/box.hpp> // for Box
4#include <string>
5#include <utility> // for move
6
7#include <cstddef>
8#include "ftxui/dom/node.hpp"
9#include "ftxui/dom/selection.hpp" // for Selection
10#include "ftxui/screen/screen.hpp" // for Screen
11
12namespace ftxui {
13
14Node::Node() = default;
15Node::Node(Elements children) : children_(std::move(children)) {}
16Node::~Node() = default;
17
18/// @brief 計算元素所需的空間大小。
20 if (children_.empty()) {
21 return;
22 }
23 for (auto& child : children_) {
24 child->ComputeRequirement();
25 }
26
27 // 預設情況下,需求是第一個子節點的需求。
28 requirement_ = children_[0]->requirement();
29
30 // 傳播焦點需求。
31 for (size_t i = 1; i < children_.size(); ++i) {
33 children_[i]->requirement().focused.enabled) {
34 requirement_.focused = children_[i]->requirement().focused;
35 }
36 }
37}
38
39/// @brief 為元素分配繪圖位置和尺寸。
40void Node::SetBox(Box box) {
41 box_ = box;
42}
43
44/// @brief 計算元素的選取範圍。
45void Node::Select(Selection& selection) {
46 // 如果此節點的 box_ 與選取範圍沒有交集,則不進行選取。
47 if (Box::Intersection(selection.GetBox(), box_).IsEmpty()) {
48 return;
49 }
50
51 // 預設情況下,我們將選取延遲到子節點。
52 for (auto& child : children_) {
53 child->Select(selection);
54 }
55}
56
57/// @brief 在 ftxui::Screen 上顯示元素。
58 for (auto& child : children_) {
59 child->Render(screen);
60 }
61}
62
63void Node::Check(Status* status) {
64 for (auto& child : children_) {
65 child->Check(status);
66 }
67 status->need_iteration |= (status->iteration == 0);
68}
69
70std::string Node::GetSelectedContent(Selection& selection) {
71 std::string content;
72
73 for (auto& child : children_) {
74 content += child->GetSelectedContent(selection);
75 }
76
77 return content;
78}
79
80/// @brief 在 ftxui::Screen 上顯示元素。
81/// @ingroup dom
82void Render(Screen& screen, const Element& element) {
83 Selection selection;
84 Render(screen, element.get(), selection);
85}
86
87/// @brief 在 ftxui::Screen 上顯示元素。
88/// @ingroup dom
89void Render(Screen& screen, Node* node) {
90 Selection selection;
91 Render(screen, node, selection);
92}
93
94void Render(Screen& screen, Node* node, Selection& selection) {
95 Box box;
96 box.x_min = 0;
97 box.y_min = 0;
98 box.x_max = screen.dimx() - 1;
99 box.y_max = screen.dimy() - 1;
100
101 Node::Status status;
102 node->Check(&status);
103 const int max_iterations = 20;
104 while (status.need_iteration && status.iteration < max_iterations) {
105 // 步驟 1:找出此元素想要的尺寸。
106 node->ComputeRequirement();
107
108 // 步驟 2:為元素分配尺寸。
109 node->SetBox(box);
110
111 // 檢查元素是否需要佈局演算法的另一次迭代。
112 status.need_iteration = false;
113 status.iteration++;
114 node->Check(&status);
115 }
116
117 // 步驟 3:選取
118 if (!selection.IsEmpty()) {
119 node->Select(selection);
120 }
121
122 if (node->requirement().focused.enabled
123#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
124 // 將游標設定到正確的位置,允許使用 CJK(中文、日文、韓文等)字元的使用者
125 // 在正確的位置看到他們的 [輸入法編輯器]。請參閱 [問題]。
126 //
127 // [輸入法編輯器]:
128 // https://zh.wikipedia.org/wiki/輸入法編輯器
129 //
130 // [問題]:
131 // https://github.com/ArthurSonzogni/FTXUI/issues/2#issuecomment-505282355
132 //
133 // 遺憾的是,Microsoft 終端機無法正確處理隱藏游標。相反地,
134 // 游標下方的字元會被隱藏,這是一個大問題。因此,我們無法啟用
135 // 將游標設定到正確的位置。它將顯示在右下角。
136 // 請參閱:
137 // https://github.com/microsoft/terminal/issues/1203
138 // https://github.com/microsoft/terminal/issues/3093
139 &&
140 node->requirement().focused.cursor_shape != Screen::Cursor::Shape::Hidden
141#endif
142 ) {
143 screen.SetCursor(Screen::Cursor{
144 node->requirement().focused.node->box_.x_max,
145 node->requirement().focused.node->box_.y_max,
146 node->requirement().focused.cursor_shape,
147 });
148 } else {
149 screen.SetCursor(Screen::Cursor{
150 screen.dimx() - 1,
151 screen.dimy() - 1,
152 Screen::Cursor::Shape::Hidden,
153 });
154 }
155
156 // 步驟 4:繪製元素。
157 screen.stencil = box;
158 node->Render(screen);
159
160 // 步驟 5:應用著色器
161 screen.ApplyShader();
162}
163
164std::string GetNodeSelectedContent(Screen& screen,
165 Node* node,
166 Selection& selection) {
167 Box box;
168 box.x_min = 0;
169 box.y_min = 0;
170 box.x_max = screen.dimx() - 1;
171 box.y_max = screen.dimy() - 1;
172
173 Node::Status status;
174 node->Check(&status);
175 const int max_iterations = 20;
176 while (status.need_iteration && status.iteration < max_iterations) {
177 // 步驟 1:找出此元素想要的尺寸。
178 node->ComputeRequirement();
179
180 // 步驟 2:為元素分配尺寸。
181 node->SetBox(box);
182
183 // 檢查元素是否需要佈局演算法的另一次迭代。
184 status.need_iteration = false;
185 status.iteration++;
186 node->Check(&status);
187 }
188
189 // 步驟 3:選取
190 node->Select(selection);
191
192 // 步驟 4:取得選取的內容。
193 return node->GetSelectedContent(selection);
194}
195
196} // namespace ftxui
const Box & GetBox() const
取得選取範圍的方塊。
virtual void Select(Selection &selection)
計算元素的選取範圍。
Definition node.cpp:45
Elements children_
Definition node.hpp:74
virtual void SetBox(Box box)
為元素分配繪圖位置和尺寸。
Definition node.cpp:40
Requirement requirement_
Definition node.hpp:75
virtual void ComputeRequirement()
計算元素所需的空間大小。
Definition node.cpp:19
virtual ~Node()
Box box_
Definition node.hpp:76
表示終端機使用者介面中的選取範圍。
Definition selection.hpp:21
void Render(Screen &screen, const Element &element)
在 ftxui::Screen 上顯示元素。
Definition node.cpp:82
static auto Intersection(Box a, Box b) -> Box
Definition box.cpp:11
Box 是一個表示二維空間中矩形區域的結構。
Definition box.hpp:14
FTXUI 的 ftxui:: 命名空間
Definition animation.hpp:10
std::vector< Element > Elements
Definition elements.hpp:23
std::string GetNodeSelectedContent(Screen &screen, Node *node, Selection &selection)
Definition node.cpp:164