FTXUI  4.1.1
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_access
3#include <utility> // for move
4#include <vector> // for __alloc_traits<>::value_type
5
6#include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, focus, frame, select, xframe, yframe
7#include "ftxui/dom/node.hpp" // for Node, Elements
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 explicit 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 - 1;
28 selected_box.y_max = requirement_.min_y - 1;
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{
75 box_.x_min,
76 box_.y_min,
78 });
79#endif
80 }
81};
82
84 return std::make_shared<Focus>(unpack(std::move(child)));
85}
86
87// -----------------------------------------------------------------------------
88
89class Frame : public Node {
90 public:
91 Frame(Elements children, bool x_frame, bool y_frame)
92 : Node(std::move(children)), x_frame_(x_frame), y_frame_(y_frame) {}
93
94 void ComputeRequirement() override {
96 requirement_ = children_[0]->requirement();
97 }
98
99 void SetBox(Box box) override {
100 Node::SetBox(box);
101 auto& selected_box = requirement_.selected_box;
102 Box children_box = box;
103
104 if (x_frame_) {
105 const int external_dimx = box.x_max - box.x_min;
106 const int internal_dimx = std::max(requirement_.min_x, external_dimx);
107 const int focused_dimx = selected_box.x_max - selected_box.x_min;
108 int dx = selected_box.x_min - external_dimx / 2 + focused_dimx / 2;
109 dx = std::max(0, std::min(internal_dimx - external_dimx - 1, dx));
110 children_box.x_min = box.x_min - dx;
111 children_box.x_max = box.x_min + internal_dimx - dx;
112 }
113
114 if (y_frame_) {
115 const int external_dimy = box.y_max - box.y_min;
116 const int internal_dimy = std::max(requirement_.min_y, external_dimy);
117 const int focused_dimy = selected_box.y_max - selected_box.y_min;
118 int dy = selected_box.y_min - external_dimy / 2 + focused_dimy / 2;
119 dy = std::max(0, std::min(internal_dimy - external_dimy - 1, dy));
120 children_box.y_min = box.y_min - dy;
121 children_box.y_max = box.y_min + internal_dimy - dy;
122 }
123
124 children_[0]->SetBox(children_box);
125 }
126
127 void Render(Screen& screen) override {
128 const AutoReset<Box> stencil(&screen.stencil,
129 Box::Intersection(box_, screen.stencil));
130 children_[0]->Render(screen);
131 }
132
133 private:
134 bool x_frame_;
135 bool y_frame_;
136};
137
138/// @brief Allow an element to be displayed inside a 'virtual' area. It size can
139/// be larger than its container. In this case only a smaller portion is
140/// displayed. The view is scrollable to make the focused element visible.
141/// @see focus
143 return std::make_shared<Frame>(unpack(std::move(child)), true, true);
144}
145
147 return std::make_shared<Frame>(unpack(std::move(child)), true, false);
148}
149
151 return std::make_shared<Frame>(unpack(std::move(child)), false, true);
152}
153
154class FocusCursor : public Focus {
155 public:
156 FocusCursor(Elements children, Screen::Cursor::Shape shape)
157 : Focus(std::move(children)), shape_(shape) {}
158
159 private:
160 void Render(Screen& screen) override {
161 Select::Render(screen); // NOLINT
162 screen.SetCursor(Screen::Cursor{
163 box_.x_min,
164 box_.y_min,
165 shape_,
166 });
167 }
169};
170
172 return std::make_shared<FocusCursor>(unpack(std::move(child)),
174}
176 return std::make_shared<FocusCursor>(unpack(std::move(child)),
178}
180 return std::make_shared<FocusCursor>(unpack(std::move(child)),
182}
184 return std::make_shared<FocusCursor>(unpack(std::move(child)),
186}
188 return std::make_shared<FocusCursor>(unpack(std::move(child)),
190}
192 return std::make_shared<FocusCursor>(unpack(std::move(child)),
194}
195
196} // namespace ftxui
197
198// Copyright 2020 Arthur Sonzogni. All rights reserved.
199// Use of this source code is governed by the MIT license that can be found in
200// the LICENSE file.
Elements children_
Definition node.hpp:53
virtual void SetBox(Box box)
Assign a position and a dimension to an element for drawing.
Definition node.cpp:23
Requirement requirement_
Definition node.hpp:54
virtual void ComputeRequirement()
Compute how much space an elements needs.
Definition node.cpp:15
virtual void Render(Screen &screen)
Display an element on a ftxui::Screen.
Definition node.cpp:29
Box box_
Definition node.hpp:55
Element xframe(Element)
Definition frame.cpp:146
std::shared_ptr< Node > Element
Definition elements.hpp:19
Element focusCursorBlock(Element)
Definition frame.cpp:171
Element focusCursorUnderlineBlinking(Element)
Definition frame.cpp:191
Element focus(Element)
Definition frame.cpp:83
Element focusCursorBar(Element)
Definition frame.cpp:179
std::vector< Element > Elements
Definition elements.hpp:20
Element focusCursorBlockBlinking(Element)
Definition frame.cpp:175
Element yframe(Element)
Definition frame.cpp:150
Element focusCursorUnderline(Element)
Definition frame.cpp:187
Element frame(Element)
Allow an element to be displayed inside a 'virtual' area. It size can be larger than its container....
Definition frame.cpp:142
Element select(Element)
Definition frame.cpp:38
Element focusCursorBarBlinking(Element)
Definition frame.cpp:183
int y_min
Definition box.hpp:9
static auto Intersection(Box a, Box b) -> Box
Definition box.cpp:9
int x_min
Definition box.hpp:7