270 lines
5.9 KiB
C++
270 lines
5.9 KiB
C++
/*
|
|
* A Progress Indicator Implementation
|
|
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
|
*
|
|
* Distributed under the Boost Software License, Version 1.0.
|
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
|
* http://www.boost.org/LICENSE_1_0.txt)
|
|
*
|
|
* @file: nana/gui/widgets/progress.cpp
|
|
*/
|
|
|
|
#include <nana/gui/widgets/progress.hpp>
|
|
|
|
namespace nana
|
|
{
|
|
namespace drawerbase
|
|
{
|
|
namespace progress
|
|
{
|
|
scheme::scheme()
|
|
{
|
|
foreground = static_cast<color_rgb>(0x107515);
|
|
}
|
|
|
|
class substance
|
|
{
|
|
public:
|
|
static const unsigned border_px = 1;
|
|
|
|
void set_widget(widget& wdg)
|
|
{
|
|
widget_ = static_cast<nana::progress*>(&wdg);
|
|
}
|
|
|
|
nana::progress* widget_ptr() const
|
|
{
|
|
return widget_;
|
|
}
|
|
|
|
unsigned inc()
|
|
{
|
|
auto val = value(nullptr) + 1;
|
|
return value(&val);
|
|
}
|
|
|
|
unsigned value(const unsigned* value_ptr)
|
|
{
|
|
//Sets new value if value_ptr is not a nullptr
|
|
if (value_ptr)
|
|
{
|
|
if (unknown_)
|
|
value_ += (*value_ptr ? 5 : 0);
|
|
else
|
|
value_ = (std::min)(max_, *value_ptr);
|
|
|
|
_m_try_refresh();
|
|
}
|
|
return value_;
|
|
}
|
|
|
|
void reset_value()
|
|
{
|
|
value_ = 0;
|
|
}
|
|
|
|
unsigned maximum(const unsigned * value_ptr)
|
|
{
|
|
//Sets new maximum if value_ptr is not a nullptr
|
|
if (value_ptr)
|
|
{
|
|
max_ = (*value_ptr > 0 ? *value_ptr : 1);
|
|
_m_try_refresh();
|
|
}
|
|
return max_;
|
|
}
|
|
|
|
bool unknown(const bool* state_ptr)
|
|
{
|
|
if (state_ptr)
|
|
{
|
|
unknown_ = *state_ptr;
|
|
if (unknown_)
|
|
value_px_ = 0;
|
|
else
|
|
value_ = (std::min)(value_, max_);
|
|
}
|
|
return unknown_;
|
|
}
|
|
|
|
unsigned value_px() const
|
|
{
|
|
return value_px_;
|
|
}
|
|
|
|
bool value_px_sync()
|
|
{
|
|
if (widget_)
|
|
{
|
|
auto value_px = (widget_->size().width - border_px * 2);
|
|
|
|
//avoid overflow
|
|
if (value_ < max_)
|
|
value_px = static_cast<unsigned>(value_px * (double(value_) / double(max_)));
|
|
|
|
if (value_px != value_px_)
|
|
{
|
|
value_px_ = value_px;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
private:
|
|
void _m_try_refresh()
|
|
{
|
|
if (value_px_sync())
|
|
API::refresh_window(*widget_);
|
|
}
|
|
private:
|
|
nana::progress * widget_{ nullptr };
|
|
unsigned max_{ 100 };
|
|
unsigned value_{ 0 };
|
|
unsigned value_px_{ 0 };
|
|
bool unknown_{ false };
|
|
};
|
|
|
|
trigger::trigger()
|
|
: progress_(new substance)
|
|
{}
|
|
|
|
trigger::~trigger()
|
|
{
|
|
delete progress_;
|
|
}
|
|
|
|
substance* trigger::progress() const
|
|
{
|
|
return progress_;
|
|
}
|
|
|
|
void trigger::attached(widget_reference wdg, graph_reference)
|
|
{
|
|
progress_->set_widget(wdg);
|
|
}
|
|
|
|
void trigger::refresh(graph_reference graph)
|
|
{
|
|
const unsigned border_px = substance::border_px;
|
|
|
|
rectangle rt_val{ graph.size() };
|
|
auto const width = rt_val.width - border_px * 2;
|
|
|
|
rt_val.pare_off(static_cast<int>(border_px));
|
|
|
|
auto rt_bground = rt_val;
|
|
if (false == progress_->unknown(nullptr))
|
|
{
|
|
//Sync the value_px otherwise the progress is incorrect when it is resized.
|
|
progress_->value_px_sync();
|
|
|
|
rt_bground.x = static_cast<int>(progress_->value_px()) + static_cast<int>(border_px);
|
|
rt_bground.width -= progress_->value_px();
|
|
|
|
rt_val.width = progress_->value_px();
|
|
}
|
|
else
|
|
{
|
|
auto const block = width / 3;
|
|
|
|
auto const value = progress_->value(nullptr);
|
|
|
|
auto left = (std::max)(0, static_cast<int>(value - block)) + static_cast<int>(border_px);
|
|
auto right = static_cast<int>((std::min)(value, width + border_px -1));
|
|
|
|
if (right > left)
|
|
{
|
|
rt_val.x = left;
|
|
rt_val.width = static_cast<unsigned>(right - left + 1);
|
|
}
|
|
else
|
|
rt_val.width = 0;
|
|
|
|
if (value >= width + block)
|
|
progress_->reset_value();
|
|
}
|
|
|
|
auto & sch = progress_->widget_ptr()->scheme();
|
|
|
|
//Draw the gradient background if gradient_bgcolor is available.
|
|
|
|
auto bgcolor = sch.background.get_color();
|
|
if (bgcolor.invisible())
|
|
bgcolor = colors::button_face;
|
|
|
|
if (sch.gradient_bgcolor.get_color().invisible())
|
|
graph.rectangle(rt_bground, true, bgcolor);
|
|
else
|
|
graph.gradual_rectangle(rt_bground, bgcolor, sch.gradient_bgcolor.get_color(), true);
|
|
|
|
//Draw the gradient fgcolor if gradient_fgcolor is available.
|
|
|
|
auto fgcolor = sch.foreground.get_color();
|
|
if (fgcolor.invisible())
|
|
fgcolor = static_cast<color_rgb>(0x107515);
|
|
|
|
if (sch.gradient_fgcolor.get_color().invisible())
|
|
graph.rectangle(rt_val, true, fgcolor);
|
|
else
|
|
graph.gradual_rectangle(rt_val, sch.gradient_fgcolor.get_color(), fgcolor, true);
|
|
|
|
graph.frame_rectangle(rectangle{ graph.size() }, colors::gray, colors::gray, colors::white, colors::white);
|
|
}
|
|
}//end namespace progress
|
|
}//end namespace drawerbase
|
|
|
|
//class progress
|
|
progress::progress(){}
|
|
|
|
progress::progress(window wd, bool visible)
|
|
{
|
|
create(wd, rectangle(), visible);
|
|
}
|
|
|
|
progress::progress(window wd, const rectangle & r, bool visible)
|
|
{
|
|
create(wd, r, visible);
|
|
}
|
|
|
|
unsigned progress::value() const
|
|
{
|
|
return get_drawer_trigger().progress()->value(nullptr);
|
|
}
|
|
|
|
unsigned progress::value(unsigned val)
|
|
{
|
|
internal_scope_guard lock;
|
|
if(API::empty_window(this->handle()) == false)
|
|
return get_drawer_trigger().progress()->value(&val);
|
|
return 0;
|
|
}
|
|
|
|
unsigned progress::inc()
|
|
{
|
|
internal_scope_guard lock;
|
|
return get_drawer_trigger().progress()->inc();
|
|
}
|
|
|
|
unsigned progress::amount() const
|
|
{
|
|
return get_drawer_trigger().progress()->maximum(nullptr);
|
|
}
|
|
|
|
unsigned progress::amount(unsigned value)
|
|
{
|
|
return get_drawer_trigger().progress()->maximum(&value);
|
|
}
|
|
|
|
void progress::unknown(bool enb)
|
|
{
|
|
internal_scope_guard lock;
|
|
get_drawer_trigger().progress()->unknown(&enb);
|
|
}
|
|
|
|
bool progress::unknown() const
|
|
{
|
|
return get_drawer_trigger().progress()->unknown(nullptr);
|
|
}
|
|
//end class progress
|
|
}//end namespace nana
|