FTXUI 7.0.3
C++ functional terminal UI.
Loading...
Searching...
No Matches
src/ftxui/dom/gauge.cpp
Go to the documentation of this file.
1// Copyright 2020 Arthur Sonzogni. All rights reserved.
2// Use of this source code is governed by the MIT license that can be found in
3// the LICENSE file.
4#include <ftxui/dom/direction.hpp> // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up
5#include <memory> // for allocator, make_shared
6#include <string> // for string
7
8#include "ftxui/dom/elements.hpp" // for Element, gauge, gaugeDirection, gaugeDown, gaugeLeft, gaugeRight, gaugeUp
9#include "ftxui/dom/node.hpp" // for Node
10#include "ftxui/dom/requirement.hpp" // for Requirement
11#include "ftxui/screen/box.hpp" // for Box
12#include "ftxui/screen/screen.hpp" // for Screen, Cell
13
14#include "ftxui/screen/terminal.hpp" // for Quirks, GetQuirks
15
16namespace ftxui {
17
18namespace {
19// NOLINTNEXTLINE
20static const std::string charset_horizontal[11] = {
21 " ", " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█",
22 // ファザーが以下のような状況を管理する場合の追加文字:
23 // int(9 * (limit - limit_int) = 9
24 "█"};
25
26// NOLINTNEXTLINE
27static const std::string charset_horizontal_microsoft[11] = {
28 " ", " ", " ", " ", "▌", "▌", "▌", "█", "█", "█",
29 // ファザーが以下のような状況を管理する場合の追加文字:
30 // int(9 * (limit - limit_int) = 9
31 "█"};
32
33// NOLINTNEXTLINE
34static const std::string charset_vertical[10] = {
35 "█",
36 "▇",
37 "▆",
38 "▅",
39 "▄",
40 "▃",
41 "▂",
42 "▁",
43 " ",
44 // ファザーが以下のような状況を管理する場合の追加文字:
45 // int(8 * (limit - limit_int) = 8
46 " ",
47};
48
49class Gauge : public Node {
50 public:
51 Gauge(float progress, Direction direction, std::vector<std::string> charset = {})
52 : progress_(progress),
53 direction_(direction),
54 charset_(std::move(charset)) {
55 // This handle NAN correctly:
56 // これはNANを正しく処理します:
57 if (!(progress_ > 0.F)) {
58 progress_ = 0.F;
59 }
60 if (!(progress_ < 1.F)) {
61 progress_ = 1.F;
62 }
63 }
64
65 void ComputeRequirement() override {
66 switch (direction_) {
68 case Direction::Left:
69 requirement_.flex_grow_x = 1;
70 requirement_.flex_grow_y = 0;
71 requirement_.flex_shrink_x = 1;
72 requirement_.flex_shrink_y = 0;
73 break;
74 case Direction::Up:
75 case Direction::Down:
76 requirement_.flex_grow_x = 0;
77 requirement_.flex_grow_y = 1;
78 requirement_.flex_shrink_x = 0;
79 requirement_.flex_shrink_y = 1;
80 break;
81 }
82 requirement_.min_x = 1;
83 requirement_.min_y = 1;
84 }
85
86 void Render(Screen& screen) override {
87 switch (direction_) {
89 RenderHorizontal(screen, /*invert=*/false);
90 break;
91 case Direction::Up:
92 RenderVertical(screen, /*invert=*/false);
93 break;
94 case Direction::Left:
95 RenderHorizontal(screen, /*invert=*/true);
96 break;
97 case Direction::Down:
98 RenderVertical(screen, /*invert=*/true);
99 break;
100 }
101 }
102
103 void RenderHorizontal(Screen& screen, bool invert) {
104 if (box_.y_min > box_.y_max) {
105 return;
106 }
107
108 // `full`は`charset`内の「full」グリフのインデックス。境界セルは
109 // int(full * fractional_fill)のグリフインデックスを選ぶ。
110 const std::string* charset;
111 int full;
112 if (charset_.empty()) {
113 charset = Terminal::GetQuirks().BlockCharacters() // NOLINT
114 ? charset_horizontal
115 : charset_horizontal_microsoft;
116 full = 9;
117 } else {
118 charset = charset_.data();
119 full = static_cast<int>(charset_.size()) - 1;
120 }
121
122 // プログレスバーを割り当てられた高さいっぱいに水平に描画する:
123 const float progress = invert ? 1.F - progress_ : progress_;
124 const auto limit =
125 float(box_.x_min) + progress * float(box_.x_max - box_.x_min + 1);
126 const int limit_int = static_cast<int>(limit);
127
128 for (int y = box_.y_min; y <= box_.y_max; y++) {
129 int x = box_.x_min;
130 while (x < limit_int) {
131 screen.at(x++, y) = charset[full];
132 }
133 if (x <= box_.x_max) {
134 screen.at(x++, y) = charset[int(full * (limit - limit_int))];
135 }
136 while (x <= box_.x_max) {
137 screen.at(x++, y) = charset[0];
138 }
139 }
140
141 if (invert) {
142 Invert(screen);
143 }
144 }
145
146 void RenderVertical(Screen& screen, bool invert) {
147 if (box_.x_min > box_.x_max) {
148 return;
149 }
150
151 const std::string* charset;
152 int full;
153 if (charset_.empty()) {
154 charset = charset_vertical;
155 full = 8;
156 } else {
157 charset = charset_.data();
158 full = static_cast<int>(charset_.size()) - 1;
159 }
160
161 // プログレスバーを割り当てられた幅いっぱいに垂直に描画する:
162 const float progress = invert ? progress_ : 1.F - progress_;
163 const float limit =
164 float(box_.y_min) + progress * float(box_.y_max - box_.y_min + 1);
165 const int limit_int = static_cast<int>(limit);
166
167 for (int x = box_.x_min; x <= box_.x_max; x++) {
168 int y = box_.y_min;
169 while (y < limit_int) {
170 screen.at(x, y++) = charset[full];
171 }
172 if (y <= box_.y_max) {
173 screen.at(x, y++) = charset[int(full * (limit - limit_int))];
174 }
175 while (y <= box_.y_max) {
176 screen.at(x, y++) = charset[0];
177 }
178 }
179 if (invert) {
180 Invert(screen);
181 }
182 }
183
184 void Invert(Screen& screen) {
185 for (int y = box_.y_min; y <= box_.y_max; y++) {
186 for (int x = box_.x_min; x <= box_.x_max; x++) {
187 screen.CellAt(x, y).inverted ^= true;
188 }
189 }
190 }
191
192 private:
193 float progress_;
194 Direction direction_;
195 std::vector<std::string> charset_;
196};
197
198} // namespace
199
200/// @brief 指定された方向に進行する高精細プログレスバーを描画します。
201/// @param progress 塗りつぶされる領域の割合。[0,1]に属します。
202/// @param direction プログレスバーの進行方向。
203/// @ingroup dom
205 return std::make_shared<Gauge>(progress, direction);
206}
207
208/// @brief 左から右へ進行する高精細プログレスバーを描画します。
209/// @param progress 塗りつぶされる領域の割合。[0,1]に属します。
210/// @ingroup dom
211///
212/// ### Example
213///
214/// ゲージ。プログレスバーとして使用できます。
215/// ~~~cpp
216/// border(gaugeRight(0.5))
217/// ~~~
218///
219/// #### Output
220///
221/// ~~~bash
222/// ┌──────────────────────────────────────────────────────────────────────────┐
223/// │█████████████████████████████████████ │
224/// └──────────────────────────────────────────────────────────────────────────┘
225/// ~~~
226Element gaugeRight(float progress) {
227 return gaugeDirection(progress, Direction::Right);
228}
229
230/// @brief 右から左へ進行する高精細プログレスバーを描画します。
231/// @param progress 塗りつぶされる領域の割合。[0,1]に属します。
232/// @ingroup dom
233///
234/// ### Example
235///
236/// ゲージ。プログレスバーとして使用できます。
237/// ~~~cpp
238/// border(gaugeLeft(0.5))
239/// ~~~
240///
241/// #### Output
242///
243/// ~~~bash
244/// ┌──────────────────────────────────────────────────────────────────────────┐
245/// │ █████████████████████████████████████│
246/// └──────────────────────────────────────────────────────────────────────────┘
247/// ~~~
248Element gaugeLeft(float progress) {
249 return gaugeDirection(progress, Direction::Left);
250}
251
252/// @brief 下から上へ進行する高精細プログレスバーを描画します。
253/// @param progress 塗りつぶされる領域の割合。[0,1]に属します。
254/// @ingroup dom
255///
256/// ### Example
257///
258/// ゲージ。プログレスバーとして使用できます。
259/// ~~~cpp
260/// border(gaugeUp(0.5))
261/// ~~~
262///
263/// #### Output
264///
265/// ~~~bash
266/// ┌─┐
267/// │ │
268/// │ │
269/// │ │
270/// │ │
271/// │█│
272/// │█│
273/// │█│
274/// │█│
275/// └─┘
276/// ~~~
277Element gaugeUp(float progress) {
278 return gaugeDirection(progress, Direction::Up);
279}
280
281/// @brief 上から下へ進行する高精細プログレスバーを描画します。
282/// @param progress 塗りつぶされる領域の割合。[0,1]に属します。
283/// @ingroup dom
284///
285/// ### Example
286///
287/// ゲージ。プログレスバーとして使用できます。
288/// ~~~cpp
289/// border(gaugeDown(0.5))
290/// ~~~
291///
292/// #### Output
293///
294/// ~~~bash
295/// ┌─┐
296/// │█│
297/// │█│
298/// │█│
299/// │█│
300/// │ │
301/// │ │
302/// │ │
303/// │ │
304/// └─┘
305/// ~~~
306Element gaugeDown(float progress) {
307 return gaugeDirection(progress, Direction::Down);
308}
309
310/// @brief 高精細プログレスバーを描画します。
311/// @param progress 塗りつぶされる領域の割合。[0,1]に属します。
312/// @ingroup dom
313///
314/// ### Example
315///
316/// ゲージ。プログレスバーとして使用できます。
317/// ~~~cpp
318/// border(gauge(0.5))
319/// ~~~
320///
321/// #### Output
322///
323/// ~~~bash
324/// ┌──────────────────────────────────────────────────────────────────────────┐
325/// │█████████████████████████████████████ │
326/// └──────────────────────────────────────────────────────────────────────────┘
327/// ~~~
328Element gauge(float progress) {
329 return gaugeRight(progress);
330}
331
332/// @brief カスタム文字セットを使って高精細なプログレスバーを描画する。
333/// @param progress 塗りつぶす領域の割合。[0,1]に属する。
334/// @param charset 「empty」(インデックス0)から「full」(最後のインデックス)
335/// までのグリフ。2要素の文字セットは単純な塗りつぶしのないバーになる。
336/// @param direction プログレスバーの進行方向。デフォルトはRight。
337/// @ingroup dom
338///
339/// ### Example
340///
341/// デフォルトのブロック文字の代わりに、カスタム文字セットで描画された
342/// ゲージ。
343/// ~~~cpp
344/// border(gaugeCharset(0.5, {".", "#"}))
345/// ~~~
346///
347/// #### Output
348///
349/// ~~~bash
350/// ┌──────────────────────────────────────────────────────────────────────────┐
351/// │#####################################.....................................│
352/// └──────────────────────────────────────────────────────────────────────────┘
353/// ~~~
354Element gaugeCharset(float progress,
355 std::vector<std::string> charset,
357 return std::make_shared<Gauge>(progress, direction, std::move(charset));
358}
359
360} // namespace ftxui
Element gaugeDirection(float progress, Direction direction)
指定された方向に進行する高精細プログレスバーを描画します。
Element gaugeRight(float progress)
左から右へ進行する高精細プログレスバーを描画します。
Direction
Directionは、東西南北の4つの基本方向を表す列挙型です。
Definition direction.hpp:14
Element gaugeUp(float progress)
下から上へ進行する高精細プログレスバーを描画します。
Element gaugeCharset(float progress, std::vector< std::string > charset, Direction direction=Direction::Right)
カスタム文字セットを使って高精細なプログレスバーを描画する。
Element gaugeLeft(float progress)
右から左へ進行する高精細プログレスバーを描画します。
Element gauge(float progress)
高精細プログレスバーを描画します。
Element gaugeDown(float progress)
上から下へ進行する高精細プログレスバーを描画します。
Quirks GetQuirks()
ターミナルのクイークを取得します。
Definition terminal.cpp:350
FTXUI ftxui::名前空間
Definition animation.hpp:11
std::shared_ptr< Node > Element
Definition elements.hpp:25
Direction direction
Definition elements.hpp:80
int y
Definition elements.hpp:131
void Render(Screen &screen, Node *node, Selection &selection)
Definition node.cpp:105
const Charset & charset_