1 #include "eventdispatcher.hxx"
3 #include "mutationevent.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
));
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
;
50 pMap
->erase(tmp_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());
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());
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
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
));
152 captureVector
.push_back(cur
);
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
161 NodeVector::const_iterator inode
;
164 inode
= captureVector
.end();
166 if (inode
!= captureVector
.end())
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
;
180 pEvent
->m_phase
= PhaseType_AT_TARGET
;
181 callListeners(*inode
, aType
, xEvent
, sal_False
);
182 if (pEvent
->m_canceled
) return sal_True
;
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
;