FTXUI 6.1.9
C++ functional terminal UI.
载入中...
搜索中...
未找到
src/ftxui/dom/gauge.cpp
浏览该文件的文档.
1// 版权所有 2020 Arthur Sonzogni。保留所有权利。
2// 本源代码的使用受 MIT 许可证的约束,该许可证可在 LICENSE 文件中找到。
3#include <ftxui/dom/direction.hpp> // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up
4#include <memory> // for allocator, make_shared
5#include <string> // for string
6
7#include "ftxui/dom/elements.hpp" // for Element, gauge, gaugeDirection, gaugeDown, gaugeLeft, gaugeRight, gaugeUp
8#include "ftxui/dom/node.hpp" // for Node
9#include "ftxui/dom/requirement.hpp" // for Requirement
10#include "ftxui/screen/box.hpp" // for Box
11#include "ftxui/screen/screen.hpp" // for Screen, Pixel
12
13namespace ftxui {
14
15namespace {
16// NOLINTNEXTLINE
17static const std::string charset_horizontal[11] = {
18#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
19 // Microsoft 终端通常使用不支持表示整个仪表盘的8个 Unicode 字符的字体。使用较少的字符作为回退。 " ", " ", " ", " ", "▌", "▌", "▌", "█", "█", "█",
20#else
21 " ", " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█",
22#endif
23 // 在模糊测试器设法得到以下情况时,额外的一个字符:
24 // int(9 * (limit - limit_int) = 9
25 "█"};
26
27// NOLINTNEXTLINE
28static const std::string charset_vertical[10] = {
29 "█",
30 "▇",
31 "▆",
32 "▅",
33 "▄",
34 "▃",
35 "▂",
36 "▁",
37 " ",
38 // 在模糊测试器设法得到以下情况时,额外的一个字符:
39 // int(8 * (limit - limit_int) = 8
40 " ",
41};
42
43class Gauge : public Node {
44 public:
45 Gauge(float progress, Direction direction)
46 : progress_(progress), direction_(direction) {
47 // 这可以正确处理 NAN:
48 if (!(progress_ > 0.F)) {
49 progress_ = 0.F;
50 }
51 if (!(progress_ < 1.F)) {
52 progress_ = 1.F;
53 }
54 }
55
56 void ComputeRequirement() override {
57 switch (direction_) {
59 case Direction::Left:
60 requirement_.flex_grow_x = 1;
61 requirement_.flex_grow_y = 0;
62 requirement_.flex_shrink_x = 1;
63 requirement_.flex_shrink_y = 0;
64 break;
65 case Direction::Up:
66 case Direction::Down:
67 requirement_.flex_grow_x = 0;
68 requirement_.flex_grow_y = 1;
69 requirement_.flex_shrink_x = 0;
70 requirement_.flex_shrink_y = 1;
71 break;
72 }
73 requirement_.min_x = 1;
74 requirement_.min_y = 1;
75 }
76
77 void Render(Screen& screen) override {
78 switch (direction_) {
80 RenderHorizontal(screen, /*invert=*/false);
81 break;
82 case Direction::Up:
83 RenderVertical(screen, /*invert=*/false);
84 break;
85 case Direction::Left:
86 RenderHorizontal(screen, /*invert=*/true);
87 break;
88 case Direction::Down:
89 RenderVertical(screen, /*invert=*/true);
90 break;
91 }
92 }
93
94 void RenderHorizontal(Screen& screen, bool invert) {
95 const int y = box_.y_min;
96 if (y > box_.y_max) {
97 return;
98 }
99
100 // Draw the progress bar horizontally.
101 {
102 const float progress = invert ? 1.F - progress_ : progress_;
103 const auto limit =
104 float(box_.x_min) + progress * float(box_.x_max - box_.x_min + 1);
105 const int limit_int = static_cast<int>(limit);
106 int x = box_.x_min;
107 while (x < limit_int) {
108 screen.at(x++, y) = charset_horizontal[9]; // NOLINT
109 }
110 // NOLINTNEXTLINE
111 screen.at(x++, y) = charset_horizontal[int(9 * (limit - limit_int))];
112 while (x <= box_.x_max) {
113 screen.at(x++, y) = charset_horizontal[0];
114 }
115 }
116
117 if (invert) {
118 for (int x = box_.x_min; x <= box_.x_max; x++) {
119 screen.PixelAt(x, y).inverted ^= true;
120 }
121 }
122 }
123
124 void RenderVertical(Screen& screen, bool invert) {
125 const int x = box_.x_min;
126 if (x > box_.x_max) {
127 return;
128 }
129
130 // Draw the progress bar vertically:
131 {
132 const float progress = invert ? progress_ : 1.F - progress_;
133 const float limit =
134 float(box_.y_min) + progress * float(box_.y_max - box_.y_min + 1);
135 const int limit_int = static_cast<int>(limit);
136 int y = box_.y_min;
137 while (y < limit_int) {
138 screen.at(x, y++) = charset_vertical[8]; // NOLINT
139 }
140 // NOLINTNEXTLINE
141 screen.at(x, y++) = charset_vertical[int(8 * (limit - limit_int))];
142 while (y <= box_.y_max) {
143 screen.at(x, y++) = charset_vertical[0];
144 }
145 }
146
147 if (invert) {
148 for (int y = box_.y_min; y <= box_.y_max; y++) {
149 screen.PixelAt(x, y).inverted ^= true;
150 }
151 }
152 }
153
154 private:
155 float progress_;
156 Direction direction_;
157};
158
159} // namespace
160
161/// @brief 绘制一个向指定方向推进的高清进度条。
162/// @param progress 要填充区域的比例。范围在 [0,1] 之间。
163/// @param direction 进度条的推进方向。
164/// @ingroup dom
165Element gaugeDirection(float progress, Direction direction) {
166 return std::make_shared<Gauge>(progress, direction);
167}
168
169/// @brief 绘制一个从左到右推进的高清进度条。
170/// @param progress 要填充区域的比例。范围在 [0,1] 之间。
171///
172/// ### 示例
173///
174/// 一个仪表盘。它可以用来表示进度条。
175/// ~~~cpp
176/// border(gaugeRight(0.5))
177/// ~~~
178///
179/// #### 输出
180///
181/// ~~~bash
182/// ┌──────────────────────────────────────────────────────────────────────────┐
183/// │█████████████████████████████████████ │
184/// └──────────────────────────────────────────────────────────────────────────┘
185/// ~~~
186Element gaugeRight(float progress) {
187 return gaugeDirection(progress, Direction::Right);
188}
189
190/// @brief 绘制一个从右到左推进的高清进度条。
191/// @param progress 要填充区域的比例。范围在 [0,1] 之间。
192///
193/// ### 示例
194///
195/// 一个仪表盘。它可以用来表示进度条。
196/// ~~~cpp
197/// border(gaugeLeft(0.5))
198/// ~~~
199///
200/// #### 输出
201///
202/// ~~~bash
203/// ┌──────────────────────────────────────────────────────────────────────────┐
204/// │ █████████████████████████████████████│
205/// └──────────────────────────────────────────────────────────────────────────┘
206/// ~~~
207Element gaugeLeft(float progress) {
208 return gaugeDirection(progress, Direction::Left);
209}
210
211/// @brief 绘制一个从下到上推进的高清进度条。
212/// @param progress 要填充区域的比例。范围在 [0,1] 之间。
213///
214/// ### 示例
215///
216/// 一个仪表盘。它可以用来表示进度条。
217/// ~~~cpp
218/// border(gaugeUp(0.5))
219/// ~~~
220///
221/// #### 输出
222///
223/// ~~~bash
224/// ┌─┐
225/// │ │
226/// │ │
227/// │ │
228/// │ │
229/// │█│
230/// │█│
231/// │█│
232/// │█│
233/// └─┘
234/// ~~~
235Element gaugeUp(float progress) {
236 return gaugeDirection(progress, Direction::Up);
237}
238
239/// @brief 绘制一个从上到下推进的高清进度条。
240/// @param progress 要填充区域的比例。范围在 [0,1] 之间。
241///
242/// ### 示例
243///
244/// 一个仪表盘。它可以用来表示进度条。
245/// ~~~cpp
246/// border(gaugeDown(0.5))
247/// ~~~
248///
249/// #### 输出
250///
251/// ~~~bash
252/// ┌─┐
253/// │█│
254/// │█│
255/// │█│
256/// │█│
257/// │ │
258/// │ │
259/// │ │
260/// │ │
261/// └─┘
262/// ~~~
263Element gaugeDown(float progress) {
264 return gaugeDirection(progress, Direction::Down);
265}
266
267/// @brief 绘制一个高清进度条。
268/// @param progress 要填充区域的比例。范围在 [0,1] 之间。
269///
270/// ### 示例
271///
272/// 一个仪表盘。它可以用来表示进度条。
273/// ~~~cpp
274/// border(gauge(0.5))
275/// ~~~
276///
277/// #### 输出
278///
279/// ~~~bash
280/// ┌──────────────────────────────────────────────────────────────────────────┐
281/// │█████████████████████████████████████ │
282/// └──────────────────────────────────────────────────────────────────────────┘
283/// ~~~
284Element gauge(float progress) {
285 return gaugeRight(progress);
286}
287
288} // namespace ftxui
Element gaugeDirection(float progress, Direction direction)
绘制一个向指定方向推进的高清进度条。
Direction
Direction 是一个枚举,表示四个基本方向。
void Render(Screen &screen, const Element &element)
在 ftxui::Screen 上显示元素。
#include "ftxui/component/component_base.hpp" // 用于 ComponentBase
std::shared_ptr< Node > Element
Element gaugeRight(float progress)
绘制一个从左到右推进的高清进度条。
Element gaugeUp(float progress)
绘制一个从下到上推进的高清进度条。
Element gaugeLeft(float progress)
绘制一个从右到左推进的高清进度条。
Element gauge(float progress)
绘制一个高清进度条。
Element gaugeDown(float progress)
绘制一个从上到下推进的高清进度条。