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

Generated by: LCOV version 1.10