FTXUI/src/ftxui/dom/gauge.cpp

281 lines
8.7 KiB
C++
Raw Normal View History

#include <iostream>
2021-09-17 02:45:26 +08:00
#include <algorithm> // for max, min
#include <memory> // for allocator, make_shared
#include <string> // for string
2021-05-02 02:40:35 +08:00
2021-05-10 02:32:27 +08:00
#include "ftxui/dom/elements.hpp" // for Element, gauge
#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
2018-09-20 03:52:25 +08:00
namespace ftxui {
static std::string charset_horizontal[11] = {
Implement Fallback for microsoft's terminals. (#138) I finally got access to a computer using the Microsoft's Windows OS. That's the opportunity to find and mitigate all the problems encountered. This patch: 1. Introduce an option and a C++ definition to enable fallback for Microsoft's terminal emulators. This allows me to see/test the Microsoft output from Linux. This also allows Windows users to remove the fallback and target non Microsoft terminals on Windows if needed. 2. Microsoft's terminal suffer from a race condition bug when reporting the cursor position: https://github.com/microsoft/terminal/pull/7583. The mitigation is not to ask for the cursor position in fullscreen mode where it isn't really needed and request it less often. This fixes: https://github.com/ArthurSonzogni/FTXUI/issues/136 3. Microsoft's terminal do not handle properly hidding the cursor. Instead the character under the cursor is hidden, which is a big problem. As a result, we don't enable setting the cursor to the best position for [input method editors](https://en.wikipedia.org/wiki/Input_method), It will be displayed at the bottom right corner. See: - https://github.com/microsoft/terminal/issues/1203 - https://github.com/microsoft/terminal/issues/3093 4. Microsoft's terminals do not provide a way to query if they support colors. As a fallback, assume true colors is supported. See issue: - https://github.com/microsoft/terminal/issues/1040 This mitigates: - https://github.com/ArthurSonzogni/FTXUI/issues/135 5. The "cmd" on Windows do not properly report its dimension. Powershell works correctly. As a fallback, use a 80x80 size instead of 0x0. 6. There are several dom elements and component displayed incorrectly, because the font used is missing several unicode glyph. Use alternatives or less detailled one as a fallback.
2021-07-04 23:38:31 +08:00
#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.
" ", " ", " ", " ", "", "", "", "", "", "",
Implement Fallback for microsoft's terminals. (#138) I finally got access to a computer using the Microsoft's Windows OS. That's the opportunity to find and mitigate all the problems encountered. This patch: 1. Introduce an option and a C++ definition to enable fallback for Microsoft's terminal emulators. This allows me to see/test the Microsoft output from Linux. This also allows Windows users to remove the fallback and target non Microsoft terminals on Windows if needed. 2. Microsoft's terminal suffer from a race condition bug when reporting the cursor position: https://github.com/microsoft/terminal/pull/7583. The mitigation is not to ask for the cursor position in fullscreen mode where it isn't really needed and request it less often. This fixes: https://github.com/ArthurSonzogni/FTXUI/issues/136 3. Microsoft's terminal do not handle properly hidding the cursor. Instead the character under the cursor is hidden, which is a big problem. As a result, we don't enable setting the cursor to the best position for [input method editors](https://en.wikipedia.org/wiki/Input_method), It will be displayed at the bottom right corner. See: - https://github.com/microsoft/terminal/issues/1203 - https://github.com/microsoft/terminal/issues/3093 4. Microsoft's terminals do not provide a way to query if they support colors. As a fallback, assume true colors is supported. See issue: - https://github.com/microsoft/terminal/issues/1040 This mitigates: - https://github.com/ArthurSonzogni/FTXUI/issues/135 5. The "cmd" on Windows do not properly report its dimension. Powershell works correctly. As a fallback, use a 80x80 size instead of 0x0. 6. There are several dom elements and component displayed incorrectly, because the font used is missing several unicode glyph. Use alternatives or less detailled one as a fallback.
2021-07-04 23:38:31 +08:00
#else
" ", " ", "", "", "", "", "", "", "", "",
Implement Fallback for microsoft's terminals. (#138) I finally got access to a computer using the Microsoft's Windows OS. That's the opportunity to find and mitigate all the problems encountered. This patch: 1. Introduce an option and a C++ definition to enable fallback for Microsoft's terminal emulators. This allows me to see/test the Microsoft output from Linux. This also allows Windows users to remove the fallback and target non Microsoft terminals on Windows if needed. 2. Microsoft's terminal suffer from a race condition bug when reporting the cursor position: https://github.com/microsoft/terminal/pull/7583. The mitigation is not to ask for the cursor position in fullscreen mode where it isn't really needed and request it less often. This fixes: https://github.com/ArthurSonzogni/FTXUI/issues/136 3. Microsoft's terminal do not handle properly hidding the cursor. Instead the character under the cursor is hidden, which is a big problem. As a result, we don't enable setting the cursor to the best position for [input method editors](https://en.wikipedia.org/wiki/Input_method), It will be displayed at the bottom right corner. See: - https://github.com/microsoft/terminal/issues/1203 - https://github.com/microsoft/terminal/issues/3093 4. Microsoft's terminals do not provide a way to query if they support colors. As a fallback, assume true colors is supported. See issue: - https://github.com/microsoft/terminal/issues/1040 This mitigates: - https://github.com/ArthurSonzogni/FTXUI/issues/135 5. The "cmd" on Windows do not properly report its dimension. Powershell works correctly. As a fallback, use a 80x80 size instead of 0x0. 6. There are several dom elements and component displayed incorrectly, because the font used is missing several unicode glyph. Use alternatives or less detailled one as a fallback.
2021-07-04 23:38:31 +08:00
#endif
// An extra character in case when the fuzzer manage to have:
// int(9 * (limit - limit_int) = 9
""};
2018-09-22 15:49:43 +08:00
static std::string charset_vertical[10] = {
"",
"",
"",
"",
"",
"",
"",
"",
" ",
// An extra character in case when the fuzzer manage to have:
// int(8 * (limit - limit_int) = 8
" ",
};
2018-09-20 03:52:25 +08:00
class Gauge : public Node {
public:
Gauge(float progress, GaugeDirection direction)
: progress_(progress), direction_(direction) {
// This handle NAN correctly:
if (!(progress_ > 0.f))
progress_ = 0.f;
if (!(progress_ < 1.f))
progress_ = 1.f;
}
2018-09-20 03:52:25 +08:00
void ComputeRequirement() override {
switch (direction_) {
case GaugeDirection::Right:
case GaugeDirection::Left:
requirement_.flex_grow_x = 1;
requirement_.flex_grow_y = 0;
requirement_.flex_shrink_x = 1;
requirement_.flex_shrink_y = 0;
break;
case GaugeDirection::Up:
case GaugeDirection::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;
2020-06-01 22:13:29 +08:00
requirement_.min_y = 1;
2018-09-20 03:52:25 +08:00
}
void Render(Screen& screen) override {
switch (direction_) {
case GaugeDirection::Right:
RenderHorizontal(screen, /*invert=*/false);
break;
case GaugeDirection::Up:
RenderVertical(screen, /*invert=*/false);
break;
case GaugeDirection::Left:
RenderHorizontal(screen, /*invert=*/true);
break;
case GaugeDirection::Down:
RenderVertical(screen, /*invert=*/true);
break;
}
}
void RenderHorizontal(Screen& screen, bool invert) {
2021-09-05 01:58:02 +08:00
int y = box_.y_min;
if (y > box_.y_max)
return;
// Draw the progress bar horizontally.
{
float progress = invert ? 1.f - progress_ : progress_;
float limit = box_.x_min + progress * (box_.x_max - box_.x_min + 1);
int limit_int = limit;
int x = box_.x_min;
while (x < limit_int)
screen.at(x++, y) = charset_horizontal[9];
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) {
2019-01-20 05:06:05 +08:00
int x = box_.x_min;
if (x > box_.x_max)
return;
// Draw the progress bar vertically:
{
float progress = invert ? progress_ : 1.f - progress_;
float limit = box_.y_min + progress * (box_.y_max - box_.y_min + 1);
int limit_int = limit;
int y = box_.y_min;
while (y < limit_int)
screen.at(x, y++) = charset_vertical[8];
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;
}
2018-09-20 03:52:25 +08:00
}
2020-03-23 05:32:44 +08:00
2018-09-20 03:52:25 +08:00
private:
float progress_;
GaugeDirection direction_;
2018-09-20 03:52:25 +08:00
};
/// @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, GaugeDirection 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, GaugeDirection::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, GaugeDirection::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, GaugeDirection::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, GaugeDirection::Down);
}
2020-05-25 07:34:13 +08:00
/// @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);
2018-09-20 03:52:25 +08:00
}
2020-02-12 04:44:55 +08:00
} // namespace ftxui
// 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.