Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : : #include <eventdispatcher.hxx>
21 : :
22 : : #include <event.hxx>
23 : : #include <mutationevent.hxx>
24 : : #include <uievent.hxx>
25 : : #include <mouseevent.hxx>
26 : :
27 : : #include "../dom/document.hxx"
28 : :
29 : :
30 : : namespace DOM { namespace events {
31 : :
32 : 14 : void CEventDispatcher::addListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture)
33 : : {
34 : : TypeListenerMap *const pTMap = (bCapture)
35 [ - + ]: 14 : ? (& m_CaptureListeners) : (& m_TargetListeners);
36 : :
37 : : // get the multimap for the specified type
38 : 14 : ListenerMap *pMap = 0;
39 [ + - ]: 14 : TypeListenerMap::const_iterator tIter = pTMap->find(aType);
40 [ + + ]: 14 : if (tIter == pTMap->end()) {
41 : : // the map has to be created
42 [ + - ][ + - ]: 6 : pMap = new ListenerMap();
43 [ + - ]: 6 : pTMap->insert(TypeListenerMap::value_type(aType, pMap));
44 : : } else {
45 : 8 : pMap = tIter->second;
46 : : }
47 [ + - ]: 14 : if (pMap !=0)
48 [ + - ][ + - ]: 14 : pMap->insert(ListenerMap::value_type(pNode, aListener));
[ + - ]
49 : 14 : }
50 : :
51 : 0 : void CEventDispatcher::removeListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture)
52 : : {
53 : : TypeListenerMap *const pTMap = (bCapture)
54 [ # # ]: 0 : ? (& m_CaptureListeners) : (& m_TargetListeners);
55 : :
56 : : // get the multimap for the specified type
57 [ # # ]: 0 : TypeListenerMap::const_iterator tIter = pTMap->find(aType);
58 [ # # ]: 0 : if (tIter != pTMap->end()) {
59 : 0 : ListenerMap *pMap = tIter->second;
60 : : // find listeners of specied type for specified node
61 [ # # ]: 0 : ListenerMap::iterator iter = pMap->find(pNode);
62 [ # # ][ # # ]: 0 : while (iter != pMap->end() && iter->first == pNode)
[ # # ][ # # ]
63 : : {
64 : : // erase all references to specified listener
65 [ # # ][ # # ]: 0 : if ((iter->second).is() && iter->second == aListener)
[ # # ][ # # ]
66 : : {
67 : 0 : ListenerMap::iterator tmp_iter = iter;
68 : 0 : ++iter;
69 [ # # ]: 0 : pMap->erase(tmp_iter);
70 : : }
71 : : else
72 : 0 : ++iter;
73 : : }
74 : : }
75 : 0 : }
76 : :
77 : 12201 : CEventDispatcher::~CEventDispatcher()
78 : : {
79 : : // delete the multimaps for the various types
80 [ - + ]: 12201 : for (TypeListenerMap::iterator aI = m_CaptureListeners.begin(); aI != m_CaptureListeners.end(); ++aI)
81 [ # # ]: 0 : delete aI->second;
82 : :
83 [ - + ]: 12201 : for (TypeListenerMap::iterator aI = m_TargetListeners.begin(); aI != m_TargetListeners.end(); ++aI)
84 [ # # ]: 0 : delete aI->second;
85 : 12201 : }
86 : :
87 : 695170 : void CEventDispatcher::callListeners(
88 : : TypeListenerMap const& rTMap,
89 : : xmlNodePtr const pNode,
90 : : OUString aType, Reference< XEvent > const& xEvent)
91 : : {
92 : : // get the multimap for the specified type
93 [ + - ]: 695170 : TypeListenerMap::const_iterator tIter = rTMap.find(aType);
94 [ + + ]: 695170 : if (tIter != rTMap.end()) {
95 : 72 : ListenerMap *pMap = tIter->second;
96 [ + - ]: 72 : ListenerMap::const_iterator iter = pMap->lower_bound(pNode);
97 [ + - ]: 72 : ListenerMap::const_iterator ibound = pMap->upper_bound(pNode);
98 [ + + ]: 154 : for( ; iter != ibound; ++iter )
99 : : {
100 [ + - ]: 82 : if((iter->second).is())
101 [ + - ][ + - ]: 82 : (iter->second)->handleEvent(xEvent);
102 : : }
103 : : }
104 : 695170 : }
105 : :
106 : 126487 : bool CEventDispatcher::dispatchEvent(
107 : : DOM::CDocument & rDocument, ::osl::Mutex & rMutex,
108 : : xmlNodePtr const pNode, Reference<XNode> const& xNode,
109 : : Reference< XEvent > const& i_xEvent) const
110 : : {
111 : 126487 : CEvent *pEvent = 0; // pointer to internal event representation
112 : :
113 [ + - ][ + - ]: 126487 : OUString const aType = i_xEvent->getType();
114 [ + + + + : 278072 : if (aType.compareToAscii("DOMSubtreeModified") == 0||
+ + + - +
+ + + +
- ][ + - ]
115 : 63937 : aType.compareToAscii("DOMNodeInserted") == 0||
116 : 23032 : aType.compareToAscii("DOMNodeRemoved") == 0||
117 : 21938 : aType.compareToAscii("DOMNodeRemovedFromDocument") == 0||
118 : 21938 : aType.compareToAscii("DOMNodeInsertedIntoDocument") == 0||
119 : 20541 : aType.compareToAscii("DOMAttrModified") == 0||
120 : 199 : aType.compareToAscii("DOMCharacterDataModified") == 0)
121 : : {
122 : : Reference< XMutationEvent > const aMEvent(i_xEvent,
123 [ + - ]: 126487 : UNO_QUERY_THROW);
124 : : // dispatch a mutation event
125 : : // we need to clone the event in order to have complete control
126 : : // over the implementation
127 [ + - ]: 126487 : CMutationEvent* pMEvent = new CMutationEvent;
128 : : pMEvent->initMutationEvent(
129 [ + - ][ + - ]: 126487 : aType, aMEvent->getBubbles(), aMEvent->getCancelable(),
[ + - ][ + - ]
130 [ + - ][ + - ]: 252974 : aMEvent->getRelatedNode(), aMEvent->getPrevValue(),
131 [ + - ][ + - ]: 252974 : aMEvent->getNewValue(), aMEvent->getAttrName(),
132 [ + - ][ + - ]: 758922 : aMEvent->getAttrChange());
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
133 : 126487 : pEvent = pMEvent;
134 [ # # ][ # # : 0 : } else if ( // UIEvent
# # # # ]
135 : 0 : aType.compareToAscii("DOMFocusIn") == 0||
136 : 0 : aType.compareToAscii("DOMFocusOut") == 0||
137 : 0 : aType.compareToAscii("DOMActivate") == 0)
138 : : {
139 [ # # ]: 0 : Reference< XUIEvent > const aUIEvent(i_xEvent, UNO_QUERY_THROW);
140 [ # # ]: 0 : CUIEvent* pUIEvent = new CUIEvent;
141 : : pUIEvent->initUIEvent(aType,
142 [ # # ][ # # ]: 0 : aUIEvent->getBubbles(), aUIEvent->getCancelable(),
[ # # ][ # # ]
143 [ # # ][ # # ]: 0 : aUIEvent->getView(), aUIEvent->getDetail());
[ # # ][ # # ]
[ # # ]
144 : 0 : pEvent = pUIEvent;
145 [ # # ][ # # : 0 : } else if ( // MouseEvent
# # # # #
# # # #
# ]
146 : 0 : aType.compareToAscii("click") == 0||
147 : 0 : aType.compareToAscii("mousedown") == 0||
148 : 0 : aType.compareToAscii("mouseup") == 0||
149 : 0 : aType.compareToAscii("mouseover") == 0||
150 : 0 : aType.compareToAscii("mousemove") == 0||
151 : 0 : aType.compareToAscii("mouseout") == 0)
152 : : {
153 : : Reference< XMouseEvent > const aMouseEvent(i_xEvent,
154 [ # # ]: 0 : UNO_QUERY_THROW);
155 [ # # ]: 0 : CMouseEvent *pMouseEvent = new CMouseEvent;
156 : : pMouseEvent->initMouseEvent(aType,
157 [ # # ][ # # ]: 0 : aMouseEvent->getBubbles(), aMouseEvent->getCancelable(),
[ # # ][ # # ]
158 [ # # ][ # # ]: 0 : aMouseEvent->getView(), aMouseEvent->getDetail(),
159 [ # # ][ # # ]: 0 : aMouseEvent->getScreenX(), aMouseEvent->getScreenY(),
160 [ # # ][ # # ]: 0 : aMouseEvent->getClientX(), aMouseEvent->getClientY(),
161 [ # # ][ # # ]: 0 : aMouseEvent->getCtrlKey(), aMouseEvent->getAltKey(),
[ # # ][ # # ]
162 [ # # ][ # # ]: 0 : aMouseEvent->getShiftKey(), aMouseEvent->getMetaKey(),
[ # # ][ # # ]
163 [ # # ][ # # ]: 0 : aMouseEvent->getButton(), aMouseEvent->getRelatedTarget());
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
164 : 0 : pEvent = pMouseEvent;
165 : : }
166 : : else // generic event
167 : : {
168 [ # # ]: 0 : pEvent = new CEvent;
169 : : pEvent->initEvent(
170 [ # # ][ # # ]: 0 : aType, i_xEvent->getBubbles(), i_xEvent->getCancelable());
[ # # ][ # # ]
[ # # ]
171 : : }
172 [ + - ]: 126487 : pEvent->m_target.set(xNode, UNO_QUERY_THROW);
173 [ + - ][ + - ]: 126487 : pEvent->m_currentTarget = i_xEvent->getCurrentTarget();
[ + - ]
174 [ + - ][ + - ]: 126487 : pEvent->m_time = i_xEvent->getTimeStamp();
175 : :
176 : : // create the reference to the provate event implementation
177 : : // that will be dispatched to the listeners
178 [ + - ][ + - ]: 126487 : Reference< XEvent > const xEvent(pEvent);
179 : :
180 : : // build the path from target node to the root
181 : : typedef std::vector< ::std::pair<Reference<XEventTarget>, xmlNodePtr> >
182 : : NodeVector_t;
183 [ + - ]: 126487 : NodeVector_t captureVector;
184 [ + - ]: 126487 : TypeListenerMap captureListeners;
185 [ + - ]: 126487 : TypeListenerMap targetListeners;
186 : : {
187 [ + - ]: 126487 : ::osl::MutexGuard g(rMutex);
188 : :
189 : 126487 : xmlNodePtr cur = pNode;
190 [ + + ]: 474072 : while (cur != NULL)
191 : : {
192 : : Reference< XEventTarget > const xRef(
193 [ + - ][ + - ]: 347585 : rDocument.GetCNode(cur).get());
[ + - ]
194 [ + - ][ + - ]: 347585 : captureVector.push_back(::std::make_pair(xRef, cur));
[ + - ]
195 : 347585 : cur = cur->parent;
196 : 347585 : }
197 [ + - ]: 126487 : captureListeners = m_CaptureListeners;
198 [ + - ][ + - ]: 126487 : targetListeners = m_TargetListeners;
199 : : }
200 : :
201 : : // the caputre vector now holds the node path from target to root
202 : : // first we must search for capture listernes in order root to
203 : : // to target. after that, any target listeners have to be called
204 : : // then bubbeling phase listeners are called in target to root
205 : : // order
206 : : // start at the root
207 : : NodeVector_t::const_reverse_iterator rinode =
208 : 126487 : const_cast<NodeVector_t const&>(captureVector).rbegin();
209 [ + - ][ + - ]: 126487 : if (rinode != const_cast<NodeVector_t const&>(captureVector).rend())
210 : : {
211 : : // capturing phase:
212 : 126487 : pEvent->m_phase = PhaseType_CAPTURING_PHASE;
213 [ + - ][ + + ]: 600559 : while (rinode !=
214 : 474072 : const_cast<NodeVector_t const&>(captureVector).rend())
215 : : {
216 [ + - ][ + - ]: 347585 : pEvent->m_currentTarget = rinode->first;
217 [ + - ][ + - ]: 347585 : callListeners(captureListeners, rinode->second, aType, xEvent);
218 [ - + ]: 347585 : if (pEvent->m_canceled) return sal_True;
219 [ + - ]: 347585 : ++rinode;
220 : : }
221 : :
222 [ + - ]: 126487 : NodeVector_t::const_iterator inode = captureVector.begin();
223 : :
224 : : // target phase
225 : 126487 : pEvent->m_phase = PhaseType_AT_TARGET;
226 [ + - ]: 126487 : pEvent->m_currentTarget = inode->first;
227 [ + - ]: 126487 : callListeners(targetListeners, inode->second, aType, xEvent);
228 [ - + ]: 126487 : if (pEvent->m_canceled) return sal_True;
229 : : // bubbeling phase
230 : 126487 : ++inode;
231 [ + - ][ + - ]: 126487 : if (i_xEvent->getBubbles()) {
[ + - ]
232 : 126487 : pEvent->m_phase = PhaseType_BUBBLING_PHASE;
233 [ + - ][ + + ]: 347585 : while (inode != captureVector.end())
234 : : {
235 [ + - ]: 221098 : pEvent->m_currentTarget = inode->first;
236 : : callListeners(targetListeners,
237 [ + - ]: 221098 : inode->second, aType, xEvent);
238 [ - + ]: 221098 : if (pEvent->m_canceled) return sal_True;
239 : 221098 : ++inode;
240 : : }
241 : : }
242 : : }
243 : 126487 : return sal_True;
244 : : }
245 : : }}
246 : :
247 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|