FTXUI  4.1.0
C++ functional terminal UI.
Loading...
Searching...
No Matches
gauge.cpp
Go to the documentation of this file.
1#include <ftxui/dom/direction.hpp> // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up
2#include <memory> // for allocator, make_shared
3#include <string> // for string
4
5#include "ftxui/dom/elements.hpp" // for Element, gauge, gaugeDirection, gaugeDown, gaugeLeft, gaugeRight, gaugeUp
6#include "ftxui/dom/node.hpp" // for Node
7#include "ftxui/dom/requirement.hpp" // for Requirement
8#include "ftxui/screen/box.hpp" // for Box
9#include "ftxui/screen/screen.hpp" // for Screen, Pixel
10
11namespace ftxui {
12
13// NOLINTNEXTLINE
14static const std::string charset_horizontal[11] = {
15#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
16 // Microsoft's terminals often use fonts not handling the 8 unicode
17 // characters for representing the whole gauge. Fallback with less.
18 " ", " ", " ", " ", "▌", "▌", "▌", "█", "█", "█",
19#else
20 " ", " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█",
21#endif
22 // An extra character in case when the fuzzer manage to have:
23 // int(9 * (limit - limit_int) = 9
24 "█"};
25
26// NOLINTNEXTLINE
27static const std::string charset_vertical[10] = {
28 "█",
29 "▇",
30 "▆",
31 "▅",
32 "▄",
33 "▃",
34 "▂",
35 "▁",
36 " ",
37 // An extra character in case when the fuzzer manage to have:
38 // int(8 * (limit - limit_int) = 8
39 " ",
40};
41
42class Gauge : public Node {
43 public:
44 Gauge(float progress, Direction direction)
45 : progress_(progress), direction_(direction) {
46 // This handle NAN correctly:
47 if (!(progress_ > 0.F)) {
48 progress_ = 0.F;
49 }
50 if (!(progress_ < 1.F)) {
51 progress_ = 1.F;
52 }
53 }
54
55 void ComputeRequirement() override {
56 switch (direction_) {
58 case Direction::Left:
63 break;
64 case Direction::Up:
65 case Direction::Down:
70 break;
71 }
74 }
75
76 void Render(Screen& screen) override {
77 switch (direction_) {
79 RenderHorizontal(screen, /*invert=*/false);
80 break;
81 case Direction::Up:
82 RenderVertical(screen, /*invert=*/false);
83 break;
84 case Direction::Left:
85 RenderHorizontal(screen, /*invert=*/true);
86 break;
87 case Direction::Down:
88 RenderVertical(screen, /*invert=*/true);
89 break;
90 }
91 }
92
93 void RenderHorizontal(Screen& screen, bool invert) {
94 const int y = box_.y_min;
95 if (y > box_.y_max) {
96 return;
97 }
98
99 // Draw the progress bar horizontally.
100 {
101 const float progress = invert ? 1.F - progress_ : progress_;
102 const float limit =
103 (float)box_.x_min + progress * (float)(box_.x_max - box_.x_min + 1);
104 const int limit_int = (int)limit;
105 int x = box_.x_min;
106 while (x < limit_int) {
107 screen.at(x++, y) = charset_horizontal[9]; // NOLINT
108 }
109 // NOLINTNEXTLINE
110 screen.at(x++, y) = charset_horizontal[int(9 * (limit - limit_int))];
111 while (x <= box_.x_max) {
112 screen.at(x++, y) = charset_horizontal[0];
113 }
114 }
115
116 if (invert) {
117 for (int x = box_.x_min; x <= box_.x_max; x++) {
118 screen.PixelAt(x, y).inverted ^= true;
119 }
120 }
121 }
122
123 void RenderVertical(Screen& screen, bool invert) {
124 const int x = box_.x_min;
125 if (x > box_.x_max) {
126 return;
127 }
128
129 // Draw the progress bar vertically:
130 {
131 const float progress = invert ? progress_ : 1.F - progress_;
132 const float limit =
133 (float)box_.y_min + progress * (float)(box_.y_max - box_.y_min + 1);
134 const int limit_int = (int)limit;
135 int y = box_.y_min;
136 while (y < limit_int) {
137 screen.at(x, y++) = charset_vertical[8]; // NOLINT
138 }
139 // NOLINTNEXTLINE
140 screen.at(x, y++) = charset_vertical[int(8 * (limit - limit_int))];
141 while (y <= box_.y_max) {
142 screen.at(x, y++) = charset_vertical[0];
143 }
144 }
145
146 if (invert) {
147 for (int y = box_.y_min; y <= box_.y_max; y++) {
148 screen.PixelAt(x, y).inverted ^= true;
149 }
150 }
151 }
152
153 private:
154 float progress_;
155 Direction direction_;
156};
157
158/// @brief Draw a high definition progress bar progressing in specified
159/// direction.
160/// @param progress The proportion of the area to be filled. Belong to [0,1].
161// @param direction Direction of progress bars progression.
162/// @ingroup dom
163Element gaugeDirection(float progress, Direction direction) {
164 return std::make_shared<Gauge>(progress, direction);
165}
166
167/// @brief Draw a high definition progress bar progressing from left to right.
168/// @param progress The proportion of the area to be filled. Belong to [0,1].
169/// @ingroup dom
170///
171/// ### Example
172///
173/// A gauge. It can be used to represent a progress bar.
174/// ~~~cpp
175/// border(gaugeRight(0.5))
176/// ~~~
177///
178/// #### Output
179///
180/// ~~~bash
181/// ┌──────────────────────────────────────────────────────────────────────────┐
182/// │█████████████████████████████████████ │
183/// └──────────────────────────────────────────────────────────────────────────┘
184/// ~~~
185Element gaugeRight(float progress) {
186 return gaugeDirection(progress, Direction::Right);
187}
188
189/// @brief Draw a high definition progress bar progressing from right to left.
190/// @param progress The proportion of the area to be filled. Belong to [0,1].
191/// @ingroup dom
192///
193/// ### Example
194///
195/// A gauge. It can be used to represent a progress bar.
196/// ~~~cpp
197/// border(gaugeLeft(0.5))
198/// ~~~
199///
200/// #### Output
201///
202/// ~~~bash
203/// ┌──────────────────────────────────────────────────────────────────────────┐
204/// │ █████████████████████████████████████│
205/// └──────────────────────────────────────────────────────────────────────────┘
206/// ~~~
207Element gaugeLeft(float progress) {
208 return gaugeDirection(progress, Direction::Left);
209}
210
211/// @brief Draw a high definition progress bar progressing from bottom to top.
212/// @param progress The proportion of the area to be filled. Belong to [0,1].
213/// @ingroup dom
214///
215/// ### Example
216///
217/// A gauge. It can be used to represent a progress bar.
218/// ~~~cpp
219/// border(gaugeUp(0.5))
220/// ~~~
221///
222/// #### Output
223///
224/// ~~~bash
225/// ┌─┐
226/// │ │
227/// │ │
228/// │ │
229/// │ │
230/// │█│
231/// │█│
232/// │█│
233/// │█│
234/// └─┘
235/// ~~~
236Element gaugeUp(float progress) {
237 return gaugeDirection(progress, Direction::Up);
238}
239
240/// @brief Draw a high definition progress bar progressing from top to bottom.
241/// @param progress The proportion of the area to be filled. Belong to [0,1].
242/// @ingroup dom
243///
244/// ### Example
245///
246/// A gauge. It can be used to represent a progress bar.
247/// ~~~cpp
248/// border(gaugeDown(0.5))
249/// ~~~
250///
251/// #### Output
252///
253/// ~~~bash
254/// ┌─┐
255/// │█│
256/// │█│
257/// │█│
258/// │█│
259/// │ │
260/// │ │
261/// │ │
262/// │ │
263/// └─┘
264/// ~~~
265Element gaugeDown(float progress) {
266 return gaugeDirection(progress, Direction::Down);
267}
268
269/// @brief Draw a high definition progress bar.
270/// @param progress The proportion of the area to be filled. Belong to [0,1].
271/// @ingroup dom
272///
273/// ### Example
274///
275/// A gauge. It can be used to represent a progress bar.
276/// ~~~cpp
277/// border(gauge(0.5))
278/// ~~~
279///
280/// #### Output
281///
282/// ~~~bash
283/// ┌──────────────────────────────────────────────────────────────────────────┐
284/// │█████████████████████████████████████ │
285/// └──────────────────────────────────────────────────────────────────────────┘
286/// ~~~
287Element gauge(float progress) {
288 return gaugeRight(progress);
289}
290
291} // namespace ftxui
292
293// Copyright 2020 Arthur Sonzogni. All rights reserved.
294// Use of this source code is governed by the MIT license that can be found in
295// the LICENSE file.
Requirement requirement_
Definition node.hpp:54
Box box_
Definition node.hpp:55
Element gaugeDirection(float progress, Direction direction)
Draw a high definition progress bar progressing in specified direction.
Definition gauge.cpp:163
std::shared_ptr< Node > Element
Definition elements.hpp:20
Element gaugeRight(float progress)
Draw a high definition progress bar progressing from left to right.
Definition gauge.cpp:185
Element gaugeUp(float progress)
Draw a high definition progress bar progressing from bottom to top.
Definition gauge.cpp:236
Element gaugeLeft(float progress)
Draw a high definition progress bar progressing from right to left.
Definition gauge.cpp:207
Element gauge(float progress)
Draw a high definition progress bar.
Definition gauge.cpp:287
Element gaugeDown(float progress)
Draw a high definition progress bar progressing from top to bottom.
Definition gauge.cpp:265
int x_max
Definition box.hpp:8
int y_min
Definition box.hpp:9
int y_max
Definition box.hpp:10
int x_min
Definition box.hpp:7