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