Loading...
Searching...
No Matches
node.cpp
Go to the documentation of this file.
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
#include <ftxui/screen/box.hpp> // for Box
#include <string>
#include <utility> // for move
#include <cstddef>
#include "ftxui/dom/node.hpp"
#include "ftxui/dom/selection.hpp" // for Selection
#include "ftxui/screen/screen.hpp" // for Screen
namespace ftxui {
Node::Node() = default;
Node::Node(Elements children) : children_(std::move(children)) {}
Node::~Node() = default;
/// @brief Compute how much space an elements needs.
/// @ingroup dom
void Node::ComputeRequirement() {
if (children_.empty()) {
return;
}
for (auto& child : children_) {
child->ComputeRequirement();
}
// By default, the requirement is the one of the first child.
requirement_ = children_[0]->requirement();
// Propagate the focused requirement.
for (size_t i = 1; i < children_.size(); ++i) {
if (!requirement_.focused.enabled &&
children_[i]->requirement().focused.enabled) {
requirement_.focused = children_[i]->requirement().focused;
}
}
}
/// @brief Assign a position and a dimension to an element for drawing.
/// @ingroup dom
void Node::SetBox(Box box) {
box_ = box;
}
/// @brief Compute the selection of an element.
/// @ingroup dom
void Node::Select(Selection& selection) {
// If this Node box_ doesn't intersect with the selection, then no selection.
if (Box::Intersection(selection.GetBox(), box_).IsEmpty()) {
return;
}
// By default we defer the selection to the children.
for (auto& child : children_) {
child->Select(selection);
}
}
/// @brief Display an element on a ftxui::Screen.
/// @ingroup dom
void Node::Render(Screen& screen) {
for (auto& child : children_) {
child->Render(screen);
}
}
void Node::Check(Status* status) {
for (auto& child : children_) {
child->Check(status);
}
status->need_iteration |= (status->iteration == 0);
}
std::string Node::GetSelectedContent(Selection& selection) {
std::string content;
for (auto& child : children_) {
content += child->GetSelectedContent(selection);
}
return content;
}
/// @brief Display an element on a ftxui::Screen.
/// @ingroup dom
void Render(Screen& screen, const Element& element) {
Selection selection;
Render(screen, element.get(), selection);
}
/// @brief Display an element on a ftxui::Screen.
/// @ingroup dom
void Render(Screen& screen, Node* node) {
Selection selection;
Render(screen, node, selection);
}
void Render(Screen& screen, Node* node, Selection& selection) {
Box box;
box.x_min = 0;
box.y_min = 0;
box.x_max = screen.dimx() - 1;
box.y_max = screen.dimy() - 1;
Node::Status status;
node->Check(&status);
const int max_iterations = 20;
while (status.need_iteration && status.iteration < max_iterations) {
// Step 1: Find what dimension this elements wants to be.
node->ComputeRequirement();
// Step 2: Assign a dimension to the element.
node->SetBox(box);
// Check if the element needs another iteration of the layout algorithm.
status.need_iteration = false;
status.iteration++;
node->Check(&status);
}
// Step 3: Selection
if (!selection.IsEmpty()) {
node->Select(selection);
}
if (node->requirement().focused.enabled
#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
// Setting the cursor to the right position allow folks using CJK (China,
// Japanese, Korean, ...) characters to see their [input method editor]
// displayed at the right location. See [issue].
//
// [input method editor]:
// https://en.wikipedia.org/wiki/Input_method
//
// [issue]:
// https://github.com/ArthurSonzogni/FTXUI/issues/2#issuecomment-505282355
//
// Unfortunately, Microsoft terminal do not handle properly hiding the
// cursor. Instead the character under the cursor is hidden, which is a
// big problem. As a result, we can't enable setting cursor to the right
// location. It will be displayed at the bottom right corner.
// See:
// https://github.com/microsoft/terminal/issues/1203
// https://github.com/microsoft/terminal/issues/3093
&&
node->requirement().focused.cursor_shape != Screen::Cursor::Shape::Hidden
#endif
) {
screen.SetCursor(Screen::Cursor{
node->requirement().focused.node->box_.x_max,
node->requirement().focused.node->box_.y_max,
node->requirement().focused.cursor_shape,
});
} else {
screen.SetCursor(Screen::Cursor{
screen.dimx() - 1,
screen.dimy() - 1,
Screen::Cursor::Shape::Hidden,
});
}
// Step 4: Draw the element.
screen.stencil = box;
node->Render(screen);
// Step 5: Apply shaders
screen.ApplyShader();
}
std::string GetNodeSelectedContent(Screen& screen,
Node* node,
Selection& selection) {
Box box;
box.x_min = 0;
box.y_min = 0;
box.x_max = screen.dimx() - 1;
box.y_max = screen.dimy() - 1;
Node::Status status;
node->Check(&status);
const int max_iterations = 20;
while (status.need_iteration && status.iteration < max_iterations) {
// Step 1: Find what dimension this elements wants to be.
node->ComputeRequirement();
// Step 2: Assign a dimension to the element.
node->SetBox(box);
// Check if the element needs another iteration of the layout algorithm.
status.need_iteration = false;
status.iteration++;
node->Check(&status);
}
// Step 3: Selection
node->Select(selection);
// Step 4: get the selected content.
return node->GetSelectedContent(selection);
}
} // namespace ftxui
box.hpp
ftxui::Node
Definition node.hpp:23
ftxui::Node::Select
virtual void Select(Selection &selection)
Compute the selection of an element.
Definition node.cpp:49
ftxui::Node::Node
Node()
ftxui::Node::children_
Elements children_
Definition node.hpp:65
ftxui::Node::GetSelectedContent
virtual std::string GetSelectedContent(Selection &selection)
Definition node.cpp:76
ftxui::Node::SetBox
virtual void SetBox(Box box)
Assign a position and a dimension to an element for drawing.
Definition node.cpp:43
ftxui::Node::requirement_
Requirement requirement_
Definition node.hpp:66
ftxui::Node::requirement
Requirement requirement()
Definition node.hpp:38
ftxui::Node::ComputeRequirement
virtual void ComputeRequirement()
Compute how much space an elements needs.
Definition node.cpp:21
ftxui::Node::Check
virtual void Check(Status *status)
Definition node.cpp:69
ftxui::Node::~Node
virtual ~Node()
ftxui::Node::Render
virtual void Render(Screen &screen)
Display an element on a ftxui::Screen.
Definition node.cpp:63
ftxui::Node::box_
Box box_
Definition node.hpp:67
ftxui::Node::Render
friend void Render(Screen &screen, Node *node, Selection &selection)
Definition node.cpp:100
ftxui::Node::Status
Definition node.hpp:56
ftxui::Screen
A rectangular grid of Pixel.
Definition screen.hpp:27
ftxui::Selection
Represent a selection in the terminal.
Definition selection.hpp:17
ftxui
Definition animation.hpp:10
ftxui::GetNodeSelectedContent
std::string GetNodeSelectedContent(Screen &screen, Node *node, Selection &selection)
Definition node.cpp:172
ftxui::Element
std::shared_ptr< Node > Element
Definition elements.hpp:22
ftxui::Make
std::shared_ptr< T > Make(Args &&... args)
Definition component.hpp:26
ftxui::Elements
std::vector< Element > Elements
Definition elements.hpp:23
ftxui::Requirement::focused
Focused focused
Definition requirement.hpp:46
ftxui::Render
void Render(Screen &screen, const Element &element)
Display an element on a ftxui::Screen.
Definition node.cpp:88
node.hpp
screen.hpp
selection.hpp
ftxui::Box
Definition box.hpp:9
ftxui::Box::x_max
int x_max
Definition box.hpp:11
ftxui::Box::y_min
int y_min
Definition box.hpp:12
ftxui::Box::Intersection
static auto Intersection(Box a, Box b) -> Box
Definition box.cpp:12
ftxui::Box::y_max
int y_max
Definition box.hpp:13
ftxui::Box::x_min
int x_min
Definition box.hpp:10
ftxui::Requirement::Focused::cursor_shape
Screen::Cursor::Shape cursor_shape
Definition requirement.hpp:29
ftxui::Requirement::Focused::enabled
bool enabled
Definition requirement.hpp:26
ftxui::Requirement::Focused::node
Node * node
Definition requirement.hpp:28
ftxui::Screen::Cursor
Definition screen.hpp:48
ftxui::Screen::Cursor::Hidden
@ Hidden
Definition screen.hpp:53