Loading...
Searching...
No Matches
gauge.cpp
Go to the documentation of this file.
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
#include <ftxui/dom/direction.hpp> // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up
#include <memory> // for allocator, make_shared
#include <string> // for string
#include "ftxui/dom/elements.hpp" // for Element, gauge, gaugeDirection, gaugeDown, gaugeLeft, gaugeRight, gaugeUp
#include "ftxui/dom/node.hpp" // for Node
#include "ftxui/dom/requirement.hpp" // for Requirement
#include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/screen.hpp" // for Screen, Pixel
namespace ftxui {
namespace {
// NOLINTNEXTLINE
static const std::string charset_horizontal[11] = {
#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
// Microsoft's terminals often use fonts not handling the 8 unicode
// characters for representing the whole gauge. Fallback with less.
" ", " ", " ", " ", "▌", "▌", "▌", "█", "█", "█",
#else
" ", " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█",
#endif
// An extra character in case when the fuzzer manage to have:
// int(9 * (limit - limit_int) = 9
"█"};
// NOLINTNEXTLINE
static const std::string charset_vertical[10] = {
"█",
"▇",
"▆",
"▅",
"▄",
"▃",
"▂",
"▁",
" ",
// An extra character in case when the fuzzer manage to have:
// int(8 * (limit - limit_int) = 8
" ",
};
class Gauge : public Node {
public:
Gauge(float progress, Direction direction)
: progress_(progress), direction_(direction) {
// This handle NAN correctly:
if (!(progress_ > 0.F)) {
progress_ = 0.F;
}
if (!(progress_ < 1.F)) {
progress_ = 1.F;
}
}
void ComputeRequirement() override {
switch (direction_) {
case Direction::Right:
case Direction::Left:
requirement_.flex_grow_x = 1;
requirement_.flex_grow_y = 0;
requirement_.flex_shrink_x = 1;
requirement_.flex_shrink_y = 0;
break;
case Direction::Up:
case Direction::Down:
requirement_.flex_grow_x = 0;
requirement_.flex_grow_y = 1;
requirement_.flex_shrink_x = 0;
requirement_.flex_shrink_y = 1;
break;
}
requirement_.min_x = 1;
requirement_.min_y = 1;
}
void Render(Screen& screen) override {
switch (direction_) {
case Direction::Right:
RenderHorizontal(screen, /*invert=*/false);
break;
case Direction::Up:
RenderVertical(screen, /*invert=*/false);
break;
case Direction::Left:
RenderHorizontal(screen, /*invert=*/true);
break;
case Direction::Down:
RenderVertical(screen, /*invert=*/true);
break;
}
}
void RenderHorizontal(Screen& screen, bool invert) {
const int y = box_.y_min;
if (y > box_.y_max) {
return;
}
// Draw the progress bar horizontally.
{
const float progress = invert ? 1.F - progress_ : progress_;
const auto limit =
float(box_.x_min) + progress * float(box_.x_max - box_.x_min + 1);
const int limit_int = static_cast<int>(limit);
int x = box_.x_min;
while (x < limit_int) {
screen.at(x++, y) = charset_horizontal[9]; // NOLINT
}
// NOLINTNEXTLINE
screen.at(x++, y) = charset_horizontal[int(9 * (limit - limit_int))];
while (x <= box_.x_max) {
screen.at(x++, y) = charset_horizontal[0];
}
}
if (invert) {
for (int x = box_.x_min; x <= box_.x_max; x++) {
screen.PixelAt(x, y).inverted ^= true;
}
}
}
void RenderVertical(Screen& screen, bool invert) {
const int x = box_.x_min;
if (x > box_.x_max) {
return;
}
// Draw the progress bar vertically:
{
const float progress = invert ? progress_ : 1.F - progress_;
const float limit =
float(box_.y_min) + progress * float(box_.y_max - box_.y_min + 1);
const int limit_int = static_cast<int>(limit);
int y = box_.y_min;
while (y < limit_int) {
screen.at(x, y++) = charset_vertical[8]; // NOLINT
}
// NOLINTNEXTLINE
screen.at(x, y++) = charset_vertical[int(8 * (limit - limit_int))];
while (y <= box_.y_max) {
screen.at(x, y++) = charset_vertical[0];
}
}
if (invert) {
for (int y = box_.y_min; y <= box_.y_max; y++) {
screen.PixelAt(x, y).inverted ^= true;
}
}
}
private:
float progress_;
Direction direction_;
};
} // namespace
/// @brief Draw a high definition progress bar progressing in specified
/// direction.
/// @param progress The proportion of the area to be filled. Belong to [0,1].
// @param direction Direction of progress bars progression.
/// @ingroup dom
Element gaugeDirection(float progress, Direction direction) {
return std::make_shared<Gauge>(progress, direction);
}
/// @brief Draw a high definition progress bar progressing from left to right.
/// @param progress The proportion of the area to be filled. Belong to [0,1].
/// @ingroup dom
///
/// ### Example
///
/// A gauge. It can be used to represent a progress bar.
/// ~~~cpp
/// border(gaugeRight(0.5))
/// ~~~
///
/// #### Output
///
/// ~~~bash
/// ┌──────────────────────────────────────────────────────────────────────────┐
/// │█████████████████████████████████████ │
/// └──────────────────────────────────────────────────────────────────────────┘
/// ~~~
Element gaugeRight(float progress) {
return gaugeDirection(progress, Direction::Right);
}
/// @brief Draw a high definition progress bar progressing from right to left.
/// @param progress The proportion of the area to be filled. Belong to [0,1].
/// @ingroup dom
///
/// ### Example
///
/// A gauge. It can be used to represent a progress bar.
/// ~~~cpp
/// border(gaugeLeft(0.5))
/// ~~~
///
/// #### Output
///
/// ~~~bash
/// ┌──────────────────────────────────────────────────────────────────────────┐
/// │ █████████████████████████████████████│
/// └──────────────────────────────────────────────────────────────────────────┘
/// ~~~
Element gaugeLeft(float progress) {
return gaugeDirection(progress, Direction::Left);
}
/// @brief Draw a high definition progress bar progressing from bottom to top.
/// @param progress The proportion of the area to be filled. Belong to [0,1].
/// @ingroup dom
///
/// ### Example
///
/// A gauge. It can be used to represent a progress bar.
/// ~~~cpp
/// border(gaugeUp(0.5))
/// ~~~
///
/// #### Output
///
/// ~~~bash
/// ┌─┐
/// │ │
/// │ │
/// │ │
/// │ │
/// │█│
/// │█│
/// │█│
/// │█│
/// └─┘
/// ~~~
Element gaugeUp(float progress) {
return gaugeDirection(progress, Direction::Up);
}
/// @brief Draw a high definition progress bar progressing from top to bottom.
/// @param progress The proportion of the area to be filled. Belong to [0,1].
/// @ingroup dom
///
/// ### Example
///
/// A gauge. It can be used to represent a progress bar.
/// ~~~cpp
/// border(gaugeDown(0.5))
/// ~~~
///
/// #### Output
///
/// ~~~bash
/// ┌─┐
/// │█│
/// │█│
/// │█│
/// │█│
/// │ │
/// │ │
/// │ │
/// │ │
/// └─┘
/// ~~~
Element gaugeDown(float progress) {
return gaugeDirection(progress, Direction::Down);
}
/// @brief Draw a high definition progress bar.
/// @param progress The proportion of the area to be filled. Belong to [0,1].
/// @ingroup dom
///
/// ### Example
///
/// A gauge. It can be used to represent a progress bar.
/// ~~~cpp
/// border(gauge(0.5))
/// ~~~
///
/// #### Output
///
/// ~~~bash
/// ┌──────────────────────────────────────────────────────────────────────────┐
/// │█████████████████████████████████████ │
/// └──────────────────────────────────────────────────────────────────────────┘
/// ~~~
Element gauge(float progress) {
return gaugeRight(progress);
}
} // namespace ftxui
box.hpp
ftxui::Node
Definition node.hpp:23
direction.hpp
elements.hpp
ftxui
Definition animation.hpp:10
ftxui::gaugeDirection
Element gaugeDirection(float progress, Direction direction)
Draw a high definition progress bar progressing in specified direction.
Definition gauge.cpp:169
ftxui::Direction
Direction
Definition direction.hpp:8
ftxui::Direction::Down
@ Down
Definition direction.hpp:10
ftxui::Direction::Up
@ Up
Definition direction.hpp:9
ftxui::Direction::Right
@ Right
Definition direction.hpp:12
ftxui::Direction::Left
@ Left
Definition direction.hpp:11
ftxui::Element
std::shared_ptr< Node > Element
Definition elements.hpp:22
ftxui::gaugeRight
Element gaugeRight(float progress)
Draw a high definition progress bar progressing from left to right.
Definition gauge.cpp:191
ftxui::gaugeUp
Element gaugeUp(float progress)
Draw a high definition progress bar progressing from bottom to top.
Definition gauge.cpp:242
ftxui::gaugeLeft
Element gaugeLeft(float progress)
Draw a high definition progress bar progressing from right to left.
Definition gauge.cpp:213
ftxui::Render
void Render(Screen &screen, const Element &element)
Display an element on a ftxui::Screen.
Definition node.cpp:88
ftxui::gauge
Element gauge(float progress)
Draw a high definition progress bar.
Definition gauge.cpp:293
ftxui::gaugeDown
Element gaugeDown(float progress)
Draw a high definition progress bar progressing from top to bottom.
Definition gauge.cpp:271
node.hpp
requirement.hpp
screen.hpp