LCOV - code coverage report
Current view: top level - unoxml/source/events - eventdispatcher.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 94 123 76.4 %
Date: 2015-06-13 12:38:46 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          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             : #include <osl/mutex.hxx>
      30             : 
      31             : using namespace css::uno;
      32             : using namespace css::xml::dom;
      33             : using namespace css::xml::dom::events;
      34             : 
      35             : namespace DOM { namespace events {
      36             : 
      37         653 :     void CEventDispatcher::addListener(xmlNodePtr pNode, const OUString& aType, const Reference<XEventListener>& aListener, bool bCapture)
      38             :     {
      39             :         TypeListenerMap *const pTMap = (bCapture)
      40         653 :             ? (& m_CaptureListeners) : (& m_TargetListeners);
      41             : 
      42             :         // get the multimap for the specified type
      43         653 :         ListenerMap *pMap = 0;
      44         653 :         TypeListenerMap::const_iterator tIter = pTMap->find(aType);
      45         653 :         if (tIter == pTMap->end()) {
      46             :             // the map has to be created
      47         649 :             pMap = new ListenerMap();
      48         649 :             pTMap->insert(TypeListenerMap::value_type(aType, pMap));
      49             :         } else {
      50           4 :             pMap = tIter->second;
      51             :         }
      52         653 :         if (pMap !=0)
      53         653 :             pMap->insert(ListenerMap::value_type(pNode, aListener));
      54         653 :     }
      55             : 
      56         653 :     void CEventDispatcher::removeListener(xmlNodePtr pNode, const OUString& aType, const Reference<XEventListener>& aListener, bool bCapture)
      57             :     {
      58             :         TypeListenerMap *const pTMap = (bCapture)
      59         653 :             ? (& m_CaptureListeners) : (& m_TargetListeners);
      60             : 
      61             :         // get the multimap for the specified type
      62         653 :         TypeListenerMap::const_iterator tIter = pTMap->find(aType);
      63         653 :         if (tIter != pTMap->end()) {
      64         653 :             ListenerMap *pMap = tIter->second;
      65             :             // find listeners of specied type for specified node
      66         653 :             ListenerMap::iterator iter = pMap->find(pNode);
      67        1966 :             while (iter != pMap->end() && iter->first == pNode)
      68             :             {
      69             :                 // erase all references to specified listener
      70         660 :                 if ((iter->second).is() && iter->second == aListener)
      71             :                 {
      72         653 :                     ListenerMap::iterator tmp_iter = iter;
      73         653 :                     ++iter;
      74         653 :                     pMap->erase(tmp_iter);
      75             :                 }
      76             :                 else
      77           7 :                     ++iter;
      78             :             }
      79             :         }
      80         653 :     }
      81             : 
      82       35178 :     CEventDispatcher::~CEventDispatcher()
      83             :     {
      84             :         // delete the multimaps for the various types
      85       17589 :         for (TypeListenerMap::iterator aI = m_CaptureListeners.begin(); aI != m_CaptureListeners.end(); ++aI)
      86           0 :             delete aI->second;
      87             : 
      88       18228 :         for (TypeListenerMap::iterator aI = m_TargetListeners.begin(); aI != m_TargetListeners.end(); ++aI)
      89         639 :             delete aI->second;
      90       17589 :     }
      91             : 
      92     1199716 :     void CEventDispatcher::callListeners(
      93             :             TypeListenerMap const& rTMap,
      94             :             xmlNodePtr const pNode,
      95             :             const OUString& aType, Reference< XEvent > const& xEvent)
      96             :     {
      97             :         // get the multimap for the specified type
      98     1199716 :         TypeListenerMap::const_iterator tIter = rTMap.find(aType);
      99     1199716 :         if (tIter != rTMap.end()) {
     100          72 :             ListenerMap *pMap = tIter->second;
     101          72 :             ListenerMap::const_iterator iter = pMap->lower_bound(pNode);
     102          72 :             ListenerMap::const_iterator ibound = pMap->upper_bound(pNode);
     103         119 :             for( ; iter != ibound; ++iter )
     104             :             {
     105          47 :                 if((iter->second).is())
     106          47 :                     (iter->second)->handleEvent(xEvent);
     107             :             }
     108             :         }
     109     1199716 :     }
     110             : 
     111      298282 :     bool CEventDispatcher::dispatchEvent(
     112             :             DOM::CDocument & rDocument, ::osl::Mutex & rMutex,
     113             :             xmlNodePtr const pNode, Reference<XNode> const& xNode,
     114             :             Reference< XEvent > const& i_xEvent) const
     115             :     {
     116      298282 :         CEvent *pEvent = 0; // pointer to internal event representation
     117             : 
     118      298282 :         OUString const aType = i_xEvent->getType();
     119      753880 :         if (aType == "DOMSubtreeModified"          ||
     120      228568 :             aType == "DOMNodeInserted"             ||
     121      138489 :             aType == "DOMNodeRemoved"              ||
     122      134474 :             aType == "DOMNodeRemovedFromDocument"  ||
     123      118119 :             aType == "DOMNodeInsertedIntoDocument" ||
     124      349366 :             aType == "DOMAttrModified"             ||
     125         202 :             aType == "DOMCharacterDataModified"    )
     126             :         {
     127             :                 Reference< XMutationEvent > const aMEvent(i_xEvent,
     128      298282 :                         UNO_QUERY_THROW);
     129             :                 // dispatch a mutation event
     130             :                 // we need to clone the event in order to have complete control
     131             :                 // over the implementation
     132      298282 :                 CMutationEvent* pMEvent = new CMutationEvent;
     133             :                 pMEvent->initMutationEvent(
     134      596564 :                     aType, aMEvent->getBubbles(), aMEvent->getCancelable(),
     135      596564 :                     aMEvent->getRelatedNode(), aMEvent->getPrevValue(),
     136      596564 :                     aMEvent->getNewValue(), aMEvent->getAttrName(),
     137     2087974 :                     aMEvent->getAttrChange());
     138      298282 :                 pEvent = pMEvent;
     139           0 :         } else if ( // UIEvent
     140           0 :             aType == "DOMFocusIn"  ||
     141           0 :             aType == "DOMFocusOut" ||
     142           0 :             aType == "DOMActivate" )
     143             :         {
     144           0 :             Reference< XUIEvent > const aUIEvent(i_xEvent, UNO_QUERY_THROW);
     145           0 :             CUIEvent* pUIEvent = new CUIEvent;
     146             :             pUIEvent->initUIEvent(aType,
     147           0 :                 aUIEvent->getBubbles(), aUIEvent->getCancelable(),
     148           0 :                 aUIEvent->getView(), aUIEvent->getDetail());
     149           0 :             pEvent = pUIEvent;
     150           0 :         } else if ( // MouseEvent
     151           0 :             aType == "click"     ||
     152           0 :             aType == "mousedown" ||
     153           0 :             aType == "mouseup"   ||
     154           0 :             aType == "mouseover" ||
     155           0 :             aType == "mousemove" ||
     156           0 :             aType == "mouseout"  )
     157             :         {
     158             :             Reference< XMouseEvent > const aMouseEvent(i_xEvent,
     159           0 :                     UNO_QUERY_THROW);
     160           0 :             CMouseEvent *pMouseEvent = new CMouseEvent;
     161             :             pMouseEvent->initMouseEvent(aType,
     162           0 :                 aMouseEvent->getBubbles(), aMouseEvent->getCancelable(),
     163           0 :                 aMouseEvent->getView(), aMouseEvent->getDetail(),
     164           0 :                 aMouseEvent->getScreenX(), aMouseEvent->getScreenY(),
     165           0 :                 aMouseEvent->getClientX(), aMouseEvent->getClientY(),
     166           0 :                 aMouseEvent->getCtrlKey(), aMouseEvent->getAltKey(),
     167           0 :                 aMouseEvent->getShiftKey(), aMouseEvent->getMetaKey(),
     168           0 :                 aMouseEvent->getButton(), aMouseEvent->getRelatedTarget());
     169           0 :             pEvent = pMouseEvent;
     170             :         }
     171             :         else // generic event
     172             :         {
     173           0 :             pEvent = new CEvent;
     174             :             pEvent->initEvent(
     175           0 :                 aType, i_xEvent->getBubbles(), i_xEvent->getCancelable());
     176             :         }
     177      298282 :         pEvent->m_target.set(xNode, UNO_QUERY_THROW);
     178      298282 :         pEvent->m_currentTarget = i_xEvent->getCurrentTarget();
     179      298282 :         pEvent->m_time = i_xEvent->getTimeStamp();
     180             : 
     181             :         // create the reference to the provate event implementation
     182             :         // that will be dispatched to the listeners
     183      596564 :         Reference< XEvent > const xEvent(pEvent);
     184             : 
     185             :         // build the path from target node to the root
     186             :         typedef std::vector< ::std::pair<Reference<XEventTarget>, xmlNodePtr> >
     187             :             NodeVector_t;
     188      596564 :         NodeVector_t captureVector;
     189      596564 :         TypeListenerMap captureListeners;
     190      596564 :         TypeListenerMap targetListeners;
     191             :         {
     192      298282 :             ::osl::MutexGuard g(rMutex);
     193             : 
     194      298282 :             xmlNodePtr cur = pNode;
     195     1196422 :             while (cur != NULL)
     196             :             {
     197             :                 Reference< XEventTarget > const xRef(
     198      599858 :                         rDocument.GetCNode(cur).get());
     199      599858 :                 captureVector.push_back(::std::make_pair(xRef, cur));
     200      599858 :                 cur = cur->parent;
     201      599858 :             }
     202      298282 :             captureListeners = m_CaptureListeners;
     203      298282 :             targetListeners = m_TargetListeners;
     204             :         }
     205             : 
     206             :         // the caputre vector now holds the node path from target to root
     207             :         // first we must search for capture listernes in order root to
     208             :         // to target. after that, any target listeners have to be called
     209             :         // then bubbeling phase listeners are called in target to root
     210             :         // order
     211             :         // start at the root
     212             :         NodeVector_t::const_reverse_iterator rinode =
     213      298282 :             const_cast<NodeVector_t const&>(captureVector).rbegin();
     214      298282 :         if (rinode != const_cast<NodeVector_t const&>(captureVector).rend())
     215             :         {
     216             :             // capturing phase:
     217      298282 :             pEvent->m_phase = PhaseType_CAPTURING_PHASE;
     218     1196422 :             while (rinode !=
     219             :                     const_cast<NodeVector_t const&>(captureVector).rend())
     220             :             {
     221      599858 :                 pEvent->m_currentTarget = rinode->first;
     222      599858 :                 callListeners(captureListeners, rinode->second, aType, xEvent);
     223      599858 :                 if  (pEvent->m_canceled) return true;
     224      599858 :                 ++rinode;
     225             :             }
     226             : 
     227      298282 :             NodeVector_t::const_iterator inode = captureVector.begin();
     228             : 
     229             :             // target phase
     230      298282 :             pEvent->m_phase = PhaseType_AT_TARGET;
     231      298282 :             pEvent->m_currentTarget = inode->first;
     232      298282 :             callListeners(targetListeners, inode->second, aType, xEvent);
     233      298282 :             if  (pEvent->m_canceled) return true;
     234             :             // bubbeling phase
     235      298282 :             ++inode;
     236      298282 :             if (i_xEvent->getBubbles()) {
     237      298282 :                 pEvent->m_phase = PhaseType_BUBBLING_PHASE;
     238      898140 :                 while (inode != captureVector.end())
     239             :                 {
     240      301576 :                     pEvent->m_currentTarget = inode->first;
     241             :                     callListeners(targetListeners,
     242      301576 :                             inode->second, aType, xEvent);
     243      301576 :                     if  (pEvent->m_canceled) return true;
     244      301576 :                     ++inode;
     245             :                 }
     246             :             }
     247             :         }
     248      596564 :         return true;
     249             :     }
     250             : }}
     251             : 
     252             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11