FTXUI 6.1.9
C++ functional terminal UI.
Loading...
Searching...
No Matches
component.cpp
Go to the documentation of this file.
1// Copyright 2020 Arthur Sonzogni. All rights reserved.
2// 本原始碼的使用受 MIT 授權約束,詳情請見 LICENSE 檔案。
3#include <algorithm> // for find_if
4#include <cassert> // for assert
5#include <cstddef> // for size_t
6#include <iterator> // for begin, end
7#include <memory> // for unique_ptr, make_unique
8#include <utility> // for move
9#include <vector> // for vector, __alloc_traits<>::value_type
10
11#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse, CapturedMouseInterface
13#include "ftxui/component/component_base.hpp" // for ComponentBase, Components
14#include "ftxui/component/event.hpp" // for Event
15#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
16#include "ftxui/dom/elements.hpp" // for text, Element
17#include "ftxui/dom/node.hpp" // for Node, Elements
18#include "ftxui/screen/box.hpp" // for Box
19
20namespace ftxui::animation {
21class Params;
22} // namespace ftxui::animation
23
24namespace ftxui {
25
26namespace {
27class CaptureMouseImpl : public CapturedMouseInterface {};
28} // namespace
29
33
34/// @brief 返回父 ComponentBase,如果沒有則返回空。
35/// @see Detach
36/// @see Parent
38 return parent_;
39}
40
41/// @brief 存取索引 `i` 處的子項。
43 assert(i < ChildCount()); // NOLINT
44 return children_[i];
45}
46
47/// @brief 返回子項的數量。
49 return children_.size();
50}
51
52/// @brief 返回組件在其父項中的索引。如果沒有父項則返回 -1。
54 if (parent_ == nullptr) {
55 return -1;
56 }
57 int index = 0;
58 for (const Component& child : parent_->children_) {
59 if (child.get() == this) {
60 return index;
61 }
62 index++;
63 }
64 return -1; // Not reached.
65}
66
67/// @brief 新增一個子項。
68/// @@param child 要附加的子項。
70 child->Detach();
71 child->parent_ = this;
72 children_.push_back(std::move(child));
73}
74
75/// @brief 將此子項從其父項中分離。
76/// @see Detach
77/// @see Parent
79 if (parent_ == nullptr) {
80 return;
81 }
82 auto it = std::find_if(std::begin(parent_->children_), //
83 std::end(parent_->children_), //
84 [this](const Component& that) { //
85 return this == that.get();
86 });
87 ComponentBase* parent = parent_;
88 parent_ = nullptr;
89 parent->children_.erase(it); // Might delete |this|.
90}
91
92/// @brief 移除所有子項。
94 while (!children_.empty()) {
95 children_[0]->Detach();
96 }
97}
98
99/// @brief 繪製組件。
100/// 建構一個 ftxui::Element,用於在表示此 ftxui::ComponentBase 的 ftxui::Screen 上繪製。請覆寫 OnRender() 以修改渲染。
102 // Some users might call `ComponentBase::Render()` from
103 // `T::OnRender()`. To avoid infinite recursion, we use a flag.
104 if (in_render) {
106 }
107
108 in_render = true;
109 Element element = OnRender();
110 in_render = false;
111
112 class Wrapper : public Node {
113 public:
114 bool active_ = false;
115
116 Wrapper(Element child, bool active)
117 : Node({std::move(child)}), active_(active) {}
118
119 void SetBox(Box box) override {
120 Node::SetBox(box);
121 children_[0]->SetBox(box);
122 }
123
124 void ComputeRequirement() override {
125 Node::ComputeRequirement();
126 requirement_.focused.component_active = active_;
127 }
128 };
129
130 return std::make_shared<Wrapper>(std::move(element), Active());
131}
132
133/// @brief 繪製組件。
134/// 建構一個 ftxui::Element,用於在表示此 ftxui::ComponentBase 的 ftxi::Screen 上繪製。此函數旨在被覆寫。
136 if (children_.size() == 1) {
137 return children_.front()->Render();
138 }
139
140 return text("Not implemented component");
141}
142
143/// @brief 回應事件時呼叫。
144/// @param event 事件。
145/// @return 當事件已處理時返回 true。
146/// 預設實作會在每個子項上呼叫 OnEvent,直到其中一個返回 true。如果都沒有返回 true,則返回 false。
147bool ComponentBase::OnEvent(Event event) { // NOLINT
148 for (Component& child : children_) { // NOLINT
149 if (child->OnEvent(event)) {
150 return true;
151 }
152 }
153 return false;
154}
155
156/// @brief 回應動畫事件時呼叫。
157/// @param params 動畫的參數
158/// 預設實作會將事件分派給每個子項。
160 for (const Component& child : children_) {
161 child->OnAnimation(params);
162 }
163}
164
165/// @brief 返回目前活躍的子項。
166/// @return 目前活躍的子項。
168 for (auto& child : children_) {
169 if (child->Focusable()) {
170 return child;
171 }
172 }
173 return nullptr;
174}
175
176/// @brief 當組件包含可聚焦元素時返回 true。
177/// 使用鍵盤導航時,不可聚焦的組件將被跳過。
179 for (const Component& child : children_) { // NOLINT
180 if (child->Focusable()) {
181 return true;
182 }
183 }
184 return false;
185}
186
187/// @brief 返回該元素是否為其父項的目前活躍子項。
189 return parent_ == nullptr || parent_->ActiveChild().get() == this;
190}
191
192/// @brief 返回元素是否被使用者聚焦。
193/// 當 ComponentBase 被使用者聚焦時返回 true。當一個元素及其所有祖先都是其父項的 ActiveChild() 並且它是 Focusable() 時,該元素被聚焦。
195 const auto* current = this;
196 while (current && current->Active()) {
197 current = current->parent_;
198 }
199 return !current && Focusable();
200}
201
202/// @brief 使 |child| 成為「活躍」的子項。
203/// @param child 要變為活躍的子項。
204void ComponentBase::SetActiveChild([[maybe_unused]] ComponentBase* child) {}
205
206/// @brief 使 |child| 成為「活躍」的子項。
207/// @param child 要變為活躍的子項。
209 SetActiveChild(child.get());
210}
211
212/// @brief 配置所有祖先以將焦點給予此組件。
214 ComponentBase* child = this;
215 while (ComponentBase* parent = child->parent_) {
216 parent->SetActiveChild(child);
217 child = parent;
218 }
219}
220
221/// @brief 如果可用,則取得 CapturedMouse。它們只有一個組件。它代表一個優先於其他組件的組件。
222/// @param event 事件
224 if (event.screen_) {
225 return event.screen_->CaptureMouse();
226 }
227 return std::make_unique<CaptureMouseImpl>();
228}
229
230} // namespace ftxui
virtual bool Focusable() const
當組件包含可聚焦元素時返回 true。 使用鍵盤導航時,不可聚焦的組件將被跳過。
bool Focused() const
返回元素是否被使用者聚焦。 當 ComponentBase 被使用者聚焦時返回 true。當一個元素及其所有祖先都是其父項的 ActiveChild() 並且它是 Focusable() 時,該元素被聚...
CapturedMouse CaptureMouse(const Event &event)
如果可用,則取得 CapturedMouse。它們只有一個組件。它代表一個優先於其他組件的組件。
void Add(Component children)
新增一個子項。 @param child 要附加的子項。
Definition component.cpp:69
Element Render()
繪製組件。 建構一個 ftxui::Element,用於在表示此 ftxui::ComponentBase 的 ftxui::Screen 上繪製。請覆寫 OnRender() 以修改渲染。
void TakeFocus()
配置所有祖先以將焦點給予此組件。
bool Active() const
返回該元素是否為其父項的目前活躍子項。
ScreenInteractive * screen_
Definition event.hpp:122
virtual Component ActiveChild()
返回目前活躍的子項。
void DetachAllChildren()
移除所有子項。
Definition component.cpp:93
virtual void SetActiveChild(ComponentBase *child)
使 |child| 成為「活躍」的子項。
int Index() const
返回組件在其父項中的索引。如果沒有父項則返回 -1。
Definition component.cpp:53
size_t ChildCount() const
返回子項的數量。
Definition component.cpp:48
ComponentBase * Parent() const
返回父 ComponentBase,如果沒有則返回空。
Definition component.cpp:37
virtual Element OnRender()
繪製組件。 建構一個 ftxui::Element,用於在表示此 ftxui::ComponentBase 的 ftxi::Screen 上繪製。此函數旨在被覆寫。
virtual bool OnEvent(Event)
回應事件時呼叫。
void Detach()
將此子項從其父項中分離。
Definition component.cpp:78
Component & ChildAt(size_t i)
存取索引 i 處的子項。
Definition component.cpp:42
virtual ~ComponentBase()
Definition component.cpp:30
virtual void OnAnimation(animation::Params &params)
回應動畫事件時呼叫。
它將自己實作為 ftxui::Element 進行渲染。它透過回應 ftxui::Event 來實現鍵盤導航。
代表一個事件。它可以是按鍵事件、終端機大小調整,或更多...
Definition event.hpp:27
節點是DOM樹中所有元素的基底類別。
Definition node.hpp:34
Element text(std::wstring text)
顯示一段 Unicode 文字。
Definition text.cpp:160
Box 是一個表示二維空間中矩形區域的結構。
Definition box.hpp:14
FTXUI ftxui::animation:: 命名空間
Definition animation.hpp:10
FTXUI 的 ftxui:: 命名空間
Definition animation.hpp:10
std::unique_ptr< CapturedMouseInterface > CapturedMouse
std::shared_ptr< Node > Element
Definition elements.hpp:22
std::shared_ptr< ComponentBase > Component