LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/framework/source/services - ContextChangeEventMultiplexer.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 67 115 58.3 %
Date: 2013-07-09 Functions: 12 20 60.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             : #include "services/ContextChangeEventMultiplexer.hxx"
      20             : #include "services.h"
      21             : 
      22             : using ::rtl::OUString;
      23             : 
      24             : #define A2S(s) ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
      25             : 
      26             : using namespace css;
      27             : using namespace cssu;
      28             : 
      29             : namespace framework {
      30             : 
      31             : #define IMPLEMENTATION_NAME "org.apache.openoffice.comp.framework.ContextChangeEventMultiplexer"
      32             : #define SERVICE_NAME "com.sun.star.ui.ContextChangeEventMultiplexer"
      33             : #define SINGLETON_NAME "org.apache.openoffice.comp.framework.ContextChangeEventMultiplexerSigleton"
      34             : 
      35             : 
      36          56 : ContextChangeEventMultiplexer::ContextChangeEventMultiplexer (
      37             :     const cssu::Reference<cssu::XComponentContext>& rxContext)
      38             :     : ContextChangeEventMultiplexerInterfaceBase(m_aMutex),
      39          56 :       maListeners()
      40             : {
      41             :     (void)rxContext;
      42          56 : }
      43             : 
      44             : 
      45             : 
      46             : 
      47         112 : ContextChangeEventMultiplexer::~ContextChangeEventMultiplexer (void)
      48             : {
      49         112 : }
      50             : 
      51             : 
      52             : 
      53             : 
      54          56 : void SAL_CALL ContextChangeEventMultiplexer::disposing (void)
      55             : {
      56          56 :     ListenerMap aListeners;
      57          56 :     aListeners.swap(maListeners);
      58             : 
      59         112 :     cssu::Reference<cssu::XInterface> xThis (static_cast<XWeak*>(this));
      60         112 :     css::lang::EventObject aEvent (xThis);
      61          58 :     for (ListenerMap::const_iterator iContainer(aListeners.begin()), iEnd(aListeners.end());
      62             :          iContainer!=iEnd;
      63             :          ++iContainer)
      64             :     {
      65             :         // Unregister from the focus object.
      66           2 :         Reference<lang::XComponent> xComponent (iContainer->first, UNO_QUERY);
      67           2 :         if (xComponent.is())
      68           2 :             xComponent->removeEventListener(this);
      69             : 
      70             :         // Tell all listeners that we are being disposed.
      71           2 :         const FocusDescriptor& rFocusDescriptor (iContainer->second);
      72           2 :         for (ListenerContainer::const_iterator
      73           2 :                  iListener(rFocusDescriptor.maListeners.begin()),
      74           2 :                  iContainerEnd(rFocusDescriptor.maListeners.end());
      75             :              iListener!=iContainerEnd;
      76             :              ++iListener)
      77             :         {
      78           0 :             (*iListener)->disposing(aEvent);
      79             :         }
      80          58 :     }
      81          56 : }
      82             : 
      83             : 
      84             : 
      85             : 
      86             : // XContextChangeEventMultiplexer
      87             : 
      88           0 : void SAL_CALL ContextChangeEventMultiplexer::addContextChangeEventListener (
      89             :     const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener,
      90             :     const cssu::Reference<cssu::XInterface>& rxEventFocus)
      91             :     throw(cssu::RuntimeException,cssl::IllegalArgumentException)
      92             : {
      93           0 :     if ( ! rxListener.is())
      94             :         throw css::lang::IllegalArgumentException(
      95           0 :             A2S("can not add an empty reference"),
      96             :             static_cast<XWeak*>(this),
      97           0 :             0);
      98             : 
      99           0 :     FocusDescriptor* pFocusDescriptor = GetFocusDescriptor(rxEventFocus, true);
     100           0 :     if (pFocusDescriptor != NULL)
     101             :     {
     102           0 :         ListenerContainer& rContainer (pFocusDescriptor->maListeners);
     103           0 :         if (::std::find(rContainer.begin(), rContainer.end(), rxListener) == rContainer.end())
     104           0 :             rContainer.push_back(rxListener);
     105             :         else
     106             :         {
     107             :             // The listener was added for the same event focus
     108             :             // previously.  That is an error.
     109           0 :             throw cssl::IllegalArgumentException(A2S("listener added twice"), static_cast<XWeak*>(this), 0);
     110             :         }
     111             :     }
     112             : 
     113             :     // Send out an initial event that informs the new listener about
     114             :     // the current context.
     115           0 :     if (rxEventFocus.is() && pFocusDescriptor!=NULL)
     116             :     {
     117             :         css::ui::ContextChangeEventObject aEvent (
     118             :             NULL,
     119             :             pFocusDescriptor->msCurrentApplicationName,
     120           0 :             pFocusDescriptor->msCurrentContextName);
     121           0 :         rxListener->notifyContextChangeEvent(aEvent);
     122             :     }
     123           0 : }
     124             : 
     125             : 
     126             : 
     127             : 
     128           0 : void SAL_CALL ContextChangeEventMultiplexer::removeContextChangeEventListener (
     129             :     const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener,
     130             :     const cssu::Reference<cssu::XInterface>& rxEventFocus)
     131             :     throw(cssu::RuntimeException,cssl::IllegalArgumentException)
     132             : {
     133           0 :     if ( ! rxListener.is())
     134             :         throw cssl::IllegalArgumentException(
     135           0 :             A2S("can not remove an empty reference"),
     136           0 :             static_cast<XWeak*>(this), 0);
     137             : 
     138           0 :     FocusDescriptor* pFocusDescriptor = GetFocusDescriptor(rxEventFocus, false);
     139           0 :     if (pFocusDescriptor != NULL)
     140             :     {
     141           0 :         ListenerContainer& rContainer (pFocusDescriptor->maListeners);
     142             :         const ListenerContainer::iterator iListener (
     143           0 :             ::std::find(rContainer.begin(), rContainer.end(), rxListener));
     144           0 :         if (iListener != rContainer.end())
     145             :         {
     146           0 :             rContainer.erase(iListener);
     147             : 
     148             :             // We hold on to the focus descriptor even when the last listener has been removed.
     149             :             // This allows us to keep track of the current context and send it to new listeners.
     150             :         }
     151             :     }
     152             : 
     153           0 : }
     154             : 
     155             : 
     156             : 
     157             : 
     158           0 : void SAL_CALL ContextChangeEventMultiplexer::removeAllContextChangeEventListeners (
     159             :     const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener)
     160             :     throw(cssu::RuntimeException,cssl::IllegalArgumentException)
     161             : {
     162           0 :     if ( ! rxListener.is())
     163             :         throw cssl::IllegalArgumentException(
     164           0 :             A2S("can not remove an empty reference"),
     165           0 :             static_cast<XWeak*>(this), 0);
     166             : 
     167           0 :     for (ListenerMap::iterator
     168           0 :              iContainer(maListeners.begin()),
     169           0 :              iEnd(maListeners.end());
     170             :          iContainer!=iEnd;
     171             :          ++iContainer)
     172             :     {
     173             :         const ListenerContainer::iterator iListener (
     174           0 :             ::std::find(iContainer->second.maListeners.begin(), iContainer->second.maListeners.end(), rxListener));
     175           0 :         if (iListener != iContainer->second.maListeners.end())
     176             :         {
     177           0 :             iContainer->second.maListeners.erase(iListener);
     178             : 
     179             :             // We hold on to the focus descriptor even when the last listener has been removed.
     180             :             // This allows us to keep track of the current context and send it to new listeners.
     181             :         }
     182             :     }
     183           0 : }
     184             : 
     185             : 
     186             : 
     187             : 
     188        1510 : void SAL_CALL ContextChangeEventMultiplexer::broadcastContextChangeEvent (
     189             :     const css::ui::ContextChangeEventObject& rEventObject,
     190             :     const cssu::Reference<cssu::XInterface>& rxEventFocus)
     191             :     throw(cssu::RuntimeException)
     192             : {
     193             :     // Remember the current context.
     194        1510 :     if (rxEventFocus.is())
     195             :     {
     196        1510 :         FocusDescriptor* pFocusDescriptor = GetFocusDescriptor(rxEventFocus, true);
     197        1510 :         if (pFocusDescriptor != NULL)
     198             :         {
     199        1510 :             pFocusDescriptor->msCurrentApplicationName = rEventObject.ApplicationName;
     200        1510 :             pFocusDescriptor->msCurrentContextName = rEventObject.ContextName;
     201             :         }
     202             :     }
     203             : 
     204        1510 :     BroadcastEventToSingleContainer(rEventObject, rxEventFocus);
     205        1510 :     if (rxEventFocus.is())
     206        1510 :         BroadcastEventToSingleContainer(rEventObject, NULL);
     207        1510 : }
     208             : 
     209             : 
     210             : 
     211             : 
     212        3020 : void ContextChangeEventMultiplexer::BroadcastEventToSingleContainer (
     213             :     const css::ui::ContextChangeEventObject& rEventObject,
     214             :     const cssu::Reference<cssu::XInterface>& rxEventFocus)
     215             : {
     216        3020 :     FocusDescriptor* pFocusDescriptor = GetFocusDescriptor(rxEventFocus, false);
     217        3020 :     if (pFocusDescriptor != NULL)
     218             :     {
     219             :         // Create a copy of the listener container to avoid problems
     220             :         // when one of the called listeners calls add... or remove...
     221        1510 :         ListenerContainer aContainer (pFocusDescriptor->maListeners);
     222        1510 :         for (ListenerContainer::const_iterator
     223        1510 :                  iListener(aContainer.begin()),
     224        1510 :                  iEnd(aContainer.end());
     225             :              iListener!=iEnd;
     226             :              ++iListener)
     227             :         {
     228           0 :             (*iListener)->notifyContextChangeEvent(rEventObject);
     229        1510 :         }
     230             :     }
     231        3020 : }
     232             : 
     233             : 
     234             : 
     235             : 
     236        4530 : ContextChangeEventMultiplexer::FocusDescriptor* ContextChangeEventMultiplexer::GetFocusDescriptor (
     237             :     const cssu::Reference<cssu::XInterface>& rxEventFocus,
     238             :     const bool bCreateWhenMissing)
     239             : {
     240        4530 :     ListenerMap::iterator iDescriptor (maListeners.find(rxEventFocus));
     241        4530 :     if (iDescriptor == maListeners.end() && bCreateWhenMissing)
     242             :     {
     243             :         // Listen for the focus being disposed.
     244        1045 :         Reference<lang::XComponent> xComponent (rxEventFocus, UNO_QUERY);
     245        1045 :         if (xComponent.is())
     246        1045 :             xComponent->addEventListener(this);
     247             : 
     248             :         // Create a new listener container for the event focus.
     249             :         iDescriptor = maListeners.insert(
     250             :             ListenerMap::value_type(
     251             :                 rxEventFocus,
     252        1045 :                 FocusDescriptor())).first;
     253             :     }
     254        4530 :     if (iDescriptor != maListeners.end())
     255        3020 :         return &iDescriptor->second;
     256             :     else
     257        1510 :         return NULL;
     258             : }
     259             : 
     260             : 
     261             : 
     262             : 
     263             : // XSingleComponentFactory
     264             : 
     265           0 : cssu::Reference<cssu::XInterface> SAL_CALL ContextChangeEventMultiplexer::createInstanceWithContext (
     266             :     const cssu::Reference<cssu::XComponentContext>& rxContext)
     267             :     throw (cssu::Exception, cssu::RuntimeException)
     268             : {
     269             :     (void)rxContext;
     270           0 :     return cssu::Reference<cssu::XInterface>();
     271             : }
     272             : 
     273             : 
     274             : 
     275             : 
     276           0 : cssu::Reference<cssu::XInterface > SAL_CALL ContextChangeEventMultiplexer::createInstanceWithArgumentsAndContext (
     277             :     const cssu::Sequence<cssu::Any>& rArguments,
     278             :     const cssu::Reference<cssu::XComponentContext>& rxContext)
     279             :     throw (cssu::Exception, cssu::RuntimeException)
     280             : {
     281             :     (void)rArguments;
     282             :     (void)rxContext;
     283           0 :     return cssu::Reference<cssu::XInterface>();
     284             : }
     285             : 
     286             : 
     287             : 
     288             : 
     289             : // XServiceInfo
     290             : 
     291           0 : ::rtl::OUString SAL_CALL ContextChangeEventMultiplexer::getImplementationName (void)
     292             :     throw(cssu::RuntimeException)
     293             : {
     294           0 :     return impl_getStaticImplementationName();
     295             : }
     296             : 
     297             : 
     298             : 
     299             : 
     300             : 
     301           0 : sal_Bool SAL_CALL ContextChangeEventMultiplexer::supportsService (
     302             :     const ::rtl::OUString& rsServiceName)
     303             :     throw (cssu::RuntimeException)
     304             : {
     305           0 :     return ::comphelper::findValue(static_GetSupportedServiceNames(), rsServiceName, sal_True).getLength() != 0;
     306             : }
     307             : 
     308             : 
     309             : 
     310             : 
     311           0 : cssu::Sequence<OUString> SAL_CALL ContextChangeEventMultiplexer::getSupportedServiceNames (void)
     312             :     throw (cssu::RuntimeException)
     313             : {
     314           0 :     return static_GetSupportedServiceNames();
     315             : }
     316             : 
     317             : 
     318             : 
     319             : 
     320        1043 : void SAL_CALL ContextChangeEventMultiplexer::disposing (
     321             :     const css::lang::EventObject& rEvent)
     322             :     throw (cssu::RuntimeException)
     323             : {
     324        1043 :     ListenerMap::iterator iDescriptor (maListeners.find(rEvent.Source));
     325             : 
     326        1043 :     if (iDescriptor == maListeners.end())
     327             :     {
     328             :         OSL_ASSERT(iDescriptor != maListeners.end());
     329        1043 :         return;
     330             :     }
     331             : 
     332             :     // Should we notify the remaining listeners?
     333             : 
     334        1043 :     maListeners.erase(iDescriptor);
     335             : }
     336             : 
     337             : 
     338             : 
     339             : 
     340             : // Local and static methods.
     341             : 
     342         152 : OUString SAL_CALL ContextChangeEventMultiplexer::impl_getStaticImplementationName (void)
     343             : {
     344         152 :     return A2S(IMPLEMENTATION_NAME);
     345             : }
     346             : 
     347             : 
     348             : 
     349             : 
     350          56 : cssu::Sequence<OUString> SAL_CALL ContextChangeEventMultiplexer::static_GetSupportedServiceNames (void)
     351             : {
     352          56 :     cssu::Sequence<OUString> aServiceNames (2);
     353          56 :     aServiceNames[0] = A2S(SERVICE_NAME);
     354          56 :     aServiceNames[1] = A2S(SINGLETON_NAME);
     355          56 :     return aServiceNames;
     356             : }
     357             : 
     358             : 
     359             : 
     360             : 
     361          56 : cssu::Reference<cssu::XInterface> ContextChangeEventMultiplexer::impl_createFactory (
     362             :     const cssu::Reference<cssl::XMultiServiceFactory>& rxServiceManager)
     363             : {
     364             :     (void)rxServiceManager;
     365             :     return cppu::createSingleComponentFactory(
     366             :         ContextChangeEventMultiplexer::static_CreateInstance,
     367             :         ContextChangeEventMultiplexer::impl_getStaticImplementationName(),
     368             :         ContextChangeEventMultiplexer::static_GetSupportedServiceNames()
     369          56 :         );
     370             : }
     371             : 
     372             : 
     373             : 
     374             : 
     375          56 : cssu::Reference<cssu::XInterface> SAL_CALL ContextChangeEventMultiplexer::static_CreateInstance (
     376             :     const cssu::Reference<cssu::XComponentContext>& rxComponentContext)
     377             :     throw (cssu::Exception)
     378             : {
     379          56 :     ContextChangeEventMultiplexer* pObject = new ContextChangeEventMultiplexer(rxComponentContext);
     380          56 :     cssu::Reference<cssu::XInterface> xService (static_cast<XWeak*>(pObject), cssu::UNO_QUERY);
     381          56 :     return xService;
     382             : }
     383             : 
     384             : }  // end of namespace framework
     385             : 
     386             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10