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// Use of this source code is governed by the MIT license that can be found in
3// the LICENSE file.
4#include <algorithm> // for find_if
5#include <cassert> // for assert
6#include <cstddef> // for size_t
7#include <iterator> // for begin, end
8#include <memory> // for unique_ptr, make_unique
9#include <utility> // for move
10#include <vector> // for vector, __alloc_traits<>::value_type
11
12#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse, CapturedMouseInterface
14#include "ftxui/component/component_base.hpp" // for ComponentBase, Components
15#include "ftxui/component/event.hpp" // for Event
16#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
17#include "ftxui/dom/elements.hpp" // for text, Element
18#include "ftxui/dom/node.hpp" // for Node, Elements
19#include "ftxui/screen/box.hpp" // for Box
20
21namespace ftxui::animation {
22class Params;
23} // namespace ftxui::animation
24
25namespace ftxui {
26
27namespace {
28class CaptureMouseImpl : public CapturedMouseInterface {};
29} // namespace
30
33}
34
35/// @brief Return the parent ComponentBase, or nul if any.
36/// @see Detach
37/// @see Parent
38/// @ingroup component
40 return parent_;
41}
42
43/// @brief Access the child at index `i`.
44/// @ingroup component
46 assert(i < ChildCount()); // NOLINT
47 return children_[i];
48}
49
50/// @brief Returns the number of children.
51/// @ingroup component
53 return children_.size();
54}
55
56/// @brief Return index of the component in its parent. -1 if no parent.
57/// @ingroup component
59 if (parent_ == nullptr) {
60 return -1;
61 }
62 int index = 0;
63 for (const Component& child : parent_->children_) {
64 if (child.get() == this) {
65 return index;
66 }
67 index++;
68 }
69 return -1; // Not reached.
70}
71
72/// @brief Add a child.
73/// @@param child The child to be attached.
74/// @ingroup component
76 child->Detach();
77 child->parent_ = this;
78 children_.push_back(std::move(child));
79}
80
81/// @brief Detach this child from its parent.
82/// @see Detach
83/// @see Parent
84/// @ingroup component
86 if (parent_ == nullptr) {
87 return;
88 }
89 auto it = std::find_if(std::begin(parent_->children_), //
90 std::end(parent_->children_), //
91 [this](const Component& that) { //
92 return this == that.get();
93 });
94 ComponentBase* parent = parent_;
95 parent_ = nullptr;
96 parent->children_.erase(it); // Might delete |this|.
97}
98
99/// @brief Remove all children.
100/// @ingroup component
102 while (!children_.empty()) {
103 children_[0]->Detach();
104 }
105}
106
107/// @brief Draw the component.
108/// Build a ftxui::Element to be drawn on the ftxui::Screen representing this
109/// ftxui::ComponentBase. Please override OnRender() to modify the rendering.
110/// @ingroup component
112 // Some users might call `ComponentBase::Render()` from
113 // `T::OnRender()`. To avoid infinite recursion, we use a flag.
114 if (in_render) {
116 }
117
118 in_render = true;
119 Element element = OnRender();
120 in_render = false;
121
122 class Wrapper : public Node {
123 public:
124 bool active_ = false;
125
126 Wrapper(Element child, bool active)
127 : Node({std::move(child)}), active_(active) {}
128
129 void SetBox(Box box) override {
130 Node::SetBox(box);
131 children_[0]->SetBox(box);
132 }
133
134 void ComputeRequirement() override {
135 Node::ComputeRequirement();
136 requirement_.focused.component_active = active_;
137 }
138 };
139
140 return std::make_shared<Wrapper>(std::move(element), Active());
141}
142
143/// @brief Draw the component.
144/// Build a ftxui::Element to be drawn on the ftxi::Screen representing this
145/// ftxui::ComponentBase. This function is means to be overridden.
146/// @ingroup component
148 if (children_.size() == 1) {
149 return children_.front()->Render();
150 }
151
152 return text("Not implemented component");
153}
154
155/// @brief Called in response to an event.
156/// @param event The event.
157/// @return True when the event has been handled.
158/// The default implementation called OnEvent on every child until one return
159/// true. If none returns true, return false.
160/// @ingroup component
161bool ComponentBase::OnEvent(Event event) { // NOLINT
162 for (Component& child : children_) { // NOLINT
163 if (child->OnEvent(event)) {
164 return true;
165 }
166 }
167 return false;
168}
169
170/// @brief Called in response to an animation event.
171/// @param params the parameters of the animation
172/// The default implementation dispatch the event to every child.
173/// @ingroup component
175 for (const Component& child : children_) {
176 child->OnAnimation(params);
177 }
178}
179
180/// @brief Return the currently Active child.
181/// @return the currently Active child.
182/// @ingroup component
184 for (auto& child : children_) {
185 if (child->Focusable()) {
186 return child;
187 }
188 }
189 return nullptr;
190}
191
192/// @brief Return true when the component contains focusable elements.
193/// The non focusable Components will be skipped when navigating using the
194/// keyboard.
195/// @ingroup component
197 for (const Component& child : children_) { // NOLINT
198 if (child->Focusable()) {
199 return true;
200 }
201 }
202 return false;
203}
204
205/// @brief Returns if the element if the currently active child of its parent.
206/// @ingroup component
208 return parent_ == nullptr || parent_->ActiveChild().get() == this;
209}
210
211/// @brief Returns if the elements if focused by the user.
212/// True when the ComponentBase is focused by the user. An element is Focused
213/// when it is with all its ancestors the ActiveChild() of their parents, and it
214/// Focusable().
215/// @ingroup component
217 const auto* current = this;
218 while (current && current->Active()) {
219 current = current->parent_;
220 }
221 return !current && Focusable();
222}
223
224/// @brief Make the |child| to be the "active" one.
225/// @param child the child to become active.
226/// @ingroup component
227void ComponentBase::SetActiveChild([[maybe_unused]] ComponentBase* child) {}
228
229/// @brief Make the |child| to be the "active" one.
230/// @param child the child to become active.
231/// @ingroup component
233 SetActiveChild(child.get());
234}
235
236/// @brief Configure all the ancestors to give focus to this component.
237/// @ingroup component
239 ComponentBase* child = this;
240 while (ComponentBase* parent = child->parent_) {
241 parent->SetActiveChild(child);
242 child = parent;
243 }
244}
245
246/// @brief Take the CapturedMouse if available. There is only one component of
247/// them. It represents a component taking priority over others.
248/// @param event The event
249/// @ingroup component
251 if (event.screen_) {
252 return event.screen_->CaptureMouse();
253 }
254 return std::make_unique<CaptureMouseImpl>();
255}
256
257} // namespace ftxui
It implement rendering itself as ftxui::Element. It implement keyboard navigation by responding to ft...
virtual bool Focusable() const
Return true when the component contains focusable elements. The non focusable Components will be skip...
Definition: component.cpp:196
bool Focused() const
Returns if the elements if focused by the user. True when the ComponentBase is focused by the user....
Definition: component.cpp:216
CapturedMouse CaptureMouse(const Event &event)
Take the CapturedMouse if available. There is only one component of them. It represents a component t...
Definition: component.cpp:250
void Add(Component children)
Add a child. @param child The child to be attached.
Definition: component.cpp:75
Element Render()
Draw the component. Build a ftxui::Element to be drawn on the ftxui::Screen representing this ftxui::...
Definition: component.cpp:111
void TakeFocus()
Configure all the ancestors to give focus to this component.
Definition: component.cpp:238
bool Active() const
Returns if the element if the currently active child of its parent.
Definition: component.cpp:207
virtual Component ActiveChild()
Return the currently Active child.
Definition: component.cpp:183
void DetachAllChildren()
Remove all children.
Definition: component.cpp:101
virtual void SetActiveChild(ComponentBase *child)
Make the |child| to be the "active" one.
Definition: component.cpp:227
int Index() const
Return index of the component in its parent. -1 if no parent.
Definition: component.cpp:58
size_t ChildCount() const
Returns the number of children.
Definition: component.cpp:52
ComponentBase * Parent() const
Return the parent ComponentBase, or nul if any.
Definition: component.cpp:39
virtual Element OnRender()
Draw the component. Build a ftxui::Element to be drawn on the ftxi::Screen representing this ftxui::C...
Definition: component.cpp:147
virtual bool OnEvent(Event)
Called in response to an event.
Definition: component.cpp:161
void Detach()
Detach this child from its parent.
Definition: component.cpp:85
Component & ChildAt(size_t i)
Access the child at index i.
Definition: component.cpp:45
virtual ~ComponentBase()
Definition: component.cpp:31
virtual void OnAnimation(animation::Params &params)
Called in response to an animation event.
Definition: component.cpp:174
std::unique_ptr< CapturedMouseInterface > CapturedMouse
std::shared_ptr< Node > Element
Definition: elements.hpp:22
std::shared_ptr< ComponentBase > Component
Element text(std::wstring text)
Display a piece of unicode text.
Definition: text.cpp:160
Represent an event. It can be key press event, a terminal resize, or more ...
Definition: event.hpp:27
ScreenInteractive * screen_
Definition: event.hpp:122