Update ooo320-m1
[ooovba.git] / unoxml / source / events / eventdispatcher.cxx
blob68c77b04a5d04e68929cae01db1cf3016e29fa53
1 #include "eventdispatcher.hxx"
2 #include "event.hxx"
3 #include "mutationevent.hxx"
4 #include "uievent.hxx"
5 #include "mouseevent.hxx"
6 #include "../dom/node.hxx"
8 namespace DOM { namespace events {
10 TypeListenerMap CEventDispatcher::captureListeners;
11 TypeListenerMap CEventDispatcher::targetListeners;
13 void CEventDispatcher::addListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture)
15 TypeListenerMap* pTMap = &targetListeners;
16 if (bCapture) pTMap = &captureListeners;
18 // get the multimap for the specified type
19 ListenerMap *pMap = 0;
20 TypeListenerMap::const_iterator tIter = pTMap->find(aType);
21 if (tIter == pTMap->end()) {
22 // the map has to be created
23 pMap = new ListenerMap();
24 pTMap->insert(TypeListenerMap::value_type(aType, pMap));
25 } else {
26 pMap = tIter->second;
28 if (pMap !=0)
29 pMap->insert(ListenerMap::value_type(pNode, aListener));
32 void CEventDispatcher::removeListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture)
34 TypeListenerMap *pTMap = &targetListeners;
35 if (bCapture) pTMap = &captureListeners;
37 // get the multimap for the specified type
38 TypeListenerMap::const_iterator tIter = pTMap->find(aType);
39 if (tIter != pTMap->end()) {
40 ListenerMap *pMap = tIter->second;
41 // find listeners of specied type for specified node
42 ListenerMap::iterator iter = pMap->find(pNode);
43 while (iter != pMap->end() && iter->first == pNode)
45 // erase all references to specified listener
46 if ((iter->second).is() && iter->second == aListener)
48 ListenerMap::iterator tmp_iter = iter;
49 iter++;
50 pMap->erase(tmp_iter);
52 else
53 iter++;
58 void CEventDispatcher::callListeners(xmlNodePtr pNode, OUString aType, const Reference< XEvent >& xEvent, sal_Bool bCapture)
60 TypeListenerMap *pTMap = &targetListeners;
61 if (bCapture) pTMap = &captureListeners;
63 // get the multimap for the specified type
64 TypeListenerMap::const_iterator tIter = pTMap->find(aType);
65 if (tIter != pTMap->end()) {
66 ListenerMap *pMap = tIter->second;
67 ListenerMap::const_iterator iter = pMap->lower_bound(pNode);
68 ListenerMap::const_iterator ibound = pMap->upper_bound(pNode);
69 for( ; iter != ibound; iter++ )
71 if((iter->second).is())
72 (iter->second)->handleEvent(xEvent);
77 sal_Bool CEventDispatcher::dispatchEvent(xmlNodePtr aNodePtr, const Reference< XEvent >& aEvent)
79 CEvent *pEvent = 0; // pointer to internal event representation
80 Reference< XEvent > xEvent; // reference to the event being dispatched;
82 OUString aType = aEvent->getType();
83 if (aType.compareToAscii("DOMSubtreeModified") == 0||
84 aType.compareToAscii("DOMNodeInserted") == 0||
85 aType.compareToAscii("DOMNodeRemoved") == 0||
86 aType.compareToAscii("DOMNodeRemovedFromDocument") == 0||
87 aType.compareToAscii("DOMNodeInsertedIntoDocument") == 0||
88 aType.compareToAscii("DOMAttrModified") == 0||
89 aType.compareToAscii("DOMCharacterDataModified") == 0)
91 Reference< XMutationEvent > aMEvent(aEvent, UNO_QUERY);
92 // dispatch a mutation event
93 // we need to clone the event in order to have complete control
94 // over the implementation
95 CMutationEvent* pMEvent = new CMutationEvent;
96 pMEvent->initMutationEvent(
97 aType, aMEvent->getBubbles(), aMEvent->getCancelable(),
98 aMEvent->getRelatedNode(), aMEvent->getPrevValue(),
99 aMEvent->getNewValue(), aMEvent->getAttrName(),
100 aMEvent->getAttrChange());
101 pEvent = pMEvent;
102 } else if ( // UIEvent
103 aType.compareToAscii("DOMFocusIn") == 0||
104 aType.compareToAscii("DOMFocusOut") == 0||
105 aType.compareToAscii("DOMActivate") == 0)
107 Reference< XUIEvent > aUIEvent(aEvent, UNO_QUERY);
108 CUIEvent* pUIEvent = new CUIEvent;
109 pUIEvent->initUIEvent(aType,
110 aUIEvent->getBubbles(), aUIEvent->getCancelable(),
111 aUIEvent->getView(), aUIEvent->getDetail());
112 pEvent = pUIEvent;
113 } else if ( // MouseEvent
114 aType.compareToAscii("click") == 0||
115 aType.compareToAscii("mousedown") == 0||
116 aType.compareToAscii("mouseup") == 0||
117 aType.compareToAscii("mouseover") == 0||
118 aType.compareToAscii("mousemove") == 0||
119 aType.compareToAscii("mouseout") == 0)
121 Reference< XMouseEvent > aMouseEvent(aEvent, UNO_QUERY);
122 CMouseEvent *pMouseEvent = new CMouseEvent;
123 pMouseEvent->initMouseEvent(aType,
124 aMouseEvent->getBubbles(), aMouseEvent->getCancelable(),
125 aMouseEvent->getView(), aMouseEvent->getDetail(),
126 aMouseEvent->getScreenX(), aMouseEvent->getScreenY(),
127 aMouseEvent->getClientX(), aMouseEvent->getClientY(),
128 aMouseEvent->getCtrlKey(), aMouseEvent->getAltKey(),
129 aMouseEvent->getShiftKey(), aMouseEvent->getMetaKey(),
130 aMouseEvent->getButton(), aMouseEvent->getRelatedTarget());
131 pEvent = pMouseEvent;
133 else // generic event
135 pEvent = new CEvent;
136 pEvent->initEvent(
137 aType, aEvent->getBubbles(), aEvent->getCancelable());
139 pEvent->m_target = Reference< XEventTarget >(DOM::CNode::get(aNodePtr));
140 pEvent->m_currentTarget = aEvent->getCurrentTarget();
141 pEvent->m_time = aEvent->getTimeStamp();
143 // create the reference to the provate event implementation
144 // that will be dispatched to the listeners
145 xEvent = Reference< XEvent >(pEvent);
147 // build the path from target node to the root
148 NodeVector captureVector;
149 xmlNodePtr cur = DOM::CNode::getNodePtr(Reference< XNode >(xEvent->getTarget(), UNO_QUERY_THROW));
150 while (cur != NULL)
152 captureVector.push_back(cur);
153 cur = cur->parent;
156 // the caputre vector now holds the node path from target to root
157 // first we must search for capture listernes in order root to
158 // to target. after that, any target listeners have to be called
159 // then bubbeling phase listeners are called in target to root
160 // order
161 NodeVector::const_iterator inode;
163 // start at the root
164 inode = captureVector.end();
165 inode--;
166 if (inode != captureVector.end())
168 // capturing phase:
169 pEvent->m_phase = PhaseType_CAPTURING_PHASE;
170 while (inode != captureVector.begin())
172 //pEvent->m_currentTarget = *inode;
173 pEvent->m_currentTarget = Reference< XEventTarget >(DOM::CNode::get(*inode));
174 callListeners(*inode, aType, xEvent, sal_True);
175 if (pEvent->m_canceled) return sal_True;
176 inode--;
179 // target phase
180 pEvent->m_phase = PhaseType_AT_TARGET;
181 callListeners(*inode, aType, xEvent, sal_False);
182 if (pEvent->m_canceled) return sal_True;
183 // bubbeling phase
184 inode++;
185 if (aEvent->getBubbles()) {
186 pEvent->m_phase = PhaseType_BUBBLING_PHASE;
187 while (inode != captureVector.end())
189 pEvent->m_currentTarget = Reference< XEventTarget >(DOM::CNode::get(*inode));
190 callListeners(*inode, aType, xEvent, sal_False);
191 if (pEvent->m_canceled) return sal_True;
192 inode++;
196 return sal_True;