FTXUI  5.0.0
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
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
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
228
229/// @brief Make the |child| to be the "active" one.
230/// @param child the child to become active.
231/// @ingroup component
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_) {
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...
bool Focused() const
Returns if the elements if focused by the user. True when the ComponentBase is focused by the user....
CapturedMouse CaptureMouse(const Event &event)
Take the CapturedMouse if available. There is only one component of them. It represents a component t...
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::...
void TakeFocus()
Configure all the ancestors to give focus to this component.
bool Active() const
Returns if the element if the currently active child of its parent.
virtual Component ActiveChild()
Return the currently Active child.
void DetachAllChildren()
Remove all children.
virtual void SetActiveChild(ComponentBase *child)
Make the |child| to be the "active" one.
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...
virtual bool OnEvent(Event)
Called in response to an event.
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.
std::unique_ptr< CapturedMouseInterface > CapturedMouse
std::shared_ptr< Node > Element
Definition elements.hpp:22
std::shared_ptr< T > Make(Args &&... args)
Definition component.hpp:26
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