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
13#include "ftxui/component/component.hpp"
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
21 namespace ftxui::animation {
22 class Params;
23} // namespace ftxui::animation
24
25 namespace ftxui {
26
27 namespace {
28 class CaptureMouseImpl : public CapturedMouseInterface {};
29} // namespace
30
31 ComponentBase::~ComponentBase() {
32 DetachAllChildren();
33}
34
35/// @brief Return the parent ComponentBase, or nul if any.
36/// @see Detach
37/// @see Parent
38 ComponentBase* ComponentBase::Parent() const {
39 return parent_;
40}
41
42/// @brief Access the child at index `i`.
43 Component& ComponentBase::ChildAt(size_t i) {
44 assert(i < ChildCount()); // NOLINT
45 return children_[i];
46}
47
48/// @brief Returns the number of children.
49 size_t ComponentBase::ChildCount() const {
50 return children_.size();
51}
52
53/// @brief Return index of the component in its parent. -1 if no parent.
54 int ComponentBase::Index() const {
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.
70 void ComponentBase::Add(Component child) {
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
79 void ComponentBase::Detach() {
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.
94 void ComponentBase::DetachAllChildren() {
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.
103 Element ComponentBase::Render() {
104 // Some users might call `ComponentBase::Render()` from
105 // `T::OnRender()`. To avoid infinite recursion, we use a flag.
106 if (in_render) {
107 return ComponentBase::OnRender();
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
118 Wrapper(Element child, bool active)
119 : Node({std::move(child)}), active_(active) {}
120
121 void SetBox(Box box) override {
122 Node::SetBox(box);
123 children_[0]->SetBox(box);
124 }
125
126 void ComputeRequirement() override {
127 Node::ComputeRequirement();
128 requirement_.focused.component_active = active_;
129 }
130 };
131
132 return std::make_shared<Wrapper>(std::move(element), Active());
133}
134
135/// @brief Draw the component.
136/// Build a ftxui::Element to be drawn on the ftxi::Screen representing this
137/// ftxui::ComponentBase. This function is means to be overridden.
138 Element ComponentBase::OnRender() {
139 if (children_.size() == 1) {
140 return children_.front()->Render();
141 }
142
143 return text("Not implemented component");
144}
145
146/// @brief Called in response to an event.
147/// @param event The event.
148/// @return True when the event has been handled.
149/// The default implementation called OnEvent on every child until one return
150/// true. If none returns true, return false.
151 bool ComponentBase::OnEvent(Event event) { // NOLINT
152 for (Component& child : children_) { // NOLINT
153 if (child->OnEvent(event)) {
154 return true;
155 }
156 }
157 return false;
158}
159
160/// @brief Called in response to an animation event.
161/// @param params the parameters of the animation
162/// The default implementation dispatch the event to every child.
163 void ComponentBase::OnAnimation(animation::Params& params) {
164 for (const Component& child : children_) {
165 child->OnAnimation(params);
166 }
167}
168
169/// @brief Return the currently Active child.
170/// @return the currently Active child.
171 Component ComponentBase::ActiveChild() {
172 for (auto& child : children_) {
173 if (child->Focusable()) {
174 return child;
175 }
176 }
177 return nullptr;
178}
179
180/// @brief Return true when the component contains focusable elements.
181/// The non focusable Components will be skipped when navigating using the
182/// keyboard.
183 bool ComponentBase::Focusable() const {
184 for (const Component& child : children_) { // NOLINT
185 if (child->Focusable()) {
186 return true;
187 }
188 }
189 return false;
190}
191
192/// @brief Returns if the element if the currently active child of its parent.
193 bool ComponentBase::Active() const {
194 return parent_ == nullptr || parent_->ActiveChild().get() == this;
195}
196
197/// @brief Returns if the elements if focused by the user.
198/// True when the ComponentBase is focused by the user. An element is Focused
199/// when it is with all its ancestors the ActiveChild() of their parents, and it
200/// Focusable().
201 bool ComponentBase::Focused() const {
202 const auto* current = this;
203 while (current && current->Active()) {
204 current = current->parent_;
205 }
206 return !current && Focusable();
207}
208
209/// @brief Make the |child| to be the "active" one.
210/// @param child the child to become active.
211 void ComponentBase::SetActiveChild([[maybe_unused]] ComponentBase* child) {}
212
213/// @brief Make the |child| to be the "active" one.
214/// @param child the child to become active.
215 void ComponentBase::SetActiveChild(Component child) { // NOLINT
216 SetActiveChild(child.get());
217}
218
219/// @brief Configure all the ancestors to give focus to this component.
220 void ComponentBase::TakeFocus() {
221 ComponentBase* child = this;
222 while (ComponentBase* parent = child->parent_) {
223 parent->SetActiveChild(child);
224 child = parent;
225 }
226}
227
228/// @brief Take the CapturedMouse if available. There is only one component of
229/// them. It represents a component taking priority over others.
230/// @param event The event
231 CapturedMouse ComponentBase::CaptureMouse(const Event& event) { // NOLINT
232 if (event.screen_) {
233 return event.screen_->CaptureMouse();
234 }
235 return std::make_unique<CaptureMouseImpl>();
236}
237
238} // namespace ftxui
box.hpp
captured_mouse.hpp
ftxui::animation::Params
Definition animation.hpp:33
component.hpp
component_base.hpp
elements.hpp
event.hpp
ftxui::ComponentBase::Focusable
virtual bool Focusable() const
Return true when the component contains focusable elements. The non focusable Components will be skip...
Definition component.cpp:183
ftxui::ComponentBase::Focused
bool Focused() const
Returns if the elements if focused by the user. True when the ComponentBase is focused by the user....
Definition component.cpp:201
ftxui::ComponentBase::CaptureMouse
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:231
ftxui::ComponentBase::Add
void Add(Component children)
Add a child. @param child The child to be attached.
Definition component.cpp:70
ftxui::ComponentBase::children_
Components children_
Definition component_base.hpp:96
ftxui::ComponentBase::Render
Element Render()
Draw the component. Build a ftxui::Element to be drawn on the ftxui::Screen representing this ftxui::...
Definition component.cpp:103
ftxui::ComponentBase::TakeFocus
void TakeFocus()
Configure all the ancestors to give focus to this component.
Definition component.cpp:220
ftxui::ComponentBase::Active
bool Active() const
Returns if the element if the currently active child of its parent.
Definition component.cpp:193
ftxui::Event::screen_
ScreenInteractive * screen_
Definition event.hpp:124
ftxui::ComponentBase::ActiveChild
virtual Component ActiveChild()
Return the currently Active child.
Definition component.cpp:171
ftxui::ComponentBase::DetachAllChildren
void DetachAllChildren()
Remove all children.
Definition component.cpp:94
ftxui::ComponentBase::SetActiveChild
virtual void SetActiveChild(ComponentBase *child)
Make the |child| to be the "active" one.
Definition component.cpp:211
ftxui::ComponentBase::Index
int Index() const
Return index of the component in its parent. -1 if no parent.
Definition component.cpp:54
ftxui::ComponentBase::ChildCount
size_t ChildCount() const
Returns the number of children.
Definition component.cpp:49
ftxui::ComponentBase::Parent
ComponentBase * Parent() const
Return the parent ComponentBase, or nul if any.
Definition component.cpp:38
ftxui::ComponentBase::OnRender
virtual Element OnRender()
Draw the component. Build a ftxui::Element to be drawn on the ftxi::Screen representing this ftxui::C...
Definition component.cpp:138
ftxui::ComponentBase::OnEvent
virtual bool OnEvent(Event)
Called in response to an event.
Definition component.cpp:151
ftxui::ComponentBase::Detach
void Detach()
Detach this child from its parent.
Definition component.cpp:79
ftxui::ComponentBase::ChildAt
Component & ChildAt(size_t i)
Access the child at index i.
Definition component.cpp:43
ftxui::ComponentBase::~ComponentBase
virtual ~ComponentBase()
Definition component.cpp:31
ftxui::ComponentBase::OnAnimation
virtual void OnAnimation(animation::Params &params)
Called in response to an animation event.
Definition component.cpp:163
ftxui::ComponentBase
It implement rendering itself as ftxui::Element. It implement keyboard navigation by responding to ft...
Definition component_base.hpp:30
ftxui::Event
Represent an event. It can be key press event, a terminal resize, or more ...
Definition event.hpp:29
ftxui::Node
Node is the base class for all elements in the DOM tree.
Definition node.hpp:37
ftxui::text
Element text(std::wstring text)
Display a piece of unicode text.
Definition text.cpp:160
ftxui::Box
Box is a structure that represents a rectangular area in a 2D space.
Definition box.hpp:16
ftxui::animation
The FTXUI ftxui::animation:: namespace.
Definition animation.hpp:10
ftxui
The FTXUI ftxui:: namespace.
Definition animation.hpp:10
ftxui::CapturedMouse
std::unique_ptr< CapturedMouseInterface > CapturedMouse
Definition captured_mouse.hpp:20
ftxui::Element
std::shared_ptr< Node > Element
Definition elements.hpp:22
ftxui::Component
std::shared_ptr< ComponentBase > Component
Definition component_base.hpp:24
node.hpp
screen_interactive.hpp