FTXUI  0.11.0
C++ functional terminal UI.
Loading...
Searching...
No Matches
frame.cpp
Go to the documentation of this file.
1#include <algorithm> // for max, min
2#include <memory> // for make_shared, shared_ptr, __shared_ptr_access
3#include <utility> // for move
4#include <vector> // for vector, __alloc_traits<>::value_type
5
6#include "ftxui/dom/elements.hpp" // for Element, unpack, focus, frame, select, xframe, yframe
7#include "ftxui/dom/node.hpp" // for Node
8#include "ftxui/dom/requirement.hpp" // for Requirement, Requirement::FOCUSED, Requirement::SELECTED
9#include "ftxui/screen/box.hpp" // for Box
10#include "ftxui/screen/screen.hpp" // for Screen, Screen::Cursor
11#include "ftxui/util/autoreset.hpp" // for AutoReset
12
13namespace ftxui {
14
15// -----------------------------------------------------------------------------
16
17class Select : public Node {
18 public:
19 Select(Elements children) : Node(std::move(children)) {}
20
21 void ComputeRequirement() override {
23 requirement_ = children_[0]->requirement();
24 auto& selected_box = requirement_.selected_box;
25 selected_box.x_min = 0;
26 selected_box.y_min = 0;
27 selected_box.x_max = requirement_.min_x;
28 selected_box.y_max = requirement_.min_y;
30 };
31
32 void SetBox(Box box) override {
33 Node::SetBox(box);
34 children_[0]->SetBox(box);
35 }
36};
37
39 return std::make_shared<Select>(unpack(std::move(child)));
40}
41
42// -----------------------------------------------------------------------------
43
44class Focus : public Select {
45 public:
46 using Select::Select;
47
48 void ComputeRequirement() override {
49 Select::ComputeRequirement();
51 };
52
53 void Render(Screen& screen) override {
54 Select::Render(screen);
55
56 // Setting the cursor to the right position allow folks using CJK (China,
57 // Japanese, Korean, ...) characters to see their [input method editor]
58 // displayed at the right location. See [issue].
59 //
60 // [input method editor]:
61 // https://en.wikipedia.org/wiki/Input_method
62 //
63 // [issue]:
64 // https://github.com/ArthurSonzogni/FTXUI/issues/2#issuecomment-505282355
65 //
66 // Unfortunately, Microsoft terminal do not handle properly hidding the
67 // cursor. Instead the character under the cursor is hidden, which is a big
68 // problem. As a result, we can't enable setting cursor to the right
69 // location. It will be displayed at the bottom right corner.
70 // See:
71 // https://github.com/microsoft/terminal/issues/1203
72 // https://github.com/microsoft/terminal/issues/3093
73#if !defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
74 screen.SetCursor(Screen::Cursor{box_.x_min, box_.y_min});
75#endif
76 }
77};
78
80 return std::make_shared<Focus>(unpack(std::move(child)));
81}
82
83// -----------------------------------------------------------------------------
84
85class Frame : public Node {
86 public:
87 Frame(Elements children, bool x_frame, bool y_frame)
88 : Node(std::move(children)), x_frame_(x_frame), y_frame_(y_frame) {}
89
90 void ComputeRequirement() override {
92 requirement_ = children_[0]->requirement();
93 }
94
95 void SetBox(Box box) override {
96 Node::SetBox(box);
97 auto& selected_box = requirement_.selected_box;
98 Box children_box = box;
99
100 if (x_frame_) {
101 int external_dimx = box.x_max - box.x_min;
102 int internal_dimx = std::max(requirement_.min_x, external_dimx);
103 int focused_dimx = selected_box.x_max - selected_box.x_min;
104 int dx = selected_box.x_min - external_dimx / 2 + focused_dimx / 2;
105 dx = std::max(0, std::min(internal_dimx - external_dimx - 1, dx));
106 children_box.x_min = box.x_min - dx;
107 children_box.x_max = box.x_min + internal_dimx - dx;
108 }
109
110 if (y_frame_) {
111 int external_dimy = box.y_max - box.y_min;
112 int internal_dimy = std::max(requirement_.min_y, external_dimy);
113 int focused_dimy = selected_box.y_max - selected_box.y_min;
114 int dy = selected_box.y_min - external_dimy / 2 + focused_dimy / 2;
115 dy = std::max(0, std::min(internal_dimy - external_dimy - 1, dy));
116 children_box.y_min = box.y_min - dy;
117 children_box.y_max = box.y_min + internal_dimy - dy;
118 }
119
120 children_[0]->SetBox(children_box);
121 }
122
123 void Render(Screen& screen) override {
124 AutoReset<Box> stencil(&screen.stencil,
125 Box::Intersection(box_, screen.stencil));
126 children_[0]->Render(screen);
127 }
128
129 private:
130 bool x_frame_;
131 bool y_frame_;
132};
133
134/// @brief Allow an element to be displayed inside a 'virtual' area. It size can
135/// be larger than its container. In this case only a smaller portion is
136/// displayed. The view is scrollable to make the focused element visible.
137/// @see focus
139 return std::make_shared<Frame>(unpack(std::move(child)), true, true);
140}
141
143 return std::make_shared<Frame>(unpack(std::move(child)), true, false);
144}
145
147 return std::make_shared<Frame>(unpack(std::move(child)), false, true);
148}
149
150} // namespace ftxui
151
152// Copyright 2020 Arthur Sonzogni. All rights reserved.
153// Use of this source code is governed by the MIT license that can be found in
154// the LICENSE file.
Elements children_
Definition node.hpp:39
virtual void SetBox(Box box)
Assign a position and a dimension to an element for drawing.
Definition node.cpp:21
Requirement requirement_
Definition node.hpp:40
virtual void ComputeRequirement()
Compute how much space an elements needs.
Definition node.cpp:14
virtual void Render(Screen &screen)
Display an element on a ftxui::Screen.
Definition node.cpp:27
Box box_
Definition node.hpp:41
Element xframe(Element)
Definition frame.cpp:142
std::shared_ptr< Node > Element
Definition elements.hpp:15
Element focus(Element)
Definition frame.cpp:79
std::vector< Element > Elements
Definition elements.hpp:16
Element yframe(Element)
Definition frame.cpp:146
Element frame(Element)
Allow an element to be displayed inside a 'virtual' area. It size can be larger than its container....
Definition frame.cpp:138
Element select(Element)
Definition frame.cpp:38
int y_min
Definition box.hpp:9
int x_min
Definition box.hpp:7
static Box Intersection(Box a, Box b)
Definition box.cpp:9