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

Generated by: LCOV version 1.10