FTXUI  5.0.0
C++ functional terminal UI.
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 <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
18namespace ftxui::animation {
19class Params;
20} // namespace ftxui::animation
21
22namespace ftxui {
23
24namespace {
25class CaptureMouseImpl : public CapturedMouseInterface {};
26} // namespace
27
30}
31
32/// @brief Return the parent ComponentBase, or nul if any.
33/// @see Detach
34/// @see Parent
35/// @ingroup component
37 return parent_;
38}
39
40/// @brief Access the child at index `i`.
41/// @ingroup component
43 assert(i < ChildCount()); // NOLINT
44 return children_[i];
45}
46
47/// @brief Returns the number of children.
48/// @ingroup component
50 return children_.size();
51}
52
53/// @brief Add a child.
54/// @@param child The child to be attached.
55/// @ingroup component
57 child->Detach();
58 child->parent_ = this;
59 children_.push_back(std::move(child));
60}
61
62/// @brief Detach this child from its parent.
63/// @see Detach
64/// @see Parent
65/// @ingroup component
67 if (parent_ == nullptr) {
68 return;
69 }
70 auto it = std::find_if(std::begin(parent_->children_), //
71 std::end(parent_->children_), //
72 [this](const Component& that) { //
73 return this == that.get();
74 });
75 ComponentBase* parent = parent_;
76 parent_ = nullptr;
77 parent->children_.erase(it); // Might delete |this|.
78}
79
80/// @brief Remove all children.
81/// @ingroup component
83 while (!children_.empty()) {
84 children_[0]->Detach();
85 }
86}
87
88/// @brief Draw the component.
89/// Build a ftxui::Element to be drawn on the ftxi::Screen representing this
90/// ftxui::ComponentBase.
91/// @ingroup component
93 if (children_.size() == 1) {
94 return children_.front()->Render();
95 }
96
97 return text("Not implemented component");
98}
99
100/// @brief Called in response to an event.
101/// @param event The event.
102/// @return True when the event has been handled.
103/// The default implementation called OnEvent on every child until one return
104/// true. If none returns true, return false.
105/// @ingroup component
106bool ComponentBase::OnEvent(Event event) { // NOLINT
107 for (Component& child : children_) { // NOLINT
108 if (child->OnEvent(event)) {
109 return true;
110 }
111 }
112 return false;
113}
114
115/// @brief Called in response to an animation event.
116/// @param params the parameters of the animation
117/// The default implementation dispatch the event to every child.
118/// @ingroup component
120 for (const Component& child : children_) {
121 child->OnAnimation(params);
122 }
123}
124
125/// @brief Return the currently Active child.
126/// @return the currently Active child.
127/// @ingroup component
129 for (auto& child : children_) {
130 if (child->Focusable()) {
131 return child;
132 }
133 }
134 return nullptr;
135}
136
137/// @brief Return true when the component contains focusable elements.
138/// The non focusable Components will be skipped when navigating using the
139/// keyboard.
140/// @ingroup component
142 for (const Component& child : children_) { // NOLINT
143 if (child->Focusable()) {
144 return true;
145 }
146 }
147 return false;
148}
149
150/// @brief Returns if the element if the currently active child of its parent.
151/// @ingroup component
153 return parent_ == nullptr || parent_->ActiveChild().get() == this;
154}
155
156/// @brief Returns if the elements if focused by the user.
157/// True when the ComponentBase is focused by the user. An element is Focused
158/// when it is with all its ancestors the ActiveChild() of their parents, and it
159/// Focusable().
160/// @ingroup component
162 const auto* current = this;
163 while (current && current->Active()) {
164 current = current->parent_;
165 }
166 return !current && Focusable();
167}
168
169/// @brief Make the |child| to be the "active" one.
170/// @param child the child to become active.
171/// @ingroup component
172void ComponentBase::SetActiveChild([[maybe_unused]] ComponentBase* child) {}
173
174/// @brief Make the |child| to be the "active" one.
175/// @param child the child to become active.
176/// @ingroup component
178 SetActiveChild(child.get());
179}
180
181/// @brief Configure all the ancestors to give focus to this component.
182/// @ingroup component
184 ComponentBase* child = this;
185 while (ComponentBase* parent = child->parent_) {
186 parent->SetActiveChild(child);
187 child = parent;
188 }
189}
190
191/// @brief Take the CapturedMouse if available. There is only one component of
192/// them. It represents a component taking priority over others.
193/// @param event The event
194/// @ingroup component
196 if (event.screen_) {
197 return event.screen_->CaptureMouse();
198 }
199 return std::make_unique<CaptureMouseImpl>();
200}
201
202} // 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:141
bool Focused() const
Returns if the elements if focused by the user. True when the ComponentBase is focused by the user....
Definition: component.cpp:161
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:195
void Add(Component children)
Add a child. @param child The child to be attached.
Definition: component.cpp:56
virtual Element Render()
Draw the component. Build a ftxui::Element to be drawn on the ftxi::Screen representing this ftxui::C...
Definition: component.cpp:92
void TakeFocus()
Configure all the ancestors to give focus to this component.
Definition: component.cpp:183
bool Active() const
Returns if the element if the currently active child of its parent.
Definition: component.cpp:152
virtual Component ActiveChild()
Return the currently Active child.
Definition: component.cpp:128
void DetachAllChildren()
Remove all children.
Definition: component.cpp:82
virtual void SetActiveChild(ComponentBase *child)
Make the |child| to be the "active" one.
Definition: component.cpp:172
size_t ChildCount() const
Returns the number of children.
Definition: component.cpp:49
ComponentBase * Parent() const
Return the parent ComponentBase, or nul if any.
Definition: component.cpp:36
virtual bool OnEvent(Event)
Called in response to an event.
Definition: component.cpp:106
void Detach()
Detach this child from its parent.
Definition: component.cpp:66
Component & ChildAt(size_t i)
Access the child at index i.
Definition: component.cpp:42
virtual ~ComponentBase()
Definition: component.cpp:28
virtual void OnAnimation(animation::Params &params)
Called in response to an animation event.
Definition: component.cpp:119
std::unique_ptr< CapturedMouseInterface > CapturedMouse
std::shared_ptr< Node > Element
Definition: elements.hpp:23
std::shared_ptr< ComponentBase > Component
Element text(std::wstring text)
Display a piece of unicode text.
Definition: text.cpp:120
Represent an event. It can be key press event, a terminal resize, or more ...
Definition: event.hpp:29
ScreenInteractive * screen_
Definition: event.hpp:90