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