bump product version to 4.1.6.2
[LibreOffice.git] / unoxml / source / events / eventdispatcher.cxx
blob665815b686d3bdb5006b8499cadbd3be8325ccf5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <eventdispatcher.hxx>
22 #include <event.hxx>
23 #include <mutationevent.hxx>
24 #include <uievent.hxx>
25 #include <mouseevent.hxx>
27 #include "../dom/document.hxx"
30 namespace DOM { namespace events {
32 void CEventDispatcher::addListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture)
34 TypeListenerMap *const pTMap = (bCapture)
35 ? (& m_CaptureListeners) : (& m_TargetListeners);
37 // get the multimap for the specified type
38 ListenerMap *pMap = 0;
39 TypeListenerMap::const_iterator tIter = pTMap->find(aType);
40 if (tIter == pTMap->end()) {
41 // the map has to be created
42 pMap = new ListenerMap();
43 pTMap->insert(TypeListenerMap::value_type(aType, pMap));
44 } else {
45 pMap = tIter->second;
47 if (pMap !=0)
48 pMap->insert(ListenerMap::value_type(pNode, aListener));
51 void CEventDispatcher::removeListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture)
53 TypeListenerMap *const pTMap = (bCapture)
54 ? (& m_CaptureListeners) : (& m_TargetListeners);
56 // get the multimap for the specified type
57 TypeListenerMap::const_iterator tIter = pTMap->find(aType);
58 if (tIter != pTMap->end()) {
59 ListenerMap *pMap = tIter->second;
60 // find listeners of specied type for specified node
61 ListenerMap::iterator iter = pMap->find(pNode);
62 while (iter != pMap->end() && iter->first == pNode)
64 // erase all references to specified listener
65 if ((iter->second).is() && iter->second == aListener)
67 ListenerMap::iterator tmp_iter = iter;
68 ++iter;
69 pMap->erase(tmp_iter);
71 else
72 ++iter;
77 CEventDispatcher::~CEventDispatcher()
79 // delete the multimaps for the various types
80 for (TypeListenerMap::iterator aI = m_CaptureListeners.begin(); aI != m_CaptureListeners.end(); ++aI)
81 delete aI->second;
83 for (TypeListenerMap::iterator aI = m_TargetListeners.begin(); aI != m_TargetListeners.end(); ++aI)
84 delete aI->second;
87 void CEventDispatcher::callListeners(
88 TypeListenerMap const& rTMap,
89 xmlNodePtr const pNode,
90 OUString aType, Reference< XEvent > const& xEvent)
92 // get the multimap for the specified type
93 TypeListenerMap::const_iterator tIter = rTMap.find(aType);
94 if (tIter != rTMap.end()) {
95 ListenerMap *pMap = tIter->second;
96 ListenerMap::const_iterator iter = pMap->lower_bound(pNode);
97 ListenerMap::const_iterator ibound = pMap->upper_bound(pNode);
98 for( ; iter != ibound; ++iter )
100 if((iter->second).is())
101 (iter->second)->handleEvent(xEvent);
106 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
111 CEvent *pEvent = 0; // pointer to internal event representation
113 OUString const aType = i_xEvent->getType();
114 if (aType.compareToAscii("DOMSubtreeModified") == 0||
115 aType.compareToAscii("DOMNodeInserted") == 0||
116 aType.compareToAscii("DOMNodeRemoved") == 0||
117 aType.compareToAscii("DOMNodeRemovedFromDocument") == 0||
118 aType.compareToAscii("DOMNodeInsertedIntoDocument") == 0||
119 aType.compareToAscii("DOMAttrModified") == 0||
120 aType.compareToAscii("DOMCharacterDataModified") == 0)
122 Reference< XMutationEvent > const aMEvent(i_xEvent,
123 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 CMutationEvent* pMEvent = new CMutationEvent;
128 pMEvent->initMutationEvent(
129 aType, aMEvent->getBubbles(), aMEvent->getCancelable(),
130 aMEvent->getRelatedNode(), aMEvent->getPrevValue(),
131 aMEvent->getNewValue(), aMEvent->getAttrName(),
132 aMEvent->getAttrChange());
133 pEvent = pMEvent;
134 } else if ( // UIEvent
135 aType.compareToAscii("DOMFocusIn") == 0||
136 aType.compareToAscii("DOMFocusOut") == 0||
137 aType.compareToAscii("DOMActivate") == 0)
139 Reference< XUIEvent > const aUIEvent(i_xEvent, UNO_QUERY_THROW);
140 CUIEvent* pUIEvent = new CUIEvent;
141 pUIEvent->initUIEvent(aType,
142 aUIEvent->getBubbles(), aUIEvent->getCancelable(),
143 aUIEvent->getView(), aUIEvent->getDetail());
144 pEvent = pUIEvent;
145 } else if ( // MouseEvent
146 aType.compareToAscii("click") == 0||
147 aType.compareToAscii("mousedown") == 0||
148 aType.compareToAscii("mouseup") == 0||
149 aType.compareToAscii("mouseover") == 0||
150 aType.compareToAscii("mousemove") == 0||
151 aType.compareToAscii("mouseout") == 0)
153 Reference< XMouseEvent > const aMouseEvent(i_xEvent,
154 UNO_QUERY_THROW);
155 CMouseEvent *pMouseEvent = new CMouseEvent;
156 pMouseEvent->initMouseEvent(aType,
157 aMouseEvent->getBubbles(), aMouseEvent->getCancelable(),
158 aMouseEvent->getView(), aMouseEvent->getDetail(),
159 aMouseEvent->getScreenX(), aMouseEvent->getScreenY(),
160 aMouseEvent->getClientX(), aMouseEvent->getClientY(),
161 aMouseEvent->getCtrlKey(), aMouseEvent->getAltKey(),
162 aMouseEvent->getShiftKey(), aMouseEvent->getMetaKey(),
163 aMouseEvent->getButton(), aMouseEvent->getRelatedTarget());
164 pEvent = pMouseEvent;
166 else // generic event
168 pEvent = new CEvent;
169 pEvent->initEvent(
170 aType, i_xEvent->getBubbles(), i_xEvent->getCancelable());
172 pEvent->m_target.set(xNode, UNO_QUERY_THROW);
173 pEvent->m_currentTarget = i_xEvent->getCurrentTarget();
174 pEvent->m_time = i_xEvent->getTimeStamp();
176 // create the reference to the provate event implementation
177 // that will be dispatched to the listeners
178 Reference< XEvent > const xEvent(pEvent);
180 // build the path from target node to the root
181 typedef std::vector< ::std::pair<Reference<XEventTarget>, xmlNodePtr> >
182 NodeVector_t;
183 NodeVector_t captureVector;
184 TypeListenerMap captureListeners;
185 TypeListenerMap targetListeners;
187 ::osl::MutexGuard g(rMutex);
189 xmlNodePtr cur = pNode;
190 while (cur != NULL)
192 Reference< XEventTarget > const xRef(
193 rDocument.GetCNode(cur).get());
194 captureVector.push_back(::std::make_pair(xRef, cur));
195 cur = cur->parent;
197 captureListeners = m_CaptureListeners;
198 targetListeners = m_TargetListeners;
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 const_cast<NodeVector_t const&>(captureVector).rbegin();
209 if (rinode != const_cast<NodeVector_t const&>(captureVector).rend())
211 // capturing phase:
212 pEvent->m_phase = PhaseType_CAPTURING_PHASE;
213 while (rinode !=
214 const_cast<NodeVector_t const&>(captureVector).rend())
216 pEvent->m_currentTarget = rinode->first;
217 callListeners(captureListeners, rinode->second, aType, xEvent);
218 if (pEvent->m_canceled) return sal_True;
219 ++rinode;
222 NodeVector_t::const_iterator inode = captureVector.begin();
224 // target phase
225 pEvent->m_phase = PhaseType_AT_TARGET;
226 pEvent->m_currentTarget = inode->first;
227 callListeners(targetListeners, inode->second, aType, xEvent);
228 if (pEvent->m_canceled) return sal_True;
229 // bubbeling phase
230 ++inode;
231 if (i_xEvent->getBubbles()) {
232 pEvent->m_phase = PhaseType_BUBBLING_PHASE;
233 while (inode != captureVector.end())
235 pEvent->m_currentTarget = inode->first;
236 callListeners(targetListeners,
237 inode->second, aType, xEvent);
238 if (pEvent->m_canceled) return sal_True;
239 ++inode;
243 return sal_True;
247 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */