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 #include <toolkit/controls/controlmodelcontainerbase.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/window.hxx>
34 #include <vcl/wall.hxx>
35 #include <vos/mutex.hxx>
36 #include <toolkit/helper/property.hxx>
37 #include <toolkit/helper/unopropertyarrayhelper.hxx>
38 #include <toolkit/controls/geometrycontrolmodel.hxx>
39 #include <toolkit/controls/unocontrols.hxx>
40 #include "toolkit/controls/formattedcontrol.hxx"
41 #include "toolkit/controls/roadmapcontrol.hxx"
42 #include "toolkit/controls/tkscrollbar.hxx"
43 #include "toolkit/controls/tabpagemodel.hxx"
44 #include <toolkit/controls/stdtabcontroller.hxx>
45 #include <com/sun/star/awt/PosSize.hpp>
46 #include <com/sun/star/awt/WindowAttribute.hpp>
47 #include <com/sun/star/resource/XStringResourceResolver.hpp>
48 #include <com/sun/star/graphic/XGraphicProvider.hpp>
49 #include <com/sun/star/lang/XInitialization.hpp>
50 #include <tools/list.hxx>
51 #include <cppuhelper/typeprovider.hxx>
52 #include <tools/debug.hxx>
53 #include <tools/diagnose_ex.h>
54 #include <comphelper/processfactory.hxx>
55 #include <vcl/svapp.hxx>
56 #include <vcl/outdev.hxx>
57 #include <comphelper/types.hxx>
58 
59 #include <comphelper/componentcontext.hxx>
60 #include <toolkit/helper/vclunohelper.hxx>
61 #include <toolkit/helper/tkresmgr.hxx>
62 #include <unotools/ucbstreamhelper.hxx>
63 #include <vcl/graph.hxx>
64 #include <vcl/image.hxx>
65 
66 #include "tree/treecontrol.hxx"
67 #include "grid/gridcontrol.hxx"
68 #include <toolkit/controls/tabpagecontainer.hxx>
69 
70 #include <map>
71 #include <algorithm>
72 #include <functional>
73 #include "tools/urlobj.hxx"
74 #include "osl/file.hxx"
75 
76 using namespace ::com::sun::star;
77 using namespace ::com::sun::star::uno;
78 using namespace ::com::sun::star::awt;
79 using namespace ::com::sun::star::lang;
80 using namespace ::com::sun::star::container;
81 using namespace ::com::sun::star::beans;
82 using namespace ::com::sun::star::util;
83 using namespace toolkit;
84 
85 #define PROPERTY_RESOURCERESOLVER ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ResourceResolver" ))
86 
87 //HELPER
88 ::rtl::OUString getPhysicalLocation( const ::com::sun::star::uno::Any& rbase, const ::com::sun::star::uno::Any& rUrl );
89 
90 struct LanguageDependentProp
91 {
92     const char* pPropName;
93     sal_Int32   nPropNameLength;
94 };
95 
96 // ----------------------------------------------------------------------------
97 namespace
98 {
99     static const Sequence< ::rtl::OUString >& lcl_getLanguageDependentProperties()
100     {
101         static Sequence< ::rtl::OUString > s_aLanguageDependentProperties;
102         if ( s_aLanguageDependentProperties.getLength() == 0 )
103         {
104             ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
105             if ( s_aLanguageDependentProperties.getLength() == 0 )
106             {
107                 s_aLanguageDependentProperties.realloc( 2 );
108                 s_aLanguageDependentProperties[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HelpText" ) );
109                 s_aLanguageDependentProperties[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) );
110                 // note: properties must be sorted
111             }
112         }
113         return s_aLanguageDependentProperties;
114 	}
115 }
116 
117 // ----------------------------------------------------------------------------
118 // functor for disposing a control model
119 struct DisposeControlModel : public ::std::unary_function< Reference< XControlModel >, void >
120 {
121 	void operator()( Reference< XControlModel >& _rxModel )
122 	{
123 		try
124 		{
125 			::comphelper::disposeComponent( _rxModel );
126 		}
127 		catch( const Exception& )
128 		{
129 			DBG_ERROR( "DisposeControlModel::(): caught an exception while disposing a component!" );
130 		}
131 	}
132 };
133 
134 // ----------------------------------------------------------------------------
135 // functor for searching control model by name
136 struct FindControlModel : public ::std::unary_function< ControlModelContainerBase::UnoControlModelHolder, bool >
137 {
138 private:
139 	const ::rtl::OUString& m_rName;
140 
141 public:
142 	FindControlModel( const ::rtl::OUString& _rName ) : m_rName( _rName ) { }
143 
144 	bool operator()( const ControlModelContainerBase::UnoControlModelHolder& _rCompare )
145 	{
146 		return ( _rCompare.second == m_rName ) ? true : false;
147 	}
148 };
149 
150 // ----------------------------------------------------------------------------
151 // functor for cloning a control model, and insertion into a target list
152 struct CloneControlModel : public ::std::unary_function< ControlModelContainerBase::UnoControlModelHolder, void >
153 {
154 private:
155 	ControlModelContainerBase::UnoControlModelHolderList&	m_rTargetList;
156 
157 public:
158 	CloneControlModel( ControlModelContainerBase::UnoControlModelHolderList& _rTargetList )
159 		:m_rTargetList( _rTargetList )
160 	{
161 	}
162 
163 	void operator()( const ControlModelContainerBase::UnoControlModelHolder& _rSource )
164 	{
165 		// clone the source object
166 		Reference< XCloneable > xCloneSource( _rSource.first, UNO_QUERY );
167 		Reference< XControlModel > xClone( xCloneSource->createClone(), UNO_QUERY );
168 		// add to target list
169 		m_rTargetList.push_back( ControlModelContainerBase::UnoControlModelHolder( xClone, _rSource.second ) );
170 	}
171 };
172 
173 // ----------------------------------------------------------------------------
174 // functor for comparing a XControlModel with a given reference
175 struct CompareControlModel : public ::std::unary_function< ControlModelContainerBase::UnoControlModelHolder, bool >
176 {
177 private:
178 	Reference< XControlModel > m_xReference;
179 public:
180 	CompareControlModel( const Reference< XControlModel >& _rxReference ) : m_xReference( _rxReference ) { }
181 
182 	bool operator()( const ControlModelContainerBase::UnoControlModelHolder& _rCompare )
183 	{
184 		return ( _rCompare.first.get() == m_xReference.get() ) ? true : false;
185 	}
186 };
187 
188 // ----------------------------------------------------------------------------
189 static void lcl_throwIllegalArgumentException( )
190 {	// throwing is expensive (in terms of code size), thus we hope the compiler does not inline this ....
191 	throw IllegalArgumentException();
192 }
193 
194 // ----------------------------------------------------------------------------
195 static void lcl_throwNoSuchElementException( )
196 {	// throwing is expensive (in terms of code size), thus we hope the compiler does not inline this ....
197 	throw NoSuchElementException();
198 }
199 
200 // ----------------------------------------------------------------------------
201 static void lcl_throwElementExistException( )
202 {	// throwing is expensive (in terms of code size), thus we hope the compiler does not inline this ....
203 	throw ElementExistException();
204 }
205 
206 // ----------------------------------------------------------------------------
207 static const ::rtl::OUString& getTabIndexPropertyName( )
208 {
209 	static const ::rtl::OUString s_sTabIndexProperty( RTL_CONSTASCII_USTRINGPARAM( "TabIndex" ) );
210 	return s_sTabIndexProperty;
211 }
212 
213 // ----------------------------------------------------------------------------
214 static const ::rtl::OUString& getStepPropertyName( )
215 {
216 	static const ::rtl::OUString s_sStepProperty( RTL_CONSTASCII_USTRINGPARAM( "Step" ) );
217 	return s_sStepProperty;
218 }
219 
220 //	----------------------------------------------------
221 //	class ControlModelContainerBase
222 //	----------------------------------------------------
223 ControlModelContainerBase::ControlModelContainerBase( const Reference< XMultiServiceFactory >& i_factory )
224     :ControlModelContainer_IBase( i_factory )
225 	,maContainerListeners( *this )
226 	,maChangeListeners ( GetMutex() )
227 	,mbGroupsUpToDate( sal_False )
228 {
229 }
230 
231 ControlModelContainerBase::ControlModelContainerBase( const ControlModelContainerBase& rModel )
232 	: ControlModelContainer_IBase( rModel )
233 	, maContainerListeners( *this )
234 	, maChangeListeners ( GetMutex() )
235 	, mbGroupsUpToDate( sal_False )
236 {
237 }
238 
239 ControlModelContainerBase::~ControlModelContainerBase()
240 {
241 	maModels.clear();
242 	mbGroupsUpToDate = sal_False;
243 }
244 
245 Any ControlModelContainerBase::ImplGetDefaultValue( sal_uInt16 nPropId ) const
246 {
247     Any aAny;
248 
249     switch ( nPropId )
250     {
251         case BASEPROPERTY_DEFAULTCONTROL:
252 		    aAny <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlDialog );
253             break;
254         default:
255             aAny = UnoControlModel::ImplGetDefaultValue( nPropId );
256     }
257 
258     return aAny;
259 }
260 
261 ::cppu::IPropertyArrayHelper& ControlModelContainerBase::getInfoHelper()
262 {
263 	static UnoPropertyArrayHelper* pHelper = NULL;
264 	if ( !pHelper )
265 	{
266 		Sequence<sal_Int32> aIDs = ImplGetPropertyIds();
267 		pHelper = new UnoPropertyArrayHelper( aIDs );
268 	}
269 	return *pHelper;
270 }
271 
272 void SAL_CALL ControlModelContainerBase::dispose(  ) throw(RuntimeException)
273 {
274     // ====================================================================
275 	// tell our listeners
276 	{
277 		::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
278 
279 		EventObject aDisposeEvent;
280 		aDisposeEvent.Source = static_cast< XAggregation* >( static_cast< ::cppu::OWeakAggObject* >( this ) );
281 
282 		maContainerListeners.disposeAndClear( aDisposeEvent );
283 		maChangeListeners.disposeAndClear( aDisposeEvent );
284 	}
285 
286     // ====================================================================
287 	// call the base class
288 	UnoControlModel::dispose();
289 
290     // ====================================================================
291 	// dispose our child models
292 	// for this, collect the models (we collect them from maModels, and this is modified when disposing children)
293 	::std::vector< Reference< XControlModel > > aChildModels( maModels.size() );
294 
295 	::std::transform(
296 		maModels.begin(), maModels.end(),				// source range
297 		aChildModels.begin(),							// target location
298 		::std::select1st< UnoControlModelHolder >( )	// operation to apply -> select the XControlModel part
299 	);
300 
301 	// now dispose
302 	::std::for_each( aChildModels.begin(), aChildModels.end(), DisposeControlModel() );
303 	aChildModels.clear();
304 
305 	mbGroupsUpToDate = sal_False;
306 }
307 
308 // XMultiPropertySet
309 Reference< XPropertySetInfo > ControlModelContainerBase::getPropertySetInfo(  ) throw(RuntimeException)
310 {
311 	static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
312 	return xInfo;
313 }
314 void ControlModelContainerBase::Clone_Impl(ControlModelContainerBase& _rClone) const
315 {
316     // clone all children
317 	::std::for_each(
318 		maModels.begin(), maModels.end(),
319 		CloneControlModel( _rClone.maModels )
320 	);
321 }
322 UnoControlModel* ControlModelContainerBase::Clone() const
323 {
324 	// clone the container itself
325 	ControlModelContainerBase* pClone = new ControlModelContainerBase( *this );
326     Clone_Impl(*pClone);
327 
328 	return pClone;
329 }
330 
331 ControlModelContainerBase::UnoControlModelHolderList::iterator ControlModelContainerBase::ImplFindElement( const ::rtl::OUString& rName )
332 {
333 	return ::std::find_if( maModels.begin(), maModels.end(), FindControlModel( rName ) );
334 }
335 
336 // ::XMultiServiceFactory
337 Reference< XInterface > ControlModelContainerBase::createInstance( const ::rtl::OUString& aServiceSpecifier ) throw(Exception, RuntimeException)
338 {
339 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
340 
341 	OGeometryControlModel_Base* pNewModel = NULL;
342 
343     const Reference< XMultiServiceFactory > xFactory( maContext.getLegacyServiceFactory() );
344 	if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlEditModel ) == 0 )
345 		pNewModel = new OGeometryControlModel< UnoControlEditModel >( xFactory );
346 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlFormattedFieldModel ) == 0 )
347 		pNewModel = new OGeometryControlModel< UnoControlFormattedFieldModel >( xFactory );
348 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlFileControlModel ) == 0 )
349 		pNewModel = new OGeometryControlModel< UnoControlFileControlModel >( xFactory );
350 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlButtonModel ) == 0 )
351 		pNewModel = new OGeometryControlModel< UnoControlButtonModel >( xFactory );
352 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlImageControlModel ) == 0 )
353 		pNewModel = new OGeometryControlModel< UnoControlImageControlModel >( xFactory );
354 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlRadioButtonModel ) == 0 )
355 		pNewModel = new OGeometryControlModel< UnoControlRadioButtonModel >( xFactory );
356 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlCheckBoxModel ) == 0 )
357 		pNewModel = new OGeometryControlModel< UnoControlCheckBoxModel >( xFactory );
358     else if ( aServiceSpecifier.compareToAscii( szServiceName_UnoControlFixedHyperlinkModel ) == 0 )
359         pNewModel = new OGeometryControlModel< UnoControlFixedHyperlinkModel >( xFactory );
360     else if ( aServiceSpecifier.compareToAscii( szServiceName_UnoControlFixedTextModel ) == 0 )
361         pNewModel = new OGeometryControlModel< UnoControlFixedTextModel >( xFactory );
362 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlGroupBoxModel ) == 0 )
363 		pNewModel = new OGeometryControlModel< UnoControlGroupBoxModel >( xFactory );
364 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlListBoxModel ) == 0 )
365 		pNewModel = new OGeometryControlModel< UnoControlListBoxModel >( xFactory );
366 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlComboBoxModel ) == 0 )
367 		pNewModel = new OGeometryControlModel< UnoControlComboBoxModel >( xFactory );
368 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlDateFieldModel ) == 0 )
369 		pNewModel = new OGeometryControlModel< UnoControlDateFieldModel >( xFactory );
370 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlTimeFieldModel ) == 0 )
371 		pNewModel = new OGeometryControlModel< UnoControlTimeFieldModel >( xFactory );
372 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlNumericFieldModel ) == 0 )
373 		pNewModel = new OGeometryControlModel< UnoControlNumericFieldModel >( xFactory );
374 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlCurrencyFieldModel ) == 0 )
375 		pNewModel = new OGeometryControlModel< UnoControlCurrencyFieldModel >( xFactory );
376 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlPatternFieldModel ) == 0 )
377 		pNewModel = new OGeometryControlModel< UnoControlPatternFieldModel >( xFactory );
378 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlProgressBarModel ) == 0 )
379 		pNewModel = new OGeometryControlModel< UnoControlProgressBarModel >( xFactory );
380 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlScrollBarModel ) == 0 )
381 		pNewModel = new OGeometryControlModel< UnoControlScrollBarModel >( xFactory );
382 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlFixedLineModel ) == 0 )
383 		pNewModel = new OGeometryControlModel< UnoControlFixedLineModel >( xFactory );
384 	else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlRoadmapModel ) == 0 )
385 		pNewModel = new OGeometryControlModel< UnoControlRoadmapModel >( xFactory );
386 	else if ( aServiceSpecifier.compareToAscii( szServiceName_TreeControlModel ) == 0 )
387 		pNewModel = new OGeometryControlModel< UnoTreeModel >( xFactory );
388 	else if ( aServiceSpecifier.compareToAscii( szServiceName_GridControlModel ) == 0 )
389 		pNewModel = new OGeometryControlModel< UnoGridModel >( xFactory );
390 	else if ( aServiceSpecifier.compareToAscii( szServiceName_UnoControlTabPageContainerModel ) == 0 )
391 		pNewModel = new OGeometryControlModel< UnoControlTabPageContainerModel >( xFactory );
392 	else if ( aServiceSpecifier.compareToAscii( szServiceName_UnoControlTabPageModel ) == 0 )
393 		pNewModel = new OGeometryControlModel< UnoControlTabPageModel >( xFactory );
394 
395 	if ( !pNewModel )
396 	{
397 		if ( xFactory.is() )
398 		{
399 			Reference< XInterface > xObject = xFactory->createInstance( aServiceSpecifier );
400 			Reference< XServiceInfo > xSI( xObject, UNO_QUERY );
401 			Reference< XCloneable > xCloneAccess( xSI, UNO_QUERY );
402 			Reference< XAggregation > xAgg( xCloneAccess, UNO_QUERY );
403 			if ( xAgg.is() )
404 			{
405 				if ( xSI->supportsService( ::rtl::OUString::createFromAscii( "com.sun.star.awt.UnoControlModel" ) ) )
406 				{
407 					// release 3 of the 4 references we have to the object
408 					xAgg.clear();
409 					xSI.clear();
410 					xObject.clear();
411 
412 					pNewModel = new OCommonGeometryControlModel( xCloneAccess, aServiceSpecifier );
413 				}
414 			}
415 		}
416 	}
417 
418 	Reference< XInterface > xNewModel = (::cppu::OWeakObject*)pNewModel;
419 	return xNewModel;
420 }
421 
422 Reference< XInterface > ControlModelContainerBase::createInstanceWithArguments( const ::rtl::OUString& ServiceSpecifier, const Sequence< Any >& i_arguments ) throw(Exception, RuntimeException)
423 {
424     const Reference< XInterface > xInstance( createInstance( ServiceSpecifier ) );
425     const Reference< XInitialization > xInstanceInit( xInstance, UNO_QUERY );
426     ENSURE_OR_RETURN( xInstanceInit.is(), "ControlModelContainerBase::createInstanceWithArguments: can't pass the arguments!", xInstance );
427     xInstanceInit->initialize( i_arguments );
428 	return xInstance;
429 }
430 
431 Sequence< ::rtl::OUString > ControlModelContainerBase::getAvailableServiceNames() throw(RuntimeException)
432 {
433 	static Sequence< ::rtl::OUString >* pNamesSeq = NULL;
434 	if ( !pNamesSeq )
435 	{
436 		pNamesSeq = new Sequence< ::rtl::OUString >( 24 );
437 		::rtl::OUString* pNames = pNamesSeq->getArray();
438 		pNames[0] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlEditModel );
439 		pNames[1] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlFormattedFieldModel );
440 		pNames[2] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlFileControlModel );
441 		pNames[3] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlButtonModel );
442 		pNames[4] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlImageControlModel );
443 		pNames[5] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlRadioButtonModel );
444 		pNames[6] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlCheckBoxModel );
445 		pNames[7] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlFixedTextModel );
446 		pNames[8] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlGroupBoxModel );
447 		pNames[9] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlListBoxModel );
448 		pNames[10] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlComboBoxModel );
449 		pNames[11] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlDateFieldModel );
450 		pNames[12] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlTimeFieldModel );
451 		pNames[13] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlNumericFieldModel );
452 		pNames[14] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlCurrencyFieldModel );
453 		pNames[15] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlPatternFieldModel );
454 		pNames[16] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlProgressBarModel );
455 		pNames[17] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlScrollBarModel );
456 		pNames[18] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlFixedLineModel );
457 		pNames[19] = ::rtl::OUString::createFromAscii( szServiceName2_UnoControlRoadmapModel );
458 		pNames[20] = ::rtl::OUString::createFromAscii( szServiceName_TreeControlModel );
459 		pNames[21] = ::rtl::OUString::createFromAscii( szServiceName_GridControlModel );
460 		pNames[22] = ::rtl::OUString::createFromAscii( szServiceName_UnoControlTabPageContainerModel );
461 		pNames[23] = ::rtl::OUString::createFromAscii( szServiceName_UnoControlTabPageModel );
462 	}
463 	return *pNamesSeq;
464 }
465 
466 // XContainer
467 void ControlModelContainerBase::addContainerListener( const Reference< XContainerListener >& l ) throw(RuntimeException)
468 {
469 	maContainerListeners.addInterface( l );
470 }
471 
472 void ControlModelContainerBase::removeContainerListener( const Reference< XContainerListener >& l ) throw(RuntimeException)
473 {
474 	maContainerListeners.removeInterface( l );
475 }
476 
477 // XElementAcces
478 Type ControlModelContainerBase::getElementType() throw(RuntimeException)
479 {
480 	Type aType = getCppuType( ( Reference< XControlModel>* ) NULL );
481 	return aType;
482 }
483 
484 sal_Bool ControlModelContainerBase::hasElements() throw(RuntimeException)
485 {
486 	return !maModels.empty();
487 }
488 
489 // XNameContainer, XNameReplace, XNameAccess
490 void ControlModelContainerBase::replaceByName( const ::rtl::OUString& aName, const Any& aElement ) throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException)
491 {
492 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
493 
494 	Reference< XControlModel > xNewModel;
495 	aElement >>= xNewModel;
496 	if ( !xNewModel.is() )
497 		lcl_throwIllegalArgumentException();
498 
499 	UnoControlModelHolderList::iterator aElementPos = ImplFindElement( aName );
500 	if ( maModels.end() == aElementPos )
501 		lcl_throwNoSuchElementException();
502 
503 	// stop listening at the old model
504 	stopControlListening( aElementPos->first );
505 	Reference< XControlModel > xReplaced( aElementPos->first );
506 	// remember the new model, and start listening
507 	aElementPos->first = xNewModel;
508 	startControlListening( xNewModel );
509 
510 	ContainerEvent aEvent;
511 	aEvent.Source = *this;
512 	aEvent.Element = aElement;
513 	aEvent.ReplacedElement <<= xReplaced;
514 	aEvent.Accessor <<= aName;
515 
516 	// notify the container listener
517 	maContainerListeners.elementReplaced( aEvent );
518 
519 	// our "tab controller model" has potentially changed -> notify this
520 	implNotifyTabModelChange( aName );
521 }
522 
523 Any ControlModelContainerBase::getByName( const ::rtl::OUString& aName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException)
524 {
525 	UnoControlModelHolderList::iterator aElementPos = ImplFindElement( aName );
526 	if ( maModels.end() == aElementPos )
527 		lcl_throwNoSuchElementException();
528 
529 	return makeAny( aElementPos->first );
530 }
531 
532 Sequence< ::rtl::OUString > ControlModelContainerBase::getElementNames() throw(RuntimeException)
533 {
534 	Sequence< ::rtl::OUString > aNames( maModels.size() );
535 
536 	::std::transform(
537 		maModels.begin(), maModels.end(),				// source range
538 		aNames.getArray(),								// target range
539 		::std::select2nd< UnoControlModelHolder >()		// operator to apply: select the second element (the name)
540 	);
541 
542 	return aNames;
543 }
544 
545 sal_Bool ControlModelContainerBase::hasByName( const ::rtl::OUString& aName ) throw(RuntimeException)
546 {
547 	return maModels.end() != ImplFindElement( aName );
548 }
549 
550 void ControlModelContainerBase::insertByName( const ::rtl::OUString& aName, const Any& aElement ) throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException)
551 {
552 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
553 
554 	Reference< XControlModel > xM;
555 	aElement >>= xM;
556 
557 	if ( xM.is() )
558 	{
559 		Reference< beans::XPropertySet > xProps( xM, UNO_QUERY );
560 			if ( xProps.is() )
561 			{
562 
563 				Reference< beans::XPropertySetInfo > xPropInfo = xProps.get()->getPropertySetInfo();
564 
565 				::rtl::OUString sImageSourceProperty = GetPropertyName( BASEPROPERTY_IMAGEURL );
566 				if ( xPropInfo.get()->hasPropertyByName(  sImageSourceProperty ) && ImplHasProperty(BASEPROPERTY_DIALOGSOURCEURL) )
567 				{
568 					Any aUrl = xProps.get()->getPropertyValue(  sImageSourceProperty );
569 
570 					::rtl::OUString absoluteUrl =
571 						getPhysicalLocation( getPropertyValue( GetPropertyName( BASEPROPERTY_DIALOGSOURCEURL ) ), aUrl );
572 
573 					aUrl <<= absoluteUrl;
574 
575 					xProps.get()->setPropertyValue(  sImageSourceProperty , aUrl );
576 				}
577 			}
578 	}
579 
580 
581 
582     if ( !aName.getLength() || !xM.is() )
583 		lcl_throwIllegalArgumentException();
584 
585 	UnoControlModelHolderList::iterator aElementPos = ImplFindElement( aName );
586 	if ( maModels.end() != aElementPos )
587         lcl_throwElementExistException();
588 
589 	maModels.push_back( UnoControlModelHolder( xM, aName ) );
590 	mbGroupsUpToDate = sal_False;
591 	startControlListening( xM );
592 
593 	ContainerEvent aEvent;
594 	aEvent.Source = *this;
595 	aEvent.Element <<= aElement;
596 	aEvent.Accessor <<= aName;
597 	maContainerListeners.elementInserted( aEvent );
598 
599 	// our "tab controller model" has potentially changed -> notify this
600 	implNotifyTabModelChange( aName );
601 }
602 
603 void ControlModelContainerBase::removeByName( const ::rtl::OUString& aName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException)
604 {
605 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
606 
607 	UnoControlModelHolderList::iterator aElementPos = ImplFindElement( aName );
608 	if ( maModels.end() == aElementPos )
609         lcl_throwNoSuchElementException();
610 
611     ContainerEvent aEvent;
612 	aEvent.Source = *this;
613 	aEvent.Element <<= aElementPos->first;
614 	aEvent.Accessor <<= aName;
615 	maContainerListeners.elementRemoved( aEvent );
616 
617 	stopControlListening( aElementPos->first );
618     Reference< XPropertySet > xPS( aElementPos->first, UNO_QUERY );
619 	maModels.erase( aElementPos );
620 	mbGroupsUpToDate = sal_False;
621 
622     if ( xPS.is() )
623         try
624         {
625             xPS->setPropertyValue( PROPERTY_RESOURCERESOLVER, makeAny( Reference< resource::XStringResourceResolver >() ) );
626         }
627         catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
628 
629 	// our "tab controller model" has potentially changed -> notify this
630 	implNotifyTabModelChange( aName );
631 }
632 
633 // ----------------------------------------------------------------------------
634 sal_Bool SAL_CALL ControlModelContainerBase::getGroupControl(  ) throw (RuntimeException)
635 {
636 	return sal_True;
637 }
638 
639 // ----------------------------------------------------------------------------
640 void SAL_CALL ControlModelContainerBase::setGroupControl( sal_Bool ) throw (RuntimeException)
641 {
642 	DBG_ERROR( "UnoControlDialogModel::setGroupControl: explicit grouping not supported" );
643 }
644 
645 // ----------------------------------------------------------------------------
646 void SAL_CALL ControlModelContainerBase::setControlModels( const Sequence< Reference< XControlModel > >& _rControls ) throw (RuntimeException)
647 {
648 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
649 
650 	// set the tab indexes according to the order of models in the sequence
651 	const Reference< XControlModel >* pControls = _rControls.getConstArray( );
652 	const Reference< XControlModel >* pControlsEnd = _rControls.getConstArray( ) + _rControls.getLength();
653 
654 	sal_Int16 nTabIndex = 1;
655 
656 	for ( ; pControls != pControlsEnd; ++pControls )
657 	{
658 		// look up the control in our own structure. This is to prevent invalid arguments
659 		UnoControlModelHolderList::const_iterator aPos =
660 			::std::find_if(
661 				maModels.begin(), maModels.end(),
662 				CompareControlModel( *pControls )
663 			);
664 		if ( maModels.end() != aPos )
665 		{
666 			// okay, this is an existent model
667 			// now set the TabIndex property (if applicable)
668 			Reference< XPropertySet > xProps( aPos->first, UNO_QUERY );
669 			Reference< XPropertySetInfo > xPSI;
670 			if ( xProps.is() )
671 				xPSI = xProps->getPropertySetInfo();
672 			if ( xPSI.is() && xPSI->hasPropertyByName( getTabIndexPropertyName() ) )
673 				xProps->setPropertyValue( getTabIndexPropertyName(), makeAny( nTabIndex++ ) );
674 		}
675 		mbGroupsUpToDate = sal_False;
676 	}
677 }
678 
679 
680 typedef ::std::multimap< sal_Int32, Reference< XControlModel >, ::std::less< sal_Int32 > > MapIndexToModel;
681 
682 // ----------------------------------------------------------------------------
683 Sequence< Reference< XControlModel > > SAL_CALL ControlModelContainerBase::getControlModels(  ) throw (RuntimeException)
684 {
685 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
686 
687 	MapIndexToModel aSortedModels;
688 		// will be the sorted container of all models which have a tab index property
689 	::std::vector< Reference< XControlModel > > aUnindexedModels;
690 		// will be the container of all models which do not have a tab index property
691 
692 	UnoControlModelHolderList::const_iterator aLoop = maModels.begin();
693 	for ( ; aLoop != maModels.end(); ++aLoop )
694 	{
695 		Reference< XControlModel > xModel( aLoop->first );
696 
697 		// see if the model has a TabIndex property
698 		Reference< XPropertySet > xControlProps( xModel, UNO_QUERY );
699 		Reference< XPropertySetInfo > xPSI;
700 		if ( xControlProps.is() )
701 			xPSI = xControlProps->getPropertySetInfo( );
702 		DBG_ASSERT( xPSI.is(), "UnoControlDialogModel::getControlModels: invalid child model!" );
703 
704 		// has it?
705 		if ( xPSI.is() && xPSI->hasPropertyByName( getTabIndexPropertyName() ) )
706 		{	// yes
707 			sal_Int32 nTabIndex = -1;
708 			xControlProps->getPropertyValue( getTabIndexPropertyName() ) >>= nTabIndex;
709 
710 			aSortedModels.insert( MapIndexToModel::value_type( nTabIndex, xModel ) );
711 		}
712 		else if ( xModel.is() )
713 			// no, it hasn't, but we have to include it, anyway
714 			aUnindexedModels.push_back( xModel );
715 	}
716 
717 	// okay, here we have a container of all our models, sorted by tab index,
718 	// plus a container of "unindexed" models
719 	// -> merge them
720 	Sequence< Reference< XControlModel > > aReturn( aUnindexedModels.size() + aSortedModels.size() );
721 	::std::transform(
722 			aSortedModels.begin(), aSortedModels.end(),
723 			::std::copy( aUnindexedModels.begin(), aUnindexedModels.end(), aReturn.getArray() ),
724 			::std::select2nd< MapIndexToModel::value_type >( )
725 		);
726 
727 	return aReturn;
728 }
729 
730 // ----------------------------------------------------------------------------
731 void SAL_CALL ControlModelContainerBase::setGroup( const Sequence< Reference< XControlModel > >&, const ::rtl::OUString& ) throw (RuntimeException)
732 {
733 	// not supported. We have only implicit grouping:
734 	// We only have a sequence of control models, and we _know_ (yes, that's a HACK relying on
735 	// implementation details) that VCL does grouping according to the order of controls automatically
736 	// At least VCL does this for all we're interested in: Radio buttons.
737 	DBG_ERROR( "UnoControlDialogModel::setGroup: grouping not supported" );
738 }
739 
740 ////----- XInitialization -------------------------------------------------------------------
741 void SAL_CALL ControlModelContainerBase::initialize (const Sequence<Any>& rArguments) throw (com::sun::star::uno::Exception, com::sun::star::uno::RuntimeException)
742 {
743 	sal_Int16 nPageId = -1;
744 	if ( rArguments.getLength() == 1 )
745     {
746          if ( !( rArguments[ 0 ] >>= nPageId ))
747              throw lang::IllegalArgumentException();
748         m_nTabPageId = nPageId;
749     }
750 	else
751 		m_nTabPageId = -1;
752 }
753 ::sal_Int16 SAL_CALL ControlModelContainerBase::getTabPageID() throw (::com::sun::star::uno::RuntimeException)
754 {
755 	return m_nTabPageId;
756 }
757 ::sal_Bool SAL_CALL ControlModelContainerBase::getEnabled() throw (::com::sun::star::uno::RuntimeException)
758 {
759 	return m_bEnabled;
760 }
761 void SAL_CALL ControlModelContainerBase::setEnabled( ::sal_Bool _enabled ) throw (::com::sun::star::uno::RuntimeException)
762 {
763 	m_bEnabled = _enabled;
764 }
765 ::rtl::OUString SAL_CALL ControlModelContainerBase::getTitle() throw (::com::sun::star::uno::RuntimeException)
766 {
767     vos::OGuard aSolarGuard( Application::GetSolarMutex() );
768 	Reference<XPropertySet> xThis(*this,UNO_QUERY);
769     ::rtl::OUString sTitle;
770     xThis->getPropertyValue(GetPropertyName(BASEPROPERTY_TITLE)) >>= sTitle;
771     return sTitle;
772 	//return m_sTitle;
773 }
774 void SAL_CALL ControlModelContainerBase::setTitle( const ::rtl::OUString& _title ) throw (::com::sun::star::uno::RuntimeException)
775 {
776     vos::OGuard aSolarGuard( Application::GetSolarMutex() );
777     Reference<XPropertySet> xThis(*this,UNO_QUERY);
778     xThis->setPropertyValue(GetPropertyName(BASEPROPERTY_TITLE),makeAny(_title));
779 }
780 ::rtl::OUString SAL_CALL ControlModelContainerBase::getImageURL() throw (::com::sun::star::uno::RuntimeException)
781 {
782 	return m_sImageURL;
783 }
784 void SAL_CALL ControlModelContainerBase::setImageURL( const ::rtl::OUString& _imageurl ) throw (::com::sun::star::uno::RuntimeException)
785 {
786 	m_sImageURL = _imageurl;
787 }
788 ::rtl::OUString SAL_CALL ControlModelContainerBase::getToolTip() throw (::com::sun::star::uno::RuntimeException)
789 {
790 	return m_sTooltip;
791 }
792 void SAL_CALL ControlModelContainerBase::setToolTip( const ::rtl::OUString& _tooltip ) throw (::com::sun::star::uno::RuntimeException)
793 {
794 	m_sTooltip = _tooltip;
795 }
796 
797 // ----------------------------------------------------------------------------
798 namespace
799 {
800 	enum GroupingMachineState
801 	{
802 		eLookingForGroup,
803 		eExpandingGroup
804 	};
805 
806 	// ........................................................................
807 	static sal_Int32 lcl_getDialogStep( const Reference< XControlModel >& _rxModel )
808 	{
809 		sal_Int32 nStep = 0;
810 		try
811 		{
812 			Reference< XPropertySet > xModelProps( _rxModel, UNO_QUERY );
813 			xModelProps->getPropertyValue( getStepPropertyName() ) >>= nStep;
814 		}
815 		catch( const Exception& )
816 		{
817 			DBG_ERROR( "lcl_getDialogStep: caught an exception while determining the dialog page!" );
818 		}
819 		return nStep;
820 	}
821 }
822 
823 // ----------------------------------------------------------------------------
824 sal_Int32 SAL_CALL ControlModelContainerBase::getGroupCount(  ) throw (RuntimeException)
825 {
826 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
827 
828 	implUpdateGroupStructure();
829 
830 	return maGroups.size();
831 }
832 
833 // ----------------------------------------------------------------------------
834 void SAL_CALL ControlModelContainerBase::getGroup( sal_Int32 _nGroup, Sequence< Reference< XControlModel > >& _rGroup, ::rtl::OUString& _rName ) throw (RuntimeException)
835 {
836 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
837 
838 	implUpdateGroupStructure();
839 
840 	if ( ( _nGroup < 0 ) || ( _nGroup >= (sal_Int32)maGroups.size() ) )
841 	{
842 		DBG_ERROR( "UnoControlDialogModel::getGroup: invalid argument and I am not allowed to throw an exception!" );
843 		_rGroup.realloc( 0 );
844 		_rName = ::rtl::OUString();
845 	}
846 	else
847 	{
848 		AllGroups::const_iterator aGroupPos = maGroups.begin() + _nGroup;
849 		_rGroup.realloc( aGroupPos->size() );
850 		// copy the models
851 		::std::copy( aGroupPos->begin(), aGroupPos->end(), _rGroup.getArray() );
852 		// give the group a name
853 		_rName = ::rtl::OUString::valueOf( _nGroup );
854 	}
855 }
856 
857 // ----------------------------------------------------------------------------
858 void SAL_CALL ControlModelContainerBase::getGroupByName( const ::rtl::OUString& _rName, Sequence< Reference< XControlModel > >& _rGroup ) throw (RuntimeException)
859 {
860 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
861 
862 	::rtl::OUString sDummyName;
863 	getGroup( _rName.toInt32( ), _rGroup, sDummyName );
864 }
865 
866 // ----------------------------------------------------------------------------
867 void SAL_CALL ControlModelContainerBase::addChangesListener( const Reference< XChangesListener >& _rxListener ) throw (RuntimeException)
868 {
869 	maChangeListeners.addInterface( _rxListener );
870 }
871 
872 // ----------------------------------------------------------------------------
873 void SAL_CALL ControlModelContainerBase::removeChangesListener( const Reference< XChangesListener >& _rxListener ) throw (RuntimeException)
874 {
875 	maChangeListeners.removeInterface( _rxListener );
876 }
877 
878 // ----------------------------------------------------------------------------
879 void ControlModelContainerBase::implNotifyTabModelChange( const ::rtl::OUString& _rAccessor )
880 {
881 	// multiplex to our change listeners:
882 	// the changes event
883 	ChangesEvent aEvent;
884 	aEvent.Source = *this;
885 	aEvent.Base <<= aEvent.Source;	// the "base of the changes root" is also ourself
886 	aEvent.Changes.realloc( 1 );	// exactly one change
887 	aEvent.Changes[ 0 ].Accessor <<= _rAccessor;
888 
889 
890 	Sequence< Reference< XInterface > > aChangeListeners( maChangeListeners.getElements() );
891 	const Reference< XInterface >* pListener = aChangeListeners.getConstArray();
892 	const Reference< XInterface >* pListenerEnd = aChangeListeners.getConstArray() + aChangeListeners.getLength();
893 	for ( ; pListener != pListenerEnd; ++pListener )
894 	{
895 		if ( pListener->is() )
896 			static_cast< XChangesListener* >( pListener->get() )->changesOccurred( aEvent );
897 	}
898 }
899 
900 
901 // ----------------------------------------------------------------------------
902 void ControlModelContainerBase::implUpdateGroupStructure()
903 {
904 	if ( mbGroupsUpToDate )
905 		// nothing to do
906 		return;
907 
908 	// conditions for a group:
909 	// * all elements of the group are radio buttons
910 	// * all elements of the group are on the same dialog page
911 	// * in the overall control order (determined by the tab index), all elements are subsequent
912 
913 	maGroups.clear();
914 
915 	Sequence< Reference< XControlModel > > aControlModels = getControlModels();
916 	const Reference< XControlModel >* pControlModels = aControlModels.getConstArray();
917 	const Reference< XControlModel >* pControlModelsEnd = pControlModels + aControlModels.getLength();
918 
919 	// in extreme we have as much groups as controls
920 	maGroups.reserve( aControlModels.getLength() );
921 
922 	GroupingMachineState eState = eLookingForGroup;		// the current state of our machine
923 	Reference< XServiceInfo > xModelSI;					// for checking for a radion button
924 	AllGroups::iterator aCurrentGroup = maGroups.end();	// the group which we're currently building
925 	sal_Int32	nCurrentGroupStep = -1;					// the step which all controls of the current group belong to
926 	sal_Bool	bIsRadioButton;							// is it a radio button?
927 
928 #if OSL_DEBUG_LEVEL > 1
929 	::std::vector< ::rtl::OUString > aCurrentGroupLabels;
930 #endif
931 
932 	for ( ; pControlModels != pControlModelsEnd; ++pControlModels )
933 	{
934 		// we'll need this in every state
935 		xModelSI = xModelSI.query( *pControlModels );
936 		bIsRadioButton = xModelSI.is() && xModelSI->supportsService( ::rtl::OUString::createFromAscii( szServiceName2_UnoControlRadioButtonModel ) );
937 
938 		switch ( eState )
939 		{
940 			case eLookingForGroup:
941 			{
942 				if ( !bIsRadioButton )
943 					// this is no radio button -> still looking for the beginning of a group
944 					continue;
945 				// the current model is a radio button
946 				// -> we found the beginning of a new group
947 				// create the place for this group
948 				size_t nGroups = maGroups.size();
949 				maGroups.resize( nGroups + 1 );
950 				aCurrentGroup = maGroups.begin() + nGroups;
951 				// and add the (only, til now) member
952 				aCurrentGroup->push_back( *pControlModels );
953 
954 				// get the step which all controls of this group now have to belong to
955 				nCurrentGroupStep = lcl_getDialogStep( *pControlModels );
956 				// new state: looking for further members
957 				eState = eExpandingGroup;
958 
959 #if OSL_DEBUG_LEVEL > 1
960 				Reference< XPropertySet > xModelProps( *pControlModels, UNO_QUERY );
961 				::rtl::OUString sLabel;
962 				if ( xModelProps.is() && xModelProps->getPropertySetInfo().is() && xModelProps->getPropertySetInfo()->hasPropertyByName( ::rtl::OUString::createFromAscii( "Label" ) ) )
963 					xModelProps->getPropertyValue( ::rtl::OUString::createFromAscii( "Label" ) ) >>= sLabel;
964 				aCurrentGroupLabels.push_back( sLabel );
965 #endif
966 			}
967 			break;
968 
969 			case eExpandingGroup:
970 			{
971 				if ( !bIsRadioButton )
972 				{	// no radio button -> the group is done
973 					aCurrentGroup = maGroups.end();
974 					eState = eLookingForGroup;
975 #if OSL_DEBUG_LEVEL > 1
976 					aCurrentGroupLabels.clear();
977 #endif
978 					continue;
979 				}
980 
981 				// it is a radio button - is it on the proper page?
982 				const sal_Int32 nThisModelStep = lcl_getDialogStep( *pControlModels );
983 				if	(	( nThisModelStep == nCurrentGroupStep )	// the current button is on the same dialog page
984 					||	( 0 == nThisModelStep )					// the current button appears on all pages
985 					)
986 				{
987 					// -> it belongs to the same group
988 					aCurrentGroup->push_back( *pControlModels );
989 					// state still is eExpandingGroup - we're looking for further elements
990 					eState = eExpandingGroup;
991 
992 #if OSL_DEBUG_LEVEL > 1
993 					Reference< XPropertySet > xModelProps( *pControlModels, UNO_QUERY );
994 					::rtl::OUString sLabel;
995 					if ( xModelProps.is() && xModelProps->getPropertySetInfo().is() && xModelProps->getPropertySetInfo()->hasPropertyByName( ::rtl::OUString::createFromAscii( "Label" ) ) )
996 						xModelProps->getPropertyValue( ::rtl::OUString::createFromAscii( "Label" ) ) >>= sLabel;
997 					aCurrentGroupLabels.push_back( sLabel );
998 #endif
999 					continue;
1000 				}
1001 
1002 				// it's a radio button, but on a different page
1003 				// -> we open a new group for it
1004 
1005 				// close the old group
1006 				aCurrentGroup = maGroups.end();
1007 #if OSL_DEBUG_LEVEL > 1
1008 				aCurrentGroupLabels.clear();
1009 #endif
1010 
1011 				// open a new group
1012 				size_t nGroups = maGroups.size();
1013 				maGroups.resize( nGroups + 1 );
1014 				aCurrentGroup = maGroups.begin() + nGroups;
1015 				// and add the (only, til now) member
1016 				aCurrentGroup->push_back( *pControlModels );
1017 
1018 				nCurrentGroupStep = nThisModelStep;
1019 
1020 				// state is the same: we still are looking for further elements of the current group
1021 				eState = eExpandingGroup;
1022 #if OSL_DEBUG_LEVEL > 1
1023 				Reference< XPropertySet > xModelProps( *pControlModels, UNO_QUERY );
1024 				::rtl::OUString sLabel;
1025 				if ( xModelProps.is() && xModelProps->getPropertySetInfo().is() && xModelProps->getPropertySetInfo()->hasPropertyByName( ::rtl::OUString::createFromAscii( "Label" ) ) )
1026 					xModelProps->getPropertyValue( ::rtl::OUString::createFromAscii( "Label" ) ) >>= sLabel;
1027 				aCurrentGroupLabels.push_back( sLabel );
1028 #endif
1029 			}
1030 			break;
1031 		}
1032 	}
1033 
1034 	mbGroupsUpToDate = sal_True;
1035 }
1036 
1037 // ----------------------------------------------------------------------------
1038 void SAL_CALL ControlModelContainerBase::propertyChange( const PropertyChangeEvent& _rEvent ) throw (RuntimeException)
1039 {
1040 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1041 
1042 	DBG_ASSERT( 0 == _rEvent.PropertyName.compareToAscii( "TabIndex" ),
1043 		"UnoControlDialogModel::propertyChange: not listening for this property!" );
1044 
1045 	// the accessor for the changed element
1046 	::rtl::OUString sAccessor;
1047 	UnoControlModelHolderList::const_iterator aPos =
1048 		::std::find_if(
1049 			maModels.begin(), maModels.end(),
1050 			CompareControlModel( Reference< XControlModel >( _rEvent.Source, UNO_QUERY ) )
1051 		);
1052 	OSL_ENSURE( maModels.end() != aPos, "UnoControlDialogModel::propertyChange: don't know this model!" );
1053 	if ( maModels.end() != aPos )
1054 		sAccessor = aPos->second;
1055 
1056 	// our groups are not up-to-date
1057 	mbGroupsUpToDate = sal_False;
1058 
1059 	// notify
1060 	implNotifyTabModelChange( sAccessor );
1061 }
1062 
1063 // ----------------------------------------------------------------------------
1064 void SAL_CALL ControlModelContainerBase::disposing( const EventObject& /*rEvent*/ ) throw (RuntimeException)
1065 {
1066 }
1067 
1068 // ----------------------------------------------------------------------------
1069 void ControlModelContainerBase::startControlListening( const Reference< XControlModel >& _rxChildModel )
1070 {
1071 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1072 
1073 	Reference< XPropertySet > xModelProps( _rxChildModel, UNO_QUERY );
1074 	Reference< XPropertySetInfo > xPSI;
1075 	if ( xModelProps.is() )
1076 		xPSI = xModelProps->getPropertySetInfo();
1077 
1078 	if ( xPSI.is() && xPSI->hasPropertyByName( getTabIndexPropertyName() ) )
1079 		xModelProps->addPropertyChangeListener( getTabIndexPropertyName(), this );
1080 }
1081 
1082 // ----------------------------------------------------------------------------
1083 void ControlModelContainerBase::stopControlListening( const Reference< XControlModel >& _rxChildModel )
1084 {
1085 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1086 
1087 	Reference< XPropertySet > xModelProps( _rxChildModel, UNO_QUERY );
1088 	Reference< XPropertySetInfo > xPSI;
1089 	if ( xModelProps.is() )
1090 		xPSI = xModelProps->getPropertySetInfo();
1091 
1092 	if ( xPSI.is() && xPSI->hasPropertyByName( getTabIndexPropertyName() ) )
1093 		xModelProps->removePropertyChangeListener( getTabIndexPropertyName(), this );
1094 }
1095 
1096 // ============================================================================
1097 // = class ResourceListener
1098 // ============================================================================
1099 
1100 ResourceListener::ResourceListener(
1101     const Reference< util::XModifyListener >& rListener ) :
1102     OWeakObject(),
1103     m_xListener( rListener ),
1104     m_bListening( false )
1105 {
1106 }
1107 
1108 ResourceListener::~ResourceListener()
1109 {
1110 }
1111 
1112 // XInterface
1113 Any SAL_CALL ResourceListener::queryInterface( const Type& rType )
1114 throw ( RuntimeException )
1115 {
1116 	Any a = ::cppu::queryInterface(
1117 				rType ,
1118                 static_cast< XModifyListener* >( this ),
1119 				static_cast< XEventListener* >( this ));
1120 
1121 	if ( a.hasValue() )
1122 		return a;
1123 
1124 	return OWeakObject::queryInterface( rType );
1125 }
1126 
1127 void SAL_CALL ResourceListener::acquire() throw ()
1128 {
1129     OWeakObject::acquire();
1130 }
1131 
1132 void SAL_CALL ResourceListener::release() throw ()
1133 {
1134     OWeakObject::release();
1135 }
1136 
1137 void ResourceListener::startListening(
1138     const Reference< resource::XStringResourceResolver  >& rResource )
1139 {
1140     Reference< util::XModifyBroadcaster > xModifyBroadcaster( rResource, UNO_QUERY );
1141 
1142     {
1143         // --- SAFE ---
1144 		::osl::ResettableGuard < ::osl::Mutex > aGuard( m_aMutex );
1145 		bool bListening( m_bListening );
1146 		bool bResourceSet( m_xResource.is() );
1147 		aGuard.clear();
1148 		// --- SAFE ---
1149 
1150         if ( bListening && bResourceSet )
1151             stopListening();
1152 
1153         // --- SAFE ---
1154         aGuard.reset();
1155         m_xResource = rResource;
1156         aGuard.clear();
1157         // --- SAFE ---
1158     }
1159 
1160     Reference< util::XModifyListener > xThis( static_cast<OWeakObject*>( this ), UNO_QUERY );
1161     if ( xModifyBroadcaster.is() )
1162     {
1163         try
1164         {
1165             xModifyBroadcaster->addModifyListener( xThis );
1166 
1167             // --- SAFE ---
1168             ::osl::ResettableGuard < ::osl::Mutex > aGuard( m_aMutex );
1169             m_bListening = true;
1170             // --- SAFE ---
1171         }
1172         catch ( RuntimeException& )
1173         {
1174             throw;
1175         }
1176         catch ( Exception& )
1177         {
1178         }
1179     }
1180 }
1181 
1182 void ResourceListener::stopListening()
1183 {
1184     Reference< util::XModifyBroadcaster > xModifyBroadcaster;
1185 
1186     // --- SAFE ---
1187     ::osl::ResettableGuard < ::osl::Mutex > aGuard( m_aMutex );
1188     if ( m_bListening && m_xResource.is() )
1189         xModifyBroadcaster = Reference< util::XModifyBroadcaster >( m_xResource, UNO_QUERY );
1190     aGuard.clear();
1191     // --- SAFE ---
1192 
1193     Reference< util::XModifyListener > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1194     if ( xModifyBroadcaster.is() )
1195     {
1196         try
1197         {
1198             // --- SAFE ---
1199             aGuard.reset();
1200             m_bListening = false;
1201             m_xResource.clear();
1202             aGuard.clear();
1203             // --- SAFE ---
1204 
1205             xModifyBroadcaster->removeModifyListener( xThis );
1206         }
1207         catch ( RuntimeException& )
1208         {
1209             throw;
1210         }
1211         catch ( Exception& )
1212         {
1213         }
1214     }
1215 }
1216 
1217 // XModifyListener
1218 void SAL_CALL ResourceListener::modified(
1219     const lang::EventObject& aEvent )
1220 throw ( RuntimeException )
1221 {
1222     Reference< util::XModifyListener > xListener;
1223 
1224     // --- SAFE ---
1225     ::osl::ResettableGuard < ::osl::Mutex > aGuard( m_aMutex );
1226     xListener = m_xListener;
1227     aGuard.clear();
1228     // --- SAFE ---
1229 
1230     if ( xListener.is() )
1231     {
1232         try
1233         {
1234             xListener->modified( aEvent );
1235         }
1236         catch ( RuntimeException& )
1237         {
1238             throw;
1239         }
1240         catch ( Exception& )
1241         {
1242         }
1243     }
1244 }
1245 
1246 // XEventListener
1247 void SAL_CALL ResourceListener::disposing(
1248     const EventObject& Source )
1249 throw ( RuntimeException )
1250 {
1251     Reference< lang::XEventListener > xListener;
1252     Reference< resource::XStringResourceResolver > xResource;
1253 
1254     // --- SAFE ---
1255     ::osl::ResettableGuard < ::osl::Mutex > aGuard( m_aMutex );
1256     Reference< XInterface > xIfacRes( m_xResource, UNO_QUERY );
1257     Reference< XInterface > xIfacList( m_xListener, UNO_QUERY );
1258     aGuard.clear();
1259     // --- SAFE ---
1260 
1261     if ( Source.Source == xIfacRes )
1262     {
1263         // --- SAFE ---
1264         aGuard.reset();
1265         m_bListening = false;
1266         xResource = m_xResource;
1267         xListener = Reference< lang::XEventListener >( m_xListener, UNO_QUERY );
1268         m_xResource.clear();
1269         aGuard.clear();
1270         // --- SAFE ---
1271 
1272         if ( xListener.is() )
1273         {
1274             try
1275             {
1276                 xListener->disposing( Source );
1277             }
1278             catch ( RuntimeException& )
1279             {
1280                 throw;
1281             }
1282             catch ( Exception& )
1283             {
1284             }
1285         }
1286     }
1287     else if ( Source.Source == xIfacList )
1288     {
1289         // --- SAFE ---
1290         aGuard.reset();
1291         m_bListening = false;
1292         xListener = Reference< lang::XEventListener >( m_xListener, UNO_QUERY );
1293         xResource = m_xResource;
1294         m_xResource.clear();
1295         m_xListener.clear();
1296         aGuard.clear();
1297         // --- SAFE ---
1298 
1299         // Remove ourself as listener from resource resolver
1300         Reference< util::XModifyBroadcaster > xModifyBroadcaster( xResource, UNO_QUERY );
1301         Reference< util::XModifyListener > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1302         if ( xModifyBroadcaster.is() )
1303         {
1304             try
1305             {
1306                 xModifyBroadcaster->removeModifyListener( xThis );
1307             }
1308             catch ( RuntimeException& )
1309             {
1310                 throw;
1311             }
1312             catch ( Exception& )
1313             {
1314             }
1315         }
1316     }
1317 }
1318 
1319 //===============================================================
1320 //	----------------------------------------------------
1321 //	class DialogContainerControl
1322 //	----------------------------------------------------
1323 ControlContainerBase::ControlContainerBase( const Reference< XMultiServiceFactory >& i_factory )
1324     :ContainerControl_IBase( i_factory )
1325     ,mbSizeModified(false)
1326     ,mbPosModified(false)
1327 {
1328 	maComponentInfos.nWidth = 280;
1329 	maComponentInfos.nHeight = 400;
1330 	mxListener = new ResourceListener( Reference< util::XModifyListener >(
1331                         static_cast< OWeakObject* >( this ), UNO_QUERY ));
1332 }
1333 
1334 ControlContainerBase::~ControlContainerBase()
1335 {
1336 }
1337 
1338 void ControlContainerBase::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer >  & rParentPeer ) throw(RuntimeException)
1339 {
1340     vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1341     UnoControlContainer::createPeer( rxToolkit, rParentPeer );
1342 }
1343 
1344 void ControlContainerBase::ImplInsertControl( Reference< XControlModel >& rxModel, const ::rtl::OUString& rName )
1345 {
1346     Reference< XPropertySet > xP( rxModel, UNO_QUERY );
1347 
1348     ::rtl::OUString aDefCtrl;
1349     xP->getPropertyValue( GetPropertyName( BASEPROPERTY_DEFAULTCONTROL ) ) >>= aDefCtrl;
1350 	Reference < XControl > xCtrl;
1351     maContext.createComponent( aDefCtrl, xCtrl );
1352 
1353     DBG_ASSERT( xCtrl.is(), "ControlContainerBase::ImplInsertControl: could not create the control!" );
1354     if ( xCtrl.is() )
1355     {
1356         xCtrl->setModel( rxModel );
1357         addControl( rName, xCtrl );
1358             // will implicitly call addingControl, where we can add the PropertiesChangeListener to the model
1359             // (which we formerly did herein)
1360             // 08.01.2001 - 96008 - fs@openoffice.org
1361 
1362         ImplSetPosSize( xCtrl );
1363     }
1364 }
1365 
1366 void ControlContainerBase::ImplRemoveControl( Reference< XControlModel >& rxModel )
1367 {
1368     Sequence< Reference< XControl > > aControls = getControls();
1369     Reference< XControl > xCtrl = StdTabController::FindControl( aControls, rxModel );
1370     if ( xCtrl.is() )
1371     {
1372         removeControl( xCtrl );
1373         try
1374         {
1375             Reference< XComponent > const xControlComp( xCtrl, UNO_QUERY_THROW );
1376             xControlComp->dispose();
1377         }
1378         catch( Exception const & )
1379         {
1380             DBG_UNHANDLED_EXCEPTION();
1381         }
1382     }
1383 }
1384 
1385 void ControlContainerBase::ImplSetPosSize( Reference< XControl >& rxCtrl )
1386 {
1387     Reference< XPropertySet > xP( rxCtrl->getModel(), UNO_QUERY );
1388 
1389     sal_Int32 nX = 0, nY = 0, nWidth = 0, nHeight = 0;
1390     xP->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PositionX" ) ) ) >>= nX;
1391     xP->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PositionY" ) ) ) >>= nY;
1392     xP->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Width" ) ) ) >>= nWidth;
1393     xP->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Height" ) ) ) >>= nHeight;
1394 	MapMode aMode( MAP_APPFONT );
1395     OutputDevice*pOutDev = Application::GetDefaultDevice();
1396     if ( pOutDev )
1397     {
1398         ::Size aTmp( nX, nY );
1399 		aTmp = pOutDev->LogicToPixel( aTmp, aMode );
1400         nX = aTmp.Width();
1401         nY = aTmp.Height();
1402         aTmp = ::Size( nWidth, nHeight );
1403 		aTmp = pOutDev->LogicToPixel( aTmp, aMode );
1404         nWidth = aTmp.Width();
1405         nHeight = aTmp.Height();
1406     }
1407     else
1408     {
1409         Reference< XWindowPeer > xPeer = ImplGetCompatiblePeer( sal_True );
1410         Reference< XDevice > xD( xPeer, UNO_QUERY );
1411 
1412         SimpleFontMetric aFM;
1413         FontDescriptor aFD;
1414         Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_FONTDESCRIPTOR ) );
1415         aVal >>= aFD;
1416         if ( aFD.StyleName.getLength() )
1417         {
1418             Reference< XFont > xFont = xD->getFont( aFD );
1419             aFM = xFont->getFontMetric();
1420         }
1421         else
1422         {
1423             Reference< XGraphics > xG = xD->createGraphics();
1424             aFM = xG->getFontMetric();
1425         }
1426 
1427         sal_Int16 nH = aFM.Ascent + aFM.Descent;
1428         sal_Int16 nW = nH/2;	// calculate avarage width?!
1429 
1430         nX *= nW;
1431         nX /= 4;
1432         nWidth *= nW;
1433         nWidth /= 4;
1434         nY *= nH;
1435         nY /= 8;
1436         nHeight *= nH;
1437         nHeight /= 8;
1438     }
1439     Reference < XWindow > xW( rxCtrl, UNO_QUERY );
1440     xW->setPosSize( nX, nY, nWidth, nHeight, PosSize::POSSIZE );
1441 }
1442 
1443 void ControlContainerBase::dispose() throw(RuntimeException)
1444 {
1445 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1446 
1447 	EventObject aEvt;
1448 	aEvt.Source = static_cast< ::cppu::OWeakObject* >( this );
1449 	// Notify our listener helper about dispose
1450     // --- SAFE ---
1451     ::osl::ResettableGuard< ::osl::Mutex > aGuard( GetMutex() );
1452     Reference< XEventListener > xListener( mxListener, UNO_QUERY );
1453     mxListener.clear();
1454     aGuard.clear();
1455     // --- SAFE ---
1456 
1457     if ( xListener.is() )
1458         xListener->disposing( aEvt );
1459     UnoControlContainer::dispose();
1460 }
1461 
1462 void SAL_CALL ControlContainerBase::disposing(
1463     const EventObject& Source )
1464 throw(RuntimeException)
1465 {
1466     UnoControlContainer::disposing( Source );
1467 }
1468 
1469 sal_Bool ControlContainerBase::setModel( const Reference< XControlModel >& rxModel ) throw(RuntimeException)
1470 {
1471     vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1472 
1473     // destroy the old tab controller, if existent
1474     if ( mxTabController.is() )
1475     {
1476         mxTabController->setModel( NULL );					// just to be sure, should not be necessary
1477         removeTabController( mxTabController );
1478         ::comphelper::disposeComponent( mxTabController );	// just to be sure, should not be necessary
1479         mxTabController.clear();
1480     }
1481 
1482     if ( getModel().is() )
1483     {
1484         Sequence< Reference< XControl > > aControls = getControls();
1485         const Reference< XControl >* pCtrls = aControls.getConstArray();
1486         const Reference< XControl >* pCtrlsEnd = pCtrls + aControls.getLength();
1487 
1488         for ( ; pCtrls < pCtrlsEnd; ++pCtrls )
1489             removeControl( *pCtrls );
1490                 // will implicitly call removingControl, which will remove the PropertyChangeListener
1491                 // (which we formerly did herein)
1492                 // 08.01.2001 - 96008 - fs@openoffice.org
1493 
1494         Reference< XContainer > xC( getModel(), UNO_QUERY );
1495         if ( xC.is() )
1496             xC->removeContainerListener( this );
1497 
1498         Reference< XChangesNotifier > xChangeNotifier( getModel(), UNO_QUERY );
1499         if ( xChangeNotifier.is() )
1500             xChangeNotifier->removeChangesListener( this );
1501     }
1502 
1503     sal_Bool bRet = UnoControl::setModel( rxModel );
1504 
1505     if ( getModel().is() )
1506     {
1507         Reference< XNameAccess > xNA( getModel(), UNO_QUERY );
1508         if ( xNA.is() )
1509         {
1510             Sequence< ::rtl::OUString > aNames = xNA->getElementNames();
1511             const ::rtl::OUString* pNames = aNames.getConstArray();
1512             sal_uInt32 nCtrls = aNames.getLength();
1513 
1514             Reference< XControlModel > xCtrlModel;
1515             for( sal_uInt32 n = 0; n < nCtrls; ++n, ++pNames )
1516             {
1517                 xNA->getByName( *pNames ) >>= xCtrlModel;
1518                 ImplInsertControl( xCtrlModel, *pNames );
1519             }
1520         }
1521 
1522         Reference< XContainer > xC( getModel(), UNO_QUERY );
1523         if ( xC.is() )
1524             xC->addContainerListener( this );
1525 
1526         Reference< XChangesNotifier > xChangeNotifier( getModel(), UNO_QUERY );
1527         if ( xChangeNotifier.is() )
1528             xChangeNotifier->addChangesListener( this );
1529     }
1530 
1531     Reference< XTabControllerModel > xTabbing( getModel(), UNO_QUERY );
1532     if ( xTabbing.is() )
1533     {
1534         mxTabController = new StdTabController;
1535         mxTabController->setModel( xTabbing );
1536         addTabController( mxTabController );
1537     }
1538     ImplStartListingForResourceEvents();
1539 
1540     return bRet;
1541 }
1542 void ControlContainerBase::setDesignMode( sal_Bool bOn ) throw(RuntimeException)
1543 {
1544     vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1545     ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
1546 
1547     UnoControl::setDesignMode( bOn );
1548 
1549     Sequence< Reference< XControl > > xCtrls = getControls();
1550     sal_Int32 nControls = xCtrls.getLength();
1551     Reference< XControl >* pControls = xCtrls.getArray();
1552     for ( sal_Int32 n = 0; n < nControls; n++ )
1553         pControls[n]->setDesignMode( bOn );
1554 
1555     // #109067# in design mode the tab controller is not notified about
1556     // tab index changes, therefore the tab order must be activated
1557     // when switching from design mode to live mode
1558     if ( mxTabController.is() && !bOn )
1559         mxTabController->activateTabOrder();
1560 }
1561 
1562 void ControlContainerBase::elementInserted( const ContainerEvent& Event ) throw(RuntimeException)
1563 {
1564     vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1565 
1566     Reference< XControlModel > xModel;
1567     ::rtl::OUString aName;
1568 
1569     Event.Accessor >>= aName;
1570     Event.Element >>= xModel;
1571     ENSURE_OR_RETURN_VOID( xModel.is(), "ControlContainerBase::elementInserted: illegal element!" );
1572     try
1573     {
1574 	    ImplInsertControl( xModel, aName );
1575     }
1576     catch ( const RuntimeException& e ) { throw; }
1577     catch( const Exception& )
1578     {
1579     	DBG_UNHANDLED_EXCEPTION();
1580     }
1581 }
1582 
1583 void ControlContainerBase::elementRemoved( const ContainerEvent& Event ) throw(RuntimeException)
1584 {
1585     vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1586 
1587     Reference< XControlModel > xModel;
1588     Event.Element >>= xModel;
1589     ENSURE_OR_RETURN_VOID( xModel.is(), "ControlContainerBase::elementRemoved: illegal element!" );
1590     try
1591     {
1592 	    ImplRemoveControl( xModel );
1593     }
1594     catch ( const RuntimeException& e ) { throw; }
1595     catch( const Exception& )
1596     {
1597 	    DBG_UNHANDLED_EXCEPTION();
1598     }
1599 }
1600 
1601 void ControlContainerBase::elementReplaced( const ContainerEvent& Event ) throw(RuntimeException)
1602 {
1603     vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1604 
1605     Reference< XControlModel > xModel;
1606     Event.ReplacedElement >>= xModel;
1607     try
1608     {
1609         OSL_ENSURE( xModel.is(), "ControlContainerBase::elementReplaced: invalid ReplacedElement!" );
1610         if ( xModel.is() )
1611 	        ImplRemoveControl( xModel );
1612     }
1613     catch ( const RuntimeException& e ) { throw; }
1614     catch( const Exception& )
1615     {
1616 	    DBG_UNHANDLED_EXCEPTION();
1617     }
1618 
1619     ::rtl::OUString aName;
1620     Event.Accessor >>= aName;
1621     Event.Element >>= xModel;
1622     ENSURE_OR_RETURN_VOID( xModel.is(), "ControlContainerBase::elementReplaced: invalid new element!" );
1623     try
1624     {
1625 	    ImplInsertControl( xModel, aName );
1626     }
1627     catch ( const RuntimeException& e ) { throw; }
1628     catch( const Exception& )
1629     {
1630     	DBG_UNHANDLED_EXCEPTION();
1631     }
1632 }
1633 
1634 // XPropertiesChangeListener
1635 void ControlContainerBase::ImplModelPropertiesChanged( const Sequence< PropertyChangeEvent >& rEvents ) throw(RuntimeException)
1636 {
1637     if( !isDesignMode() && !mbCreatingCompatiblePeer )
1638     {
1639         ::rtl::OUString s1( RTL_CONSTASCII_USTRINGPARAM( "PositionX" ) );
1640         ::rtl::OUString s2( RTL_CONSTASCII_USTRINGPARAM( "PositionY" ) );
1641         ::rtl::OUString s3( RTL_CONSTASCII_USTRINGPARAM( "Width" ) );
1642         ::rtl::OUString s4( RTL_CONSTASCII_USTRINGPARAM( "Height" ) );
1643 
1644         sal_Int32 nLen = rEvents.getLength();
1645         for( sal_Int32 i = 0; i < nLen; i++ )
1646         {
1647             const PropertyChangeEvent& rEvt = rEvents.getConstArray()[i];
1648             Reference< XControlModel > xModel( rEvt.Source, UNO_QUERY );
1649             sal_Bool bOwnModel = (XControlModel*)xModel.get() == (XControlModel*)getModel().get();
1650             if ( ( rEvt.PropertyName == s1 ) ||
1651                  ( rEvt.PropertyName == s2 ) ||
1652                  ( rEvt.PropertyName == s3 ) ||
1653                  ( rEvt.PropertyName == s4 ) )
1654             {
1655                 if ( bOwnModel )
1656                 {
1657                     if ( !mbPosModified && !mbSizeModified )
1658                     {
1659                         // Don't set new pos/size if we get new values from window listener
1660                         Reference< XControl > xThis( (XAggregation*)(::cppu::OWeakAggObject*)this, UNO_QUERY );
1661                         ImplSetPosSize( xThis );
1662                     }
1663                 }
1664                 else
1665                 {
1666                     Sequence<Reference<XControl> > aControlSequence(getControls());
1667                     Reference<XControl> aControlRef( StdTabController::FindControl( aControlSequence, xModel ) );
1668                     ImplSetPosSize( aControlRef );
1669                 }
1670                 break;
1671             }
1672         }
1673     }
1674 
1675     UnoControlContainer::ImplModelPropertiesChanged( rEvents );
1676 }
1677 
1678 void ControlContainerBase::addingControl( const Reference< XControl >& _rxControl )
1679 {
1680     vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1681     UnoControlContainer::addingControl( _rxControl );
1682 
1683     if ( _rxControl.is() )
1684     {
1685         Reference< XMultiPropertySet > xProps( _rxControl->getModel(), UNO_QUERY );
1686         if ( xProps.is() )
1687         {
1688             Sequence< ::rtl::OUString > aNames( 4 );
1689             ::rtl::OUString* pNames = aNames.getArray();
1690             *pNames++ = ::rtl::OUString::createFromAscii( "PositionX" );
1691             *pNames++ = ::rtl::OUString::createFromAscii( "PositionY" );
1692             *pNames++ = ::rtl::OUString::createFromAscii( "Width" );
1693             *pNames++ = ::rtl::OUString::createFromAscii( "Height" );
1694 
1695             xProps->addPropertiesChangeListener( aNames, this );
1696         }
1697     }
1698 }
1699 
1700 void ControlContainerBase::removingControl( const Reference< XControl >& _rxControl )
1701 {
1702     vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1703     UnoControlContainer::removingControl( _rxControl );
1704 
1705     if ( _rxControl.is() )
1706     {
1707         Reference< XMultiPropertySet > xProps( _rxControl->getModel(), UNO_QUERY );
1708         if ( xProps.is() )
1709             xProps->removePropertiesChangeListener( this );
1710     }
1711 
1712 }
1713 
1714 void SAL_CALL ControlContainerBase::changesOccurred( const ChangesEvent& ) throw (RuntimeException)
1715 {
1716     vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1717     // a tab controller model may have changed
1718 
1719     // #109067# in design mode don't notify the tab controller
1720     // about tab index changes
1721     if ( mxTabController.is() && !mbDesignMode )
1722         mxTabController->activateTabOrder();
1723 }
1724 void lcl_ApplyResolverToNestedContainees(  const Reference< resource::XStringResourceResolver >& xStringResourceResolver, const Reference< XControlContainer >& xContainer )
1725 {
1726     rtl::OUString aPropName( PROPERTY_RESOURCERESOLVER );
1727 
1728     Any xNewStringResourceResolver; xNewStringResourceResolver <<= xStringResourceResolver;
1729 
1730     Sequence< rtl::OUString > aPropNames(1);
1731     aPropNames[0] = aPropName;
1732 
1733     const Sequence< Reference< awt::XControl > > aSeq = xContainer->getControls();
1734     for ( sal_Int32 i = 0; i < aSeq.getLength(); i++ )
1735     {
1736 		Reference< XControl > xControl( aSeq[i] );
1737         Reference< XPropertySet > xPropertySet;
1738 
1739         if ( xControl.is() )
1740             xPropertySet = Reference< XPropertySet >( xControl->getModel(), UNO_QUERY );
1741 
1742         if ( !xPropertySet.is() )
1743             continue;
1744 
1745         try
1746         {
1747             Reference< resource::XStringResourceResolver > xCurrStringResourceResolver;
1748             Any aOldValue = xPropertySet->getPropertyValue( aPropName );
1749             if  (   ( aOldValue >>= xCurrStringResourceResolver )
1750                 &&  ( xStringResourceResolver == xCurrStringResourceResolver )
1751                 )
1752             {
1753                 Reference< XMultiPropertySet >	xMultiPropSet( xPropertySet, UNO_QUERY );
1754                 Reference< XPropertiesChangeListener > xListener( xPropertySet, UNO_QUERY );
1755                 xMultiPropSet->firePropertiesChangeEvent( aPropNames, xListener );
1756             }
1757             else
1758                 xPropertySet->setPropertyValue( aPropName, xNewStringResourceResolver );
1759         }
1760         /*catch ( NoSuchElementException& )*/ // that's nonsense, this is never thrown above ...
1761         catch ( const Exception& )
1762         {
1763         }
1764 
1765         uno::Reference< XControlContainer > xNestedContainer( xControl, uno::UNO_QUERY );
1766         if ( xNestedContainer.is() )
1767             lcl_ApplyResolverToNestedContainees(  xStringResourceResolver, xNestedContainer );
1768 
1769     }
1770 
1771 }
1772 void ControlContainerBase::ImplStartListingForResourceEvents()
1773 {
1774     Reference< resource::XStringResourceResolver > xStringResourceResolver;
1775 
1776     ImplGetPropertyValue( PROPERTY_RESOURCERESOLVER ) >>= xStringResourceResolver;
1777 
1778     // Add our helper as listener to retrieve notifications about changes
1779     Reference< util::XModifyListener > rListener( mxListener );
1780     ResourceListener* pResourceListener = static_cast< ResourceListener* >( rListener.get() );
1781 
1782     // resource listener will stop listening if resolver reference is empty
1783     if ( pResourceListener )
1784         pResourceListener->startListening( xStringResourceResolver );
1785     ImplUpdateResourceResolver();
1786 }
1787 
1788 void ControlContainerBase::ImplUpdateResourceResolver()
1789 {
1790     rtl::OUString aPropName( PROPERTY_RESOURCERESOLVER );
1791     Reference< resource::XStringResourceResolver > xStringResourceResolver;
1792 
1793     ImplGetPropertyValue( aPropName ) >>= xStringResourceResolver;
1794     if ( !xStringResourceResolver.is() )
1795         return;
1796 
1797     lcl_ApplyResolverToNestedContainees(  xStringResourceResolver, this );
1798 
1799     // propagate resource resolver changes to language dependent props of the dialog
1800     Reference< XPropertySet > xPropertySet( getModel(), UNO_QUERY );
1801     if ( xPropertySet.is() )
1802     {
1803         Reference< XMultiPropertySet >	xMultiPropSet( xPropertySet, UNO_QUERY );
1804         Reference< XPropertiesChangeListener > xListener( xPropertySet, UNO_QUERY );
1805         xMultiPropSet->firePropertiesChangeEvent( lcl_getLanguageDependentProperties(), xListener );
1806     }
1807 }
1808 
1809 
1810 uno::Reference< graphic::XGraphic > ControlContainerBase::Impl_getGraphicFromURL_nothrow( const ::rtl::OUString& _rURL )
1811 {
1812     uno::Reference< graphic::XGraphic > xGraphic;
1813     if ( !_rURL.getLength() )
1814         return xGraphic;
1815 
1816     try
1817     {
1818         uno::Reference< graphic::XGraphicProvider > xProvider;
1819         if ( maContext.createComponent( "com.sun.star.graphic.GraphicProvider", xProvider ) )
1820         {
1821             uno::Sequence< beans::PropertyValue > aMediaProperties(1);
1822             aMediaProperties[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
1823             aMediaProperties[0].Value <<= _rURL;
1824             xGraphic = xProvider->queryGraphic( aMediaProperties );
1825         }
1826     }
1827     catch( const Exception& )
1828     {
1829     	DBG_UNHANDLED_EXCEPTION();
1830     }
1831 
1832     return xGraphic;
1833 }
1834 ////	----------------------------------------------------
1835 ////	Helper Method to convert relative url to physical location
1836 ////	----------------------------------------------------
1837 
1838 ::rtl::OUString getPhysicalLocation( const ::com::sun::star::uno::Any& rbase, const ::com::sun::star::uno::Any& rUrl )
1839 {
1840 
1841 	::rtl::OUString baseLocation;
1842 	::rtl::OUString url;
1843 
1844 	rbase  >>= baseLocation;
1845 	rUrl  >>= url;
1846 
1847     ::rtl::OUString absoluteURL( url );
1848 	if ( url.getLength() > 0 )
1849 	{
1850 		INetURLObject urlObj(baseLocation);
1851 		urlObj.removeSegment();
1852 		baseLocation = urlObj.GetMainURL( INetURLObject::NO_DECODE );
1853 
1854         const INetURLObject protocolCheck( url );
1855         const INetProtocol protocol = protocolCheck.GetProtocol();
1856         if ( protocol == INET_PROT_NOT_VALID )
1857         {
1858             ::rtl::OUString testAbsoluteURL;
1859             if ( ::osl::FileBase::E_None == ::osl::FileBase::getAbsoluteFileURL( baseLocation, url, testAbsoluteURL ) )
1860                 absoluteURL = testAbsoluteURL;
1861         }
1862 	}
1863 
1864 	return absoluteURL;
1865 }
1866 
1867