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