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