From 371bcb2c3b506576bf3115cc30605922b62d7b01 Mon Sep 17 00:00:00 2001 From: "Kevin M. Godby" Date: Thu, 30 Apr 2020 21:37:06 -0500 Subject: [PATCH] Add a MaxProgress option (default: 100). The MaxProgress option allows you to set the maximum number of ticks that are within a progress bar. Each call to tick() increments the tick count. The progress bar percentage is the number of ticks divided by the MaxProgress option. The default MaxProgress is 100, so each tick would be 1%. If MaxProgress is set to 500, for example, then each tick would be 0.2%. --- include/indicators/block_progress_bar.hpp | 21 ++++++++++------ include/indicators/progress_bar.hpp | 19 ++++++++------ include/indicators/progress_spinner.hpp | 16 +++++++----- include/indicators/setting.hpp | 4 ++- samples/CMakeLists.txt | 4 +++ samples/max_progress.cpp | 30 +++++++++++++++++++++++ 6 files changed, 71 insertions(+), 23 deletions(-) create mode 100644 samples/max_progress.cpp diff --git a/include/indicators/block_progress_bar.hpp b/include/indicators/block_progress_bar.hpp index fa532c5..031a968 100644 --- a/include/indicators/block_progress_bar.hpp +++ b/include/indicators/block_progress_bar.hpp @@ -46,7 +46,8 @@ class BlockProgressBar { using Settings = std::tuple; + option::SavedStartTime, option::MaxPostfixTextLen, option::FontStyles, + option::MaxProgress>; public: template ( option::MaxPostfixTextLen{0}, std::forward(args)...), details::get( - option::FontStyles{std::vector{}}, std::forward(args)...)) {} + option::FontStyles{std::vector{}}, std::forward(args)...), + details::get(option::MaxProgress{100}, + std::forward(args)...) + ) {} template void set_option(details::Setting &&setting) { @@ -138,7 +142,7 @@ public: size_t current() { std::lock_guard lock{mutex_}; - return std::min(static_cast(progress_), size_t(100)); + return std::min(static_cast(progress_), size_t(get_value())); } bool is_completed() const { return get_value(); } @@ -180,8 +184,9 @@ private: } void print_progress(bool from_multi_progress = false) { + const auto max_progress = get_value(); if (multi_progress_mode_ && !from_multi_progress) { - if (progress_ > 100.0) { + if (progress_ > max_progress) { get_value() = true; } return; @@ -201,11 +206,11 @@ private: details::BlockProgressScaleWriter writer{std::cout, get_value()}; - writer.write(progress_); + writer.write(progress_ / max_progress * 100); std::cout << get_value(); if (get_value()) { - std::cout << " " << std::min(static_cast(progress_), size_t(100)) << "%"; + std::cout << " " << std::min(static_cast(progress_ / max_progress * 100.0), size_t(100)) << "%"; } auto &saved_start_time = get_value(); @@ -226,7 +231,7 @@ private: if (saved_start_time) { auto eta = std::chrono::nanoseconds( - progress_ > 0 ? static_cast(elapsed.count() * 100 / progress_) : 0); + progress_ > 0 ? static_cast(elapsed.count() * max_progress / progress_) : 0); auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); details::write_duration(std::cout, remaining); } else { @@ -245,7 +250,7 @@ private: << std::string(get_value(), ' ') << "\r"; std::cout.flush(); - if (progress_ > 100.0) { + if (progress_ > max_progress) { get_value() = true; } if (get_value() && diff --git a/include/indicators/progress_bar.hpp b/include/indicators/progress_bar.hpp index 02c514f..1fdb8fe 100644 --- a/include/indicators/progress_bar.hpp +++ b/include/indicators/progress_bar.hpp @@ -50,7 +50,7 @@ class ProgressBar { option::End, option::Fill, option::Lead, option::Remainder, option::MaxPostfixTextLen, option::Completed, option::ShowPercentage, option::ShowElapsedTime, option::ShowRemainingTime, option::SavedStartTime, - option::ForegroundColor, option::FontStyles>; + option::ForegroundColor, option::FontStyles, option::MaxProgress>; public: template ( option::ForegroundColor{Color::unspecified}, std::forward(args)...), details::get( - option::FontStyles{std::vector{}}, std::forward(args)...)) {} + option::FontStyles{std::vector{}}, std::forward(args)...), + details::get( + option::MaxProgress{100}, std::forward(args)...)) {} template void set_option(details::Setting &&setting) { @@ -149,7 +151,7 @@ public: size_t current() { std::lock_guard lock{mutex_}; - return std::min(progress_, size_t(100)); + return std::min(progress_, size_t(get_value())); } bool is_completed() const { return get_value(); } @@ -193,8 +195,9 @@ private: void print_progress(bool from_multi_progress = false) { std::lock_guard lock{mutex_}; + const auto max_progress = get_value(); if (multi_progress_mode_ && !from_multi_progress) { - if (progress_ > 100) { + if (progress_ >= max_progress) { get_value() = true; } return; @@ -218,12 +221,12 @@ private: get_value(), get_value(), get_value()}; - writer.write(progress_); + writer.write(progress_ / max_progress * 100); std::cout << get_value(); if (get_value()) { - std::cout << " " << std::min(progress_, size_t(100)) << "%"; + std::cout << " " << std::min(static_cast(static_cast(progress_) / max_progress * 100), size_t(100)) << "%"; } auto &saved_start_time = get_value(); @@ -244,7 +247,7 @@ private: if (saved_start_time) { auto eta = std::chrono::nanoseconds( - progress_ > 0 ? static_cast(elapsed_.count() * 100 / progress_) : 0); + progress_ > 0 ? static_cast(elapsed_.count() * max_progress / progress_) : 0); auto remaining = eta > elapsed_ ? (eta - elapsed_) : (elapsed_ - eta); details::write_duration(std::cout, remaining); } else { @@ -263,7 +266,7 @@ private: << std::string(get_value(), ' ') << "\r"; std::cout.flush(); - if (progress_ > 100) { + if (progress_ >= max_progress) { get_value() = true; } if (get_value() && diff --git a/include/indicators/progress_spinner.hpp b/include/indicators/progress_spinner.hpp index 62571d9..994ac64 100644 --- a/include/indicators/progress_spinner.hpp +++ b/include/indicators/progress_spinner.hpp @@ -49,7 +49,8 @@ class ProgressSpinner { std::tuple; + option::MaxPostfixTextLen, option::SpinnerStates, option::FontStyles, + option::MaxProgress>; public: template (args)...), details::get( - option::FontStyles{std::vector{}}, std::forward(args)...)) {} + option::FontStyles{std::vector{}}, std::forward(args)...), + details::get( + option::MaxProgress{100}, std::forward(args)...)) {} template void set_option(details::Setting &&setting) { @@ -141,7 +144,7 @@ public: size_t current() { std::lock_guard lock{mutex_}; - return std::min(progress_, size_t(100)); + return std::min(progress_, size_t(get_value())); } bool is_completed() const { return get_value(); } @@ -181,6 +184,7 @@ private: void print_progress() { std::lock_guard lock{mutex_}; + const auto max_progress = get_value(); auto now = std::chrono::high_resolution_clock::now(); auto elapsed = std::chrono::duration_cast(now - start_time_point_); @@ -195,7 +199,7 @@ private: std::cout << get_value() [index_ % get_value().size()]; if (get_value()) { - std::cout << " " << std::min(progress_, size_t(100)) << "%"; + std::cout << " " << std::min(progress_, size_t(max_progress)) << "%"; } if (get_value()) { @@ -209,7 +213,7 @@ private: else std::cout << " ["; auto eta = std::chrono::nanoseconds( - progress_ > 0 ? static_cast(elapsed.count() * 100 / progress_) : 0); + progress_ > 0 ? static_cast(elapsed.count() * max_progress / progress_) : 0); auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); details::write_duration(std::cout, remaining); std::cout << "]"; @@ -225,7 +229,7 @@ private: << "\r"; std::cout.flush(); index_ += 1; - if (progress_ > 100) { + if (progress_ > max_progress) { get_value() = true; } if (get_value()) diff --git a/include/indicators/setting.hpp b/include/indicators/setting.hpp index e4a09d5..26686b6 100644 --- a/include/indicators/setting.hpp +++ b/include/indicators/setting.hpp @@ -89,7 +89,8 @@ enum class ProgressBarOption { spinner_show, spinner_states, font_styles, - hide_bar_when_complete + hide_bar_when_complete, + max_progress }; template struct Setting { @@ -204,5 +205,6 @@ using HideBarWhenComplete = details::BooleanSetting; using FontStyles = details::Setting, details::ProgressBarOption::font_styles>; +using MaxProgress = details::IntegerSetting; } // namespace option } // namespace indicators diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 9aa8218..5cdb763 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -25,3 +25,7 @@ target_link_libraries(multi_block_progress_bar PRIVATE indicators::indicators) add_executable(dynamic_progress dynamic_progress.cpp) target_link_libraries(dynamic_progress PRIVATE indicators::indicators) + +add_executable(max_progress max_progress.cpp) +target_link_libraries(max_progress PRIVATE indicators::indicators) + diff --git a/samples/max_progress.cpp b/samples/max_progress.cpp new file mode 100644 index 0000000..8495821 --- /dev/null +++ b/samples/max_progress.cpp @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +int main() { + + // Hide cursor + indicators::show_console_cursor(false); + + indicators::BlockProgressBar bar{ + indicators::option::BarWidth{80}, + indicators::option::FontStyles{ + std::vector{indicators::FontStyle::bold}}, + indicators::option::MaxProgress{400} + }; + + // Update bar state + while (true) { + bar.tick(); + if (bar.is_completed()) + break; + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + + // Show cursor + indicators::show_console_cursor(true); + + return 0; +}