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