#ifndef JEZUK_DOM_SimpleDOM_EVENTTARGET_IMPL_H #define JEZUK_DOM_SimpleDOM_EVENTTARGET_IMPL_H //////////////////////////// // C++ EventTarget implementation //////////////////////////// #include #include #include #include #include #include #include #include #include namespace Arabica { namespace SimpleDOM { //////////////////////////////////////////////////////////////////// template class EventTargetImpl : virtual public Arabica::DOM::Events::EventTarget_impl { public: typedef Arabica::DOM::Node DOMNodeT; typedef Arabica::DOM::Node_impl DOMNode_implT; typedef Arabica::DOM::Text_impl DOMText_implT; typedef Arabica::DOM::Document_impl DOMDocument_implT; typedef Arabica::DOM::Events::Event EventT; typedef Arabica::DOM::Events::Event_impl Event_implT; typedef EventImpl EventImplT; typedef Arabica::DOM::Events::EventTarget EventTargetT; typedef EventTargetImpl EventTargetImplT; typedef Arabica::DOM::Events::EventTarget_impl EventTarget_implT; typedef Arabica::DOM::Events::EventListener EventListenerT; EventTargetImpl() { //std::cout << std::endl << "born " << this << std::endl; } // EventTargetImpl virtual ~EventTargetImpl() { //std::cout << std::endl << "die " << this << std::endl; } /////////////////////////////////////////////////////// // EventTarget methods virtual void addEventListener(const stringT type, EventListenerT& listener, bool useCapture) { typedef typename std::multimap::iterator iterator; if (useCapture) { std::pair range = eventCapturers_.equal_range(type); for (iterator it = range.first; it != range.second; ++it) { if (it->second == &listener) return; } eventCapturers_.insert(std::make_pair(type, &listener)); } else { std::pair range = eventListeners_.equal_range(type); for (iterator it = range.first; it != range.second; ++it) { if (it->second == &listener) return; } eventListeners_.insert(std::make_pair(type, &listener)); } } virtual void removeEventListener(const stringT type, EventListenerT& listener, bool useCapture) { typedef typename std::multimap::iterator iterator; if (useCapture) { std::pair range = eventCapturers_.equal_range(type); for (iterator it = range.first; it != range.second; ++it) { if (it->second == &listener) eventCapturers_.erase(it); return; } } else { std::pair range = eventListeners_.equal_range(type); for (iterator it = range.first; it != range.second; ++it) { if (it->second == &listener) eventListeners_.erase(it); return; } } } virtual bool dispatchEvent(EventT& event) { typedef typename std::multimap::iterator eventListenerIterator; EventImplT* eventImpl = dynamic_cast(*event); eventImpl->target_ = EventTargetT(this); std::list eventAncestorChain; DOMNode_implT* curr = dynamic_cast(this); while((curr = curr->getParentNode())) { eventAncestorChain.push_front(EventTargetT(curr)); } // capturing eventImpl->phase_ = EventT::CAPTURING_PHASE; typename std::list::iterator it = eventAncestorChain.begin(); while(it != eventAncestorChain.end()) { EventTargetImplT* nodeImpl = dynamic_cast(it->Impl()); if (nodeImpl != NULL) { std::pair range = nodeImpl->eventCapturers_.equal_range(event.getType()); for (eventListenerIterator itListener = range.first; itListener != range.second; ++itListener) { itListener->second->handleEvent(event); } // stopPropagation was called on the event if (eventImpl->stopped_) return false; } ++it; } // at target eventImpl->phase_ = EventT::AT_TARGET; std::pair range = eventListeners_.equal_range(event.getType()); for (eventListenerIterator rit = range.first; rit != range.second; ++rit) { rit->second->handleEvent(event); } // bubbling if (eventImpl->getBubbles()) { eventImpl->phase_ = EventT::BUBBLING_PHASE; typename std::list::reverse_iterator rit = eventAncestorChain.rbegin(); while(rit != eventAncestorChain.rend()) { EventTargetImplT* nodeImpl = dynamic_cast(rit->Impl()); if (nodeImpl != NULL) { std::pair range1 = nodeImpl->eventListeners_.equal_range(event.getType()); for (eventListenerIterator ritListener = range1.first; ritListener != range1.second; ++ritListener) { ritListener->second->handleEvent(event); } // stopPropagation was called on the event if (eventImpl->stopped_) return false; } ++rit; } } return true; } protected: std::multimap eventListeners_; std::multimap eventCapturers_; }; // class EventTargetImpl } // namespace SimpleDOM } // namespace Arabica #endif // JEZUK_DOM_SimpleDOM_EVENTTARGET_H // end of file