diff --git a/rhubarb/src/tools/ProgressBar.cpp b/rhubarb/src/tools/ProgressBar.cpp index a436e69..5ba39d2 100644 --- a/rhubarb/src/tools/ProgressBar.cpp +++ b/rhubarb/src/tools/ProgressBar.cpp @@ -8,9 +8,21 @@ using std::string; -ProgressBar::ProgressBar(std::ostream& stream) : +double sanitizeProgress(double progress) { + // Make sure value is in [0..1] range + return std::isnan(progress) + ? 0.0 + : boost::algorithm::clamp(progress, 0.0, 1.0); +} + +ProgressBar::ProgressBar(double progress) : + ProgressBar(std::cerr, progress) +{} + +ProgressBar::ProgressBar(std::ostream& stream, double progress) : stream(stream) { + currentProgress = sanitizeProgress(progress); updateLoopFuture = std::async(std::launch::async, &ProgressBar::updateLoop, this); } @@ -20,37 +32,38 @@ ProgressBar::~ProgressBar() { } void ProgressBar::reportProgress(double value) { - // Make sure value is in [0..1] range - value = boost::algorithm::clamp(value, 0.0, 1.0); - if (std::isnan(value)) { - value = 0.0; - } - - currentProgress = value; + currentProgress = sanitizeProgress(value); } void ProgressBar::updateLoop() { - const int blockCount = 20; const std::chrono::milliseconds animationInterval(1000 / 8); - const string animation = "|/-\\"; while (!done) { - int progressBlockCount = static_cast(currentProgress * blockCount); - int percent = static_cast(currentProgress * 100); - string text = fmt::format("[{0}{1}] {2:3}% {3}", - string(progressBlockCount, '#'), string(blockCount - progressBlockCount, '-'), - percent, - animation[animationIndex++ % animation.size()]); - updateText(text); - + update(); std::this_thread::sleep_for(animationInterval); } if (clearOnDestruction) { updateText(""); + } else { + update(); } } +void ProgressBar::update() { + const int blockCount = 20; + const string animation = "|/-\\"; + + int progressBlockCount = static_cast(currentProgress * blockCount); + const double epsilon = 0.0001; + int percent = static_cast(currentProgress * 100 + epsilon); + string text = fmt::format("[{0}{1}] {2:3}% {3}", + string(progressBlockCount, '#'), string(blockCount - progressBlockCount, '-'), + percent, + animation[animationIndex++ % animation.size()]); + updateText(text); +} + void ProgressBar::updateText(const string& text) { // Get length of common portion int commonPrefixLength = 0; diff --git a/rhubarb/src/tools/ProgressBar.h b/rhubarb/src/tools/ProgressBar.h index 7e5bd8f..2c58509 100644 --- a/rhubarb/src/tools/ProgressBar.h +++ b/rhubarb/src/tools/ProgressBar.h @@ -7,7 +7,8 @@ class ProgressBar : public ProgressSink { public: - ProgressBar(std::ostream& stream = std::cerr); + explicit ProgressBar(double progress = 0.0); + ProgressBar(std::ostream& stream, double progress = 0.0); ~ProgressBar(); void reportProgress(double value) override; @@ -21,6 +22,7 @@ public: private: void updateLoop(); + void update(); void updateText(const std::string& text); std::future updateLoopFuture;