1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_toolkit.hxx"
30 
31 
32 #include <com/sun/star/awt/XVclContainerPeer.hpp>
33 #include <com/sun/star/beans/XPropertyChangeListener.hpp>
34 
35 #include <cppuhelper/typeprovider.hxx>
36 #include <cppuhelper/implbase1.hxx>
37 #include <rtl/memory.h>
38 #include <rtl/uuid.h>
39 
40 #include <toolkit/controls/unocontrolcontainer.hxx>
41 #include <toolkit/helper/property.hxx>
42 #include <toolkit/helper/servicenames.hxx>
43 #include <comphelper/sequence.hxx>
44 
45 #include <tools/debug.hxx>
46 #include <tools/list.hxx>
47 #include <vcl/svapp.hxx>
48 #include <vcl/window.hxx>
49 
50 #include <limits>
51 #include <map>
52 #include <boost/shared_ptr.hpp>
53 
54 using namespace ::com::sun::star;
55 
56 extern WorkWindow* lcl_GetDefaultWindow();
57 
58 //	----------------------------------------------------
59 //	class UnoControlHolder
60 //	----------------------------------------------------
61 struct UnoControlHolder
62 {
63 	uno::Reference< awt::XControl > mxControl;
64 	::rtl::OUString                 msName;
65 
66 public:
67 	UnoControlHolder( const ::rtl::OUString& rName, const uno::Reference< awt::XControl > & rControl )
68 	:	mxControl( rControl ),
69 		msName( rName )
70 	{
71 	}
72 
73     inline const ::rtl::OUString&                   getName() const { return msName; }
74     inline const uno::Reference< awt::XControl >&   getControl() const { return mxControl; }
75 };
76 
77 //DECLARE_LIST( UnoControlHolderList, UnoControlHolder* );
78 
79 class UnoControlHolderList
80 {
81 public:
82     typedef sal_Int32                                       ControlIdentifier;
83 private:
84     typedef ::boost::shared_ptr< UnoControlHolder >         ControlInfo;
85     typedef ::std::map< ControlIdentifier, ControlInfo >    ControlMap;
86 
87 private:
88     ControlMap  maControls;
89 
90 public:
91     UnoControlHolderList();
92     ~UnoControlHolderList();
93 
94     /** adds a control with the given name to the list
95         @param _rxControl
96             the control to add. Must not be <NULL/>
97         @param _pBName
98             the name of the control, or <NULL/> if an automatic name should be generated
99         @return
100             the identifier of the newly added control
101     */
102     ControlIdentifier   addControl( const uno::Reference< awt::XControl >& _rxControl, const ::rtl::OUString* _pName );
103 
104     /** returns the number of controls in the list
105     */
106     inline size_t       size() const { return maControls.size(); }
107 
108     /** determines whether or not the list is empty
109     */
110     inline bool         empty() const { return maControls.empty(); }
111 
112     /** retrieves all controls currently in the list
113         @return
114             the number of controls in the list
115     */
116     size_t  getControls( uno::Sequence< uno::Reference< awt::XControl > >& _out_rControls ) const;
117 
118     /** retrieves all identifiers of all controls currently in the list
119         @return
120             the number of controls in the list
121     */
122     size_t  getIdentifiers( uno::Sequence< sal_Int32 >& _out_rIdentifiers ) const;
123 
124     /** returns the first control which is registered under the given name
125     */
126     uno::Reference< awt::XControl >
127             getControlForName( const ::rtl::OUString& _rName ) const;
128 
129     /** returns the identifier which a control is registered for, or -1 if the control
130             isn't registered
131     */
132     ControlIdentifier
133             getControlIdentifier( const uno::Reference< awt::XControl >& _rxControl );
134 
135     /** retrieves the control for a given id
136         @param _nIdentifier
137             the identifier for the control
138         @param _out_rxControl
139             takes the XControl upon successful return
140         @return
141             <TRUE/> if and only if a control with the given id is part of the list
142     */
143     bool    getControlForIdentifier( ControlIdentifier _nIdentifier, uno::Reference< awt::XControl >& _out_rxControl ) const;
144 
145     /** removes a control from the list, given by id
146         @param _nId
147             The identifier of the control to remove.
148     */
149     void    removeControlById( ControlIdentifier _nId );
150 
151     /** replaces a control from the list with another one
152         @param _nId
153             The identifier of the control to replace
154         @param _rxNewControl
155             the new control to put into the list
156     */
157     void    replaceControlById( ControlIdentifier _nId, const uno::Reference< awt::XControl >& _rxNewControl );
158 
159 private:
160     /** adds a control
161     @param _rxControl
162         the control to add to the container
163     @param _pName
164         pointer to the name of the control. Might be <NULL/>, in this case, a name is generated.
165     @return
166         the identifier of the newly inserted control
167     */
168     ControlIdentifier impl_addControl(
169         const uno::Reference< awt::XControl >& _rxControl,
170         const ::rtl::OUString*  _pName
171     );
172 
173     /** finds a free identifier
174         @throw uno::RuntimeException
175             if no free identifier can be found
176     */
177     ControlIdentifier impl_getFreeIdentifier_throw();
178 
179     /** finds a free name
180         @throw uno::RuntimeException
181             if no free name can be found
182     */
183     ::rtl::OUString impl_getFreeName_throw();
184 };
185 
186 //------------------------------------------------------------------------
187 UnoControlHolderList::UnoControlHolderList()
188 {
189 }
190 
191 //------------------------------------------------------------------------
192 UnoControlHolderList::~UnoControlHolderList()
193 {
194 }
195 
196 //------------------------------------------------------------------------
197 UnoControlHolderList::ControlIdentifier UnoControlHolderList::addControl( const uno::Reference< awt::XControl >& _rxControl, const ::rtl::OUString* _pName )
198 {
199     return impl_addControl( _rxControl, _pName );
200 }
201 
202 //------------------------------------------------------------------------
203 size_t UnoControlHolderList::getControls( uno::Sequence< uno::Reference< awt::XControl > >& _out_rControls ) const
204 {
205     _out_rControls.realloc( maControls.size() );
206     uno::Reference< awt::XControl >* pControls = _out_rControls.getArray();
207     for (   ControlMap::const_iterator loop = maControls.begin();
208             loop != maControls.end();
209             ++loop, ++pControls
210         )
211         *pControls = loop->second->getControl();
212     return maControls.size();
213 }
214 
215 //------------------------------------------------------------------------
216 size_t UnoControlHolderList::getIdentifiers( uno::Sequence< sal_Int32 >& _out_rIdentifiers ) const
217 {
218     _out_rIdentifiers.realloc( maControls.size() );
219     sal_Int32* pIndentifiers = _out_rIdentifiers.getArray();
220     for (   ControlMap::const_iterator loop = maControls.begin();
221             loop != maControls.end();
222             ++loop, ++pIndentifiers
223         )
224         *pIndentifiers = loop->first;
225     return maControls.size();
226 }
227 
228 //------------------------------------------------------------------------
229 uno::Reference< awt::XControl > UnoControlHolderList::getControlForName( const ::rtl::OUString& _rName ) const
230 {
231     for (   ControlMap::const_iterator loop = maControls.begin();
232             loop != maControls.end();
233             ++loop
234         )
235         if ( loop->second->getName() == _rName )
236             return loop->second->getControl();
237     return uno::Reference< awt::XControl >();
238 }
239 
240 //------------------------------------------------------------------------
241 UnoControlHolderList::ControlIdentifier UnoControlHolderList::getControlIdentifier( const uno::Reference< awt::XControl >& _rxControl )
242 {
243     for (   ControlMap::iterator loop = maControls.begin();
244             loop != maControls.end();
245             ++loop
246         )
247     {
248         if ( loop->second->getControl().get() == _rxControl.get() )
249             return loop->first;
250     }
251     return -1;
252 }
253 
254 //------------------------------------------------------------------------
255 bool UnoControlHolderList::getControlForIdentifier( UnoControlHolderList::ControlIdentifier _nIdentifier, uno::Reference< awt::XControl >& _out_rxControl ) const
256 {
257     ControlMap::const_iterator pos = maControls.find( _nIdentifier );
258     if ( pos == maControls.end() )
259         return false;
260     _out_rxControl = pos->second->getControl();
261     return true;
262 }
263 
264 //------------------------------------------------------------------------
265 void UnoControlHolderList::removeControlById( UnoControlHolderList::ControlIdentifier _nId )
266 {
267     ControlMap::iterator pos = maControls.find( _nId );
268     DBG_ASSERT( pos != maControls.end(), "UnoControlHolderList::removeControlById: invalid id!" );
269     if ( pos == maControls.end() )
270         return;
271 
272     maControls.erase( pos );
273 }
274 
275 //------------------------------------------------------------------------
276 void UnoControlHolderList::replaceControlById( ControlIdentifier _nId, const uno::Reference< awt::XControl >& _rxNewControl )
277 {
278     DBG_ASSERT( _rxNewControl.is(), "UnoControlHolderList::replaceControlById: invalid new control!" );
279 
280     ControlMap::iterator pos = maControls.find( _nId );
281     DBG_ASSERT( pos != maControls.end(), "UnoControlHolderList::replaceControlById: invalid id!" );
282     if ( pos == maControls.end() )
283         return;
284 
285     pos->second.reset( new UnoControlHolder( pos->second->getName(), _rxNewControl ) );
286 }
287 
288 //------------------------------------------------------------------------
289 UnoControlHolderList::ControlIdentifier UnoControlHolderList::impl_addControl( const uno::Reference< awt::XControl >& _rxControl, const ::rtl::OUString* _pName )
290 {
291     DBG_ASSERT( _rxControl.is(), "UnoControlHolderList::impl_addControl: invalid control!" );
292 
293     ::rtl::OUString sName = _pName ? *_pName : impl_getFreeName_throw();
294     sal_Int32 nId = impl_getFreeIdentifier_throw();
295 
296     maControls[ nId ] = ControlInfo( new UnoControlHolder( sName, _rxControl ) );
297     return nId;
298 }
299 
300 //------------------------------------------------------------------------
301 UnoControlHolderList::ControlIdentifier UnoControlHolderList::impl_getFreeIdentifier_throw()
302 {
303     for ( ControlIdentifier candidateId = 0; candidateId < ::std::numeric_limits< ControlIdentifier >::max(); ++candidateId )
304     {
305         ControlMap::const_iterator existent = maControls.find( candidateId );
306         if ( existent == maControls.end() )
307             return candidateId;
308     }
309     throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "out of identifiers" ) ), NULL );
310 }
311 
312 //------------------------------------------------------------------------
313 ::rtl::OUString UnoControlHolderList::impl_getFreeName_throw()
314 {
315     ::rtl::OUString name( RTL_CONSTASCII_USTRINGPARAM( "control_" ) );
316     for ( ControlIdentifier candidateId = 0; candidateId < ::std::numeric_limits< ControlIdentifier >::max(); ++candidateId )
317     {
318         ::rtl::OUString candidateName( name + ::rtl::OUString::valueOf( candidateId ) );
319         ControlMap::const_iterator loop = maControls.begin();
320         for ( ; loop != maControls.end(); ++loop )
321         {
322             if ( loop->second->getName() == candidateName )
323                 break;
324         }
325         if ( loop == maControls.end() )
326             return candidateName;
327     }
328     throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "out of identifiers" ) ), NULL );
329 }
330 //	----------------------------------------------------
331 //	Function to set the controls' visibility according
332 //	to the dialog's "Step" property
333 //	----------------------------------------------------
334 void implUpdateVisibility
335 (
336 	sal_Int32 nDialogStep,
337 	uno::Reference< awt::XControlContainer > xControlContainer
338 )
339 {
340 	uno::Sequence< uno::Reference< awt::XControl > >
341 		aCtrls = xControlContainer->getControls();
342 	const uno::Reference< awt::XControl >* pCtrls = aCtrls.getConstArray();
343 	sal_uInt32 nCtrls = aCtrls.getLength();
344 	sal_Bool bCompleteVisible = (nDialogStep == 0);
345 	for( sal_uInt32 n = 0; n < nCtrls; n++ )
346 	{
347 		uno::Reference< awt::XControl > xControl = pCtrls[ n ];
348 
349 		sal_Bool bVisible = bCompleteVisible;
350 		if( !bVisible )
351 		{
352 			uno::Reference< awt::XControlModel > xModel( xControl->getModel() );
353 			uno::Reference< beans::XPropertySet > xPSet
354 				( xModel, uno::UNO_QUERY );
355 			uno::Reference< beans::XPropertySetInfo >
356 				xInfo = xPSet->getPropertySetInfo();
357 			::rtl::OUString aPropName(RTL_CONSTASCII_USTRINGPARAM( "Step" ) );
358 			sal_Int32 nControlStep = 0;
359 			if ( xInfo->hasPropertyByName( aPropName ) )
360 			{
361 				uno::Any aVal = xPSet->getPropertyValue( aPropName );
362 				aVal >>= nControlStep;
363 			}
364 			bVisible = (nControlStep == 0) || (nControlStep == nDialogStep);
365 		}
366 
367 		uno::Reference< awt::XWindow> xWindow
368 			( xControl, uno::UNO_QUERY );
369 		if( xWindow.is() )
370 			xWindow->setVisible( bVisible );
371 	}
372 }
373 
374 
375 //	----------------------------------------------------
376 //	class DialogStepChangedListener
377 //	----------------------------------------------------
378 typedef ::cppu::WeakImplHelper1< beans::XPropertyChangeListener > PropertyChangeListenerHelper;
379 
380 class DialogStepChangedListener: public PropertyChangeListenerHelper
381 {
382 private:
383 	uno::Reference< awt::XControlContainer > mxControlContainer;
384 
385 public:
386 	DialogStepChangedListener( uno::Reference< awt::XControlContainer > xControlContainer )
387 		: mxControlContainer( xControlContainer ) {}
388 
389 	// XEventListener
390 	virtual void SAL_CALL disposing( const	lang::EventObject& Source ) throw( uno::RuntimeException);
391 
392 	// XPropertyChangeListener
393 	virtual void SAL_CALL propertyChange( const  beans::PropertyChangeEvent& evt ) throw( uno::RuntimeException);
394 
395 };
396 
397 void SAL_CALL DialogStepChangedListener::disposing( const  lang::EventObject& /*_rSource*/)
398 	throw( uno::RuntimeException)
399 {
400 	mxControlContainer.clear();
401 }
402 
403 void SAL_CALL DialogStepChangedListener::propertyChange( const	beans::PropertyChangeEvent& evt )
404 	throw( uno::RuntimeException)
405 {
406 	// evt.PropertyName HAS to be "Step" because we only use the listener for that
407 	sal_Int32 nDialogStep = 0;
408 	evt.NewValue >>= nDialogStep;
409 	implUpdateVisibility( nDialogStep, mxControlContainer );
410 }
411 
412 //	----------------------------------------------------
413 //	class UnoControlContainer
414 //	----------------------------------------------------
415 UnoControlContainer::UnoControlContainer( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& i_factory )
416     :UnoControlContainer_Base( i_factory )
417     ,maCListeners( *this )
418 {
419 	mpControls = new UnoControlHolderList;
420 }
421 
422 UnoControlContainer::UnoControlContainer( const uno::Reference< lang::XMultiServiceFactory >& i_factory, const uno::Reference< awt::XWindowPeer >& xP )
423 	:UnoControlContainer_Base( i_factory )
424     ,maCListeners( *this )
425 {
426 	setPeer( xP );
427 	mbDisposePeer = sal_False;
428 	mpControls = new UnoControlHolderList;
429 }
430 
431 UnoControlContainer::~UnoControlContainer()
432 {
433     DELETEZ( mpControls );
434 }
435 
436 void UnoControlContainer::ImplActivateTabControllers()
437 {
438 	sal_uInt32 nCount = maTabControllers.getLength();
439 	for ( sal_uInt32 n = 0; n < nCount; n++ )
440 	{
441 		maTabControllers.getArray()[n]->setContainer( this );
442 		maTabControllers.getArray()[n]->activateTabOrder();
443 	}
444 }
445 
446 // lang::XComponent
447 void UnoControlContainer::dispose(	) throw(uno::RuntimeException)
448 {
449 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
450 
451 	lang::EventObject aDisposeEvent;
452 	aDisposeEvent.Source = static_cast< uno::XAggregation* >( this );
453 
454     // DG: zuerst der Welt mitteilen, dass der Container wegfliegt. Dieses ist um einiges
455 	// schneller wenn die Welt sowohl an den Controls als auch am Container horcht
456 	maDisposeListeners.disposeAndClear( aDisposeEvent );
457 	maCListeners.disposeAndClear( aDisposeEvent );
458 
459 
460 	uno::Sequence< uno::Reference< awt::XControl > > aCtrls = getControls();
461 	uno::Reference< awt::XControl >* pCtrls = aCtrls.getArray();
462 	uno::Reference< awt::XControl >* pCtrlsEnd = pCtrls + aCtrls.getLength();
463 
464 	for( ; pCtrls < pCtrlsEnd; ++pCtrls )
465 	{
466 		removingControl( *pCtrls );
467 		// Control wegwerfen
468 		(*pCtrls)->dispose();
469 	}
470 
471 
472 	// alle Strukturen entfernen
473     DELETEZ( mpControls );
474     mpControls = new UnoControlHolderList;
475 
476 	UnoControlBase::dispose();
477 }
478 
479 // lang::XEventListener
480 void UnoControlContainer::disposing( const lang::EventObject& _rEvt ) throw(uno::RuntimeException)
481 {
482 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
483 
484 	uno::Reference< awt::XControl >  xControl( _rEvt.Source, uno::UNO_QUERY );
485 	if ( xControl.is() )
486 		removeControl( xControl );
487 
488 	UnoControlBase::disposing( _rEvt );
489 }
490 
491 // container::XContainer
492 void UnoControlContainer::addContainerListener( const uno::Reference< container::XContainerListener >& rxListener ) throw(uno::RuntimeException)
493 {
494 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
495 
496 	maCListeners.addInterface( rxListener );
497 }
498 
499 void UnoControlContainer::removeContainerListener( const uno::Reference< container::XContainerListener >& rxListener ) throw(uno::RuntimeException)
500 {
501 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
502 
503 	maCListeners.removeInterface( rxListener );
504 }
505 
506 
507 ::sal_Int32 SAL_CALL UnoControlContainer::insert( const uno::Any& _rElement ) throw (lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
508 {
509 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
510 
511     uno::Reference< awt::XControl > xControl;
512     if ( !( _rElement >>= xControl ) || !xControl.is() )
513         throw lang::IllegalArgumentException(
514             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Elements must support the XControl interface." ) ),
515             *this,
516             1
517         );
518 
519     return impl_addControl( xControl, NULL );
520 }
521 
522 void SAL_CALL UnoControlContainer::removeByIdentifier( ::sal_Int32 _nIdentifier ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
523 {
524 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
525 
526     uno::Reference< awt::XControl > xControl;
527     if ( !mpControls->getControlForIdentifier( _nIdentifier, xControl ) )
528         throw container::NoSuchElementException(
529             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "There is no element with the given identifier." ) ),
530             *this
531         );
532 
533     impl_removeControl( _nIdentifier, xControl, NULL );
534 }
535 
536 void SAL_CALL UnoControlContainer::replaceByIdentifer( ::sal_Int32 _nIdentifier, const uno::Any& _rElement ) throw (lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
537 {
538 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
539 
540     uno::Reference< awt::XControl > xExistentControl;
541     if ( !mpControls->getControlForIdentifier( _nIdentifier, xExistentControl ) )
542         throw container::NoSuchElementException(
543             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "There is no element with the given identifier." ) ),
544             *this
545         );
546 
547     uno::Reference< awt::XControl > xNewControl;
548     if ( !( _rElement >>= xNewControl ) )
549         throw lang::IllegalArgumentException(
550             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Elements must support the XControl interface." ) ),
551             *this,
552             1
553         );
554 
555     removingControl( xExistentControl );
556 
557     mpControls->replaceControlById( _nIdentifier, xNewControl );
558 
559     addingControl( xNewControl );
560 
561     impl_createControlPeerIfNecessary( xNewControl );
562 
563     if ( maCListeners.getLength() )
564 	{
565 		container::ContainerEvent aEvent;
566 		aEvent.Source = *this;
567         aEvent.Accessor <<= _nIdentifier;
568 		aEvent.Element <<= xNewControl;
569         aEvent.ReplacedElement <<= xExistentControl;
570 		maCListeners.elementReplaced( aEvent );
571 	}
572 }
573 
574 uno::Any SAL_CALL UnoControlContainer::getByIdentifier( ::sal_Int32 _nIdentifier ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
575 {
576 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
577 
578     uno::Reference< awt::XControl > xControl;
579     if ( !mpControls->getControlForIdentifier( _nIdentifier, xControl ) )
580         throw container::NoSuchElementException();
581     return uno::makeAny( xControl );
582 }
583 
584 uno::Sequence< ::sal_Int32 > SAL_CALL UnoControlContainer::getIdentifiers(  ) throw (uno::RuntimeException)
585 {
586 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
587 
588     uno::Sequence< ::sal_Int32 > aIdentifiers;
589     mpControls->getIdentifiers( aIdentifiers );
590     return aIdentifiers;
591 }
592 
593 // container::XElementAccess
594 uno::Type SAL_CALL UnoControlContainer::getElementType(  ) throw (uno::RuntimeException)
595 {
596     return awt::XControlModel::static_type();
597 }
598 
599 ::sal_Bool SAL_CALL UnoControlContainer::hasElements(  ) throw (uno::RuntimeException)
600 {
601 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
602     return !mpControls->empty();
603 }
604 
605 // awt::XControlContainer
606 void UnoControlContainer::setStatusText( const ::rtl::OUString& rStatusText ) throw(uno::RuntimeException)
607 {
608 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
609 
610 	// In der Parenthierarchie nach unten gehen
611 	uno::Reference< awt::XControlContainer >  xContainer( mxContext, uno::UNO_QUERY );
612 	if( xContainer.is() )
613 		xContainer->setStatusText( rStatusText );
614 }
615 
616 uno::Sequence< uno::Reference< awt::XControl > > UnoControlContainer::getControls(  ) throw(uno::RuntimeException)
617 {
618 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
619     uno::Sequence< uno::Reference< awt::XControl > > aControls;
620     mpControls->getControls( aControls );
621     return aControls;
622 }
623 
624 uno::Reference< awt::XControl > UnoControlContainer::getControl( const ::rtl::OUString& rName ) throw(uno::RuntimeException)
625 {
626 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
627     return mpControls->getControlForName( rName );
628 }
629 
630 void UnoControlContainer::addingControl( const uno::Reference< awt::XControl >& _rxControl )
631 {
632 	if ( _rxControl.is() )
633 	{
634 		uno::Reference< uno::XInterface > xThis;
635 		OWeakAggObject::queryInterface( ::getCppuType( static_cast< uno::Reference< uno::XInterface >* >( NULL ) ) ) >>= xThis;
636 
637 		_rxControl->setContext( xThis );
638 		_rxControl->addEventListener( this );
639 	}
640 }
641 
642 void UnoControlContainer::impl_createControlPeerIfNecessary( const uno::Reference< awt::XControl >& _rxControl )
643 {
644     OSL_PRECOND( _rxControl.is(), "UnoControlContainer::impl_createControlPeerIfNecessary: invalid control, this will crash!" );
645 
646     // if the container already has a peer, then also create a peer for the control
647     uno::Reference< awt::XWindowPeer > xMyPeer( getPeer() );
648 
649     if( xMyPeer.is() )
650 	{
651         _rxControl->createPeer( NULL, xMyPeer );
652 		ImplActivateTabControllers();
653 	}
654 
655 }
656 
657 sal_Int32 UnoControlContainer::impl_addControl( const uno::Reference< awt::XControl >& _rxControl, const ::rtl::OUString* _pName )
658 {
659 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
660     UnoControlHolderList::ControlIdentifier id = mpControls->addControl( _rxControl, _pName );
661 
662     addingControl( _rxControl );
663 
664     impl_createControlPeerIfNecessary( _rxControl );
665 
666 	if ( maCListeners.getLength() )
667 	{
668 		container::ContainerEvent aEvent;
669 		aEvent.Source = *this;
670         _pName ? ( aEvent.Accessor <<= *_pName ) : ( aEvent.Accessor <<= (sal_Int32)id );
671 		aEvent.Element <<= _rxControl;
672 		maCListeners.elementInserted( aEvent );
673 	}
674 
675     return id;
676 }
677 
678 void UnoControlContainer::addControl( const ::rtl::OUString& rName, const uno::Reference< awt::XControl >& rControl ) throw(uno::RuntimeException)
679 {
680 	if ( rControl.is() )
681         impl_addControl( rControl, &rName );
682 }
683 
684 void UnoControlContainer::removingControl( const uno::Reference< awt::XControl >& _rxControl )
685 {
686 	if ( _rxControl.is() )
687 	{
688 		_rxControl->removeEventListener( this );
689 		_rxControl->setContext( NULL );
690 	}
691 }
692 
693 void UnoControlContainer::impl_removeControl( sal_Int32 _nId, const uno::Reference< awt::XControl >& _rxControl, const ::rtl::OUString* _pNameAccessor )
694 {
695 #ifdef DBG_UTIL
696     {
697         uno::Reference< awt::XControl > xControl;
698         bool bHas = mpControls->getControlForIdentifier( _nId, xControl );
699         DBG_ASSERT( bHas && xControl == _rxControl, "UnoControlContainer::impl_removeControl: inconsistency in the parameters!" );
700     }
701 #endif
702 	removingControl( _rxControl );
703 
704     mpControls->removeControlById( _nId );
705 
706     if ( maCListeners.getLength() )
707 	{
708 		container::ContainerEvent aEvent;
709 		aEvent.Source = *this;
710         _pNameAccessor ? ( aEvent.Accessor <<= *_pNameAccessor ) : ( aEvent.Accessor <<= _nId );
711 		aEvent.Element <<= _rxControl;
712 		maCListeners.elementRemoved( aEvent );
713 	}
714 }
715 
716 void UnoControlContainer::removeControl( const uno::Reference< awt::XControl >& _rxControl ) throw(uno::RuntimeException)
717 {
718 	if ( _rxControl.is() )
719 	{
720 		::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
721 
722         UnoControlHolderList::ControlIdentifier id = mpControls->getControlIdentifier( _rxControl );
723         if ( id != -1 )
724             impl_removeControl( id, _rxControl, NULL );
725 	}
726 }
727 
728 
729 
730 // awt::XUnoControlContainer
731 void UnoControlContainer::setTabControllers( const uno::Sequence< uno::Reference< awt::XTabController > >& TabControllers ) throw(uno::RuntimeException)
732 {
733 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
734 
735 	maTabControllers = TabControllers;
736 }
737 
738 uno::Sequence< uno::Reference< awt::XTabController > > UnoControlContainer::getTabControllers(  ) throw(uno::RuntimeException)
739 {
740 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
741 
742 	return maTabControllers;
743 }
744 
745 void UnoControlContainer::addTabController( const uno::Reference< awt::XTabController >& TabController ) throw(uno::RuntimeException)
746 {
747 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
748 
749 	sal_uInt32 nCount = maTabControllers.getLength();
750 	maTabControllers.realloc( nCount + 1 );
751 	maTabControllers[ nCount ] = TabController;
752 }
753 
754 void UnoControlContainer::removeTabController( const uno::Reference< awt::XTabController >& TabController ) throw(uno::RuntimeException)
755 {
756 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
757 
758 	sal_uInt32 nCount = maTabControllers.getLength();
759 	const uno::Reference< awt::XTabController >* pLoop = maTabControllers.getConstArray();
760 	for ( sal_uInt32 n = 0; n < nCount; ++n, ++pLoop )
761 	{
762 		if( pLoop->get() == TabController.get() )
763 		{
764 			::comphelper::removeElementAt( maTabControllers, n );
765 			break;
766 		}
767 	}
768 }
769 
770 // awt::XControl
771 void UnoControlContainer::createPeer( const uno::Reference< awt::XToolkit >& rxToolkit, const uno::Reference< awt::XWindowPeer >& rParent ) throw(uno::RuntimeException)
772 {
773 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
774 
775 	if( !getPeer().is() )
776 	{
777 		sal_Bool bVis = maComponentInfos.bVisible;
778 		if( bVis )
779 			UnoControl::setVisible( sal_False );
780 		// eigenes Peer erzeugen
781 		UnoControl::createPeer( rxToolkit, rParent );
782 
783 		// alle Peers der Childs erzeugen
784 		if ( !mbCreatingCompatiblePeer )
785 		{
786 			// Evaluate "Step" property
787 			uno::Reference< awt::XControlModel > xModel( getModel() );
788 			uno::Reference< beans::XPropertySet > xPSet
789 				( xModel, uno::UNO_QUERY );
790 			uno::Reference< beans::XPropertySetInfo >
791 				xInfo = xPSet->getPropertySetInfo();
792 			::rtl::OUString aPropName(RTL_CONSTASCII_USTRINGPARAM( "Step" ) );
793 			if ( xInfo->hasPropertyByName( aPropName ) )
794 			{
795 				::com::sun::star::uno::Any aVal = xPSet->getPropertyValue( aPropName );
796 				sal_Int32 nDialogStep = 0;
797 				aVal >>= nDialogStep;
798 				uno::Reference< awt::XControlContainer > xContainer =
799 					SAL_STATIC_CAST( awt::XControlContainer*, this );
800 				implUpdateVisibility( nDialogStep, xContainer );
801 
802 				uno::Reference< beans::XPropertyChangeListener > xListener =
803 					SAL_STATIC_CAST( beans::XPropertyChangeListener*,
804 						new DialogStepChangedListener( xContainer ) );
805 				xPSet->addPropertyChangeListener( aPropName, xListener );
806 			}
807 
808 			uno::Sequence< uno::Reference< awt::XControl > > aCtrls = getControls();
809 			sal_uInt32 nCtrls = aCtrls.getLength();
810 			for( sal_uInt32 n = 0; n < nCtrls; n++ )
811 				aCtrls.getArray()[n]->createPeer( rxToolkit, getPeer() );
812 
813 			uno::Reference< awt::XVclContainerPeer >  xC( getPeer(), uno::UNO_QUERY );
814             OSL_ENSURE(xC.is(),"Peer isn't valid. Please check!");
815 
816 			xC->enableDialogControl( sal_True );
817 			ImplActivateTabControllers();
818 		}
819 
820 		if( bVis && !isDesignMode() )
821 			UnoControl::setVisible( sal_True );
822 	}
823 }
824 
825 
826 // awt::XWindow
827 void UnoControlContainer::setVisible( sal_Bool bVisible ) throw(uno::RuntimeException)
828 {
829 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
830 
831 	UnoControl::setVisible( bVisible );
832 	if( !mxContext.is() && bVisible )
833 		// Es ist ein TopWindow, also automatisch anzeigen
834 		createPeer( uno::Reference< awt::XToolkit > (), uno::Reference< awt::XWindowPeer > () );
835 }
836 
837 
838 
839