* Copyright (C) 2015-2021 by Liangliang Nan <liangliang.nan@gmail.com>
* Copyright (C) 2000-2005 INRIA - Project ALICE
*
* The code in this file is partly from OGF/Graphite (2.0 alpha-4) with
* modifications and enhancement:
* https://gforge.inria.fr/forum/forum.php?forum_id=11459
* The original code was distributed under the GNU GPL license.
********************************************************************/
#include <easy3d/util/progress.h>
#include <cassert>
#include <algorithm>
namespace easy3d {
namespace internal {
class Progress {
public:
static Progress* instance();
virtual void notify(std::size_t percent, bool update_viewer);
void set_client(ProgressClient *c) { client_ = c; }
void push();
void pop();
void cancel() { canceled_ = true; }
void clear_canceled() { canceled_ = false; }
bool is_canceled() const { return canceled_; }
protected:
Progress() : client_(nullptr), level_(0), canceled_(false) {}
virtual ~Progress() = default;
ProgressClient *client_;
int level_;
bool canceled_;
};
Progress* Progress::instance() {
static Progress instance;
return &instance;
}
void Progress::push() {
level_++;
if (level_ == 1) {
clear_canceled();
}
}
void Progress::pop() {
assert(level_ > 0);
level_--;
}
void Progress::notify(std::size_t percent, bool update_viewer) {
if (client_ != nullptr && level_ < 2)
client_->notify(percent, update_viewer);
}
}
ProgressClient::ProgressClient() {
internal::Progress::instance()->set_client(this);
}
void ProgressClient::cancel() {
internal::Progress::instance()->cancel();
}
ProgressLogger::ProgressLogger(std::size_t max_val, bool update_viewer, bool quiet)
: max_val_(max_val)
, cur_val_(0)
, cur_percent_(0)
, quiet_(quiet)
, update_viewer_(update_viewer)
{
internal::Progress::instance()->push();
if (!quiet_) {
internal::Progress::instance()->notify(0, update_viewer_);
}
}
ProgressLogger::~ProgressLogger() {
internal::Progress::instance()->notify(100, update_viewer_);
internal::Progress::instance()->pop();
}
void ProgressLogger::notify(std::size_t new_value) {
cur_val_ = new_value;
update();
}
void ProgressLogger::next() {
cur_val_++;
update();
}
bool ProgressLogger::is_canceled() const {
return internal::Progress::instance()->is_canceled();
}
void ProgressLogger::reset(std::size_t max_val) {
max_val_ = max_val;
reset();
}
void ProgressLogger::update() {
std::size_t percent = cur_val_ * 100 / std::max<std::size_t>(1, max_val_ - 1);
if (percent != cur_percent_) {
cur_percent_ = percent;
if (!quiet_) {
internal::Progress::instance()->notify(std::min<std::size_t>(cur_percent_, 100), update_viewer_);
}
}
}
void print_progress(float percentage) {
static const int width = 60;
const int lpad = static_cast<int>(percentage * width);
const int rpad = width - lpad;
const int value = static_cast<int>(percentage * 100);
#if 1
static const std::string filling_str(width, '|');
printf("\r%3d%% [%.*s%*s]", value, lpad, filling_str.data(), rpad, "");
fflush(stdout);
#else
printf("\r%3d%% [%s%s] ", value, std::string(lpad, '|').c_str(), std::string(rpad, '-').c_str());
fflush(stdout);
#endif
}
}