Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / unoxml / source / events / eventdispatcher.cxx
blobbe45adb09dce12e259b94cf2dd7dc4479af204d9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <eventdispatcher.hxx>
31 #include <event.hxx>
32 #include <mutationevent.hxx>
33 #include <uievent.hxx>
34 #include <mouseevent.hxx>
36 #include "../dom/document.hxx"
39 namespace DOM { namespace events {
41 void CEventDispatcher::addListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture)
43 TypeListenerMap *const pTMap = (bCapture)
44 ? (& m_CaptureListeners) : (& m_TargetListeners);
46 // get the multimap for the specified type
47 ListenerMap *pMap = 0;
48 TypeListenerMap::const_iterator tIter = pTMap->find(aType);
49 if (tIter == pTMap->end()) {
50 // the map has to be created
51 pMap = new ListenerMap();
52 pTMap->insert(TypeListenerMap::value_type(aType, pMap));
53 } else {
54 pMap = tIter->second;
56 if (pMap !=0)
57 pMap->insert(ListenerMap::value_type(pNode, aListener));
60 void CEventDispatcher::removeListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture)
62 TypeListenerMap *const pTMap = (bCapture)
63 ? (& m_CaptureListeners) : (& m_TargetListeners);
65 // get the multimap for the specified type
66 TypeListenerMap::const_iterator tIter = pTMap->find(aType);
67 if (tIter != pTMap->end()) {
68 ListenerMap *pMap = tIter->second;
69 // find listeners of specied type for specified node
70 ListenerMap::iterator iter = pMap->find(pNode);
71 while (iter != pMap->end() && iter->first == pNode)
73 // erase all references to specified listener
74 if ((iter->second).is() && iter->second == aListener)
76 ListenerMap::iterator tmp_iter = iter;
77 ++iter;
78 pMap->erase(tmp_iter);
80 else
81 ++iter;
86 void CEventDispatcher::callListeners(
87 TypeListenerMap const& rTMap,
88 xmlNodePtr const pNode,
89 OUString aType, Reference< XEvent > const& xEvent)
91 // get the multimap for the specified type
92 TypeListenerMap::const_iterator tIter = rTMap.find(aType);
93 if (tIter != rTMap.end()) {
94 ListenerMap *pMap = tIter->second;
95 ListenerMap::const_iterator iter = pMap->lower_bound(pNode);
96 ListenerMap::const_iterator ibound = pMap->upper_bound(pNode);
97 for( ; iter != ibound; ++iter )
99 if((iter->second).is())
100 (iter->second)->handleEvent(xEvent);
105 bool CEventDispatcher::dispatchEvent(
106 DOM::CDocument & rDocument, ::osl::Mutex & rMutex,
107 xmlNodePtr const pNode, Reference<XNode> const& xNode,
108 Reference< XEvent > const& i_xEvent) const
110 CEvent *pEvent = 0; // pointer to internal event representation
112 OUString const aType = i_xEvent->getType();
113 if (aType.compareToAscii("DOMSubtreeModified") == 0||
114 aType.compareToAscii("DOMNodeInserted") == 0||
115 aType.compareToAscii("DOMNodeRemoved") == 0||
116 aType.compareToAscii("DOMNodeRemovedFromDocument") == 0||
117 aType.compareToAscii("DOMNodeInsertedIntoDocument") == 0||
118 aType.compareToAscii("DOMAttrModified") == 0||
119 aType.compareToAscii("DOMCharacterDataModified") == 0)
121 Reference< XMutationEvent > const aMEvent(i_xEvent,
122 UNO_QUERY_THROW);
123 // dispatch a mutation event
124 // we need to clone the event in order to have complete control
125 // over the implementation
126 CMutationEvent* pMEvent = new CMutationEvent;
127 pMEvent->initMutationEvent(
128 aType, aMEvent->getBubbles(), aMEvent->getCancelable(),
129 aMEvent->getRelatedNode(), aMEvent->getPrevValue(),
130 aMEvent->getNewValue(), aMEvent->getAttrName(),
131 aMEvent->getAttrChange());
132 pEvent = pMEvent;
133 } else if ( // UIEvent
134 aType.compareToAscii("DOMFocusIn") == 0||
135 aType.compareToAscii("DOMFocusOut") == 0||
136 aType.compareToAscii("DOMActivate") == 0)
138 Reference< XUIEvent > const aUIEvent(i_xEvent, UNO_QUERY_THROW);
139 CUIEvent* pUIEvent = new CUIEvent;
140 pUIEvent->initUIEvent(aType,
141 aUIEvent->getBubbles(), aUIEvent->getCancelable(),
142 aUIEvent->getView(), aUIEvent->getDetail());
143 pEvent = pUIEvent;
144 } else if ( // MouseEvent
145 aType.compareToAscii("click") == 0||
146 aType.compareToAscii("mousedown") == 0||
147 aType.compareToAscii("mouseup") == 0||
148 aType.compareToAscii("mouseover") == 0||
149 aType.compareToAscii("mousemove") == 0||
150 aType.compareToAscii("mouseout") == 0)
152 Reference< XMouseEvent > const aMouseEvent(i_xEvent,
153 UNO_QUERY_THROW);
154 CMouseEvent *pMouseEvent = new CMouseEvent;
155 pMouseEvent->initMouseEvent(aType,
156 aMouseEvent->getBubbles(), aMouseEvent->getCancelable(),
157 aMouseEvent->getView(), aMouseEvent->getDetail(),
158 aMouseEvent->getScreenX(), aMouseEvent->getScreenY(),
159 aMouseEvent->getClientX(), aMouseEvent->getClientY(),
160 aMouseEvent->getCtrlKey(), aMouseEvent->getAltKey(),
161 aMouseEvent->getShiftKey(), aMouseEvent->getMetaKey(),
162 aMouseEvent->getButton(), aMouseEvent->getRelatedTarget());
163 pEvent = pMouseEvent;
165 else // generic event
167 pEvent = new CEvent;
168 pEvent->initEvent(
169 aType, i_xEvent->getBubbles(), i_xEvent->getCancelable());
171 pEvent->m_target.set(xNode, UNO_QUERY_THROW);
172 pEvent->m_currentTarget = i_xEvent->getCurrentTarget();
173 pEvent->m_time = i_xEvent->getTimeStamp();
175 // create the reference to the provate event implementation
176 // that will be dispatched to the listeners
177 Reference< XEvent > const xEvent(pEvent);
179 // build the path from target node to the root
180 typedef std::vector< ::std::pair<Reference<XEventTarget>, xmlNodePtr> >
181 NodeVector_t;
182 NodeVector_t captureVector;
183 TypeListenerMap captureListeners;
184 TypeListenerMap targetListeners;
186 ::osl::MutexGuard g(rMutex);
188 xmlNodePtr cur = pNode;
189 while (cur != NULL)
191 Reference< XEventTarget > const xRef(
192 rDocument.GetCNode(cur).get());
193 captureVector.push_back(::std::make_pair(xRef, cur));
194 cur = cur->parent;
196 captureListeners = m_CaptureListeners;
197 targetListeners = m_TargetListeners;
200 // the caputre vector now holds the node path from target to root
201 // first we must search for capture listernes in order root to
202 // to target. after that, any target listeners have to be called
203 // then bubbeling phase listeners are called in target to root
204 // order
205 // start at the root
206 NodeVector_t::const_reverse_iterator rinode =
207 const_cast<NodeVector_t const&>(captureVector).rbegin();
208 if (rinode != const_cast<NodeVector_t const&>(captureVector).rend())
210 // capturing phase:
211 pEvent->m_phase = PhaseType_CAPTURING_PHASE;
212 while (rinode !=
213 const_cast<NodeVector_t const&>(captureVector).rend())
215 pEvent->m_currentTarget = rinode->first;
216 callListeners(captureListeners, rinode->second, aType, xEvent);
217 if (pEvent->m_canceled) return sal_True;
218 ++rinode;
221 NodeVector_t::const_iterator inode = captureVector.begin();
223 // target phase
224 pEvent->m_phase = PhaseType_AT_TARGET;
225 pEvent->m_currentTarget = inode->first;
226 callListeners(targetListeners, inode->second, aType, xEvent);
227 if (pEvent->m_canceled) return sal_True;
228 // bubbeling phase
229 ++inode;
230 if (i_xEvent->getBubbles()) {
231 pEvent->m_phase = PhaseType_BUBBLING_PHASE;
232 while (inode != captureVector.end())
234 pEvent->m_currentTarget = inode->first;
235 callListeners(targetListeners,
236 inode->second, aType, xEvent);
237 if (pEvent->m_canceled) return sal_True;
238 ++inode;
242 return sal_True;
246 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */