153 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <nana/gui/detail/events_operation.hpp>
 | |
| #include <nana/gui/detail/bedrock.hpp>
 | |
| 
 | |
| namespace nana
 | |
| {
 | |
| 	namespace detail
 | |
| 	{
 | |
| 		//class events_operation
 | |
| 			using lock_guard = std::lock_guard<std::recursive_mutex>;
 | |
| 
 | |
| 			void events_operation::register_evt(event_handle evt)
 | |
| 			{
 | |
| 				lock_guard lock(mutex_);
 | |
| 				handles_.insert(evt);
 | |
| 			}
 | |
| 
 | |
| 			void events_operation::cancel(event_handle evt)
 | |
| 			{
 | |
| 				lock_guard lock(mutex_);
 | |
| 				handles_.erase(evt);
 | |
| 			}
 | |
| 
 | |
| 			void events_operation::erase(event_handle evt)
 | |
| 			{
 | |
| 				lock_guard lock(mutex_);
 | |
| 
 | |
| 				auto i = handles_.find(evt);
 | |
| 				if (i != handles_.end())
 | |
| 				{
 | |
| 					reinterpret_cast<detail::docker_interface*>(evt)->get_event()->remove(evt);
 | |
| 				}
 | |
| 			}
 | |
| 		//end namespace events_operation
 | |
| 
 | |
| 
 | |
| 		//class docker_base
 | |
| 			docker_base::docker_base(event_interface* evt, bool unignorable_flag):
 | |
| 				event_ptr(evt),
 | |
| 				flag_deleted(false),
 | |
| 				unignorable(unignorable_flag)
 | |
| 			{}
 | |
| 
 | |
| 			detail::event_interface * docker_base::get_event() const
 | |
| 			{
 | |
| 				return event_ptr;
 | |
| 			}
 | |
| 		//end class docker_base
 | |
| 
 | |
| 		//class event_base
 | |
| 			event_base::~event_base()
 | |
| 			{
 | |
| 				clear();
 | |
| 			}
 | |
| 
 | |
| 			std::size_t event_base::length() const
 | |
| 			{
 | |
| 				internal_scope_guard lock;
 | |
| 				return (nullptr == dockers_ ? 0 : dockers_->size());
 | |
| 			}
 | |
| 
 | |
| 			void event_base::clear() noexcept
 | |
| 			{
 | |
| 				internal_scope_guard lock;
 | |
| 				if (dockers_)
 | |
| 				{
 | |
| 					auto & evt_operation = bedrock::instance().evt_operation();
 | |
| 
 | |
| 					for (auto p : *dockers_)
 | |
| 					{
 | |
| 						evt_operation.cancel(reinterpret_cast<event_handle>(p));
 | |
| 						delete p;
 | |
| 					}
 | |
| 					dockers_->clear();
 | |
| 
 | |
| 					delete dockers_;
 | |
| 					dockers_ = nullptr;
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			void event_base::remove(event_handle evt)
 | |
| 			{
 | |
| 				internal_scope_guard lock;
 | |
| 				if (dockers_)
 | |
| 				{
 | |
| 					for (auto i = dockers_->begin(), end = dockers_->end(); i != end; ++i)
 | |
| 					{
 | |
| 						if (reinterpret_cast<detail::docker_interface*>(evt) == *i)
 | |
| 						{
 | |
| 							//Checks whether this event is working now.
 | |
| 							if (emitting_count_)
 | |
| 							{
 | |
| 								static_cast<docker_base*>(*i)->flag_deleted = true;
 | |
| 								deleted_flags_ = true;
 | |
| 							}
 | |
| 							else
 | |
| 							{
 | |
| 								bedrock::instance().evt_operation().cancel(evt);
 | |
| 								dockers_->erase(i);
 | |
| 								delete reinterpret_cast<detail::docker_interface*>(evt);
 | |
| 							}
 | |
| 							break;
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			event_handle event_base::_m_emplace(detail::docker_interface* docker_ptr, bool in_front)
 | |
| 			{
 | |
| 				internal_scope_guard lock;
 | |
| 				if (nullptr == dockers_)
 | |
| 					dockers_ = new std::vector<detail::docker_interface*>;
 | |
| 
 | |
| 				auto evt = reinterpret_cast<event_handle>(docker_ptr);
 | |
| 
 | |
| 				if (in_front)
 | |
| 					dockers_->emplace(dockers_->begin(), docker_ptr);
 | |
| 				else
 | |
| 					dockers_->emplace_back(docker_ptr);
 | |
| 
 | |
| 				detail::events_operation_register(evt);
 | |
| 				return evt;
 | |
| 			}
 | |
| 			
 | |
| 			//class emit_counter
 | |
| 				event_base::emit_counter::emit_counter(event_base* evt)
 | |
| 					: evt_{ evt }
 | |
| 				{
 | |
| 					++evt->emitting_count_;
 | |
| 				}
 | |
| 
 | |
| 				event_base::emit_counter::~emit_counter()
 | |
| 				{
 | |
| 					if ((0 == --evt_->emitting_count_) && evt_->deleted_flags_)
 | |
| 					{
 | |
| 						evt_->deleted_flags_ = false;
 | |
| 						for (auto i = evt_->dockers_->begin(); i != evt_->dockers_->end();)
 | |
| 						{
 | |
| 							if (static_cast<docker_base*>(*i)->flag_deleted)
 | |
| 							{
 | |
| 								bedrock::instance().evt_operation().cancel(reinterpret_cast<event_handle>(*i));
 | |
| 								delete (*i);
 | |
| 								i = evt_->dockers_->erase(i);
 | |
| 							}
 | |
| 							else
 | |
| 								++i;
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 			//end class emit_counter
 | |
| 		//end class event_base
 | |
| 
 | |
| 	}//end namespace detail
 | |
| }//end namespace nana
 | 
