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