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