summaryrefslogtreecommitdiff
path: root/unoxml/source/events/eventdispatcher.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'unoxml/source/events/eventdispatcher.cxx')
-rw-r--r--unoxml/source/events/eventdispatcher.cxx198
1 files changed, 198 insertions, 0 deletions
diff --git a/unoxml/source/events/eventdispatcher.cxx b/unoxml/source/events/eventdispatcher.cxx
new file mode 100644
index 000000000000..4b1c1548bf38
--- /dev/null
+++ b/unoxml/source/events/eventdispatcher.cxx
@@ -0,0 +1,198 @@
+#include "eventdispatcher.hxx"
+#include "event.hxx"
+#include "mutationevent.hxx"
+#include "uievent.hxx"
+#include "mouseevent.hxx"
+#include "../dom/node.hxx"
+
+namespace DOM { namespace events {
+
+ TypeListenerMap CEventDispatcher::captureListeners;
+ TypeListenerMap CEventDispatcher::targetListeners;
+
+ void CEventDispatcher::addListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture)
+ {
+ TypeListenerMap* pTMap = &targetListeners;
+ if (bCapture) pTMap = &captureListeners;
+
+ // get the multimap for the specified type
+ ListenerMap *pMap = 0;
+ TypeListenerMap::const_iterator tIter = pTMap->find(aType);
+ if (tIter == pTMap->end()) {
+ // the map has to be created
+ pMap = new ListenerMap();
+ pTMap->insert(TypeListenerMap::value_type(aType, pMap));
+ } else {
+ pMap = tIter->second;
+ }
+ if (pMap !=0)
+ pMap->insert(ListenerMap::value_type(pNode, aListener));
+ }
+
+ void CEventDispatcher::removeListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture)
+ {
+ TypeListenerMap *pTMap = &targetListeners;
+ if (bCapture) pTMap = &captureListeners;
+
+ // get the multimap for the specified type
+ TypeListenerMap::const_iterator tIter = pTMap->find(aType);
+ if (tIter != pTMap->end()) {
+ ListenerMap *pMap = tIter->second;
+ // find listeners of specied type for specified node
+ ListenerMap::iterator iter = pMap->find(pNode);
+ while (iter != pMap->end() && iter->first == pNode)
+ {
+ // erase all references to specified listener
+ if ((iter->second).is() && iter->second == aListener)
+ {
+ ListenerMap::iterator tmp_iter = iter;
+ iter++;
+ pMap->erase(tmp_iter);
+ }
+ else
+ iter++;
+ }
+ }
+ }
+
+ void CEventDispatcher::callListeners(xmlNodePtr pNode, OUString aType, const Reference< XEvent >& xEvent, sal_Bool bCapture)
+ {
+ TypeListenerMap *pTMap = &targetListeners;
+ if (bCapture) pTMap = &captureListeners;
+
+ // get the multimap for the specified type
+ TypeListenerMap::const_iterator tIter = pTMap->find(aType);
+ if (tIter != pTMap->end()) {
+ ListenerMap *pMap = tIter->second;
+ ListenerMap::const_iterator iter = pMap->lower_bound(pNode);
+ ListenerMap::const_iterator ibound = pMap->upper_bound(pNode);
+ for( ; iter != ibound; iter++ )
+ {
+ if((iter->second).is())
+ (iter->second)->handleEvent(xEvent);
+ }
+ }
+ }
+
+ sal_Bool CEventDispatcher::dispatchEvent(xmlNodePtr aNodePtr, const Reference< XEvent >& aEvent)
+ {
+ CEvent *pEvent = 0; // pointer to internal event representation
+ Reference< XEvent > xEvent; // reference to the event being dispatched;
+
+ OUString aType = aEvent->getType();
+ if (aType.compareToAscii("DOMSubtreeModified") == 0||
+ aType.compareToAscii("DOMNodeInserted") == 0||
+ aType.compareToAscii("DOMNodeRemoved") == 0||
+ aType.compareToAscii("DOMNodeRemovedFromDocument") == 0||
+ aType.compareToAscii("DOMNodeInsertedIntoDocument") == 0||
+ aType.compareToAscii("DOMAttrModified") == 0||
+ aType.compareToAscii("DOMCharacterDataModified") == 0)
+ {
+ Reference< XMutationEvent > aMEvent(aEvent, UNO_QUERY);
+ // dispatch a mutation event
+ // we need to clone the event in order to have complete control
+ // over the implementation
+ CMutationEvent* pMEvent = new CMutationEvent;
+ pMEvent->initMutationEvent(
+ aType, aMEvent->getBubbles(), aMEvent->getCancelable(),
+ aMEvent->getRelatedNode(), aMEvent->getPrevValue(),
+ aMEvent->getNewValue(), aMEvent->getAttrName(),
+ aMEvent->getAttrChange());
+ pEvent = pMEvent;
+ } else if ( // UIEvent
+ aType.compareToAscii("DOMFocusIn") == 0||
+ aType.compareToAscii("DOMFocusOut") == 0||
+ aType.compareToAscii("DOMActivate") == 0)
+ {
+ Reference< XUIEvent > aUIEvent(aEvent, UNO_QUERY);
+ CUIEvent* pUIEvent = new CUIEvent;
+ pUIEvent->initUIEvent(aType,
+ aUIEvent->getBubbles(), aUIEvent->getCancelable(),
+ aUIEvent->getView(), aUIEvent->getDetail());
+ pEvent = pUIEvent;
+ } else if ( // MouseEvent
+ aType.compareToAscii("click") == 0||
+ aType.compareToAscii("mousedown") == 0||
+ aType.compareToAscii("mouseup") == 0||
+ aType.compareToAscii("mouseover") == 0||
+ aType.compareToAscii("mousemove") == 0||
+ aType.compareToAscii("mouseout") == 0)
+ {
+ Reference< XMouseEvent > aMouseEvent(aEvent, UNO_QUERY);
+ CMouseEvent *pMouseEvent = new CMouseEvent;
+ pMouseEvent->initMouseEvent(aType,
+ aMouseEvent->getBubbles(), aMouseEvent->getCancelable(),
+ aMouseEvent->getView(), aMouseEvent->getDetail(),
+ aMouseEvent->getScreenX(), aMouseEvent->getScreenY(),
+ aMouseEvent->getClientX(), aMouseEvent->getClientY(),
+ aMouseEvent->getCtrlKey(), aMouseEvent->getAltKey(),
+ aMouseEvent->getShiftKey(), aMouseEvent->getMetaKey(),
+ aMouseEvent->getButton(), aMouseEvent->getRelatedTarget());
+ pEvent = pMouseEvent;
+ }
+ else // generic event
+ {
+ pEvent = new CEvent;
+ pEvent->initEvent(
+ aType, aEvent->getBubbles(), aEvent->getCancelable());
+ }
+ pEvent->m_target = Reference< XEventTarget >(DOM::CNode::get(aNodePtr));
+ pEvent->m_currentTarget = aEvent->getCurrentTarget();
+ pEvent->m_time = aEvent->getTimeStamp();
+
+ // create the reference to the provate event implementation
+ // that will be dispatched to the listeners
+ xEvent = Reference< XEvent >(pEvent);
+
+ // build the path from target node to the root
+ NodeVector captureVector;
+ xmlNodePtr cur = DOM::CNode::getNodePtr(Reference< XNode >(xEvent->getTarget(), UNO_QUERY_THROW));
+ while (cur != NULL)
+ {
+ captureVector.push_back(cur);
+ cur = cur->parent;
+ }
+
+ // the caputre vector now holds the node path from target to root
+ // first we must search for capture listernes in order root to
+ // to target. after that, any target listeners have to be called
+ // then bubbeling phase listeners are called in target to root
+ // order
+ NodeVector::const_iterator inode;
+
+ // start at the root
+ inode = captureVector.end();
+ inode--;
+ if (inode != captureVector.end())
+ {
+ // capturing phase:
+ pEvent->m_phase = PhaseType_CAPTURING_PHASE;
+ while (inode != captureVector.begin())
+ {
+ //pEvent->m_currentTarget = *inode;
+ pEvent->m_currentTarget = Reference< XEventTarget >(DOM::CNode::get(*inode));
+ callListeners(*inode, aType, xEvent, sal_True);
+ if (pEvent->m_canceled) return sal_True;
+ inode--;
+ }
+
+ // target phase
+ pEvent->m_phase = PhaseType_AT_TARGET;
+ callListeners(*inode, aType, xEvent, sal_False);
+ if (pEvent->m_canceled) return sal_True;
+ // bubbeling phase
+ inode++;
+ if (aEvent->getBubbles()) {
+ pEvent->m_phase = PhaseType_BUBBLING_PHASE;
+ while (inode != captureVector.end())
+ {
+ pEvent->m_currentTarget = Reference< XEventTarget >(DOM::CNode::get(*inode));
+ callListeners(*inode, aType, xEvent, sal_False);
+ if (pEvent->m_canceled) return sal_True;
+ inode++;
+ }
+ }
+ }
+ return sal_True;
+ }
+}}