256 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			256 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  *	A Progress Indicator Implementation
 | |
|  *	Copyright(C) 2003-2017 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_;
 | |
| 				}
 | |
| 			private:
 | |
| 				void _m_try_refresh()
 | |
| 				{
 | |
| 					if (nullptr == widget_)
 | |
| 						return;
 | |
| 
 | |
| 					auto value_px = (widget_->size().width - border_px * 2) * value_ / max_;
 | |
| 
 | |
| 					if (value_px != value_px_)
 | |
| 					{
 | |
| 						value_px_ = value_px;
 | |
| 						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))
 | |
| 				{
 | |
| 					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
 | 
