Updated core
[LibreOffice.git] / toolkit / source / controls / controlmodelcontainerbase.cxx
blob52f290fdd3d8673beb928d7d0ecc86925b216462
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <toolkit/controls/controlmodelcontainerbase.hxx>
22 #include <vcl/svapp.hxx>
23 #include <vcl/window.hxx>
24 #include <vcl/wall.hxx>
25 #include <osl/mutex.hxx>
26 #include <toolkit/helper/property.hxx>
27 #include <toolkit/helper/unopropertyarrayhelper.hxx>
28 #include <toolkit/controls/geometrycontrolmodel.hxx>
29 #include <toolkit/controls/unocontrols.hxx>
30 #include "toolkit/controls/formattedcontrol.hxx"
31 #include "toolkit/controls/roadmapcontrol.hxx"
32 #include "toolkit/controls/tkscrollbar.hxx"
33 #include "toolkit/controls/tabpagemodel.hxx"
34 #include <toolkit/controls/stdtabcontroller.hxx>
35 #include <com/sun/star/awt/PosSize.hpp>
36 #include <com/sun/star/awt/WindowAttribute.hpp>
37 #include <com/sun/star/resource/XStringResourceResolver.hpp>
38 #include <com/sun/star/graphic/XGraphicProvider.hpp>
39 #include <com/sun/star/lang/XInitialization.hpp>
40 #include <cppuhelper/typeprovider.hxx>
41 #include <tools/debug.hxx>
42 #include <tools/diagnose_ex.h>
43 #include <comphelper/processfactory.hxx>
44 #include <vcl/outdev.hxx>
45 #include <comphelper/types.hxx>
47 #include <comphelper/componentcontext.hxx>
48 #include <toolkit/helper/vclunohelper.hxx>
49 #include <toolkit/helper/tkresmgr.hxx>
50 #include <unotools/ucbstreamhelper.hxx>
51 #include <vcl/graph.hxx>
52 #include <vcl/image.hxx>
54 #include "tree/treecontrol.hxx"
55 #include "grid/gridcontrol.hxx"
56 #include <toolkit/controls/tabpagecontainer.hxx>
58 #include <boost/bind.hpp>
60 #include <map>
61 #include <algorithm>
62 #include <functional>
63 #include "tools/urlobj.hxx"
64 #include "osl/file.hxx"
65 #include "toolkit/controls/dialogcontrol.hxx"
67 using namespace ::com::sun::star;
68 using namespace ::com::sun::star::uno;
69 using namespace ::com::sun::star::awt;
70 using namespace ::com::sun::star::lang;
71 using namespace ::com::sun::star::container;
72 using namespace ::com::sun::star::beans;
73 using namespace ::com::sun::star::util;
74 using namespace toolkit;
76 #define PROPERTY_RESOURCERESOLVER OUString( "ResourceResolver" )
78 //HELPER
79 OUString getPhysicalLocation( const ::com::sun::star::uno::Any& rbase, const ::com::sun::star::uno::Any& rUrl );
81 struct LanguageDependentProp
83 const char* pPropName;
84 sal_Int32 nPropNameLength;
87 // ----------------------------------------------------------------------------
88 namespace
90 static const Sequence< OUString >& lcl_getLanguageDependentProperties()
92 static Sequence< OUString > s_aLanguageDependentProperties;
93 if ( s_aLanguageDependentProperties.getLength() == 0 )
95 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
96 if ( s_aLanguageDependentProperties.getLength() == 0 )
98 s_aLanguageDependentProperties.realloc( 2 );
99 s_aLanguageDependentProperties[0] = "HelpText";
100 s_aLanguageDependentProperties[1] = "Title";
101 // note: properties must be sorted
104 return s_aLanguageDependentProperties;
108 // ----------------------------------------------------------------------------
109 // functor for disposing a control model
110 struct DisposeControlModel : public ::std::unary_function< Reference< XControlModel >, void >
112 void operator()( Reference< XControlModel >& _rxModel )
116 ::comphelper::disposeComponent( _rxModel );
118 catch (const Exception&)
120 OSL_TRACE( "DisposeControlModel::(): caught an exception while disposing a component!" );
125 // ----------------------------------------------------------------------------
126 // functor for searching control model by name
127 struct FindControlModel : public ::std::unary_function< ControlModelContainerBase::UnoControlModelHolder, bool >
129 private:
130 const OUString& m_rName;
132 public:
133 FindControlModel( const OUString& _rName ) : m_rName( _rName ) { }
135 bool operator()( const ControlModelContainerBase::UnoControlModelHolder& _rCompare )
137 return ( _rCompare.second == m_rName ) ? true : false;
141 // ----------------------------------------------------------------------------
142 // functor for cloning a control model, and insertion into a target list
143 struct CloneControlModel : public ::std::unary_function< ControlModelContainerBase::UnoControlModelHolder, void >
145 private:
146 ControlModelContainerBase::UnoControlModelHolderList& m_rTargetList;
148 public:
149 CloneControlModel( ControlModelContainerBase::UnoControlModelHolderList& _rTargetList )
150 :m_rTargetList( _rTargetList )
154 void operator()( const ControlModelContainerBase::UnoControlModelHolder& _rSource )
156 // clone the source object
157 Reference< XCloneable > xCloneSource( _rSource.first, UNO_QUERY );
158 Reference< XControlModel > xClone( xCloneSource->createClone(), UNO_QUERY );
159 // add to target list
160 m_rTargetList.push_back( ControlModelContainerBase::UnoControlModelHolder( xClone, _rSource.second ) );
164 // ----------------------------------------------------------------------------
165 // functor for comparing a XControlModel with a given reference
166 struct CompareControlModel : public ::std::unary_function< ControlModelContainerBase::UnoControlModelHolder, bool >
168 private:
169 Reference< XControlModel > m_xReference;
170 public:
171 CompareControlModel( const Reference< XControlModel >& _rxReference ) : m_xReference( _rxReference ) { }
173 bool operator()( const ControlModelContainerBase::UnoControlModelHolder& _rCompare )
175 return ( _rCompare.first.get() == m_xReference.get() ) ? true : false;
179 // ----------------------------------------------------------------------------
180 static void lcl_throwIllegalArgumentException( )
181 { // throwing is expensive (in terms of code size), thus we hope the compiler does not inline this ....
182 throw IllegalArgumentException();
185 // ----------------------------------------------------------------------------
186 static void lcl_throwNoSuchElementException( )
187 { // throwing is expensive (in terms of code size), thus we hope the compiler does not inline this ....
188 throw NoSuchElementException();
191 // ----------------------------------------------------------------------------
192 static void lcl_throwElementExistException( )
193 { // throwing is expensive (in terms of code size), thus we hope the compiler does not inline this ....
194 throw ElementExistException();
197 // ----------------------------------------------------------------------------
198 static const OUString& getTabIndexPropertyName( )
200 static const OUString s_sTabIndexProperty( "TabIndex" );
201 return s_sTabIndexProperty;
204 // ----------------------------------------------------------------------------
205 static const OUString& getStepPropertyName( )
207 static const OUString s_sStepProperty( "Step" );
208 return s_sStepProperty;
211 // ----------------------------------------------------
212 // class ControlModelContainerBase
213 // ----------------------------------------------------
214 ControlModelContainerBase::ControlModelContainerBase( const Reference< XComponentContext >& rxContext )
215 :ControlModelContainer_IBase( rxContext )
216 ,maContainerListeners( *this )
217 ,maChangeListeners ( GetMutex() )
218 ,mbGroupsUpToDate( sal_False )
222 ControlModelContainerBase::ControlModelContainerBase( const ControlModelContainerBase& rModel )
223 : ControlModelContainer_IBase( rModel )
224 , maContainerListeners( *this )
225 , maChangeListeners ( GetMutex() )
226 , mbGroupsUpToDate( sal_False )
230 ControlModelContainerBase::~ControlModelContainerBase()
232 maModels.clear();
233 mbGroupsUpToDate = sal_False;
236 Any ControlModelContainerBase::ImplGetDefaultValue( sal_uInt16 nPropId ) const
238 Any aAny;
240 switch ( nPropId )
242 case BASEPROPERTY_DEFAULTCONTROL:
243 aAny <<= OUString::createFromAscii( szServiceName_UnoControlDialog );
244 break;
245 default:
246 aAny = UnoControlModel::ImplGetDefaultValue( nPropId );
249 return aAny;
252 ::cppu::IPropertyArrayHelper& ControlModelContainerBase::getInfoHelper()
254 static UnoPropertyArrayHelper* pHelper = NULL;
255 if ( !pHelper )
257 Sequence<sal_Int32> aIDs = ImplGetPropertyIds();
258 pHelper = new UnoPropertyArrayHelper( aIDs );
260 return *pHelper;
263 void SAL_CALL ControlModelContainerBase::dispose( ) throw(RuntimeException)
265 // ====================================================================
266 // tell our listeners
268 ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
270 EventObject aDisposeEvent;
271 aDisposeEvent.Source = static_cast< XAggregation* >( static_cast< ::cppu::OWeakAggObject* >( this ) );
273 maContainerListeners.disposeAndClear( aDisposeEvent );
274 maChangeListeners.disposeAndClear( aDisposeEvent );
277 // ====================================================================
278 // call the base class
279 UnoControlModel::dispose();
281 // ====================================================================
282 // dispose our child models
283 // for this, collect the models (we collect them from maModels, and this is modified when disposing children)
284 ::std::vector< Reference< XControlModel > > aChildModels( maModels.size() );
286 ::std::transform(
287 maModels.begin(), maModels.end(), // source range
288 aChildModels.begin(), // target location
289 ::boost::bind( &UnoControlModelHolder::first, _1 ) // operation to apply -> select the XControlModel part
292 // now dispose
293 ::std::for_each( aChildModels.begin(), aChildModels.end(), DisposeControlModel() );
294 aChildModels.clear();
296 mbGroupsUpToDate = sal_False;
299 // XMultiPropertySet
300 Reference< XPropertySetInfo > ControlModelContainerBase::getPropertySetInfo( ) throw(RuntimeException)
302 static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
303 return xInfo;
305 void ControlModelContainerBase::Clone_Impl(ControlModelContainerBase& _rClone) const
307 // clone all children
308 ::std::for_each(
309 maModels.begin(), maModels.end(),
310 CloneControlModel( _rClone.maModels )
313 UnoControlModel* ControlModelContainerBase::Clone() const
315 // clone the container itself
316 ControlModelContainerBase* pClone = new ControlModelContainerBase( *this );
317 Clone_Impl(*pClone);
319 return pClone;
322 ControlModelContainerBase::UnoControlModelHolderList::iterator ControlModelContainerBase::ImplFindElement( const OUString& rName )
324 return ::std::find_if( maModels.begin(), maModels.end(), FindControlModel( rName ) );
327 // ::XMultiServiceFactory
328 Reference< XInterface > ControlModelContainerBase::createInstance( const OUString& aServiceSpecifier ) throw(Exception, RuntimeException)
330 SolarMutexGuard aGuard;
332 OGeometryControlModel_Base* pNewModel = NULL;
334 if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlEditModel ) == 0 )
335 pNewModel = new OGeometryControlModel< UnoControlEditModel >( m_xContext );
336 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlFormattedFieldModel ) == 0 )
337 pNewModel = new OGeometryControlModel< UnoControlFormattedFieldModel >( m_xContext);
338 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlFileControlModel ) == 0 )
339 pNewModel = new OGeometryControlModel< UnoControlFileControlModel >( m_xContext );
340 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlButtonModel ) == 0 )
341 pNewModel = new OGeometryControlModel< UnoControlButtonModel >( m_xContext );
342 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlImageControlModel ) == 0 )
343 pNewModel = new OGeometryControlModel< UnoControlImageControlModel >( m_xContext );
344 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlRadioButtonModel ) == 0 )
345 pNewModel = new OGeometryControlModel< UnoControlRadioButtonModel >( m_xContext );
346 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlCheckBoxModel ) == 0 )
347 pNewModel = new OGeometryControlModel< UnoControlCheckBoxModel >( m_xContext );
348 else if ( aServiceSpecifier.compareToAscii( szServiceName_UnoControlFixedHyperlinkModel ) == 0 )
349 pNewModel = new OGeometryControlModel< UnoControlFixedHyperlinkModel >( m_xContext );
350 else if ( aServiceSpecifier.compareToAscii( szServiceName_UnoControlFixedTextModel ) == 0 )
351 pNewModel = new OGeometryControlModel< UnoControlFixedTextModel >( m_xContext );
352 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlGroupBoxModel ) == 0 )
353 pNewModel = new OGeometryControlModel< UnoControlGroupBoxModel >( m_xContext );
354 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlListBoxModel ) == 0 )
355 pNewModel = new OGeometryControlModel< UnoControlListBoxModel >( m_xContext );
356 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlComboBoxModel ) == 0 )
357 pNewModel = new OGeometryControlModel< UnoControlComboBoxModel >( m_xContext );
358 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlDateFieldModel ) == 0 )
359 pNewModel = new OGeometryControlModel< UnoControlDateFieldModel >( m_xContext );
360 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlTimeFieldModel ) == 0 )
361 pNewModel = new OGeometryControlModel< UnoControlTimeFieldModel >( m_xContext );
362 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlNumericFieldModel ) == 0 )
363 pNewModel = new OGeometryControlModel< UnoControlNumericFieldModel >( m_xContext );
364 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlCurrencyFieldModel ) == 0 )
365 pNewModel = new OGeometryControlModel< UnoControlCurrencyFieldModel >( m_xContext );
366 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlPatternFieldModel ) == 0 )
367 pNewModel = new OGeometryControlModel< UnoControlPatternFieldModel >( m_xContext );
368 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlProgressBarModel ) == 0 )
369 pNewModel = new OGeometryControlModel< UnoControlProgressBarModel >( m_xContext );
370 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlScrollBarModel ) == 0 )
371 pNewModel = new OGeometryControlModel< UnoControlScrollBarModel >( m_xContext );
372 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlFixedLineModel ) == 0 )
373 pNewModel = new OGeometryControlModel< UnoControlFixedLineModel >( m_xContext );
374 else if ( aServiceSpecifier.compareToAscii( szServiceName2_UnoControlRoadmapModel ) == 0 )
375 pNewModel = new OGeometryControlModel< UnoControlRoadmapModel >( m_xContext );
376 else if ( aServiceSpecifier.compareToAscii( szServiceName_TreeControlModel ) == 0 )
377 pNewModel = new OGeometryControlModel< UnoTreeModel >( m_xContext );
378 else if ( aServiceSpecifier.compareToAscii( szServiceName_GridControlModel ) == 0 )
379 pNewModel = new OGeometryControlModel< UnoGridModel >( m_xContext );
380 else if ( aServiceSpecifier.compareToAscii( szServiceName_UnoControlTabPageContainerModel ) == 0 )
381 pNewModel = new OGeometryControlModel< UnoControlTabPageContainerModel >( m_xContext );
382 else if ( aServiceSpecifier.compareToAscii( szServiceName_UnoMultiPageModel ) == 0 )
383 pNewModel = new OGeometryControlModel< UnoMultiPageModel >( m_xContext );
384 else if ( aServiceSpecifier.compareToAscii( szServiceName_UnoControlTabPageModel ) == 0 )
385 pNewModel = new OGeometryControlModel< UnoControlTabPageModel >( m_xContext );
386 else if ( aServiceSpecifier.compareToAscii( szServiceName_UnoPageModel ) == 0 )
387 pNewModel = new OGeometryControlModel< UnoPageModel >( m_xContext );
388 else if ( aServiceSpecifier.compareToAscii( szServiceName_UnoFrameModel ) == 0 )
389 pNewModel = new OGeometryControlModel< UnoFrameModel >( m_xContext );
391 if ( !pNewModel )
393 Reference< XInterface > xObject = m_xContext->getServiceManager()->createInstanceWithContext(aServiceSpecifier, m_xContext);
394 Reference< XServiceInfo > xSI( xObject, UNO_QUERY );
395 Reference< XCloneable > xCloneAccess( xSI, UNO_QUERY );
396 Reference< XAggregation > xAgg( xCloneAccess, UNO_QUERY );
397 if ( xAgg.is() )
399 if ( xSI->supportsService(OUString("com.sun.star.awt.UnoControlModel")) )
401 // release 3 of the 4 references we have to the object
402 xAgg.clear();
403 xSI.clear();
404 xObject.clear();
406 pNewModel = new OCommonGeometryControlModel( xCloneAccess, aServiceSpecifier );
411 Reference< XInterface > xNewModel = (::cppu::OWeakObject*)pNewModel;
412 return xNewModel;
415 Reference< XInterface > ControlModelContainerBase::createInstanceWithArguments( const OUString& ServiceSpecifier, const Sequence< Any >& i_arguments ) throw(Exception, RuntimeException)
417 const Reference< XInterface > xInstance( createInstance( ServiceSpecifier ) );
418 const Reference< XInitialization > xInstanceInit( xInstance, UNO_QUERY );
419 ENSURE_OR_RETURN( xInstanceInit.is(), "ControlModelContainerBase::createInstanceWithArguments: can't pass the arguments!", xInstance );
420 xInstanceInit->initialize( i_arguments );
421 return xInstance;
424 Sequence< OUString > ControlModelContainerBase::getAvailableServiceNames() throw(RuntimeException)
426 static Sequence< OUString >* pNamesSeq = NULL;
427 if ( !pNamesSeq )
429 pNamesSeq = new Sequence< OUString >( 26 );
430 OUString* pNames = pNamesSeq->getArray();
431 pNames[0] = OUString::createFromAscii( szServiceName2_UnoControlEditModel );
432 pNames[1] = OUString::createFromAscii( szServiceName2_UnoControlFormattedFieldModel );
433 pNames[2] = OUString::createFromAscii( szServiceName2_UnoControlFileControlModel );
434 pNames[3] = OUString::createFromAscii( szServiceName2_UnoControlButtonModel );
435 pNames[4] = OUString::createFromAscii( szServiceName2_UnoControlImageControlModel );
436 pNames[5] = OUString::createFromAscii( szServiceName2_UnoControlRadioButtonModel );
437 pNames[6] = OUString::createFromAscii( szServiceName2_UnoControlCheckBoxModel );
438 pNames[7] = OUString::createFromAscii( szServiceName2_UnoControlFixedTextModel );
439 pNames[8] = OUString::createFromAscii( szServiceName2_UnoControlGroupBoxModel );
440 pNames[9] = OUString::createFromAscii( szServiceName2_UnoControlListBoxModel );
441 pNames[10] = OUString::createFromAscii( szServiceName2_UnoControlComboBoxModel );
442 pNames[11] = OUString::createFromAscii( szServiceName2_UnoControlDateFieldModel );
443 pNames[12] = OUString::createFromAscii( szServiceName2_UnoControlTimeFieldModel );
444 pNames[13] = OUString::createFromAscii( szServiceName2_UnoControlNumericFieldModel );
445 pNames[14] = OUString::createFromAscii( szServiceName2_UnoControlCurrencyFieldModel );
446 pNames[15] = OUString::createFromAscii( szServiceName2_UnoControlPatternFieldModel );
447 pNames[16] = OUString::createFromAscii( szServiceName2_UnoControlProgressBarModel );
448 pNames[17] = OUString::createFromAscii( szServiceName2_UnoControlScrollBarModel );
449 pNames[18] = OUString::createFromAscii( szServiceName2_UnoControlFixedLineModel );
450 pNames[19] = OUString::createFromAscii( szServiceName2_UnoControlRoadmapModel );
451 pNames[20] = OUString::createFromAscii( szServiceName_TreeControlModel );
452 pNames[21] = OUString::createFromAscii( szServiceName_GridControlModel );
453 pNames[22] = OUString::createFromAscii( szServiceName_UnoControlTabPageContainerModel );
454 pNames[23] = OUString::createFromAscii( szServiceName_UnoControlTabPageModel );
455 pNames[24] = OUString::createFromAscii( szServiceName_UnoMultiPageModel );
456 pNames[25] = OUString::createFromAscii( szServiceName_UnoFrameModel );
458 return *pNamesSeq;
461 // XContainer
462 void ControlModelContainerBase::addContainerListener( const Reference< XContainerListener >& l ) throw(RuntimeException)
464 maContainerListeners.addInterface( l );
467 void ControlModelContainerBase::removeContainerListener( const Reference< XContainerListener >& l ) throw(RuntimeException)
469 maContainerListeners.removeInterface( l );
472 // XElementAcces
473 Type ControlModelContainerBase::getElementType() throw(RuntimeException)
475 Type aType = getCppuType( ( Reference< XControlModel>* ) NULL );
476 return aType;
479 sal_Bool ControlModelContainerBase::hasElements() throw(RuntimeException)
481 return !maModels.empty();
484 // XNameContainer, XNameReplace, XNameAccess
485 void ControlModelContainerBase::replaceByName( const OUString& aName, const Any& aElement ) throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException)
487 SolarMutexGuard aGuard;
489 Reference< XControlModel > xNewModel;
490 aElement >>= xNewModel;
491 if ( !xNewModel.is() )
492 lcl_throwIllegalArgumentException();
494 UnoControlModelHolderList::iterator aElementPos = ImplFindElement( aName );
495 if ( maModels.end() == aElementPos )
496 lcl_throwNoSuchElementException();
497 // Dialog behaviour is to have all containee names unique ( MSO Userform is the same )
498 // With container controls you could have constructed an existing hierachy and are now
499 // add this to an existing container, in this case a name nested in the containment
500 // hierachy of the added control could contain a name clash, if we have access to the
501 // list of global names then recursively check for previously existing names ( we need
502 // to do this obviously before the 'this' objects container is updated
503 Reference< XNameContainer > xAllChildren( getPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ) ), UNO_QUERY );
504 if ( xAllChildren.is() )
506 // remove old control ( and children ) from global list of containees
507 updateUserFormChildren( xAllChildren, aName, Remove, uno::Reference< XControlModel >() );
508 // Add new control ( and containees if they exist )
509 updateUserFormChildren( xAllChildren, aName, Insert, xNewModel );
511 // stop listening at the old model
512 stopControlListening( aElementPos->first );
513 Reference< XControlModel > xReplaced( aElementPos->first );
514 // remember the new model, and start listening
515 aElementPos->first = xNewModel;
516 startControlListening( xNewModel );
518 ContainerEvent aEvent;
519 aEvent.Source = *this;
520 aEvent.Element = aElement;
521 aEvent.ReplacedElement <<= xReplaced;
522 aEvent.Accessor <<= aName;
524 // notify the container listener
525 maContainerListeners.elementReplaced( aEvent );
527 // our "tab controller model" has potentially changed -> notify this
528 implNotifyTabModelChange( aName );
531 Any ControlModelContainerBase::getByName( const OUString& aName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException)
533 UnoControlModelHolderList::iterator aElementPos = ImplFindElement( aName );
534 if ( maModels.end() == aElementPos )
535 lcl_throwNoSuchElementException();
537 return makeAny( aElementPos->first );
540 Sequence< OUString > ControlModelContainerBase::getElementNames() throw(RuntimeException)
542 Sequence< OUString > aNames( maModels.size() );
544 ::std::transform(
545 maModels.begin(), maModels.end(), // source range
546 aNames.getArray(), // target range
547 ::boost::bind( &UnoControlModelHolder::second, _1 ) // operator to apply: select the second element (the name)
550 return aNames;
553 sal_Bool ControlModelContainerBase::hasByName( const OUString& aName ) throw(RuntimeException)
555 return maModels.end() != ImplFindElement( aName );
558 void ControlModelContainerBase::insertByName( const OUString& aName, const Any& aElement ) throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException)
560 SolarMutexGuard aGuard;
562 Reference< XControlModel > xM;
563 aElement >>= xM;
565 if ( xM.is() )
567 Reference< beans::XPropertySet > xProps( xM, UNO_QUERY );
568 if ( xProps.is() )
571 Reference< beans::XPropertySetInfo > xPropInfo = xProps.get()->getPropertySetInfo();
573 OUString sImageSourceProperty = GetPropertyName( BASEPROPERTY_IMAGEURL );
574 if ( xPropInfo.get()->hasPropertyByName( sImageSourceProperty ) && ImplHasProperty(BASEPROPERTY_DIALOGSOURCEURL) )
576 Any aUrl = xProps.get()->getPropertyValue( sImageSourceProperty );
578 OUString absoluteUrl =
579 getPhysicalLocation( getPropertyValue( GetPropertyName( BASEPROPERTY_DIALOGSOURCEURL ) ), aUrl );
581 aUrl <<= absoluteUrl;
583 xProps.get()->setPropertyValue( sImageSourceProperty , aUrl );
590 if ( aName.isEmpty() || !xM.is() )
591 lcl_throwIllegalArgumentException();
593 UnoControlModelHolderList::iterator aElementPos = ImplFindElement( aName );
594 if ( maModels.end() != aElementPos )
595 lcl_throwElementExistException();
597 // Dialog behaviour is to have all containee names unique ( MSO Userform is the same )
598 // With container controls you could have constructed an existing hierachy and are now
599 // add this to an existing container, in this case a name nested in the containment
600 // hierachy of the added control could contain a name clash, if we have access to the
601 // list of global names then we need to recursively check for previously existing
602 // names ( we need to do this obviously before the 'this' objects container is updated
603 // remove old control ( and children ) from global list of containees
604 Reference< XNameContainer > xAllChildren( getPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ) ), UNO_QUERY );
606 if ( xAllChildren.is() )
607 updateUserFormChildren( xAllChildren, aName, Insert, xM );
608 maModels.push_back( UnoControlModelHolder( xM, aName ) );
609 mbGroupsUpToDate = sal_False;
610 startControlListening( xM );
612 ContainerEvent aEvent;
613 aEvent.Source = *this;
614 aEvent.Element <<= aElement;
615 aEvent.Accessor <<= aName;
616 maContainerListeners.elementInserted( aEvent );
618 // our "tab controller model" has potentially changed -> notify this
619 implNotifyTabModelChange( aName );
622 void ControlModelContainerBase::removeByName( const OUString& aName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException)
624 SolarMutexGuard aGuard;
626 UnoControlModelHolderList::iterator aElementPos = ImplFindElement( aName );
627 if ( maModels.end() == aElementPos )
628 lcl_throwNoSuchElementException();
630 // Dialog behaviour is to have all containee names unique ( MSO Userform is the same )
631 // With container controls you could have constructed an existing hierachy and are now
632 // removing this control from an existing container, in this case all nested names in
633 // the containment hierachy of the control to be removed need to be removed from the global
634 // names cache ( we need to do this obviously before the 'this' objects container is updated )
635 Reference< XNameContainer > xAllChildren( getPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ) ), UNO_QUERY );
636 if ( xAllChildren.is() )
637 updateUserFormChildren( xAllChildren, aName, Remove, uno::Reference< XControlModel >() );
639 ContainerEvent aEvent;
640 aEvent.Source = *this;
641 aEvent.Element <<= aElementPos->first;
642 aEvent.Accessor <<= aName;
643 maContainerListeners.elementRemoved( aEvent );
645 stopControlListening( aElementPos->first );
646 Reference< XPropertySet > xPS( aElementPos->first, UNO_QUERY );
647 maModels.erase( aElementPos );
648 mbGroupsUpToDate = sal_False;
650 if ( xPS.is() )
654 xPS->setPropertyValue( PROPERTY_RESOURCERESOLVER, makeAny( Reference< resource::XStringResourceResolver >() ) );
656 catch (const Exception&)
658 DBG_UNHANDLED_EXCEPTION();
662 // our "tab controller model" has potentially changed -> notify this
663 implNotifyTabModelChange( aName );
666 // ----------------------------------------------------------------------------
667 sal_Bool SAL_CALL ControlModelContainerBase::getGroupControl( ) throw (RuntimeException)
669 return sal_True;
672 // ----------------------------------------------------------------------------
673 void SAL_CALL ControlModelContainerBase::setGroupControl( sal_Bool ) throw (RuntimeException)
675 OSL_TRACE( "UnoControlDialogModel::setGroupControl: explicit grouping not supported" );
678 // ----------------------------------------------------------------------------
679 void SAL_CALL ControlModelContainerBase::setControlModels( const Sequence< Reference< XControlModel > >& _rControls ) throw (RuntimeException)
681 SolarMutexGuard aGuard;
683 // set the tab indexes according to the order of models in the sequence
684 const Reference< XControlModel >* pControls = _rControls.getConstArray( );
685 const Reference< XControlModel >* pControlsEnd = _rControls.getConstArray( ) + _rControls.getLength();
687 sal_Int16 nTabIndex = 1;
689 for ( ; pControls != pControlsEnd; ++pControls )
691 // look up the control in our own structure. This is to prevent invalid arguments
692 UnoControlModelHolderList::const_iterator aPos =
693 ::std::find_if(
694 maModels.begin(), maModels.end(),
695 CompareControlModel( *pControls )
697 if ( maModels.end() != aPos )
699 // okay, this is an existent model
700 // now set the TabIndex property (if applicable)
701 Reference< XPropertySet > xProps( aPos->first, UNO_QUERY );
702 Reference< XPropertySetInfo > xPSI;
703 if ( xProps.is() )
704 xPSI = xProps->getPropertySetInfo();
705 if ( xPSI.is() && xPSI->hasPropertyByName( getTabIndexPropertyName() ) )
706 xProps->setPropertyValue( getTabIndexPropertyName(), makeAny( nTabIndex++ ) );
708 mbGroupsUpToDate = sal_False;
713 typedef ::std::multimap< sal_Int32, Reference< XControlModel >, ::std::less< sal_Int32 > > MapIndexToModel;
715 // ----------------------------------------------------------------------------
716 Sequence< Reference< XControlModel > > SAL_CALL ControlModelContainerBase::getControlModels( ) throw (RuntimeException)
718 SolarMutexGuard aGuard;
720 MapIndexToModel aSortedModels;
721 // will be the sorted container of all models which have a tab index property
722 ::std::vector< Reference< XControlModel > > aUnindexedModels;
723 // will be the container of all models which do not have a tab index property
725 UnoControlModelHolderList::const_iterator aLoop = maModels.begin();
726 for ( ; aLoop != maModels.end(); ++aLoop )
728 Reference< XControlModel > xModel( aLoop->first );
730 // see if the model has a TabIndex property
731 Reference< XPropertySet > xControlProps( xModel, UNO_QUERY );
732 Reference< XPropertySetInfo > xPSI;
733 if ( xControlProps.is() )
734 xPSI = xControlProps->getPropertySetInfo( );
735 DBG_ASSERT( xPSI.is(), "UnoControlDialogModel::getControlModels: invalid child model!" );
737 // has it?
738 if ( xPSI.is() && xPSI->hasPropertyByName( getTabIndexPropertyName() ) )
739 { // yes
740 sal_Int32 nTabIndex = -1;
741 xControlProps->getPropertyValue( getTabIndexPropertyName() ) >>= nTabIndex;
743 aSortedModels.insert( MapIndexToModel::value_type( nTabIndex, xModel ) );
745 else if ( xModel.is() )
746 // no, it hasn't, but we have to include it, anyway
747 aUnindexedModels.push_back( xModel );
750 // okay, here we have a container of all our models, sorted by tab index,
751 // plus a container of "unindexed" models
752 // -> merge them
753 Sequence< Reference< XControlModel > > aReturn( aUnindexedModels.size() + aSortedModels.size() );
754 ::std::transform(
755 aSortedModels.begin(), aSortedModels.end(),
756 ::std::copy( aUnindexedModels.begin(), aUnindexedModels.end(), aReturn.getArray() ),
757 ::boost::bind( &MapIndexToModel::value_type::second, _1 )
760 return aReturn;
763 // ----------------------------------------------------------------------------
764 void SAL_CALL ControlModelContainerBase::setGroup( const Sequence< Reference< XControlModel > >&, const OUString& ) throw (RuntimeException)
766 // not supported. We have only implicit grouping:
767 // We only have a sequence of control models, and we _know_ (yes, that's a HACK relying on
768 // implementation details) that VCL does grouping according to the order of controls automatically
769 // At least VCL does this for all we're interested in: Radio buttons.
770 OSL_TRACE( "UnoControlDialogModel::setGroup: grouping not supported" );
773 ////----- XInitialization -------------------------------------------------------------------
774 void SAL_CALL ControlModelContainerBase::initialize (const Sequence<Any>& rArguments) throw (com::sun::star::uno::Exception, com::sun::star::uno::RuntimeException)
776 if ( rArguments.getLength() == 1 )
778 sal_Int16 nPageId = -1;
779 if ( !( rArguments[ 0 ] >>= nPageId ))
780 throw lang::IllegalArgumentException();
781 m_nTabPageId = nPageId;
783 else
784 m_nTabPageId = -1;
786 ::sal_Int16 SAL_CALL ControlModelContainerBase::getTabPageID() throw (::com::sun::star::uno::RuntimeException)
788 return m_nTabPageId;
790 ::sal_Bool SAL_CALL ControlModelContainerBase::getEnabled() throw (::com::sun::star::uno::RuntimeException)
792 return m_bEnabled;
794 void SAL_CALL ControlModelContainerBase::setEnabled( ::sal_Bool _enabled ) throw (::com::sun::star::uno::RuntimeException)
796 m_bEnabled = _enabled;
798 OUString SAL_CALL ControlModelContainerBase::getTitle() throw (::com::sun::star::uno::RuntimeException)
800 SolarMutexGuard aGuard;
801 Reference<XPropertySet> xThis(*this,UNO_QUERY);
802 OUString sTitle;
803 xThis->getPropertyValue(GetPropertyName(BASEPROPERTY_TITLE)) >>= sTitle;
804 return sTitle;
805 //return m_sTitle;
807 void SAL_CALL ControlModelContainerBase::setTitle( const OUString& _title ) throw (::com::sun::star::uno::RuntimeException)
809 SolarMutexGuard aGuard;
810 Reference<XPropertySet> xThis(*this,UNO_QUERY);
811 xThis->setPropertyValue(GetPropertyName(BASEPROPERTY_TITLE),makeAny(_title));
813 OUString SAL_CALL ControlModelContainerBase::getImageURL() throw (::com::sun::star::uno::RuntimeException)
815 return m_sImageURL;
817 void SAL_CALL ControlModelContainerBase::setImageURL( const OUString& _imageurl ) throw (::com::sun::star::uno::RuntimeException)
819 m_sImageURL = _imageurl;
821 OUString SAL_CALL ControlModelContainerBase::getToolTip() throw (::com::sun::star::uno::RuntimeException)
823 return m_sTooltip;
825 void SAL_CALL ControlModelContainerBase::setToolTip( const OUString& _tooltip ) throw (::com::sun::star::uno::RuntimeException)
827 m_sTooltip = _tooltip;
830 // ----------------------------------------------------------------------------
831 namespace
833 enum GroupingMachineState
835 eLookingForGroup,
836 eExpandingGroup
839 // ........................................................................
840 static sal_Int32 lcl_getDialogStep( const Reference< XControlModel >& _rxModel )
842 sal_Int32 nStep = 0;
845 Reference< XPropertySet > xModelProps( _rxModel, UNO_QUERY );
846 xModelProps->getPropertyValue( getStepPropertyName() ) >>= nStep;
848 catch (const Exception&)
850 OSL_TRACE( "lcl_getDialogStep: caught an exception while determining the dialog page!" );
852 return nStep;
856 // ----------------------------------------------------------------------------
857 sal_Int32 SAL_CALL ControlModelContainerBase::getGroupCount( ) throw (RuntimeException)
859 SolarMutexGuard aGuard;
861 implUpdateGroupStructure();
863 return maGroups.size();
866 // ----------------------------------------------------------------------------
867 void SAL_CALL ControlModelContainerBase::getGroup( sal_Int32 _nGroup, Sequence< Reference< XControlModel > >& _rGroup, OUString& _rName ) throw (RuntimeException)
869 SolarMutexGuard aGuard;
871 implUpdateGroupStructure();
873 if ( ( _nGroup < 0 ) || ( _nGroup >= (sal_Int32)maGroups.size() ) )
875 OSL_TRACE( "UnoControlDialogModel::getGroup: invalid argument and I am not allowed to throw an exception!" );
876 _rGroup.realloc( 0 );
877 _rName = OUString();
879 else
881 AllGroups::const_iterator aGroupPos = maGroups.begin() + _nGroup;
882 _rGroup.realloc( aGroupPos->size() );
883 // copy the models
884 ::std::copy( aGroupPos->begin(), aGroupPos->end(), _rGroup.getArray() );
885 // give the group a name
886 _rName = OUString::valueOf( _nGroup );
890 // ----------------------------------------------------------------------------
891 void SAL_CALL ControlModelContainerBase::getGroupByName( const OUString& _rName, Sequence< Reference< XControlModel > >& _rGroup ) throw (RuntimeException)
893 SolarMutexGuard aGuard;
895 OUString sDummyName;
896 getGroup( _rName.toInt32( ), _rGroup, sDummyName );
899 // ----------------------------------------------------------------------------
900 void SAL_CALL ControlModelContainerBase::addChangesListener( const Reference< XChangesListener >& _rxListener ) throw (RuntimeException)
902 maChangeListeners.addInterface( _rxListener );
905 // ----------------------------------------------------------------------------
906 void SAL_CALL ControlModelContainerBase::removeChangesListener( const Reference< XChangesListener >& _rxListener ) throw (RuntimeException)
908 maChangeListeners.removeInterface( _rxListener );
911 // ----------------------------------------------------------------------------
912 void ControlModelContainerBase::implNotifyTabModelChange( const OUString& _rAccessor )
914 // multiplex to our change listeners:
915 // the changes event
916 ChangesEvent aEvent;
917 aEvent.Source = *this;
918 aEvent.Base <<= aEvent.Source; // the "base of the changes root" is also ourself
919 aEvent.Changes.realloc( 1 ); // exactly one change
920 aEvent.Changes[ 0 ].Accessor <<= _rAccessor;
923 Sequence< Reference< XInterface > > aChangeListeners( maChangeListeners.getElements() );
924 const Reference< XInterface >* pListener = aChangeListeners.getConstArray();
925 const Reference< XInterface >* pListenerEnd = aChangeListeners.getConstArray() + aChangeListeners.getLength();
926 for ( ; pListener != pListenerEnd; ++pListener )
928 if ( pListener->is() )
929 static_cast< XChangesListener* >( pListener->get() )->changesOccurred( aEvent );
934 // ----------------------------------------------------------------------------
935 void ControlModelContainerBase::implUpdateGroupStructure()
937 if ( mbGroupsUpToDate )
938 // nothing to do
939 return;
941 // conditions for a group:
942 // * all elements of the group are radio buttons
943 // * all elements of the group are on the same dialog page
944 // * in the overall control order (determined by the tab index), all elements are subsequent
946 maGroups.clear();
948 Sequence< Reference< XControlModel > > aControlModels = getControlModels();
949 const Reference< XControlModel >* pControlModels = aControlModels.getConstArray();
950 const Reference< XControlModel >* pControlModelsEnd = pControlModels + aControlModels.getLength();
952 // in extreme we have as much groups as controls
953 maGroups.reserve( aControlModels.getLength() );
955 GroupingMachineState eState = eLookingForGroup; // the current state of our machine
956 Reference< XServiceInfo > xModelSI; // for checking for a radion button
957 AllGroups::iterator aCurrentGroup = maGroups.end(); // the group which we're currently building
958 sal_Int32 nCurrentGroupStep = -1; // the step which all controls of the current group belong to
959 sal_Bool bIsRadioButton; // is it a radio button?
961 #if OSL_DEBUG_LEVEL > 1
962 ::std::vector< OUString > aCurrentGroupLabels;
963 #endif
965 for ( ; pControlModels != pControlModelsEnd; ++pControlModels )
967 // we'll need this in every state
968 xModelSI = xModelSI.query( *pControlModels );
969 bIsRadioButton = xModelSI.is() && xModelSI->supportsService( OUString::createFromAscii( szServiceName2_UnoControlRadioButtonModel ) );
971 switch ( eState )
973 case eLookingForGroup:
975 if ( !bIsRadioButton )
976 // this is no radio button -> still looking for the beginning of a group
977 continue;
978 // the current model is a radio button
979 // -> we found the beginning of a new group
980 // create the place for this group
981 size_t nGroups = maGroups.size();
982 maGroups.resize( nGroups + 1 );
983 aCurrentGroup = maGroups.begin() + nGroups;
984 // and add the (only, til now) member
985 aCurrentGroup->push_back( *pControlModels );
987 // get the step which all controls of this group now have to belong to
988 nCurrentGroupStep = lcl_getDialogStep( *pControlModels );
989 // new state: looking for further members
990 eState = eExpandingGroup;
992 #if OSL_DEBUG_LEVEL > 1
993 Reference< XPropertySet > xModelProps( *pControlModels, UNO_QUERY );
994 OUString sLabel;
995 if ( xModelProps.is() && xModelProps->getPropertySetInfo().is() && xModelProps->getPropertySetInfo()->hasPropertyByName( OUString("Label") ) )
996 xModelProps->getPropertyValue( OUString("Label") ) >>= sLabel;
997 aCurrentGroupLabels.push_back( sLabel );
998 #endif
1000 break;
1002 case eExpandingGroup:
1004 if ( !bIsRadioButton )
1005 { // no radio button -> the group is done
1006 aCurrentGroup = maGroups.end();
1007 eState = eLookingForGroup;
1008 #if OSL_DEBUG_LEVEL > 1
1009 aCurrentGroupLabels.clear();
1010 #endif
1011 continue;
1014 // it is a radio button - is it on the proper page?
1015 const sal_Int32 nThisModelStep = lcl_getDialogStep( *pControlModels );
1016 if ( ( nThisModelStep == nCurrentGroupStep ) // the current button is on the same dialog page
1017 || ( 0 == nThisModelStep ) // the current button appears on all pages
1020 // -> it belongs to the same group
1021 aCurrentGroup->push_back( *pControlModels );
1022 // state still is eExpandingGroup - we're looking for further elements
1023 eState = eExpandingGroup;
1025 #if OSL_DEBUG_LEVEL > 1
1026 Reference< XPropertySet > xModelProps( *pControlModels, UNO_QUERY );
1027 OUString sLabel;
1028 if ( xModelProps.is() && xModelProps->getPropertySetInfo().is() && xModelProps->getPropertySetInfo()->hasPropertyByName( OUString("Label") ) )
1029 xModelProps->getPropertyValue( OUString("Label") ) >>= sLabel;
1030 aCurrentGroupLabels.push_back( sLabel );
1031 #endif
1032 continue;
1035 // it's a radio button, but on a different page
1036 // -> we open a new group for it
1038 // close the old group
1039 aCurrentGroup = maGroups.end();
1040 #if OSL_DEBUG_LEVEL > 1
1041 aCurrentGroupLabels.clear();
1042 #endif
1044 // open a new group
1045 size_t nGroups = maGroups.size();
1046 maGroups.resize( nGroups + 1 );
1047 aCurrentGroup = maGroups.begin() + nGroups;
1048 // and add the (only, til now) member
1049 aCurrentGroup->push_back( *pControlModels );
1051 nCurrentGroupStep = nThisModelStep;
1053 // state is the same: we still are looking for further elements of the current group
1054 eState = eExpandingGroup;
1055 #if OSL_DEBUG_LEVEL > 1
1056 Reference< XPropertySet > xModelProps( *pControlModels, UNO_QUERY );
1057 OUString sLabel;
1058 if ( xModelProps.is() && xModelProps->getPropertySetInfo().is() && xModelProps->getPropertySetInfo()->hasPropertyByName( OUString("Label") ) )
1059 xModelProps->getPropertyValue( OUString("Label") ) >>= sLabel;
1060 aCurrentGroupLabels.push_back( sLabel );
1061 #endif
1063 break;
1067 mbGroupsUpToDate = sal_True;
1070 // ----------------------------------------------------------------------------
1071 void SAL_CALL ControlModelContainerBase::propertyChange( const PropertyChangeEvent& _rEvent ) throw (RuntimeException)
1073 SolarMutexGuard aGuard;
1075 DBG_ASSERT( 0 == _rEvent.PropertyName.compareToAscii( "TabIndex" ),
1076 "UnoControlDialogModel::propertyChange: not listening for this property!" );
1078 // the accessor for the changed element
1079 OUString sAccessor;
1080 UnoControlModelHolderList::const_iterator aPos =
1081 ::std::find_if(
1082 maModels.begin(), maModels.end(),
1083 CompareControlModel( Reference< XControlModel >( _rEvent.Source, UNO_QUERY ) )
1085 OSL_ENSURE( maModels.end() != aPos, "UnoControlDialogModel::propertyChange: don't know this model!" );
1086 if ( maModels.end() != aPos )
1087 sAccessor = aPos->second;
1089 // our groups are not up-to-date
1090 mbGroupsUpToDate = sal_False;
1092 // notify
1093 implNotifyTabModelChange( sAccessor );
1096 // ----------------------------------------------------------------------------
1097 void SAL_CALL ControlModelContainerBase::disposing( const EventObject& /*rEvent*/ ) throw (RuntimeException)
1101 // ----------------------------------------------------------------------------
1102 void ControlModelContainerBase::startControlListening( const Reference< XControlModel >& _rxChildModel )
1104 SolarMutexGuard aGuard;
1106 Reference< XPropertySet > xModelProps( _rxChildModel, UNO_QUERY );
1107 Reference< XPropertySetInfo > xPSI;
1108 if ( xModelProps.is() )
1109 xPSI = xModelProps->getPropertySetInfo();
1111 if ( xPSI.is() && xPSI->hasPropertyByName( getTabIndexPropertyName() ) )
1112 xModelProps->addPropertyChangeListener( getTabIndexPropertyName(), this );
1115 // ----------------------------------------------------------------------------
1116 void ControlModelContainerBase::stopControlListening( const Reference< XControlModel >& _rxChildModel )
1118 SolarMutexGuard aGuard;
1120 Reference< XPropertySet > xModelProps( _rxChildModel, UNO_QUERY );
1121 Reference< XPropertySetInfo > xPSI;
1122 if ( xModelProps.is() )
1123 xPSI = xModelProps->getPropertySetInfo();
1125 if ( xPSI.is() && xPSI->hasPropertyByName( getTabIndexPropertyName() ) )
1126 xModelProps->removePropertyChangeListener( getTabIndexPropertyName(), this );
1129 // ============================================================================
1130 // = class ResourceListener
1131 // ============================================================================
1133 ResourceListener::ResourceListener(
1134 const Reference< util::XModifyListener >& rListener ) :
1135 OWeakObject(),
1136 m_xListener( rListener ),
1137 m_bListening( false )
1141 ResourceListener::~ResourceListener()
1145 // XInterface
1146 Any SAL_CALL ResourceListener::queryInterface( const Type& rType )
1147 throw ( RuntimeException )
1149 Any a = ::cppu::queryInterface(
1150 rType ,
1151 static_cast< XModifyListener* >( this ),
1152 static_cast< XEventListener* >( this ));
1154 if ( a.hasValue() )
1155 return a;
1157 return OWeakObject::queryInterface( rType );
1160 void SAL_CALL ResourceListener::acquire() throw ()
1162 OWeakObject::acquire();
1165 void SAL_CALL ResourceListener::release() throw ()
1167 OWeakObject::release();
1170 void ResourceListener::startListening(
1171 const Reference< resource::XStringResourceResolver >& rResource )
1173 Reference< util::XModifyBroadcaster > xModifyBroadcaster( rResource, UNO_QUERY );
1176 // --- SAFE ---
1177 ::osl::ResettableGuard < ::osl::Mutex > aGuard( m_aMutex );
1178 bool bListening( m_bListening );
1179 bool bResourceSet( m_xResource.is() );
1180 aGuard.clear();
1181 // --- SAFE ---
1183 if ( bListening && bResourceSet )
1184 stopListening();
1186 // --- SAFE ---
1187 aGuard.reset();
1188 m_xResource = rResource;
1189 aGuard.clear();
1190 // --- SAFE ---
1193 Reference< util::XModifyListener > xThis( static_cast<OWeakObject*>( this ), UNO_QUERY );
1194 if ( xModifyBroadcaster.is() )
1198 xModifyBroadcaster->addModifyListener( xThis );
1200 // --- SAFE ---
1201 ::osl::ResettableGuard < ::osl::Mutex > aGuard( m_aMutex );
1202 m_bListening = true;
1203 // --- SAFE ---
1205 catch (const RuntimeException&)
1207 throw;
1209 catch (const Exception&)
1215 void ResourceListener::stopListening()
1217 Reference< util::XModifyBroadcaster > xModifyBroadcaster;
1219 // --- SAFE ---
1220 ::osl::ResettableGuard < ::osl::Mutex > aGuard( m_aMutex );
1221 if ( m_bListening && m_xResource.is() )
1222 xModifyBroadcaster = Reference< util::XModifyBroadcaster >( m_xResource, UNO_QUERY );
1223 aGuard.clear();
1224 // --- SAFE ---
1226 Reference< util::XModifyListener > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1227 if ( xModifyBroadcaster.is() )
1231 // --- SAFE ---
1232 aGuard.reset();
1233 m_bListening = false;
1234 m_xResource.clear();
1235 aGuard.clear();
1236 // --- SAFE ---
1238 xModifyBroadcaster->removeModifyListener( xThis );
1240 catch (const RuntimeException&)
1242 throw;
1244 catch (const Exception&)
1250 // XModifyListener
1251 void SAL_CALL ResourceListener::modified(
1252 const lang::EventObject& aEvent )
1253 throw ( RuntimeException )
1255 Reference< util::XModifyListener > xListener;
1257 // --- SAFE ---
1258 ::osl::ResettableGuard < ::osl::Mutex > aGuard( m_aMutex );
1259 xListener = m_xListener;
1260 aGuard.clear();
1261 // --- SAFE ---
1263 if ( xListener.is() )
1267 xListener->modified( aEvent );
1269 catch (const RuntimeException&)
1271 throw;
1273 catch (const Exception&)
1279 // XEventListener
1280 void SAL_CALL ResourceListener::disposing(
1281 const EventObject& Source )
1282 throw ( RuntimeException )
1284 Reference< lang::XEventListener > xListener;
1285 Reference< resource::XStringResourceResolver > xResource;
1287 // --- SAFE ---
1288 ::osl::ResettableGuard < ::osl::Mutex > aGuard( m_aMutex );
1289 Reference< XInterface > xIfacRes( m_xResource, UNO_QUERY );
1290 Reference< XInterface > xIfacList( m_xListener, UNO_QUERY );
1291 aGuard.clear();
1292 // --- SAFE ---
1294 if ( Source.Source == xIfacRes )
1296 // --- SAFE ---
1297 aGuard.reset();
1298 m_bListening = false;
1299 xResource = m_xResource;
1300 xListener = Reference< lang::XEventListener >( m_xListener, UNO_QUERY );
1301 m_xResource.clear();
1302 aGuard.clear();
1303 // --- SAFE ---
1305 if ( xListener.is() )
1309 xListener->disposing( Source );
1311 catch (const RuntimeException&)
1313 throw;
1315 catch (const Exception&)
1320 else if ( Source.Source == xIfacList )
1322 // --- SAFE ---
1323 aGuard.reset();
1324 m_bListening = false;
1325 xListener = Reference< lang::XEventListener >( m_xListener, UNO_QUERY );
1326 xResource = m_xResource;
1327 m_xResource.clear();
1328 m_xListener.clear();
1329 aGuard.clear();
1330 // --- SAFE ---
1332 // Remove ourself as listener from resource resolver
1333 Reference< util::XModifyBroadcaster > xModifyBroadcaster( xResource, UNO_QUERY );
1334 Reference< util::XModifyListener > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1335 if ( xModifyBroadcaster.is() )
1339 xModifyBroadcaster->removeModifyListener( xThis );
1341 catch (const RuntimeException&)
1343 throw;
1345 catch (const Exception&)
1352 //===============================================================
1353 // ----------------------------------------------------
1354 // class DialogContainerControl
1355 // ----------------------------------------------------
1356 ControlContainerBase::ControlContainerBase( const Reference< XComponentContext >& rxContext )
1357 :ContainerControl_IBase()
1358 ,m_xContext(rxContext)
1359 ,mbSizeModified(false)
1360 ,mbPosModified(false)
1362 maComponentInfos.nWidth = 280;
1363 maComponentInfos.nHeight = 400;
1364 mxListener = new ResourceListener( Reference< util::XModifyListener >(
1365 static_cast< OWeakObject* >( this ), UNO_QUERY ));
1368 ControlContainerBase::~ControlContainerBase()
1372 void ControlContainerBase::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer ) throw(RuntimeException)
1374 SolarMutexGuard aGuard;
1375 UnoControlContainer::createPeer( rxToolkit, rParentPeer );
1378 void ControlContainerBase::ImplInsertControl( Reference< XControlModel >& rxModel, const OUString& rName )
1380 Reference< XPropertySet > xP( rxModel, UNO_QUERY );
1382 OUString aDefCtrl;
1383 xP->getPropertyValue( GetPropertyName( BASEPROPERTY_DEFAULTCONTROL ) ) >>= aDefCtrl;
1384 Reference < XControl > xCtrl( m_xContext->getServiceManager()->createInstanceWithContext(aDefCtrl, m_xContext), UNO_QUERY );
1386 DBG_ASSERT( xCtrl.is(), "ControlContainerBase::ImplInsertControl: could not create the control!" );
1387 if ( xCtrl.is() )
1389 xCtrl->setModel( rxModel );
1390 addControl( rName, xCtrl );
1391 // will implicitly call addingControl, where we can add the PropertiesChangeListener to the model
1392 // (which we formerly did herein)
1393 // 08.01.2001 - 96008 - fs@openoffice.org
1395 ImplSetPosSize( xCtrl );
1399 void ControlContainerBase::ImplRemoveControl( Reference< XControlModel >& rxModel )
1401 Sequence< Reference< XControl > > aControls = getControls();
1402 Reference< XControl > xCtrl = StdTabController::FindControl( aControls, rxModel );
1403 if ( xCtrl.is() )
1405 removeControl( xCtrl );
1408 Reference< XComponent > const xControlComp( xCtrl, UNO_QUERY_THROW );
1409 xControlComp->dispose();
1411 catch (const Exception&)
1413 DBG_UNHANDLED_EXCEPTION();
1418 void ControlContainerBase::ImplSetPosSize( Reference< XControl >& rxCtrl )
1420 Reference< XPropertySet > xP( rxCtrl->getModel(), UNO_QUERY );
1422 sal_Int32 nX = 0, nY = 0, nWidth = 0, nHeight = 0;
1423 xP->getPropertyValue( OUString( "PositionX" ) ) >>= nX;
1424 xP->getPropertyValue( OUString( "PositionY" ) ) >>= nY;
1425 xP->getPropertyValue( OUString( "Width" ) ) >>= nWidth;
1426 xP->getPropertyValue( OUString( "Height" ) ) >>= nHeight;
1427 MapMode aMode( MAP_APPFONT );
1428 OutputDevice*pOutDev = Application::GetDefaultDevice();
1429 if ( pOutDev )
1431 ::Size aTmp( nX, nY );
1432 aTmp = pOutDev->LogicToPixel( aTmp, aMode );
1433 nX = aTmp.Width();
1434 nY = aTmp.Height();
1435 aTmp = ::Size( nWidth, nHeight );
1436 aTmp = pOutDev->LogicToPixel( aTmp, aMode );
1437 nWidth = aTmp.Width();
1438 nHeight = aTmp.Height();
1440 else
1442 Reference< XWindowPeer > xPeer = ImplGetCompatiblePeer( sal_True );
1443 Reference< XDevice > xD( xPeer, UNO_QUERY );
1445 SimpleFontMetric aFM;
1446 FontDescriptor aFD;
1447 Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_FONTDESCRIPTOR ) );
1448 aVal >>= aFD;
1449 if ( !aFD.StyleName.isEmpty() )
1451 Reference< XFont > xFont = xD->getFont( aFD );
1452 aFM = xFont->getFontMetric();
1454 else
1456 Reference< XGraphics > xG = xD->createGraphics();
1457 aFM = xG->getFontMetric();
1460 sal_Int16 nH = aFM.Ascent + aFM.Descent;
1461 sal_Int16 nW = nH/2; // calculate avarage width?!
1463 nX *= nW;
1464 nX /= 4;
1465 nWidth *= nW;
1466 nWidth /= 4;
1467 nY *= nH;
1468 nY /= 8;
1469 nHeight *= nH;
1470 nHeight /= 8;
1472 Reference < XWindow > xW( rxCtrl, UNO_QUERY );
1473 xW->setPosSize( nX, nY, nWidth, nHeight, PosSize::POSSIZE );
1476 void ControlContainerBase::dispose() throw(RuntimeException)
1478 EventObject aEvt;
1479 aEvt.Source = static_cast< ::cppu::OWeakObject* >( this );
1480 // Notify our listener helper about dispose
1481 // --- SAFE ---
1483 SolarMutexClearableGuard aGuard;
1484 Reference< XEventListener > xListener( mxListener, UNO_QUERY );
1485 mxListener.clear();
1486 aGuard.clear();
1487 // --- SAFE ---
1489 if ( xListener.is() )
1490 xListener->disposing( aEvt );
1491 UnoControlContainer::dispose();
1494 void SAL_CALL ControlContainerBase::disposing(
1495 const EventObject& Source )
1496 throw(RuntimeException)
1498 UnoControlContainer::disposing( Source );
1501 sal_Bool ControlContainerBase::setModel( const Reference< XControlModel >& rxModel ) throw(RuntimeException)
1503 SolarMutexGuard aGuard;
1505 // destroy the old tab controller, if existent
1506 if ( mxTabController.is() )
1508 mxTabController->setModel( NULL ); // just to be sure, should not be necessary
1509 removeTabController( mxTabController );
1510 ::comphelper::disposeComponent( mxTabController ); // just to be sure, should not be necessary
1511 mxTabController.clear();
1514 if ( getModel().is() )
1516 Sequence< Reference< XControl > > aControls = getControls();
1517 const Reference< XControl >* pCtrls = aControls.getConstArray();
1518 const Reference< XControl >* pCtrlsEnd = pCtrls + aControls.getLength();
1520 for ( ; pCtrls < pCtrlsEnd; ++pCtrls )
1521 removeControl( *pCtrls );
1522 // will implicitly call removingControl, which will remove the PropertyChangeListener
1523 // (which we formerly did herein)
1524 // 08.01.2001 - 96008 - fs@openoffice.org
1526 Reference< XContainer > xC( getModel(), UNO_QUERY );
1527 if ( xC.is() )
1528 xC->removeContainerListener( this );
1530 Reference< XChangesNotifier > xChangeNotifier( getModel(), UNO_QUERY );
1531 if ( xChangeNotifier.is() )
1532 xChangeNotifier->removeChangesListener( this );
1535 sal_Bool bRet = UnoControl::setModel( rxModel );
1537 if ( getModel().is() )
1539 Reference< XNameAccess > xNA( getModel(), UNO_QUERY );
1540 if ( xNA.is() )
1542 Sequence< OUString > aNames = xNA->getElementNames();
1543 const OUString* pNames = aNames.getConstArray();
1544 sal_uInt32 nCtrls = aNames.getLength();
1546 Reference< XControlModel > xCtrlModel;
1547 for( sal_uInt32 n = 0; n < nCtrls; ++n, ++pNames )
1549 xNA->getByName( *pNames ) >>= xCtrlModel;
1550 ImplInsertControl( xCtrlModel, *pNames );
1554 Reference< XContainer > xC( getModel(), UNO_QUERY );
1555 if ( xC.is() )
1556 xC->addContainerListener( this );
1558 Reference< XChangesNotifier > xChangeNotifier( getModel(), UNO_QUERY );
1559 if ( xChangeNotifier.is() )
1560 xChangeNotifier->addChangesListener( this );
1563 Reference< XTabControllerModel > xTabbing( getModel(), UNO_QUERY );
1564 if ( xTabbing.is() )
1566 mxTabController = new StdTabController;
1567 mxTabController->setModel( xTabbing );
1568 addTabController( mxTabController );
1570 ImplStartListingForResourceEvents();
1572 return bRet;
1574 void ControlContainerBase::setDesignMode( sal_Bool bOn ) throw(RuntimeException)
1576 SolarMutexGuard aGuard;
1578 UnoControl::setDesignMode( bOn );
1580 Sequence< Reference< XControl > > xCtrls = getControls();
1581 sal_Int32 nControls = xCtrls.getLength();
1582 Reference< XControl >* pControls = xCtrls.getArray();
1583 for ( sal_Int32 n = 0; n < nControls; n++ )
1584 pControls[n]->setDesignMode( bOn );
1586 // #109067# in design mode the tab controller is not notified about
1587 // tab index changes, therefore the tab order must be activated
1588 // when switching from design mode to live mode
1589 if ( mxTabController.is() && !bOn )
1590 mxTabController->activateTabOrder();
1593 void ControlContainerBase::elementInserted( const ContainerEvent& Event ) throw(RuntimeException)
1595 SolarMutexGuard aGuard;
1597 Reference< XControlModel > xModel;
1598 OUString aName;
1600 Event.Accessor >>= aName;
1601 Event.Element >>= xModel;
1602 ENSURE_OR_RETURN_VOID( xModel.is(), "ControlContainerBase::elementInserted: illegal element!" );
1605 ImplInsertControl( xModel, aName );
1607 catch (const RuntimeException&)
1609 throw;
1611 catch (const Exception&)
1613 DBG_UNHANDLED_EXCEPTION();
1617 void ControlContainerBase::elementRemoved( const ContainerEvent& Event ) throw(RuntimeException)
1619 SolarMutexGuard aGuard;
1621 Reference< XControlModel > xModel;
1622 Event.Element >>= xModel;
1623 ENSURE_OR_RETURN_VOID( xModel.is(), "ControlContainerBase::elementRemoved: illegal element!" );
1626 ImplRemoveControl( xModel );
1628 catch (const RuntimeException&)
1630 throw;
1632 catch (const Exception&)
1634 DBG_UNHANDLED_EXCEPTION();
1638 void ControlContainerBase::elementReplaced( const ContainerEvent& Event ) throw(RuntimeException)
1640 SolarMutexGuard aGuard;
1642 Reference< XControlModel > xModel;
1643 Event.ReplacedElement >>= xModel;
1646 OSL_ENSURE( xModel.is(), "ControlContainerBase::elementReplaced: invalid ReplacedElement!" );
1647 if ( xModel.is() )
1648 ImplRemoveControl( xModel );
1650 catch (const RuntimeException&)
1652 throw;
1654 catch (const Exception&)
1656 DBG_UNHANDLED_EXCEPTION();
1659 OUString aName;
1660 Event.Accessor >>= aName;
1661 Event.Element >>= xModel;
1662 ENSURE_OR_RETURN_VOID( xModel.is(), "ControlContainerBase::elementReplaced: invalid new element!" );
1665 ImplInsertControl( xModel, aName );
1667 catch (const RuntimeException&)
1669 throw;
1671 catch (const Exception&)
1673 DBG_UNHANDLED_EXCEPTION();
1677 // XPropertiesChangeListener
1678 void ControlContainerBase::ImplModelPropertiesChanged( const Sequence< PropertyChangeEvent >& rEvents ) throw(RuntimeException)
1680 if( !isDesignMode() && !mbCreatingCompatiblePeer )
1682 OUString s1( "PositionX" );
1683 OUString s2( "PositionY" );
1684 OUString s3( "Width" );
1685 OUString s4( "Height" );
1687 sal_Int32 nLen = rEvents.getLength();
1688 for( sal_Int32 i = 0; i < nLen; i++ )
1690 const PropertyChangeEvent& rEvt = rEvents.getConstArray()[i];
1691 Reference< XControlModel > xModel( rEvt.Source, UNO_QUERY );
1692 sal_Bool bOwnModel = (XControlModel*)xModel.get() == (XControlModel*)getModel().get();
1693 if ( ( rEvt.PropertyName == s1 ) ||
1694 ( rEvt.PropertyName == s2 ) ||
1695 ( rEvt.PropertyName == s3 ) ||
1696 ( rEvt.PropertyName == s4 ) )
1698 if ( bOwnModel )
1700 if ( !mbPosModified && !mbSizeModified )
1702 // Don't set new pos/size if we get new values from window listener
1703 Reference< XControl > xThis( (XAggregation*)(::cppu::OWeakAggObject*)this, UNO_QUERY );
1704 ImplSetPosSize( xThis );
1707 else
1709 Sequence<Reference<XControl> > aControlSequence(getControls());
1710 Reference<XControl> aControlRef( StdTabController::FindControl( aControlSequence, xModel ) );
1711 ImplSetPosSize( aControlRef );
1713 break;
1718 UnoControlContainer::ImplModelPropertiesChanged( rEvents );
1721 void ControlContainerBase::addingControl( const Reference< XControl >& _rxControl )
1723 SolarMutexGuard aGuard;
1724 UnoControlContainer::addingControl( _rxControl );
1726 if ( _rxControl.is() )
1728 Reference< XMultiPropertySet > xProps( _rxControl->getModel(), UNO_QUERY );
1729 if ( xProps.is() )
1731 Sequence< OUString > aNames( 4 );
1732 OUString* pNames = aNames.getArray();
1733 *pNames++ = "PositionX";
1734 *pNames++ = "PositionY";
1735 *pNames++ = "Width";
1736 *pNames++ = "Height";
1738 xProps->addPropertiesChangeListener( aNames, this );
1743 void ControlContainerBase::removingControl( const Reference< XControl >& _rxControl )
1745 SolarMutexGuard aGuard;
1746 UnoControlContainer::removingControl( _rxControl );
1748 if ( _rxControl.is() )
1750 Reference< XMultiPropertySet > xProps( _rxControl->getModel(), UNO_QUERY );
1751 if ( xProps.is() )
1752 xProps->removePropertiesChangeListener( this );
1757 void SAL_CALL ControlContainerBase::changesOccurred( const ChangesEvent& ) throw (RuntimeException)
1759 SolarMutexGuard aGuard;
1760 // a tab controller model may have changed
1762 // #109067# in design mode don't notify the tab controller
1763 // about tab index changes
1764 if ( mxTabController.is() && !mbDesignMode )
1765 mxTabController->activateTabOrder();
1767 static void lcl_ApplyResolverToNestedContainees( const Reference< resource::XStringResourceResolver >& xStringResourceResolver, const Reference< XControlContainer >& xContainer )
1769 OUString aPropName( PROPERTY_RESOURCERESOLVER );
1771 Any xNewStringResourceResolver; xNewStringResourceResolver <<= xStringResourceResolver;
1773 Sequence< OUString > aPropNames(1);
1774 aPropNames[0] = aPropName;
1776 const Sequence< Reference< awt::XControl > > aSeq = xContainer->getControls();
1777 for ( sal_Int32 i = 0; i < aSeq.getLength(); i++ )
1779 Reference< XControl > xControl( aSeq[i] );
1780 Reference< XPropertySet > xPropertySet;
1782 if ( xControl.is() )
1783 xPropertySet = Reference< XPropertySet >( xControl->getModel(), UNO_QUERY );
1785 if ( !xPropertySet.is() )
1786 continue;
1790 Reference< resource::XStringResourceResolver > xCurrStringResourceResolver;
1791 Any aOldValue = xPropertySet->getPropertyValue( aPropName );
1792 if ( ( aOldValue >>= xCurrStringResourceResolver )
1793 && ( xStringResourceResolver == xCurrStringResourceResolver )
1796 Reference< XMultiPropertySet > xMultiPropSet( xPropertySet, UNO_QUERY );
1797 Reference< XPropertiesChangeListener > xListener( xPropertySet, UNO_QUERY );
1798 xMultiPropSet->firePropertiesChangeEvent( aPropNames, xListener );
1800 else
1801 xPropertySet->setPropertyValue( aPropName, xNewStringResourceResolver );
1803 catch (const Exception&)
1807 uno::Reference< XControlContainer > xNestedContainer( xControl, uno::UNO_QUERY );
1808 if ( xNestedContainer.is() )
1809 lcl_ApplyResolverToNestedContainees( xStringResourceResolver, xNestedContainer );
1814 void ControlContainerBase::ImplStartListingForResourceEvents()
1816 Reference< resource::XStringResourceResolver > xStringResourceResolver;
1818 ImplGetPropertyValue( PROPERTY_RESOURCERESOLVER ) >>= xStringResourceResolver;
1820 // Add our helper as listener to retrieve notifications about changes
1821 Reference< util::XModifyListener > rListener( mxListener );
1822 ResourceListener* pResourceListener = static_cast< ResourceListener* >( rListener.get() );
1824 // resource listener will stop listening if resolver reference is empty
1825 if ( pResourceListener )
1826 pResourceListener->startListening( xStringResourceResolver );
1827 ImplUpdateResourceResolver();
1830 void ControlContainerBase::ImplUpdateResourceResolver()
1832 OUString aPropName( PROPERTY_RESOURCERESOLVER );
1833 Reference< resource::XStringResourceResolver > xStringResourceResolver;
1835 ImplGetPropertyValue( aPropName ) >>= xStringResourceResolver;
1836 if ( !xStringResourceResolver.is() )
1837 return;
1839 lcl_ApplyResolverToNestedContainees( xStringResourceResolver, this );
1841 // propagate resource resolver changes to language dependent props of the dialog
1842 Reference< XPropertySet > xPropertySet( getModel(), UNO_QUERY );
1843 if ( xPropertySet.is() )
1845 Reference< XMultiPropertySet > xMultiPropSet( xPropertySet, UNO_QUERY );
1846 Reference< XPropertiesChangeListener > xListener( xPropertySet, UNO_QUERY );
1847 xMultiPropSet->firePropertiesChangeEvent( lcl_getLanguageDependentProperties(), xListener );
1851 //// ----------------------------------------------------
1852 //// Helper Method to convert relative url to physical location
1853 //// ----------------------------------------------------
1855 OUString getPhysicalLocation( const ::com::sun::star::uno::Any& rbase, const ::com::sun::star::uno::Any& rUrl )
1858 OUString baseLocation;
1859 OUString url;
1861 rbase >>= baseLocation;
1862 rUrl >>= url;
1864 OUString absoluteURL( url );
1865 if ( !url.isEmpty() )
1867 INetURLObject urlObj(baseLocation);
1868 urlObj.removeSegment();
1869 baseLocation = urlObj.GetMainURL( INetURLObject::NO_DECODE );
1871 const INetURLObject protocolCheck( url );
1872 const INetProtocol protocol = protocolCheck.GetProtocol();
1873 if ( protocol == INET_PROT_NOT_VALID )
1875 OUString testAbsoluteURL;
1876 if ( ::osl::FileBase::E_None == ::osl::FileBase::getAbsoluteFileURL( baseLocation, url, testAbsoluteURL ) )
1877 absoluteURL = testAbsoluteURL;
1881 return absoluteURL;
1884 void
1885 ControlModelContainerBase::updateUserFormChildren( const Reference< XNameContainer >& xAllChildren, const OUString& aName, ChildOperation Operation, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >& xTarget ) throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException)
1887 if ( Operation < Insert || Operation > Remove )
1888 throw IllegalArgumentException();
1890 if ( xAllChildren.is() )
1892 if ( Operation == Remove )
1894 Reference< XControlModel > xOldModel( xAllChildren->getByName( aName ), UNO_QUERY );
1895 xAllChildren->removeByName( aName );
1897 Reference< XNameContainer > xChildContainer( xOldModel, UNO_QUERY );
1898 if ( xChildContainer.is() )
1900 Reference< XPropertySet > xProps( xChildContainer, UNO_QUERY );
1901 // container control is being removed from this container, reset the
1902 // global list of containees
1903 if ( xProps.is() )
1904 xProps->setPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ), uno::makeAny( uno::Reference< XNameContainer >() ) );
1905 Sequence< OUString > aChildNames = xChildContainer->getElementNames();
1906 for ( sal_Int32 index=0; index< aChildNames.getLength(); ++index )
1907 updateUserFormChildren( xAllChildren, aChildNames[ index ], Operation, Reference< XControlModel > () );
1910 else if ( Operation == Insert )
1912 xAllChildren->insertByName( aName, uno::makeAny( xTarget ) );
1913 Reference< XNameContainer > xChildContainer( xTarget, UNO_QUERY );
1914 if ( xChildContainer.is() )
1916 // container control is being added from this container, reset the
1917 // global list of containees to point to the correct global list
1918 Reference< XPropertySet > xProps( xChildContainer, UNO_QUERY );
1919 if ( xProps.is() )
1920 xProps->setPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ), uno::makeAny( xAllChildren ) );
1921 Sequence< OUString > aChildNames = xChildContainer->getElementNames();
1922 for ( sal_Int32 index=0; index< aChildNames.getLength(); ++index )
1924 Reference< XControlModel > xChildTarget( xChildContainer->getByName( aChildNames[ index ] ), UNO_QUERY );
1925 updateUserFormChildren( xAllChildren, aChildNames[ index ], Operation, xChildTarget );
1930 else
1931 throw IllegalArgumentException();
1934 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */