LCOV - code coverage report
Current view: top level - forms/source/misc - InterfaceContainer.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 413 593 69.6 %
Date: 2014-11-03 Functions: 57 72 79.2 %
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             : 
      21             : #include "frm_resource.hrc"
      22             : #include "frm_resource.hxx"
      23             : #include "InterfaceContainer.hxx"
      24             : #include "componenttools.hxx"
      25             : #include "property.hrc"
      26             : #include "services.hxx"
      27             : 
      28             : #include <com/sun/star/beans/XPropertySet.hpp>
      29             : #include <com/sun/star/container/XNamed.hpp>
      30             : #include <com/sun/star/io/WrongFormatException.hpp>
      31             : #include <com/sun/star/io/XMarkableStream.hpp>
      32             : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
      33             : #include <com/sun/star/lang/XComponent.hpp>
      34             : #include <com/sun/star/util/XCloneable.hpp>
      35             : #include <com/sun/star/form/XForm.hpp>
      36             : 
      37             : #include <comphelper/container.hxx>
      38             : #include <comphelper/enumhelper.hxx>
      39             : #include <comphelper/eventattachermgr.hxx>
      40             : #include <comphelper/property.hxx>
      41             : #include <comphelper/sequence.hxx>
      42             : #include <comphelper/types.hxx>
      43             : #include <cppuhelper/exc_hlp.hxx>
      44             : #include <cppuhelper/queryinterface.hxx>
      45             : #include <tools/debug.hxx>
      46             : #include <tools/diagnose_ex.h>
      47             : 
      48             : #include <algorithm>
      49             : #include <boost/scoped_ptr.hpp>
      50             : 
      51             : 
      52             : #include <com/sun/star/frame/XModel.hpp>
      53             : #include <com/sun/star/document/XCodeNameQuery.hpp>
      54             : #include <ooo/vba/XVBAToOOEventDescGen.hpp>
      55             : #include <comphelper/processfactory.hxx>
      56             : 
      57             : namespace frm
      58             : {
      59             : 
      60             : 
      61             : using namespace ::com::sun::star::frame;
      62             : using namespace ::com::sun::star::lang;
      63             : using namespace ::com::sun::star::uno;
      64             : using namespace ::com::sun::star::beans;
      65             : using namespace ::com::sun::star::document;
      66             : using namespace ::com::sun::star::container;
      67             : using namespace ::com::sun::star::script;
      68             : using namespace ::com::sun::star::io;
      69             : using namespace ::com::sun::star::form;
      70             : using namespace ::com::sun::star::util;
      71             : 
      72             : namespace
      73             : {
      74             : 
      75           0 :     static void lcl_throwIllegalArgumentException()
      76             :     {
      77           0 :         throw IllegalArgumentException();
      78             :     }
      79             : }
      80             : 
      81             : bool
      82          28 : lcl_hasVbaEvents( const Sequence< ScriptEventDescriptor >& sEvents  )
      83             : {
      84          28 :     const ScriptEventDescriptor* pDesc = sEvents.getConstArray();
      85          28 :     const ScriptEventDescriptor* pEnd = ( pDesc + sEvents.getLength() );
      86          40 :     for ( ; pDesc != pEnd; ++pDesc )
      87             :     {
      88          12 :         if ( pDesc->ScriptType == "VBAInterop" )
      89           0 :             return true;
      90             :     }
      91          28 :     return false;
      92             : }
      93             : 
      94             : Sequence< ScriptEventDescriptor >
      95           0 : lcl_stripVbaEvents( const Sequence< ScriptEventDescriptor >& sEvents )
      96             : {
      97           0 :     Sequence< ScriptEventDescriptor > sStripped( sEvents.getLength() );
      98             : 
      99           0 :     const ScriptEventDescriptor* pDesc = sEvents.getConstArray();
     100           0 :     const ScriptEventDescriptor* pEnd = ( pDesc + sEvents.getLength() );
     101           0 :     sal_Int32 nCopied = 0;
     102           0 :     for ( ; pDesc != pEnd; ++pDesc )
     103             :     {
     104           0 :         if ( pDesc->ScriptType != "VBAInterop" )
     105             :         {
     106           0 :             sStripped[ nCopied++ ] = *pDesc;
     107             :         }
     108             :     }
     109           0 :     if ( nCopied )
     110           0 :         sStripped.realloc( nCopied );
     111           0 :     return sStripped;
     112             : }
     113             : 
     114         488 : void OInterfaceContainer::impl_addVbEvents_nolck_nothrow(  const sal_Int32 i_nIndex )
     115             : {
     116             :     // we are dealing with form controls
     117             :     try
     118             :     {
     119             :         do
     120             :         {
     121         488 :             Reference< XModel > xDoc( getXModel( static_cast< XContainer *> ( this ) ) );
     122         488 :             if ( !xDoc.is() )
     123           0 :                 break;
     124             : 
     125         500 :             Reference< XMultiServiceFactory > xDocFac( xDoc, UNO_QUERY_THROW );
     126         490 :             Reference< XCodeNameQuery > xNameQuery( xDocFac->createInstance("ooo.vba.VBACodeNameProvider"), UNO_QUERY );
     127         478 :             if ( !xNameQuery.is() )
     128         476 :                 break;
     129             : 
     130           4 :             ::osl::MutexGuard aGuard( m_rMutex );
     131           2 :             bool hasVBABindings = lcl_hasVbaEvents( m_xEventAttacher->getScriptEvents( i_nIndex ) );
     132           2 :             if ( hasVBABindings )
     133           0 :                 break;
     134             : 
     135           4 :             Reference< XInterface > xElement( getByIndex( i_nIndex ) , UNO_QUERY_THROW );
     136           4 :             Reference< XForm > xElementAsForm( xElement, UNO_QUERY );
     137           2 :             if ( xElementAsForm.is() )
     138           0 :                 break;
     139             : 
     140             :             // Try getting the code name from the container first (faster),
     141             :             // then from the element if that fails (slower).
     142           4 :             Reference<XInterface> xThis = static_cast<XContainer*>(this);
     143           4 :             OUString sCodeName = xNameQuery->getCodeNameForContainer(xThis);
     144           2 :             if (sCodeName.isEmpty())
     145           0 :                 sCodeName = xNameQuery->getCodeNameForObject(xElement);
     146             : 
     147           4 :             Reference< XPropertySet > xProps( xElement, UNO_QUERY_THROW );
     148           4 :             OUString sServiceName;
     149           2 :             xProps->getPropertyValue("DefaultControl") >>= sServiceName;
     150             : 
     151           4 :             Reference< ooo::vba::XVBAToOOEventDescGen > xDescSupplier( m_xContext->getServiceManager()->createInstanceWithContext("ooo.vba.VBAToOOEventDesc", m_xContext), UNO_QUERY_THROW );
     152           4 :             Sequence< ScriptEventDescriptor > vbaEvents = xDescSupplier->getEventDescriptions( sServiceName , sCodeName );
     153             : 
     154             :             // register the vba script events
     155          14 :             m_xEventAttacher->registerScriptEvents( i_nIndex, vbaEvents );
     156             :         }
     157             :         while ( false );
     158             :     }
     159          10 :     catch ( const ServiceNotRegisteredException& )
     160             :     {
     161             :         // silence this, not all document types support the ooo.vba.VBACodeNameProvider service
     162             :     }
     163           0 :     catch( const Exception& )
     164             :     {
     165             :         DBG_UNHANDLED_EXCEPTION();
     166             :     }
     167             : 
     168         488 : }
     169             : 
     170        1056 : ElementDescription::ElementDescription( )
     171             : {
     172        1056 : }
     173             : 
     174             : 
     175        1996 : ElementDescription::~ElementDescription()
     176             : {
     177        1996 : }
     178             : 
     179        1098 : OInterfaceContainer::OInterfaceContainer(
     180             :                 const Reference<XComponentContext>& _rxContext,
     181             :                 ::osl::Mutex& _rMutex,
     182             :                 const Type& _rElementType)
     183             :     :OInterfaceContainer_BASE()
     184             :     ,m_rMutex(_rMutex)
     185             :     ,m_aContainerListeners(_rMutex)
     186             :     ,m_aElementType(_rElementType)
     187        1098 :     ,m_xContext(_rxContext)
     188             : {
     189        1098 :     impl_createEventAttacher_nothrow();
     190        1098 : }
     191             : 
     192             : 
     193           0 : OInterfaceContainer::OInterfaceContainer( ::osl::Mutex& _rMutex, const OInterfaceContainer& _cloneSource )
     194             :     :OInterfaceContainer_BASE()
     195             :     ,m_rMutex( _rMutex )
     196             :     ,m_aContainerListeners( _rMutex )
     197             :     ,m_aElementType( _cloneSource.m_aElementType )
     198           0 :     ,m_xContext( _cloneSource.m_xContext )
     199             : {
     200           0 :     impl_createEventAttacher_nothrow();
     201           0 : }
     202             : 
     203           0 : void OInterfaceContainer::clonedFrom(const OInterfaceContainer& _cloneSource) throw(RuntimeException, std::exception)
     204             : {
     205             :     try
     206             :     {
     207           0 :         const Reference< XIndexAccess > xSourceHierarchy( const_cast< OInterfaceContainer* >( &_cloneSource ) );
     208           0 :         const sal_Int32 nCount = xSourceHierarchy->getCount();
     209           0 :         for ( sal_Int32 i=0; i<nCount; ++i )
     210             :         {
     211           0 :             Reference< XCloneable > xCloneable( xSourceHierarchy->getByIndex( i ), UNO_QUERY_THROW );
     212           0 :             Reference< XInterface > xClone( xCloneable->createClone() );
     213           0 :             insertByIndex( i, makeAny( xClone ) );
     214           0 :         }
     215             :     }
     216           0 :     catch (const RuntimeException&)
     217             :     {
     218           0 :         throw;
     219             :     }
     220           0 :     catch (const Exception&)
     221             :     {
     222             :         throw WrappedTargetRuntimeException(
     223             :             "Could not clone the given interface hierarchy.",
     224             :             static_cast< XIndexContainer* >( const_cast< OInterfaceContainer* >( &_cloneSource ) ),
     225             :             ::cppu::getCaughtException()
     226           0 :         );
     227             :     }
     228           0 : }
     229             : 
     230        1098 : void OInterfaceContainer::impl_createEventAttacher_nothrow()
     231             : {
     232             :     try
     233             :     {
     234        1098 :         m_xEventAttacher.set( ::comphelper::createEventAttacherManager( m_xContext ), UNO_SET_THROW );
     235             :     }
     236           0 :     catch( const Exception& )
     237             :     {
     238             :         DBG_UNHANDLED_EXCEPTION();
     239             :     }
     240        1098 : }
     241             : 
     242             : 
     243        1090 : OInterfaceContainer::~OInterfaceContainer()
     244             : {
     245        1090 : }
     246             : 
     247             : 
     248        1092 : void OInterfaceContainer::disposing()
     249             : {
     250             :     // dispose all elements
     251        1626 :     for (sal_Int32 i = m_aItems.size(); i > 0; --i)
     252             :     {
     253         534 :         Reference<XPropertySet>  xSet(m_aItems[i - 1], UNO_QUERY);
     254         534 :         if (xSet.is())
     255         534 :             xSet->removePropertyChangeListener(PROPERTY_NAME, this);
     256             : 
     257             :         // revoke event knittings
     258         534 :         if ( m_xEventAttacher.is() )
     259             :         {
     260         534 :             m_xEventAttacher->detach( i - 1, Reference<XInterface>(xSet, UNO_QUERY) );
     261         534 :             m_xEventAttacher->removeEntry( i - 1 );
     262             :         }
     263             : 
     264        1068 :         Reference<XComponent>  xComponent(xSet, UNO_QUERY);
     265         534 :         if (xComponent.is())
     266         534 :             xComponent->dispose();
     267         534 :     }
     268        1092 :     m_aMap.clear();
     269        1092 :     m_aItems.clear();
     270             : 
     271        1092 :     css::lang::EventObject aEvt(static_cast<XContainer*>(this));
     272        1092 :     m_aContainerListeners.disposeAndClear(aEvt);
     273        1092 : }
     274             : 
     275             : // XPersistObject
     276             : 
     277             : namespace
     278             : {
     279             : 
     280           2 :     void lcl_saveEvents( ::std::vector< Sequence< ScriptEventDescriptor > >& _rSave,
     281             :         const Reference< XEventAttacherManager >& _rxManager, const sal_Int32 _nItemCount )
     282             :     {
     283             :         OSL_ENSURE( _rxManager.is(), "lcl_saveEvents: invalid event attacher manager!" );
     284           2 :         if ( !_rxManager.is() )
     285           2 :             return;
     286             : 
     287             :         // reserve the space needed
     288           2 :         _rSave.reserve( _nItemCount );
     289             : 
     290             :         // copy the events
     291           6 :         for (sal_Int32 i=0; i<_nItemCount; ++i)
     292           4 :             _rSave.push_back(_rxManager->getScriptEvents( i ));
     293             :     }
     294             : 
     295             : 
     296           2 :     void lcl_restoreEvents( const ::std::vector< Sequence< ScriptEventDescriptor > >& _rSave,
     297             :         const Reference< XEventAttacherManager >& _rxManager )
     298             :     {
     299             :         OSL_ENSURE( _rxManager.is(), "lcl_restoreEvents: invalid event attacher manager!" );
     300           2 :         if ( !_rxManager.is() )
     301           2 :             return;
     302             : 
     303           2 :         ::std::vector< Sequence< ScriptEventDescriptor > >::const_iterator aLoop = _rSave.begin();
     304           2 :         ::std::vector< Sequence< ScriptEventDescriptor > >::const_iterator aEnd = _rSave.end();
     305           6 :         for ( sal_Int32 i=0; aLoop != aEnd; ++aLoop, ++i )
     306             :         {
     307           4 :             _rxManager->revokeScriptEvents( i );
     308           4 :             _rxManager->registerScriptEvents( i, *aLoop );
     309             :         }
     310             :     }
     311             : }
     312             : 
     313             : 
     314           2 : void SAL_CALL OInterfaceContainer::writeEvents(const Reference<XObjectOutputStream>& _rxOutStream)
     315             : {
     316             :     // We're writing a document in SO 5.2 format (or even from earlier versions)
     317             :     // -> convert the events from the new runtime format to the format of the 5.2 files
     318             :     // but before, remember the current script events set for our children
     319           2 :     ::std::vector< Sequence< ScriptEventDescriptor > > aSave;
     320           2 :     if ( m_xEventAttacher.is() )
     321           2 :         lcl_saveEvents( aSave, m_xEventAttacher, m_aItems.size() );
     322             : 
     323           2 :     transformEvents( efVersionSO5x );
     324             : 
     325             :     try
     326             :     {
     327           2 :         Reference<XMarkableStream>  xMark(_rxOutStream, UNO_QUERY);
     328           2 :         sal_Int32 nMark = xMark->createMark();
     329             : 
     330           2 :         sal_Int32 nObjLen = 0;
     331           2 :         _rxOutStream->writeLong(nObjLen);
     332             : 
     333           4 :         Reference<XPersistObject>  xScripts(m_xEventAttacher, UNO_QUERY);
     334           2 :         if (xScripts.is())
     335           2 :             xScripts->write(_rxOutStream);
     336             : 
     337             :         // Determine length
     338           2 :         nObjLen = xMark->offsetToMark(nMark) - 4;
     339           2 :         xMark->jumpToMark(nMark);
     340           2 :         _rxOutStream->writeLong(nObjLen);
     341           2 :         xMark->jumpToFurthest();
     342           4 :         xMark->deleteMark(nMark);
     343             :     }
     344           0 :     catch( const Exception& )
     345             :     {
     346             :         // restore the events
     347           0 :         if ( m_xEventAttacher.is() )
     348           0 :             lcl_restoreEvents( aSave, m_xEventAttacher );
     349           0 :         throw;
     350             :     }
     351             : 
     352             :     // restore the events
     353           2 :     if ( m_xEventAttacher.is() )
     354           2 :         lcl_restoreEvents( aSave, m_xEventAttacher );
     355           2 : }
     356             : 
     357             : 
     358             : struct TransformEventTo52Format : public ::std::unary_function< ScriptEventDescriptor, void >
     359             : {
     360           0 :     void operator()( ScriptEventDescriptor& _rDescriptor )
     361             :     {
     362           0 :         if ( _rDescriptor.ScriptType.equalsAscii( "StarBasic" ) )
     363             :         {   // it's a starbasic macro
     364           0 :             sal_Int32 nPrefixLength = _rDescriptor.ScriptCode.indexOf( ':' );
     365           0 :             if ( 0 <= nPrefixLength )
     366             :             {   // the macro name does not already contain a :
     367             : #ifdef DBG_UTIL
     368             :                 const OUString sPrefix = _rDescriptor.ScriptCode.copy( 0, nPrefixLength );
     369             :                 DBG_ASSERT( sPrefix.equalsAscii( "document" )
     370             :                         ||  sPrefix.equalsAscii( "application" ),
     371             :                         "TransformEventTo52Format: invalid (unknown) prefix!" );
     372             : #endif
     373             :                 // cut the prefix
     374           0 :                 _rDescriptor.ScriptCode = _rDescriptor.ScriptCode.copy( nPrefixLength + 1 );
     375             :             }
     376             :         }
     377           0 :     }
     378             : };
     379             : 
     380             : 
     381             : struct TransformEventTo60Format : public ::std::unary_function< ScriptEventDescriptor, void >
     382             : {
     383           0 :     void operator()( ScriptEventDescriptor& _rDescriptor )
     384             :     {
     385           0 :         if ( _rDescriptor.ScriptType.equalsAscii( "StarBasic" ) )
     386             :         {   // it's a starbasic macro
     387           0 :             if ( _rDescriptor.ScriptCode.indexOf( ':' ) < 0 )
     388             :             {   // the macro name does not already contain a :
     389             :                 // -> default the type to "document"
     390           0 :                 _rDescriptor.ScriptCode = "document:" + _rDescriptor.ScriptCode;
     391             :             }
     392             :         }
     393           0 :     }
     394             : };
     395             : 
     396             : 
     397           2 : void OInterfaceContainer::transformEvents( const EventFormat _eTargetFormat )
     398             : {
     399             :     OSL_ENSURE( m_xEventAttacher.is(), "OInterfaceContainer::transformEvents: no event attacher manager!" );
     400           2 :     if ( !m_xEventAttacher.is() )
     401           2 :         return;
     402             : 
     403             :     try
     404             :     {
     405             :         // loop through all our children
     406           2 :         sal_Int32 nItems = m_aItems.size();
     407           2 :         Sequence< ScriptEventDescriptor > aChildEvents;
     408             : 
     409           6 :         for (sal_Int32 i=0; i<nItems; ++i)
     410             :         {
     411             :             // get the script events for this object
     412           4 :             aChildEvents = m_xEventAttacher->getScriptEvents( i );
     413             : 
     414           4 :             if ( aChildEvents.getLength() )
     415             :             {
     416             :                 // the "iterators" for the events for this child
     417           0 :                 ScriptEventDescriptor* pChildEvents     =                       aChildEvents.getArray();
     418           0 :                 ScriptEventDescriptor* pChildEventsEnd  =   pChildEvents    +   aChildEvents.getLength();
     419             : 
     420             :                 // do the transformation
     421           0 :                 if ( efVersionSO6x == _eTargetFormat )
     422           0 :                     ::std::for_each( pChildEvents, pChildEventsEnd, TransformEventTo60Format() );
     423             :                 else
     424           0 :                     ::std::for_each( pChildEvents, pChildEventsEnd, TransformEventTo52Format() );
     425             : 
     426             :                 // revoke the script events
     427           0 :                 m_xEventAttacher->revokeScriptEvents( i );
     428             :                 // and re-register them
     429           0 :                 m_xEventAttacher->registerScriptEvents( i, aChildEvents );
     430             :             }
     431           2 :         }
     432             :     }
     433           0 :     catch( const Exception& )
     434             :     {
     435             :         DBG_UNHANDLED_EXCEPTION();
     436             :     }
     437             : }
     438             : 
     439             : 
     440           0 : void SAL_CALL OInterfaceContainer::readEvents(const Reference<XObjectInputStream>& _rxInStream)
     441             : {
     442           0 :     ::osl::MutexGuard aGuard( m_rMutex );
     443             : 
     444             :     // Read scripting info
     445           0 :     Reference<XMarkableStream>  xMark(_rxInStream, UNO_QUERY);
     446           0 :     sal_Int32 nObjLen = _rxInStream->readLong();
     447           0 :     if (nObjLen)
     448             :     {
     449           0 :         sal_Int32 nMark = xMark->createMark();
     450           0 :         Reference<XPersistObject>  xObj(m_xEventAttacher, UNO_QUERY);
     451           0 :         if (xObj.is())
     452           0 :             xObj->read(_rxInStream);
     453           0 :         xMark->jumpToMark(nMark);
     454           0 :         _rxInStream->skipBytes(nObjLen);
     455           0 :         xMark->deleteMark(nMark);
     456             :     }
     457             : 
     458             :     // Read Attachement
     459           0 :     if ( m_xEventAttacher.is() )
     460             :     {
     461           0 :         OInterfaceArray::const_iterator aAttach = m_aItems.begin();
     462           0 :         OInterfaceArray::const_iterator aAttachEnd = m_aItems.end();
     463           0 :         for ( sal_Int32 i=0; aAttach != aAttachEnd; ++aAttach, ++i )
     464             :         {
     465           0 :             Reference< XInterface > xAsIFace( *aAttach, UNO_QUERY );    // important to normalize this ....
     466           0 :             Reference< XPropertySet > xAsSet( xAsIFace, UNO_QUERY );
     467           0 :             m_xEventAttacher->attach( i, xAsIFace, makeAny( xAsSet ) );
     468           0 :         }
     469           0 :     }
     470           0 : }
     471             : 
     472             : 
     473           0 : void SAL_CALL OInterfaceContainer::write( const Reference< XObjectOutputStream >& _rxOutStream ) throw(IOException, RuntimeException, std::exception)
     474             : {
     475           0 :     ::osl::MutexGuard aGuard( m_rMutex );
     476           0 :     sal_Int32 nLen = m_aItems.size();
     477             : 
     478             :     // Write length
     479           0 :     _rxOutStream->writeLong(nLen);
     480             : 
     481           0 :     if (nLen)
     482             :     {
     483             :         // 1. Version
     484           0 :         _rxOutStream->writeShort(0x0001);
     485             : 
     486             :         // 2. Objects
     487           0 :         for (sal_Int32 i = 0; i < nLen; i++)
     488             :         {
     489           0 :             Reference<XPersistObject>  xObj(m_aItems[i], UNO_QUERY);
     490           0 :             if (xObj.is())
     491           0 :                 _rxOutStream->writeObject(xObj);
     492             :             else
     493             :             {
     494             :                 // Error
     495             :             }
     496           0 :         }
     497             : 
     498             :         // 3. Scripts
     499           0 :         writeEvents(_rxOutStream);
     500           0 :     }
     501           0 : }
     502             : 
     503             : 
     504             : namespace
     505             : {
     506           0 :     Reference< XPersistObject > lcl_createPlaceHolder( const Reference< XComponentContext >& _rxORB )
     507             :     {
     508           0 :         Reference< XPersistObject > xObject( _rxORB->getServiceManager()->createInstanceWithContext(FRM_COMPONENT_HIDDENCONTROL, _rxORB), UNO_QUERY );
     509             :         DBG_ASSERT( xObject.is(), "lcl_createPlaceHolder: could not create a substitute for the unknown object!" );
     510           0 :         if ( xObject.is() )
     511             :         {
     512             :             // set some properties describing what we did
     513           0 :             Reference< XPropertySet > xObjProps( xObject, UNO_QUERY );
     514           0 :             if ( xObject.is()  )
     515             :             {
     516             :                 try
     517             :                 {
     518           0 :                     xObjProps->setPropertyValue( PROPERTY_NAME, makeAny( FRM_RES_STRING( RID_STR_CONTROL_SUBSTITUTED_NAME ) ) );
     519           0 :                     xObjProps->setPropertyValue( PROPERTY_TAG, makeAny( FRM_RES_STRING( RID_STR_CONTROL_SUBSTITUTED_EPXPLAIN ) ) );
     520             :                 }
     521           0 :                 catch(const Exception&)
     522             :                 {
     523             :                 }
     524           0 :             }
     525             :         }
     526           0 :         return xObject;
     527             :     }
     528             : }
     529             : 
     530             : 
     531           0 : void SAL_CALL OInterfaceContainer::read( const Reference< XObjectInputStream >& _rxInStream ) throw(IOException, RuntimeException, std::exception)
     532             : {
     533           0 :     ::osl::MutexGuard aGuard( m_rMutex );
     534             : 
     535             :     // after ::read the object is expected to be in the state it was when ::write was called, so we have
     536             :     // to empty ourself here
     537           0 :     while (getCount())
     538           0 :         removeByIndex(0);
     539             : 
     540             :     // Only writes depending on the length
     541           0 :     sal_Int32 nLen = _rxInStream->readLong();
     542             : 
     543           0 :     if (nLen)
     544             :     {
     545             :         // 1. Version
     546           0 :         sal_uInt16 nVersion = _rxInStream->readShort(); (void)nVersion;
     547             : 
     548             :         // 2. Objects
     549           0 :         for (sal_Int32 i = 0; i < nLen; i++)
     550             :         {
     551           0 :             Reference<XPersistObject>  xObj;
     552             :             try
     553             :             {
     554           0 :                 xObj = _rxInStream->readObject();
     555             :             }
     556           0 :             catch(const WrongFormatException&)
     557             :             {
     558             :                 // the object could not be read
     559             :                 // create a object (so the readEvents below will assign the events to the right controls)
     560           0 :                 xObj = lcl_createPlaceHolder( m_xContext );
     561           0 :                 if ( !xObj.is() )
     562             :                     // couldn't handle it
     563           0 :                     throw;
     564             :             }
     565           0 :             catch(const Exception&)
     566             :             {
     567             :                 // Clear the map
     568           0 :                 while (!m_aItems.empty())
     569           0 :                     removeElementsNoEvents(0);
     570             : 
     571             :                 // Rethrow the exception
     572           0 :                 throw;
     573             :             }
     574             : 
     575           0 :             if ( xObj.is() )
     576             :             {
     577           0 :                 Reference< XPropertySet > xElement( xObj, UNO_QUERY );
     578             :                 try
     579             :                 {
     580             :                     implInsert(
     581           0 :                         m_aItems.size(),    // position
     582             :                         xElement,           // element to insert
     583             :                         false,              // no event attacher manager handling
     584             :                         NULL,               // not yet approved - let implInsert do it
     585             :                         true                // fire the event
     586           0 :                     );
     587             :                 }
     588           0 :                 catch( const Exception& )
     589             :                 {
     590             :                     SAL_WARN("forms.misc", "OInterfaceContainerHelper::read: reading succeeded, but not inserting!" );
     591             :                     // create a placeholder
     592           0 :                     xElement.set(lcl_createPlaceHolder( m_xContext ), css::uno::UNO_QUERY);
     593           0 :                     if ( !xElement.is() )
     594             :                         // couldn't handle it
     595           0 :                         throw;
     596             :                     // insert the placeholder
     597           0 :                     implInsert( m_aItems.size(), xElement, false, NULL, true );
     598           0 :                 }
     599             :             }
     600           0 :         }
     601             : 
     602           0 :         readEvents(_rxInStream);
     603             :     }
     604             :     else
     605             :     {
     606             :         try
     607             :         {
     608           0 :             m_xEventAttacher = ::comphelper::createEventAttacherManager( m_xContext );
     609             :             OSL_ENSURE( m_xEventAttacher.is(), "OInterfaceContainer::read: could not create an event attacher manager!" );
     610             :         }
     611           0 :         catch( const Exception& )
     612             :         {
     613             :             DBG_UNHANDLED_EXCEPTION();
     614             :         }
     615           0 :     }
     616           0 : }
     617             : 
     618             : // XContainer
     619             : 
     620        1889 : void SAL_CALL OInterfaceContainer::addContainerListener(const Reference<XContainerListener>& _rxListener) throw( RuntimeException, std::exception )
     621             : {
     622        1889 :     m_aContainerListeners.addInterface(_rxListener);
     623        1889 : }
     624             : 
     625             : 
     626        1559 : void SAL_CALL OInterfaceContainer::removeContainerListener(const Reference<XContainerListener>& _rxListener) throw( RuntimeException, std::exception )
     627             : {
     628        1559 :     m_aContainerListeners.removeInterface(_rxListener);
     629        1559 : }
     630             : 
     631             : // XEventListener
     632             : 
     633         102 : void SAL_CALL OInterfaceContainer::disposing(const css::lang::EventObject& _rSource) throw( RuntimeException, std::exception )
     634             : {
     635         102 :     ::osl::MutexGuard aGuard( m_rMutex );
     636             : 
     637         204 :     Reference< XInterface > xSource( _rSource.Source, UNO_QUERY );
     638             :         // normalized source
     639             : 
     640         102 :     OInterfaceArray::iterator j;
     641         586 :     for ( j = m_aItems.begin(); j != m_aItems.end(); ++j )
     642             :     {
     643             :         DBG_ASSERT( j->get() == Reference< XInterface >( *j, UNO_QUERY ).get(),
     644             :             "OInterfaceContainer::disposing: vector element not normalized!" );
     645             : 
     646         554 :         if ( xSource.get() == j->get() )
     647             :             // found the element
     648          70 :             break;
     649             :     }
     650             : 
     651         102 :     if ( m_aItems.end() != j )
     652             :     {
     653          70 :         m_aItems.erase(j);
     654             : 
     655             :         // look up in, and erase from, m_aMap, too
     656          70 :         OInterfaceMap::iterator i = m_aMap.begin();
     657         556 :         while ( i != m_aMap.end() )
     658             :         {
     659             :             DBG_ASSERT( i->second.get() == Reference< XInterface >( i->second, UNO_QUERY ).get(),
     660             :                 "OInterfaceContainer::disposing: map element not normalized!" );
     661             : 
     662         486 :             if ( i->second.get() == xSource.get() )
     663             :             {
     664             :                 // found it
     665          70 :                 m_aMap.erase(i);
     666          70 :                 break;
     667             :             }
     668             : 
     669         416 :             ++i;
     670             : 
     671             :             DBG_ASSERT( i != m_aMap.end(), "OInterfaceContainer::disposing: inconsistency: the element was in m_aItems, but not in m_aMap!" );
     672             :         }
     673         102 :     }
     674         102 : }
     675             : 
     676             : // XPropertyChangeListener
     677             : 
     678         463 : void OInterfaceContainer::propertyChange(const PropertyChangeEvent& evt)
     679             : throw (::com::sun::star::uno::RuntimeException, std::exception) {
     680         463 :     if (evt.PropertyName == PROPERTY_NAME)
     681             :     {
     682         463 :         ::osl::MutexGuard aGuard( m_rMutex );
     683             :         OInterfaceMap::iterator i = ::std::find(m_aMap.begin(), m_aMap.end(),
     684         463 :             ::std::pair<const OUString, InterfaceRef >(::comphelper::getString(evt.OldValue),evt.Source));
     685         463 :         if (i != m_aMap.end())
     686             :         {
     687         463 :             InterfaceRef  xCorrectType((*i).second);
     688         463 :             m_aMap.erase(i);
     689         463 :             m_aMap.insert(::std::pair<const OUString, InterfaceRef >(::comphelper::getString(evt.NewValue),xCorrectType));
     690         463 :         }
     691             :     }
     692         463 : }
     693             : 
     694             : // XElementAccess
     695             : 
     696         840 : sal_Bool SAL_CALL OInterfaceContainer::hasElements() throw( RuntimeException, std::exception )
     697             : {
     698         840 :     return !m_aMap.empty();
     699             : }
     700             : 
     701             : 
     702           2 : Type SAL_CALL OInterfaceContainer::getElementType() throw(RuntimeException, std::exception)
     703             : {
     704           2 :     return m_aElementType;
     705             : }
     706             : 
     707             : // XEnumerationAccess
     708             : 
     709           2 : Reference<XEnumeration> SAL_CALL OInterfaceContainer::createEnumeration() throw( RuntimeException, std::exception )
     710             : {
     711           2 :     ::osl::MutexGuard aGuard( m_rMutex );
     712           2 :     return new ::comphelper::OEnumerationByIndex(static_cast<XIndexAccess*>(this));
     713             : }
     714             : 
     715             : // XNameAccess
     716             : 
     717          20 : Any SAL_CALL OInterfaceContainer::getByName( const OUString& _rName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException, std::exception)
     718             : {
     719             :     ::std::pair <OInterfaceMap::iterator,
     720          20 :           OInterfaceMap::iterator> aPair = m_aMap.equal_range(_rName);
     721             : 
     722          20 :     if (aPair.first == aPair.second)
     723           2 :         throw NoSuchElementException();
     724             : 
     725          18 :     return (*aPair.first).second->queryInterface( m_aElementType );
     726             : }
     727             : 
     728             : 
     729          22 : StringSequence SAL_CALL OInterfaceContainer::getElementNames() throw(RuntimeException, std::exception)
     730             : {
     731          22 :     StringSequence aNameList(m_aItems.size());
     732          22 :     OUString* pStringArray = aNameList.getArray();
     733             : 
     734          66 :     for (OInterfaceMap::const_iterator i = m_aMap.begin(); i != m_aMap.end(); ++i, ++pStringArray)
     735             :     {
     736          44 :         *pStringArray = (*i).first;
     737             :     }
     738          22 :     return aNameList;
     739             : }
     740             : 
     741             : 
     742         576 : sal_Bool SAL_CALL OInterfaceContainer::hasByName( const OUString& _rName ) throw(RuntimeException, std::exception)
     743             : {
     744             :     ::std::pair <OInterfaceMap::iterator,
     745         576 :           OInterfaceMap::iterator> aPair = m_aMap.equal_range(_rName);
     746         576 :     return aPair.first != aPair.second;
     747             : }
     748             : 
     749             : // XIndexAccess
     750             : 
     751        7805 : sal_Int32 OInterfaceContainer::getCount() throw( RuntimeException, std::exception )
     752             : {
     753        7805 :     return m_aItems.size();
     754             : }
     755             : 
     756             : 
     757        5765 : Any OInterfaceContainer::getByIndex(sal_Int32 _nIndex) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
     758             : {
     759        5765 :     if (_nIndex < 0 || (_nIndex >= (sal_Int32)m_aItems.size()))
     760          50 :         throw IndexOutOfBoundsException();
     761             : 
     762        5715 :     return m_aItems[_nIndex]->queryInterface( m_aElementType );
     763             : }
     764             : 
     765             : 
     766        1050 : void OInterfaceContainer::approveNewElement( const Reference< XPropertySet >& _rxObject, ElementDescription* _pElement )
     767             : {
     768             :     // it has to be non-NULL
     769        1050 :     if ( !_rxObject.is() )
     770           0 :         throw IllegalArgumentException(FRM_RES_STRING(RID_STR_NEED_NON_NULL_OBJECT), static_cast<XContainer*>(this), 1);
     771             : 
     772             :     // it has to support our element type interface
     773        1050 :     Any aCorrectType = _rxObject->queryInterface( m_aElementType );
     774        1050 :     if ( !aCorrectType.hasValue() )
     775           0 :         lcl_throwIllegalArgumentException();
     776             : 
     777             :     // it has to have a "Name" property
     778        1050 :     if ( !hasProperty( PROPERTY_NAME, _rxObject ) )
     779           0 :         lcl_throwIllegalArgumentException();
     780             : 
     781             :     // it has to be a child, and it must not have a parent already
     782        2100 :     Reference< XChild > xChild( _rxObject, UNO_QUERY );
     783        1050 :     if ( !xChild.is() || xChild->getParent().is() )
     784             :     {
     785           0 :         lcl_throwIllegalArgumentException();
     786             :     }
     787             : 
     788             :     // passed all tests. cache the information we have so far
     789             :     DBG_ASSERT( _pElement, "OInterfaceContainer::approveNewElement: invalid event descriptor!" );
     790        1050 :     if ( _pElement )
     791             :     {
     792        1050 :         _pElement->xPropertySet = _rxObject;
     793        1050 :         _pElement->xChild = xChild;
     794        1050 :         _pElement->aElementTypeInterface = aCorrectType;
     795        1050 :         _pElement->xInterface = Reference< XInterface >( _rxObject, UNO_QUERY );    // normalized XInterface
     796        1050 :     }
     797        1050 : }
     798             : 
     799             : 
     800        1040 : void OInterfaceContainer::implInsert(sal_Int32 _nIndex, const Reference< XPropertySet >& _rxElement,
     801             :     bool _bEvents, ElementDescription* _pApprovalResult, bool _bFire ) throw( IllegalArgumentException )
     802             : {
     803        1040 :     const bool bHandleEvents = _bEvents && m_xEventAttacher.is();
     804             : 
     805             :     // SYNCHRONIZED ----->
     806        1040 :     ::osl::ClearableMutexGuard aGuard( m_rMutex );
     807             : 
     808        2080 :     boost::scoped_ptr< ElementDescription > aAutoDeleteMetaData;
     809        1040 :     ElementDescription* pElementMetaData = _pApprovalResult;
     810        1040 :     if ( !pElementMetaData )
     811             :     {   // not yet approved by the caller -> do ourself
     812         574 :         pElementMetaData = createElementMetaData();
     813             :         DBG_ASSERT( pElementMetaData, "OInterfaceContainer::implInsert: createElementMetaData returned nonsense!" );
     814             : 
     815             :         // ensure that the meta data structure will be deleted later on
     816         574 :         aAutoDeleteMetaData.reset( pElementMetaData );
     817             : 
     818             :         // will throw an exception if necessary
     819         574 :         approveNewElement( _rxElement, pElementMetaData );
     820             :     }
     821             : 
     822             : 
     823             :     // approveNewElement (no matter if called here or outside) has ensure that all relevant interfaces
     824             :     // exist
     825             : 
     826             :     // set the name, and add as change listener for the name
     827        2076 :     OUString sName;
     828        1038 :     _rxElement->getPropertyValue(PROPERTY_NAME) >>= sName;
     829        1038 :     _rxElement->addPropertyChangeListener(PROPERTY_NAME, this);
     830             : 
     831             :     // insert the object into our internal structures
     832        1038 :     if (_nIndex > (sal_Int32)m_aItems.size()) // Calculate the actual index
     833             :     {
     834           0 :         _nIndex = m_aItems.size();
     835           0 :         m_aItems.push_back( pElementMetaData->xInterface );
     836             :     }
     837             :     else
     838        1038 :         m_aItems.insert( m_aItems.begin() + _nIndex, pElementMetaData->xInterface );
     839             : 
     840        1038 :     m_aMap.insert( ::std::pair< const OUString, InterfaceRef >( sName, pElementMetaData->xInterface ) );
     841             : 
     842             :     // announce ourself as parent to the new element
     843        1038 :     pElementMetaData->xChild->setParent(static_cast<XContainer*>(this));
     844             : 
     845             :     // handle the events
     846        1038 :     if ( bHandleEvents )
     847             :     {
     848        1034 :         m_xEventAttacher->insertEntry(_nIndex);
     849        1034 :         m_xEventAttacher->attach( _nIndex, pElementMetaData->xInterface, makeAny( _rxElement ) );
     850             :     }
     851             : 
     852             :     // notify derived classes
     853        1038 :     implInserted( pElementMetaData );
     854             : 
     855        1038 :     aGuard.clear();
     856             :     // <----- SYNCHRONIZED
     857             : 
     858             :     // insert faked VBA events?
     859        1038 :     bool bHandleVbaEvents = false;
     860             :     try
     861             :     {
     862        1390 :         _rxElement->getPropertyValue("GenerateVbaEvents") >>= bHandleVbaEvents;
     863             :     }
     864         352 :     catch( const Exception& )
     865             :     {
     866             :     }
     867        1038 :     if ( bHandleVbaEvents )
     868             :     {
     869           0 :         Reference< XEventAttacherManager > xMgr ( pElementMetaData->xInterface, UNO_QUERY );
     870           0 :         OInterfaceContainer* pIfcMgr = xMgr.is() ? dynamic_cast<OInterfaceContainer*>(xMgr.get()) : NULL;
     871           0 :         if (pIfcMgr)
     872             :         {
     873           0 :             sal_Int32 nLen = pIfcMgr->getCount();
     874           0 :             for (sal_Int32 i = 0; i < nLen; ++i)
     875             :             {
     876             :                 // add fake events to the control at index i
     877           0 :                 pIfcMgr->impl_addVbEvents_nolck_nothrow( i );
     878             :             }
     879             :         }
     880             :         else
     881             :         {
     882             :             // add fake events to the control at index i
     883           0 :             impl_addVbEvents_nolck_nothrow( _nIndex );
     884           0 :         }
     885             :     }
     886             : 
     887             :     // fire the notification about the change
     888        1038 :     if ( _bFire )
     889             :     {
     890             :         // notify listeners
     891        1034 :         ContainerEvent aEvt;
     892        1034 :         aEvt.Source   = static_cast<XContainer*>(this);
     893        1034 :         aEvt.Accessor <<= _nIndex;
     894        1034 :         aEvt.Element  = pElementMetaData->aElementTypeInterface;
     895             : 
     896        1034 :         aGuard.clear();
     897        1034 :         m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvt );
     898        1040 :     }
     899        1038 : }
     900             : 
     901             : 
     902           0 : void OInterfaceContainer::removeElementsNoEvents(sal_Int32 nIndex)
     903             : {
     904           0 :     OInterfaceArray::iterator i = m_aItems.begin() + nIndex;
     905           0 :     InterfaceRef  xElement(*i);
     906             : 
     907           0 :     OInterfaceMap::iterator j = m_aMap.begin();
     908           0 :     while (j != m_aMap.end() && (*j).second != xElement) ++j;
     909             : 
     910           0 :     m_aItems.erase(i);
     911           0 :     m_aMap.erase(j);
     912             : 
     913           0 :     Reference<XPropertySet>  xSet(xElement, UNO_QUERY);
     914           0 :     if (xSet.is())
     915           0 :         xSet->removePropertyChangeListener(PROPERTY_NAME, this);
     916             : 
     917           0 :     Reference<XChild>  xChild(xElement, UNO_QUERY);
     918           0 :     if (xChild.is())
     919           0 :         xChild->setParent(InterfaceRef ());
     920           0 : }
     921             : 
     922             : 
     923        1038 : void OInterfaceContainer::implInserted( const ElementDescription* /*_pElement*/ )
     924             : {
     925             :     // not inrerested in
     926        1038 : }
     927             : 
     928             : 
     929         460 : void OInterfaceContainer::implRemoved( const InterfaceRef& /*_rxObject*/ )
     930             : {
     931             :     // not inrerested in
     932         460 : }
     933             : 
     934             : 
     935          12 : void OInterfaceContainer::impl_replacedElement( const ContainerEvent& _rEvent, ::osl::ClearableMutexGuard& _rInstanceLock )
     936             : {
     937          12 :     _rInstanceLock.clear();
     938          12 :     m_aContainerListeners.notifyEach( &XContainerListener::elementReplaced, _rEvent );
     939          12 : }
     940             : 
     941             : // XIndexContainer
     942             : 
     943         570 : void SAL_CALL OInterfaceContainer::insertByIndex( sal_Int32 _nIndex, const Any& _rElement ) throw(IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception)
     944             : {
     945         570 :     Reference< XPropertySet > xElement;
     946         570 :     _rElement >>= xElement;
     947         572 :     implInsert( _nIndex, xElement, true /* event handling */ , NULL /* not yet approved */ , true /* notification */ );
     948         568 : }
     949             : 
     950             : 
     951          14 : void OInterfaceContainer::implReplaceByIndex( const sal_Int32 _nIndex, const Any& _rNewElement, ::osl::ClearableMutexGuard& _rClearBeforeNotify )
     952             : {
     953             :     OSL_PRECOND( ( _nIndex >= 0 ) && ( _nIndex < (sal_Int32)m_aItems.size() ), "OInterfaceContainer::implReplaceByIndex: precondition not met (index)!" );
     954             : 
     955             :     // approve the new object
     956          14 :     boost::scoped_ptr< ElementDescription > aElementMetaData( createElementMetaData() );
     957             :     DBG_ASSERT( aElementMetaData.get(), "OInterfaceContainer::implReplaceByIndex: createElementMetaData returned nonsense!" );
     958             :     {
     959          14 :         Reference< XPropertySet > xElementProps;
     960          14 :         _rNewElement >>= xElementProps;
     961          16 :         approveNewElement( xElementProps, aElementMetaData.get() );
     962             :     }
     963             : 
     964             :     // get the old element
     965          24 :     InterfaceRef  xOldElement( m_aItems[ _nIndex ] );
     966             :     DBG_ASSERT( xOldElement.get() == Reference< XInterface >( xOldElement, UNO_QUERY ).get(),
     967             :         "OInterfaceContainer::implReplaceByIndex: elements should be held normalized!" );
     968             : 
     969             :     // locate the old element in the map
     970          12 :     OInterfaceMap::iterator j = m_aMap.begin();
     971          26 :     while ( ( j != m_aMap.end() ) && ( j->second.get() != xOldElement.get() ) )
     972           2 :         ++j;
     973             : 
     974             :     // remove event knittings
     975          12 :     if ( m_xEventAttacher.is() )
     976             :     {
     977          12 :         InterfaceRef xNormalized( xOldElement, UNO_QUERY );
     978          12 :         m_xEventAttacher->detach( _nIndex, xNormalized );
     979          12 :         m_xEventAttacher->removeEntry( _nIndex );
     980             :     }
     981             : 
     982             :     // don't listen for property changes anymore
     983          24 :     Reference<XPropertySet>  xSet( xOldElement, UNO_QUERY );
     984          12 :     if (xSet.is())
     985          12 :         xSet->removePropertyChangeListener(PROPERTY_NAME, this);
     986             : 
     987             :     // give the old element a new (void) parent
     988          24 :     Reference<XChild>  xChild(xOldElement, UNO_QUERY);
     989          12 :     if (xChild.is())
     990          12 :         xChild->setParent(InterfaceRef ());
     991             : 
     992             :     // remove the old one
     993          12 :     m_aMap.erase(j);
     994             : 
     995             :     // examine the new element
     996          24 :     OUString sName;
     997             :     DBG_ASSERT( aElementMetaData.get()->xPropertySet.is(), "OInterfaceContainer::implReplaceByIndex: what did approveNewElement do?" );
     998             : 
     999          12 :     aElementMetaData.get()->xPropertySet->getPropertyValue(PROPERTY_NAME) >>= sName;
    1000          12 :     aElementMetaData.get()->xPropertySet->addPropertyChangeListener(PROPERTY_NAME, this);
    1001             : 
    1002             :     // insert the new one
    1003          12 :     m_aMap.insert( ::std::pair<const OUString, InterfaceRef  >( sName, aElementMetaData.get()->xInterface ) );
    1004          12 :     m_aItems[ _nIndex ] = aElementMetaData.get()->xInterface;
    1005             : 
    1006          12 :     aElementMetaData.get()->xChild->setParent(static_cast<XContainer*>(this));
    1007             : 
    1008          12 :     if ( m_xEventAttacher.is() )
    1009             :     {
    1010          12 :         m_xEventAttacher->insertEntry( _nIndex );
    1011          12 :         m_xEventAttacher->attach( _nIndex, aElementMetaData.get()->xInterface, makeAny( aElementMetaData.get()->xPropertySet ) );
    1012             :     }
    1013             : 
    1014          24 :     ContainerEvent aReplaceEvent;
    1015          12 :     aReplaceEvent.Source   = static_cast< XContainer* >( this );
    1016          12 :     aReplaceEvent.Accessor <<= _nIndex;
    1017          12 :     aReplaceEvent.Element  = aElementMetaData.get()->xInterface->queryInterface( m_aElementType );
    1018          12 :     aReplaceEvent.ReplacedElement = xOldElement->queryInterface( m_aElementType );
    1019             : 
    1020          26 :     impl_replacedElement( aReplaceEvent, _rClearBeforeNotify );
    1021          12 : }
    1022             : 
    1023             : 
    1024         470 : void OInterfaceContainer::implCheckIndex( const sal_Int32 _nIndex )
    1025             : {
    1026         470 :     if (_nIndex < 0 || _nIndex >= (sal_Int32)m_aItems.size())
    1027           4 :         throw IndexOutOfBoundsException();
    1028         466 : }
    1029             : 
    1030             : 
    1031           8 : void SAL_CALL OInterfaceContainer::replaceByIndex(sal_Int32 _nIndex, const Any& Element) throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
    1032             : {
    1033           8 :     ::osl::ClearableMutexGuard aGuard( m_rMutex );
    1034             :     // check the index
    1035           8 :     implCheckIndex( _nIndex );
    1036             :     // do the replace
    1037          10 :     implReplaceByIndex( _nIndex, Element, aGuard );
    1038           4 : }
    1039             : 
    1040             : 
    1041         460 : void OInterfaceContainer::implRemoveByIndex( const sal_Int32 _nIndex, ::osl::ClearableMutexGuard& _rClearBeforeNotify )
    1042             : {
    1043             :     OSL_PRECOND( ( _nIndex >= 0 ) && ( _nIndex < (sal_Int32)m_aItems.size() ), "OInterfaceContainer::implRemoveByIndex: precondition not met (index)!" );
    1044             : 
    1045         460 :     OInterfaceArray::iterator i = m_aItems.begin() + _nIndex;
    1046         460 :     InterfaceRef  xElement(*i);
    1047             : 
    1048         460 :     OInterfaceMap::iterator j = m_aMap.begin();
    1049         460 :     while (j != m_aMap.end() && (*j).second != xElement) ++j;
    1050             : 
    1051         460 :     m_aItems.erase(i);
    1052         460 :     m_aMap.erase(j);
    1053             : 
    1054             :     // remove event knittings
    1055         460 :     if ( m_xEventAttacher.is() )
    1056             :     {
    1057         460 :         InterfaceRef xNormalized( xElement, UNO_QUERY );
    1058         460 :         m_xEventAttacher->detach( _nIndex, xNormalized );
    1059         460 :         m_xEventAttacher->removeEntry( _nIndex );
    1060             :     }
    1061             : 
    1062         920 :     Reference<XPropertySet>  xSet(xElement, UNO_QUERY);
    1063         460 :     if (xSet.is())
    1064         460 :         xSet->removePropertyChangeListener(PROPERTY_NAME, this);
    1065             : 
    1066         920 :     Reference<XChild>  xChild(xElement, UNO_QUERY);
    1067         460 :     if (xChild.is())
    1068         460 :         xChild->setParent(InterfaceRef ());
    1069             : 
    1070             :     // notify derived classes
    1071         460 :     implRemoved(xElement);
    1072             : 
    1073             :     // notify listeners
    1074         920 :     ContainerEvent aEvt;
    1075         460 :     aEvt.Source     = static_cast<XContainer*>(this);
    1076         460 :     aEvt.Element    = xElement->queryInterface( m_aElementType );
    1077         460 :     aEvt.Accessor   <<= _nIndex;
    1078             : 
    1079         460 :     _rClearBeforeNotify.clear();
    1080         920 :     m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvt );
    1081         460 : }
    1082             : 
    1083             : 
    1084         462 : void SAL_CALL OInterfaceContainer::removeByIndex(sal_Int32 _nIndex) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
    1085             : {
    1086         462 :     ::osl::ClearableMutexGuard aGuard( m_rMutex );
    1087             :     // check the index
    1088         462 :     implCheckIndex( _nIndex );
    1089             :     // do the removal
    1090         462 :     implRemoveByIndex( _nIndex, aGuard );
    1091         460 : }
    1092             : 
    1093             : 
    1094         940 : ElementDescription* OInterfaceContainer::createElementMetaData( )
    1095             : {
    1096         940 :     return new ElementDescription;
    1097             : }
    1098             : 
    1099             : 
    1100         468 : void SAL_CALL OInterfaceContainer::insertByName(const OUString& _rName, const Any& _rElement) throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException, std::exception )
    1101             : {
    1102         468 :     Reference< XPropertySet > xElementProps;
    1103             : 
    1104         936 :     boost::scoped_ptr< ElementDescription > aElementMetaData( createElementMetaData() );
    1105             :     DBG_ASSERT( aElementMetaData.get(), "OInterfaceContainer::insertByName: createElementMetaData returned nonsense!" );
    1106             : 
    1107             :     // ensure the correct name of the element
    1108             :     try
    1109             :     {
    1110         468 :         _rElement >>= xElementProps;
    1111         468 :         approveNewElement( xElementProps, aElementMetaData.get() );
    1112             : 
    1113         466 :         xElementProps->setPropertyValue( PROPERTY_NAME, makeAny( _rName ) );
    1114             :     }
    1115           4 :     catch( const IllegalArgumentException& )
    1116             :     {
    1117           2 :         throw;  // allowed to leave
    1118             :     }
    1119           0 :     catch( const ElementExistException& )
    1120             :     {
    1121           0 :         throw;  // allowed to leave
    1122             :     }
    1123           0 :     catch( const Exception& )
    1124             :     {
    1125             :         SAL_WARN("forms.misc", "OInterfaceContainer::insertByName: caught an exception!" );
    1126             :     }
    1127         934 :     implInsert( m_aItems.size(), xElementProps, true, aElementMetaData.get(), true );
    1128         466 : }
    1129             : 
    1130             : 
    1131           8 : void SAL_CALL OInterfaceContainer::replaceByName(const OUString& Name, const Any& Element) throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException, std::exception )
    1132             : {
    1133           8 :     ::osl::ClearableMutexGuard aGuard( m_rMutex );
    1134             :     ::std::pair <OInterfaceMap::iterator,
    1135           8 :           OInterfaceMap::iterator> aPair = m_aMap.equal_range(Name);
    1136           8 :     if (aPair.first == aPair.second)
    1137           0 :         throw NoSuchElementException();
    1138             : 
    1139           8 :     if (Element.getValueType().getTypeClass() != TypeClass_INTERFACE)
    1140           0 :         lcl_throwIllegalArgumentException();
    1141             : 
    1142          16 :     Reference<XPropertySet> xSet;
    1143           8 :     Element >>= xSet;
    1144           8 :     if (xSet.is())
    1145             :     {
    1146           8 :         if (!hasProperty(PROPERTY_NAME, xSet))
    1147           0 :             lcl_throwIllegalArgumentException();
    1148             : 
    1149           8 :         xSet->setPropertyValue(PROPERTY_NAME, makeAny(Name));
    1150             :     }
    1151             : 
    1152             :     // determine the element pos
    1153           8 :     sal_Int32 nPos = ::std::find(m_aItems.begin(), m_aItems.end(), (*aPair.first).second) - m_aItems.begin();
    1154             : 
    1155          16 :     implReplaceByIndex( nPos, Element, aGuard );
    1156           8 : }
    1157             : 
    1158             : 
    1159           8 : void SAL_CALL OInterfaceContainer::removeByName(const OUString& Name) throw( NoSuchElementException, WrappedTargetException, RuntimeException, std::exception )
    1160             : {
    1161           8 :     ::osl::MutexGuard aGuard( m_rMutex );
    1162             :     ::std::pair <OInterfaceMap::iterator,
    1163           8 :           OInterfaceMap::iterator> aPair = m_aMap.equal_range(Name);
    1164           8 :     if (aPair.first == aPair.second)
    1165           2 :         throw NoSuchElementException();
    1166             : 
    1167           6 :     sal_Int32 nPos = ::std::find(m_aItems.begin(), m_aItems.end(), (*aPair.first).second) - m_aItems.begin();
    1168           8 :     removeByIndex(nPos);
    1169           6 : }
    1170             : 
    1171             : 
    1172             : // XEventAttacherManager
    1173             : 
    1174           6 : void SAL_CALL OInterfaceContainer::registerScriptEvent( sal_Int32 nIndex, const ScriptEventDescriptor& aScriptEvent ) throw(IllegalArgumentException, RuntimeException, std::exception)
    1175             : {
    1176           6 :     ::osl::ClearableMutexGuard aGuard( m_rMutex );
    1177           6 :     if ( m_xEventAttacher.is() )
    1178             :     {
    1179           6 :         m_xEventAttacher->registerScriptEvent( nIndex, aScriptEvent );
    1180           6 :         aGuard.clear();
    1181           6 :         impl_addVbEvents_nolck_nothrow( nIndex ); // add fake vba events
    1182           6 :     }
    1183           6 : }
    1184             : 
    1185             : 
    1186         482 : void SAL_CALL OInterfaceContainer::registerScriptEvents( sal_Int32 nIndex, const Sequence< ScriptEventDescriptor >& aScriptEvents ) throw(IllegalArgumentException, RuntimeException, std::exception)
    1187             : {
    1188         482 :     ::osl::ClearableMutexGuard aGuard( m_rMutex );
    1189         482 :     if ( m_xEventAttacher.is() )
    1190             :     {
    1191         482 :         m_xEventAttacher->registerScriptEvents( nIndex, aScriptEvents );
    1192         482 :         aGuard.clear();
    1193         482 :         impl_addVbEvents_nolck_nothrow( nIndex ); // add fake vba events
    1194         482 :     }
    1195         482 : }
    1196             : 
    1197             : 
    1198           2 : void SAL_CALL OInterfaceContainer::revokeScriptEvent( sal_Int32 nIndex, const OUString& aListenerType, const OUString& aEventMethod, const OUString& aRemoveListenerParam ) throw(IllegalArgumentException, RuntimeException, std::exception)
    1199             : {
    1200           2 :     if ( m_xEventAttacher.is() )
    1201           2 :         m_xEventAttacher->revokeScriptEvent( nIndex, aListenerType, aEventMethod, aRemoveListenerParam );
    1202           2 : }
    1203             : 
    1204             : 
    1205           2 : void SAL_CALL OInterfaceContainer::revokeScriptEvents( sal_Int32 nIndex ) throw(IllegalArgumentException, RuntimeException, std::exception)
    1206             : {
    1207           2 :     if ( m_xEventAttacher.is() )
    1208           2 :         m_xEventAttacher->revokeScriptEvents( nIndex );
    1209           2 : }
    1210             : 
    1211             : 
    1212           2 : void SAL_CALL OInterfaceContainer::insertEntry( sal_Int32 nIndex ) throw(IllegalArgumentException, RuntimeException, std::exception)
    1213             : {
    1214           2 :     if ( m_xEventAttacher.is() )
    1215           2 :         m_xEventAttacher->insertEntry( nIndex );
    1216           2 : }
    1217             : 
    1218             : 
    1219           2 : void SAL_CALL OInterfaceContainer::removeEntry( sal_Int32 nIndex ) throw(IllegalArgumentException, RuntimeException, std::exception)
    1220             : {
    1221           2 :     if ( m_xEventAttacher.is() )
    1222           2 :         m_xEventAttacher->removeEntry( nIndex );
    1223           2 : }
    1224             : 
    1225             : 
    1226          26 : Sequence< ScriptEventDescriptor > SAL_CALL OInterfaceContainer::getScriptEvents( sal_Int32 nIndex ) throw(IllegalArgumentException, RuntimeException, std::exception)
    1227             : {
    1228          26 :     Sequence< ScriptEventDescriptor > aReturn;
    1229          26 :     if ( m_xEventAttacher.is() )
    1230             :     {
    1231          26 :         aReturn = m_xEventAttacher->getScriptEvents( nIndex );
    1232          26 :             if ( lcl_hasVbaEvents( aReturn ) )
    1233             :             {
    1234           0 :                 aReturn = lcl_stripVbaEvents( aReturn );
    1235             :             }
    1236             :     }
    1237          26 :     return aReturn;
    1238             : }
    1239             : 
    1240             : 
    1241         298 : void SAL_CALL OInterfaceContainer::attach( sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any& aHelper ) throw(IllegalArgumentException, ServiceNotRegisteredException, RuntimeException, std::exception)
    1242             : {
    1243         298 :     if ( m_xEventAttacher.is() )
    1244         298 :         m_xEventAttacher->attach( nIndex, xObject, aHelper );
    1245         298 : }
    1246             : 
    1247             : 
    1248         298 : void SAL_CALL OInterfaceContainer::detach( sal_Int32 nIndex, const Reference< XInterface >& xObject ) throw(IllegalArgumentException, RuntimeException, std::exception)
    1249             : {
    1250         298 :     if ( m_xEventAttacher.is() )
    1251         298 :         m_xEventAttacher->detach( nIndex, xObject );
    1252         298 : }
    1253             : 
    1254             : 
    1255        1898 : void SAL_CALL OInterfaceContainer::addScriptListener( const Reference< XScriptListener >& xListener ) throw(IllegalArgumentException, RuntimeException, std::exception)
    1256             : {
    1257        1898 :     if ( m_xEventAttacher.is() )
    1258        1898 :         m_xEventAttacher->addScriptListener( xListener );
    1259        1898 : }
    1260             : 
    1261             : 
    1262        1894 : void SAL_CALL OInterfaceContainer::removeScriptListener( const Reference< XScriptListener >& xListener ) throw(IllegalArgumentException, RuntimeException, std::exception)
    1263             : {
    1264        1894 :     if ( m_xEventAttacher.is() )
    1265        1894 :         m_xEventAttacher->removeScriptListener( xListener );
    1266        1894 : }
    1267             : 
    1268             : 
    1269             : //= OFormComponents
    1270             : 
    1271             : 
    1272       11636 : Any SAL_CALL OFormComponents::queryAggregation(const Type& _rType) throw(RuntimeException, std::exception)
    1273             : {
    1274       11636 :     Any aReturn = OFormComponents_BASE::queryInterface(_rType);
    1275       11636 :     if (!aReturn.hasValue())
    1276             :     {
    1277       11500 :         aReturn = OInterfaceContainer::queryInterface(_rType);
    1278             : 
    1279       11500 :         if (!aReturn.hasValue())
    1280        5144 :             aReturn = FormComponentsBase::queryAggregation(_rType);
    1281             :     }
    1282             : 
    1283       11636 :     return aReturn;
    1284             : }
    1285             : 
    1286             : 
    1287           0 : Sequence<Type> SAL_CALL OFormComponents::getTypes() throw(RuntimeException, std::exception)
    1288             : {
    1289           0 :     return ::comphelper::concatSequences(OInterfaceContainer::getTypes(), FormComponentsBase::getTypes(), OFormComponents_BASE::getTypes());
    1290             : }
    1291             : 
    1292             : 
    1293         462 : OFormComponents::OFormComponents(const Reference<XComponentContext>& _rxFactory)
    1294             :     :FormComponentsBase( m_aMutex )
    1295         462 :     ,OInterfaceContainer( _rxFactory, m_aMutex, cppu::UnoType<XFormComponent>::get() )
    1296         924 :     ,OFormComponents_BASE()
    1297             : {
    1298         462 : }
    1299             : 
    1300             : 
    1301           0 : OFormComponents::OFormComponents( const OFormComponents& _cloneSource )
    1302             :     :FormComponentsBase( m_aMutex )
    1303             :     ,OInterfaceContainer( m_aMutex, _cloneSource )
    1304           0 :     ,OFormComponents_BASE()
    1305             : {
    1306           0 : }
    1307             : 
    1308             : 
    1309         916 : OFormComponents::~OFormComponents()
    1310             : {
    1311         458 :     if (!FormComponentsBase::rBHelper.bDisposed)
    1312             :     {
    1313         136 :         acquire();
    1314         136 :         dispose();
    1315             :     }
    1316         458 : }
    1317             : 
    1318             : // OComponentHelper
    1319             : 
    1320         460 : void OFormComponents::disposing()
    1321             : {
    1322         460 :     OInterfaceContainer::disposing();
    1323         460 :     FormComponentsBase::disposing();
    1324         460 :     m_xParent = NULL;
    1325         460 : }
    1326             : 
    1327             : //XChild
    1328             : 
    1329         322 : void OFormComponents::setParent(const InterfaceRef& Parent) throw( NoSupportException, RuntimeException, std::exception )
    1330             : {
    1331         322 :     ::osl::MutexGuard aGuard( m_aMutex );
    1332         322 :     m_xParent = Parent;
    1333         322 : }
    1334             : 
    1335             : 
    1336        3040 : InterfaceRef OFormComponents::getParent() throw( RuntimeException, std::exception )
    1337             : {
    1338        3040 :     return m_xParent;
    1339             : }
    1340             : 
    1341             : 
    1342             : }   // namespace frm
    1343             : 
    1344             : 
    1345             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10