1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/controls/geometrycontrolmodel.hxx>
28 #include <toolkit/controls/unocontrols.hxx>
29 #include "toolkit/controls/formattedcontrol.hxx"
30 #include "toolkit/controls/roadmapcontrol.hxx"
31 #include "toolkit/controls/tkscrollbar.hxx"
32 #include "toolkit/controls/tabpagemodel.hxx"
33 #include <toolkit/controls/stdtabcontroller.hxx>
34 #include <com/sun/star/awt/PosSize.hpp>
35 #include <com/sun/star/awt/WindowAttribute.hpp>
36 #include <com/sun/star/resource/XStringResourceResolver.hpp>
37 #include <com/sun/star/graphic/XGraphicProvider.hpp>
38 #include <com/sun/star/lang/XInitialization.hpp>
39 #include <cppuhelper/typeprovider.hxx>
40 #include <cppuhelper/queryinterface.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 <toolkit/helper/vclunohelper.hxx>
48 #include <unotools/ucbstreamhelper.hxx>
49 #include <vcl/graph.hxx>
50 #include <vcl/image.hxx>
52 #include "tree/treecontrol.hxx"
53 #include "grid/gridcontrol.hxx"
54 #include <toolkit/controls/tabpagecontainer.hxx>
56 #include <boost/bind.hpp>
61 #include "tools/urlobj.hxx"
62 #include "osl/file.hxx"
63 #include "toolkit/controls/dialogcontrol.hxx"
65 #include "helper/tkresmgr.hxx"
66 #include "helper/unopropertyarrayhelper.hxx"
67 #include "controlmodelcontainerbase_internal.hxx"
69 using namespace ::com::sun::star
;
70 using namespace ::com::sun::star::uno
;
71 using namespace ::com::sun::star::awt
;
72 using namespace ::com::sun::star::lang
;
73 using namespace ::com::sun::star::container
;
74 using namespace ::com::sun::star::beans
;
75 using namespace ::com::sun::star::util
;
76 using namespace toolkit
;
78 #define PROPERTY_RESOURCERESOLVER OUString( "ResourceResolver" )
80 struct LanguageDependentProp
82 const char* pPropName
;
83 sal_Int32 nPropNameLength
;
89 static const Sequence
< OUString
>& lcl_getLanguageDependentProperties()
91 static Sequence
< OUString
> s_aLanguageDependentProperties
;
92 if ( s_aLanguageDependentProperties
.getLength() == 0 )
94 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
95 if ( s_aLanguageDependentProperties
.getLength() == 0 )
97 s_aLanguageDependentProperties
.realloc( 2 );
98 s_aLanguageDependentProperties
[0] = "HelpText";
99 s_aLanguageDependentProperties
[1] = "Title";
100 // note: properties must be sorted
103 return s_aLanguageDependentProperties
;
108 // functor for disposing a control model
109 struct DisposeControlModel
: public ::std::unary_function
< Reference
< XControlModel
>, void >
111 void operator()( Reference
< XControlModel
>& _rxModel
)
115 ::comphelper::disposeComponent( _rxModel
);
117 catch (const Exception
&)
119 OSL_TRACE( "DisposeControlModel::(): caught an exception while disposing a component!" );
125 // functor for searching control model by name
126 struct FindControlModel
: public ::std::unary_function
< ControlModelContainerBase::UnoControlModelHolder
, bool >
129 const OUString
& m_rName
;
132 FindControlModel( const OUString
& _rName
) : m_rName( _rName
) { }
134 bool operator()( const ControlModelContainerBase::UnoControlModelHolder
& _rCompare
)
136 return _rCompare
.second
== m_rName
;
141 // functor for cloning a control model, and insertion into a target list
142 struct CloneControlModel
: public ::std::unary_function
< ControlModelContainerBase::UnoControlModelHolder
, void >
145 ControlModelContainerBase::UnoControlModelHolderList
& m_rTargetList
;
148 CloneControlModel( ControlModelContainerBase::UnoControlModelHolderList
& _rTargetList
)
149 :m_rTargetList( _rTargetList
)
153 void operator()( const ControlModelContainerBase::UnoControlModelHolder
& _rSource
)
155 // clone the source object
156 Reference
< XCloneable
> xCloneSource( _rSource
.first
, UNO_QUERY
);
157 Reference
< XControlModel
> xClone( xCloneSource
->createClone(), UNO_QUERY
);
158 // add to target list
159 m_rTargetList
.push_back( ControlModelContainerBase::UnoControlModelHolder( xClone
, _rSource
.second
) );
164 // functor for comparing a XControlModel with a given reference
165 struct CompareControlModel
: public ::std::unary_function
< ControlModelContainerBase::UnoControlModelHolder
, bool >
168 Reference
< XControlModel
> m_xReference
;
170 CompareControlModel( const Reference
< XControlModel
>& _rxReference
) : m_xReference( _rxReference
) { }
172 bool operator()( const ControlModelContainerBase::UnoControlModelHolder
& _rCompare
)
174 return _rCompare
.first
.get() == m_xReference
.get();
179 static void lcl_throwIllegalArgumentException( )
180 { // throwing is expensive (in terms of code size), thus we hope the compiler does not inline this ....
181 throw IllegalArgumentException();
185 static void lcl_throwNoSuchElementException( )
186 { // throwing is expensive (in terms of code size), thus we hope the compiler does not inline this ....
187 throw NoSuchElementException();
191 static void lcl_throwElementExistException( )
192 { // throwing is expensive (in terms of code size), thus we hope the compiler does not inline this ....
193 throw ElementExistException();
197 static OUString
getTabIndexPropertyName( )
199 return OUString( "TabIndex" );
203 static OUString
getStepPropertyName( )
205 return OUString( "Step" );
209 // class ControlModelContainerBase
211 ControlModelContainerBase::ControlModelContainerBase( const Reference
< XComponentContext
>& rxContext
)
212 :ControlModelContainer_IBase( rxContext
)
213 ,maContainerListeners( *this )
214 ,maChangeListeners ( GetMutex() )
215 ,mbGroupsUpToDate( false )
221 ControlModelContainerBase::ControlModelContainerBase( const ControlModelContainerBase
& rModel
)
222 : ControlModelContainer_IBase( rModel
)
223 , maContainerListeners( *this )
224 , maChangeListeners ( GetMutex() )
225 , mbGroupsUpToDate( false )
226 , m_bEnabled( rModel
.m_bEnabled
)
227 , m_nTabPageId( rModel
.m_nTabPageId
)
231 ControlModelContainerBase::~ControlModelContainerBase()
234 mbGroupsUpToDate
= false;
237 Any
ControlModelContainerBase::ImplGetDefaultValue( sal_uInt16 nPropId
) const
243 case BASEPROPERTY_DEFAULTCONTROL
:
244 aAny
<<= OUString::createFromAscii( szServiceName_UnoControlDialog
);
247 aAny
= UnoControlModel::ImplGetDefaultValue( nPropId
);
253 ::cppu::IPropertyArrayHelper
& ControlModelContainerBase::getInfoHelper()
255 static UnoPropertyArrayHelper
* pHelper
= NULL
;
258 Sequence
<sal_Int32
> aIDs
= ImplGetPropertyIds();
259 pHelper
= new UnoPropertyArrayHelper( aIDs
);
264 void SAL_CALL
ControlModelContainerBase::dispose( ) throw(RuntimeException
, std::exception
)
267 // tell our listeners
269 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
271 EventObject aDisposeEvent
;
272 aDisposeEvent
.Source
= static_cast< XAggregation
* >( static_cast< ::cppu::OWeakAggObject
* >( this ) );
274 maContainerListeners
.disposeAndClear( aDisposeEvent
);
275 maChangeListeners
.disposeAndClear( aDisposeEvent
);
279 // call the base class
280 UnoControlModel::dispose();
283 // dispose our child models
284 // for this, collect the models (we collect them from maModels, and this is modified when disposing children)
285 ::std::vector
< Reference
< XControlModel
> > aChildModels( maModels
.size() );
288 maModels
.begin(), maModels
.end(), // source range
289 aChildModels
.begin(), // target location
290 ::boost::bind( &UnoControlModelHolder::first
, _1
) // operation to apply -> select the XControlModel part
294 ::std::for_each( aChildModels
.begin(), aChildModels
.end(), DisposeControlModel() );
295 aChildModels
.clear();
297 mbGroupsUpToDate
= false;
301 Reference
< XPropertySetInfo
> ControlModelContainerBase::getPropertySetInfo( ) throw(RuntimeException
, std::exception
)
303 static Reference
< XPropertySetInfo
> xInfo( createPropertySetInfo( getInfoHelper() ) );
306 void ControlModelContainerBase::Clone_Impl(ControlModelContainerBase
& _rClone
) const
308 // clone all children
310 maModels
.begin(), maModels
.end(),
311 CloneControlModel( _rClone
.maModels
)
314 UnoControlModel
* ControlModelContainerBase::Clone() const
316 // clone the container itself
317 ControlModelContainerBase
* pClone
= new ControlModelContainerBase( *this );
323 ControlModelContainerBase::UnoControlModelHolderList::iterator
ControlModelContainerBase::ImplFindElement( const OUString
& rName
)
325 return ::std::find_if( maModels
.begin(), maModels
.end(), FindControlModel( rName
) );
328 // ::XMultiServiceFactory
329 Reference
< XInterface
> ControlModelContainerBase::createInstance( const OUString
& aServiceSpecifier
) throw(Exception
, RuntimeException
, std::exception
)
331 SolarMutexGuard aGuard
;
333 OGeometryControlModel_Base
* pNewModel
= NULL
;
335 if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlEditModel" )
336 pNewModel
= new OGeometryControlModel
< UnoControlEditModel
>( m_xContext
);
337 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlFormattedFieldModel" )
338 pNewModel
= new OGeometryControlModel
< UnoControlFormattedFieldModel
>( m_xContext
);
339 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlFileControlModel" )
340 pNewModel
= new OGeometryControlModel
< UnoControlFileControlModel
>( m_xContext
);
341 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlButtonModel" )
342 pNewModel
= new OGeometryControlModel
< UnoControlButtonModel
>( m_xContext
);
343 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlImageControlModel" )
344 pNewModel
= new OGeometryControlModel
< UnoControlImageControlModel
>( m_xContext
);
345 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlRadioButtonModel" )
346 pNewModel
= new OGeometryControlModel
< UnoControlRadioButtonModel
>( m_xContext
);
347 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlCheckBoxModel" )
348 pNewModel
= new OGeometryControlModel
< UnoControlCheckBoxModel
>( m_xContext
);
349 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlFixedHyperlinkModel" )
350 pNewModel
= new OGeometryControlModel
< UnoControlFixedHyperlinkModel
>( m_xContext
);
351 else if ( aServiceSpecifier
== "stardiv.vcl.controlmodel.FixedText" )
352 pNewModel
= new OGeometryControlModel
< UnoControlFixedTextModel
>( m_xContext
);
353 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlGroupBoxModel" )
354 pNewModel
= new OGeometryControlModel
< UnoControlGroupBoxModel
>( m_xContext
);
355 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlListBoxModel" )
356 pNewModel
= new OGeometryControlModel
< UnoControlListBoxModel
>( m_xContext
);
357 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlComboBoxModel" )
358 pNewModel
= new OGeometryControlModel
< UnoControlComboBoxModel
>( m_xContext
);
359 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlDateFieldModel" )
360 pNewModel
= new OGeometryControlModel
< UnoControlDateFieldModel
>( m_xContext
);
361 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlTimeFieldModel" )
362 pNewModel
= new OGeometryControlModel
< UnoControlTimeFieldModel
>( m_xContext
);
363 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlNumericFieldModel" )
364 pNewModel
= new OGeometryControlModel
< UnoControlNumericFieldModel
>( m_xContext
);
365 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlCurrencyFieldModel" )
366 pNewModel
= new OGeometryControlModel
< UnoControlCurrencyFieldModel
>( m_xContext
);
367 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlPatternFieldModel" )
368 pNewModel
= new OGeometryControlModel
< UnoControlPatternFieldModel
>( m_xContext
);
369 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlProgressBarModel" )
370 pNewModel
= new OGeometryControlModel
< UnoControlProgressBarModel
>( m_xContext
);
371 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlScrollBarModel" )
372 pNewModel
= new OGeometryControlModel
< UnoControlScrollBarModel
>( m_xContext
);
373 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlFixedLineModel" )
374 pNewModel
= new OGeometryControlModel
< UnoControlFixedLineModel
>( m_xContext
);
375 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoControlRoadmapModel" )
376 pNewModel
= new OGeometryControlModel
< UnoControlRoadmapModel
>( m_xContext
);
377 else if ( aServiceSpecifier
== "com.sun.star.awt.tree.TreeControlModel" )
378 pNewModel
= new OGeometryControlModel
< UnoTreeModel
>( m_xContext
);
379 else if ( aServiceSpecifier
== "com.sun.star.awt.grid.UnoControlGridModel" )
380 pNewModel
= new OGeometryControlModel
< UnoGridModel
>( m_xContext
);
381 else if ( aServiceSpecifier
== "com.sun.star.awt.tab.UnoControlTabPageContainerModel" )
382 pNewModel
= new OGeometryControlModel
< UnoControlTabPageContainerModel
>( m_xContext
);
383 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoMultiPageModel" )
384 pNewModel
= new OGeometryControlModel
< UnoMultiPageModel
>( m_xContext
);
385 else if ( aServiceSpecifier
== "com.sun.star.awt.tab.UnoControlTabPageModel" )
386 pNewModel
= new OGeometryControlModel
< UnoControlTabPageModel
>( m_xContext
);
387 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoPageModel" )
388 pNewModel
= new OGeometryControlModel
< UnoPageModel
>( m_xContext
);
389 else if ( aServiceSpecifier
== "com.sun.star.awt.UnoFrameModel" )
390 pNewModel
= new OGeometryControlModel
< UnoFrameModel
>( m_xContext
);
394 Reference
< XInterface
> xObject
= m_xContext
->getServiceManager()->createInstanceWithContext(aServiceSpecifier
, m_xContext
);
395 Reference
< XServiceInfo
> xSI( xObject
, UNO_QUERY
);
396 Reference
< XCloneable
> xCloneAccess( xSI
, UNO_QUERY
);
397 Reference
< XAggregation
> xAgg( xCloneAccess
, UNO_QUERY
);
400 if ( xSI
->supportsService("com.sun.star.awt.UnoControlModel") )
402 // release 3 of the 4 references we have to the object
407 pNewModel
= new OCommonGeometryControlModel( xCloneAccess
, aServiceSpecifier
);
412 Reference
< XInterface
> xNewModel
= (::cppu::OWeakObject
*)pNewModel
;
416 Reference
< XInterface
> ControlModelContainerBase::createInstanceWithArguments( const OUString
& ServiceSpecifier
, const Sequence
< Any
>& i_arguments
) throw(Exception
, RuntimeException
, std::exception
)
418 const Reference
< XInterface
> xInstance( createInstance( ServiceSpecifier
) );
419 const Reference
< XInitialization
> xInstanceInit( xInstance
, UNO_QUERY
);
420 ENSURE_OR_RETURN( xInstanceInit
.is(), "ControlModelContainerBase::createInstanceWithArguments: can't pass the arguments!", xInstance
);
421 xInstanceInit
->initialize( i_arguments
);
425 Sequence
< OUString
> ControlModelContainerBase::getAvailableServiceNames() throw(RuntimeException
, std::exception
)
427 static Sequence
< OUString
>* pNamesSeq
= NULL
;
430 pNamesSeq
= new Sequence
< OUString
>( 26 );
431 OUString
* pNames
= pNamesSeq
->getArray();
432 pNames
[0] = "com.sun.star.awt.UnoControlEditModel";
433 pNames
[1] = "com.sun.star.awt.UnoControlFormattedFieldModel";
434 pNames
[2] = "com.sun.star.awt.UnoControlFileControlModel";
435 pNames
[3] = "com.sun.star.awt.UnoControlButtonModel";
436 pNames
[4] = "com.sun.star.awt.UnoControlImageControlModel";
437 pNames
[5] = "com.sun.star.awt.UnoControlRadioButtonModel";
438 pNames
[6] = "com.sun.star.awt.UnoControlCheckBoxModel";
439 pNames
[7] = "com.sun.star.awt.UnoControlFixedTextModel";
440 pNames
[8] = "com.sun.star.awt.UnoControlGroupBoxModel";
441 pNames
[9] = "com.sun.star.awt.UnoControlListBoxModel";
442 pNames
[10] = "com.sun.star.awt.UnoControlComboBoxModel";
443 pNames
[11] = "com.sun.star.awt.UnoControlDateFieldModel";
444 pNames
[12] = "com.sun.star.awt.UnoControlTimeFieldModel";
445 pNames
[13] = "com.sun.star.awt.UnoControlNumericFieldModel";
446 pNames
[14] = "com.sun.star.awt.UnoControlCurrencyFieldModel";
447 pNames
[15] = "com.sun.star.awt.UnoControlPatternFieldModel";
448 pNames
[16] = "com.sun.star.awt.tree.TreeControlModel";
449 pNames
[21] = "com.sun.star.awt.grid.UnoControlGridModel";
450 pNames
[22] = "com.sun.star.awt.tab.UnoControlTabPageContainerModel";
451 pNames
[23] = "com.sun.star.awt.tab.UnoControlTabPageModel";
452 pNames
[24] = "com.sun.star.awt.UnoMultiPageModel";
453 pNames
[25] = "com.sun.star.awt.UnoFrameModel";
459 void ControlModelContainerBase::addContainerListener( const Reference
< XContainerListener
>& l
) throw(RuntimeException
, std::exception
)
461 maContainerListeners
.addInterface( l
);
464 void ControlModelContainerBase::removeContainerListener( const Reference
< XContainerListener
>& l
) throw(RuntimeException
, std::exception
)
466 maContainerListeners
.removeInterface( l
);
470 Type
ControlModelContainerBase::getElementType() throw(RuntimeException
, std::exception
)
472 Type aType
= cppu::UnoType
<XControlModel
>::get();
476 sal_Bool
ControlModelContainerBase::hasElements() throw(RuntimeException
, std::exception
)
478 return !maModels
.empty();
481 // XNameContainer, XNameReplace, XNameAccess
482 void ControlModelContainerBase::replaceByName( const OUString
& aName
, const Any
& aElement
) throw(IllegalArgumentException
, NoSuchElementException
, WrappedTargetException
, RuntimeException
, std::exception
)
484 SolarMutexGuard aGuard
;
486 Reference
< XControlModel
> xNewModel
;
487 aElement
>>= xNewModel
;
488 if ( !xNewModel
.is() )
489 lcl_throwIllegalArgumentException();
491 UnoControlModelHolderList::iterator aElementPos
= ImplFindElement( aName
);
492 if ( maModels
.end() == aElementPos
)
493 lcl_throwNoSuchElementException();
494 // Dialog behaviour is to have all containee names unique (MSO Userform is the same)
495 // With container controls you could have constructed an existing hierarchy and are now
496 // add this to an existing container, in this case a name nested in the containment
497 // hierarchy of the added control could contain a name clash, if we have access to the
498 // list of global names then recursively check for previously existing names (we need
499 // to do this obviously before the 'this' objects container is updated)
500 Reference
< XNameContainer
> xAllChildren( getPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES
) ), UNO_QUERY
);
501 if ( xAllChildren
.is() )
503 // remove old control (and children) from global list of containees
504 updateUserFormChildren( xAllChildren
, aName
, Remove
, uno::Reference
< XControlModel
>() );
505 // Add new control (and containees if they exist)
506 updateUserFormChildren( xAllChildren
, aName
, Insert
, xNewModel
);
508 // stop listening at the old model
509 stopControlListening( aElementPos
->first
);
510 Reference
< XControlModel
> xReplaced( aElementPos
->first
);
511 // remember the new model, and start listening
512 aElementPos
->first
= xNewModel
;
513 startControlListening( xNewModel
);
515 ContainerEvent aEvent
;
516 aEvent
.Source
= *this;
517 aEvent
.Element
= aElement
;
518 aEvent
.ReplacedElement
<<= xReplaced
;
519 aEvent
.Accessor
<<= aName
;
521 // notify the container listener
522 maContainerListeners
.elementReplaced( aEvent
);
524 // our "tab controller model" has potentially changed -> notify this
525 implNotifyTabModelChange( aName
);
528 Any
ControlModelContainerBase::getByName( const OUString
& aName
) throw(NoSuchElementException
, WrappedTargetException
, RuntimeException
, std::exception
)
530 UnoControlModelHolderList::iterator aElementPos
= ImplFindElement( aName
);
531 if ( maModels
.end() == aElementPos
)
532 lcl_throwNoSuchElementException();
534 return makeAny( aElementPos
->first
);
537 Sequence
< OUString
> ControlModelContainerBase::getElementNames() throw(RuntimeException
, std::exception
)
539 Sequence
< OUString
> aNames( maModels
.size() );
542 maModels
.begin(), maModels
.end(), // source range
543 aNames
.getArray(), // target range
544 ::boost::bind( &UnoControlModelHolder::second
, _1
) // operator to apply: select the second element (the name)
550 sal_Bool
ControlModelContainerBase::hasByName( const OUString
& aName
) throw(RuntimeException
, std::exception
)
552 return maModels
.end() != ImplFindElement( aName
);
555 void ControlModelContainerBase::insertByName( const OUString
& aName
, const Any
& aElement
) throw(IllegalArgumentException
, ElementExistException
, WrappedTargetException
, RuntimeException
, std::exception
)
557 SolarMutexGuard aGuard
;
559 Reference
< XControlModel
> xM
;
564 Reference
< beans::XPropertySet
> xProps( xM
, UNO_QUERY
);
568 Reference
< beans::XPropertySetInfo
> xPropInfo
= xProps
.get()->getPropertySetInfo();
570 OUString sImageSourceProperty
= GetPropertyName( BASEPROPERTY_IMAGEURL
);
571 if ( xPropInfo
.get()->hasPropertyByName( sImageSourceProperty
) && ImplHasProperty(BASEPROPERTY_DIALOGSOURCEURL
) )
573 Any aUrl
= xProps
.get()->getPropertyValue( sImageSourceProperty
);
575 OUString absoluteUrl
=
576 getPhysicalLocation( getPropertyValue( GetPropertyName( BASEPROPERTY_DIALOGSOURCEURL
) ), aUrl
);
578 aUrl
<<= absoluteUrl
;
580 xProps
.get()->setPropertyValue( sImageSourceProperty
, aUrl
);
587 if ( aName
.isEmpty() || !xM
.is() )
588 lcl_throwIllegalArgumentException();
590 UnoControlModelHolderList::iterator aElementPos
= ImplFindElement( aName
);
591 if ( maModels
.end() != aElementPos
)
592 lcl_throwElementExistException();
594 // Dialog behaviour is to have all containee names unique (MSO Userform is the same)
595 // With container controls you could have constructed an existing hierarchy and are now
596 // add this to an existing container, in this case a name nested in the containment
597 // hierarchy of the added control could contain a name clash, if we have access to the
598 // list of global names then we need to recursively check for previously existing
599 // names (we need to do this obviously before the 'this' objects container is updated)
600 // remove old control (and children) from global list of containees
601 Reference
< XNameContainer
> xAllChildren( getPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES
) ), UNO_QUERY
);
603 if ( xAllChildren
.is() )
604 updateUserFormChildren( xAllChildren
, aName
, Insert
, xM
);
605 maModels
.push_back( UnoControlModelHolder( xM
, aName
) );
606 mbGroupsUpToDate
= false;
607 startControlListening( xM
);
609 ContainerEvent aEvent
;
610 aEvent
.Source
= *this;
611 aEvent
.Element
<<= aElement
;
612 aEvent
.Accessor
<<= aName
;
613 maContainerListeners
.elementInserted( aEvent
);
615 // our "tab controller model" has potentially changed -> notify this
616 implNotifyTabModelChange( aName
);
619 void ControlModelContainerBase::removeByName( const OUString
& aName
) throw(NoSuchElementException
, WrappedTargetException
, RuntimeException
, std::exception
)
621 SolarMutexGuard aGuard
;
623 UnoControlModelHolderList::iterator aElementPos
= ImplFindElement( aName
);
624 if ( maModels
.end() == aElementPos
)
625 lcl_throwNoSuchElementException();
627 // Dialog behaviour is to have all containee names unique (MSO Userform is the same)
628 // With container controls you could have constructed an existing hierarchy and are now
629 // removing this control from an existing container, in this case all nested names in
630 // the containment hierarchy of the control to be removed need to be removed from the global
631 // names cache (we need to do this obviously before the 'this' objects container is updated)
632 Reference
< XNameContainer
> xAllChildren( getPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES
) ), UNO_QUERY
);
633 if ( xAllChildren
.is() )
634 updateUserFormChildren( xAllChildren
, aName
, Remove
, uno::Reference
< XControlModel
>() );
636 ContainerEvent aEvent
;
637 aEvent
.Source
= *this;
638 aEvent
.Element
<<= aElementPos
->first
;
639 aEvent
.Accessor
<<= aName
;
640 maContainerListeners
.elementRemoved( aEvent
);
642 stopControlListening( aElementPos
->first
);
643 Reference
< XPropertySet
> xPS( aElementPos
->first
, UNO_QUERY
);
644 maModels
.erase( aElementPos
);
645 mbGroupsUpToDate
= false;
651 xPS
->setPropertyValue( PROPERTY_RESOURCERESOLVER
, makeAny( Reference
< resource::XStringResourceResolver
>() ) );
653 catch (const Exception
&)
655 DBG_UNHANDLED_EXCEPTION();
659 // our "tab controller model" has potentially changed -> notify this
660 implNotifyTabModelChange( aName
);
664 sal_Bool SAL_CALL
ControlModelContainerBase::getGroupControl( ) throw (RuntimeException
, std::exception
)
670 void SAL_CALL
ControlModelContainerBase::setGroupControl( sal_Bool
) throw (RuntimeException
, std::exception
)
672 OSL_TRACE( "ControlModelContainerBase::setGroupControl: explicit grouping not supported" );
676 void SAL_CALL
ControlModelContainerBase::setControlModels( const Sequence
< Reference
< XControlModel
> >& _rControls
) throw (RuntimeException
, std::exception
)
678 SolarMutexGuard aGuard
;
680 // set the tab indexes according to the order of models in the sequence
681 const Reference
< XControlModel
>* pControls
= _rControls
.getConstArray( );
682 const Reference
< XControlModel
>* pControlsEnd
= _rControls
.getConstArray( ) + _rControls
.getLength();
684 sal_Int16 nTabIndex
= 1;
686 for ( ; pControls
!= pControlsEnd
; ++pControls
)
688 // look up the control in our own structure. This is to prevent invalid arguments
689 UnoControlModelHolderList::const_iterator aPos
=
691 maModels
.begin(), maModels
.end(),
692 CompareControlModel( *pControls
)
694 if ( maModels
.end() != aPos
)
696 // okay, this is an existent model
697 // now set the TabIndex property (if applicable)
698 Reference
< XPropertySet
> xProps( aPos
->first
, UNO_QUERY
);
699 Reference
< XPropertySetInfo
> xPSI
;
701 xPSI
= xProps
->getPropertySetInfo();
702 if ( xPSI
.is() && xPSI
->hasPropertyByName( getTabIndexPropertyName() ) )
703 xProps
->setPropertyValue( getTabIndexPropertyName(), makeAny( nTabIndex
++ ) );
705 mbGroupsUpToDate
= false;
710 typedef ::std::multimap
< sal_Int32
, Reference
< XControlModel
>, ::std::less
< sal_Int32
> > MapIndexToModel
;
713 Sequence
< Reference
< XControlModel
> > SAL_CALL
ControlModelContainerBase::getControlModels( ) throw (RuntimeException
, std::exception
)
715 SolarMutexGuard aGuard
;
717 MapIndexToModel aSortedModels
;
718 // will be the sorted container of all models which have a tab index property
719 ::std::vector
< Reference
< XControlModel
> > aUnindexedModels
;
720 // will be the container of all models which do not have a tab index property
722 UnoControlModelHolderList::const_iterator aLoop
= maModels
.begin();
723 for ( ; aLoop
!= maModels
.end(); ++aLoop
)
725 Reference
< XControlModel
> xModel( aLoop
->first
);
727 // see if the model has a TabIndex property
728 Reference
< XPropertySet
> xControlProps( xModel
, UNO_QUERY
);
729 Reference
< XPropertySetInfo
> xPSI
;
730 if ( xControlProps
.is() )
731 xPSI
= xControlProps
->getPropertySetInfo( );
732 DBG_ASSERT( xPSI
.is(), "ControlModelContainerBase::getControlModels: invalid child model!" );
735 if ( xPSI
.is() && xPSI
->hasPropertyByName( getTabIndexPropertyName() ) )
737 sal_Int32 nTabIndex
= -1;
738 xControlProps
->getPropertyValue( getTabIndexPropertyName() ) >>= nTabIndex
;
740 aSortedModels
.insert( MapIndexToModel::value_type( nTabIndex
, xModel
) );
742 else if ( xModel
.is() )
743 // no, it hasn't, but we have to include it, anyway
744 aUnindexedModels
.push_back( xModel
);
747 // okay, here we have a container of all our models, sorted by tab index,
748 // plus a container of "unindexed" models
750 Sequence
< Reference
< XControlModel
> > aReturn( aUnindexedModels
.size() + aSortedModels
.size() );
752 aSortedModels
.begin(), aSortedModels
.end(),
753 ::std::copy( aUnindexedModels
.begin(), aUnindexedModels
.end(), aReturn
.getArray() ),
754 ::boost::bind( &MapIndexToModel::value_type::second
, _1
)
761 void SAL_CALL
ControlModelContainerBase::setGroup( const Sequence
< Reference
< XControlModel
> >&, const OUString
& ) throw (RuntimeException
, std::exception
)
763 // not supported. We have only implicit grouping:
764 // We only have a sequence of control models, and we _know_ (yes, that's a HACK relying on
765 // implementation details) that VCL does grouping according to the order of controls automatically
766 // At least VCL does this for all we're interested in: Radio buttons.
767 OSL_TRACE( "ControlModelContainerBase::setGroup: grouping not supported" );
770 ////----- XInitialization -------------------------------------------------------------------
771 void SAL_CALL
ControlModelContainerBase::initialize (const Sequence
<Any
>& rArguments
) throw (com::sun::star::uno::Exception
, com::sun::star::uno::RuntimeException
, std::exception
)
773 if ( rArguments
.getLength() == 1 )
775 sal_Int16 nPageId
= -1;
776 if ( !( rArguments
[ 0 ] >>= nPageId
))
777 throw lang::IllegalArgumentException();
778 m_nTabPageId
= nPageId
;
783 ::sal_Int16 SAL_CALL
ControlModelContainerBase::getTabPageID() throw (::com::sun::star::uno::RuntimeException
, std::exception
)
787 sal_Bool SAL_CALL
ControlModelContainerBase::getEnabled() throw (::com::sun::star::uno::RuntimeException
, std::exception
)
791 void SAL_CALL
ControlModelContainerBase::setEnabled( sal_Bool _enabled
) throw (::com::sun::star::uno::RuntimeException
, std::exception
)
793 m_bEnabled
= _enabled
;
795 OUString SAL_CALL
ControlModelContainerBase::getTitle() throw (::com::sun::star::uno::RuntimeException
, std::exception
)
797 SolarMutexGuard aGuard
;
798 Reference
<XPropertySet
> xThis(*this,UNO_QUERY
);
800 xThis
->getPropertyValue(GetPropertyName(BASEPROPERTY_TITLE
)) >>= sTitle
;
803 void SAL_CALL
ControlModelContainerBase::setTitle( const OUString
& _title
) throw (::com::sun::star::uno::RuntimeException
, std::exception
)
805 SolarMutexGuard aGuard
;
806 Reference
<XPropertySet
> xThis(*this,UNO_QUERY
);
807 xThis
->setPropertyValue(GetPropertyName(BASEPROPERTY_TITLE
),makeAny(_title
));
809 OUString SAL_CALL
ControlModelContainerBase::getImageURL() throw (::com::sun::star::uno::RuntimeException
, std::exception
)
813 void SAL_CALL
ControlModelContainerBase::setImageURL( const OUString
& _imageurl
) throw (::com::sun::star::uno::RuntimeException
, std::exception
)
815 m_sImageURL
= _imageurl
;
817 OUString SAL_CALL
ControlModelContainerBase::getToolTip() throw (::com::sun::star::uno::RuntimeException
, std::exception
)
821 void SAL_CALL
ControlModelContainerBase::setToolTip( const OUString
& _tooltip
) throw (::com::sun::star::uno::RuntimeException
, std::exception
)
823 m_sTooltip
= _tooltip
;
829 enum GroupingMachineState
836 static sal_Int32
lcl_getDialogStep( const Reference
< XControlModel
>& _rxModel
)
841 Reference
< XPropertySet
> xModelProps( _rxModel
, UNO_QUERY
);
842 xModelProps
->getPropertyValue( getStepPropertyName() ) >>= nStep
;
844 catch (const Exception
&)
846 OSL_TRACE( "lcl_getDialogStep: caught an exception while determining the dialog page!" );
853 sal_Int32 SAL_CALL
ControlModelContainerBase::getGroupCount( ) throw (RuntimeException
, std::exception
)
855 SolarMutexGuard aGuard
;
857 implUpdateGroupStructure();
859 return maGroups
.size();
863 void SAL_CALL
ControlModelContainerBase::getGroup( sal_Int32 _nGroup
, Sequence
< Reference
< XControlModel
> >& _rGroup
, OUString
& _rName
) throw (RuntimeException
, std::exception
)
865 SolarMutexGuard aGuard
;
867 implUpdateGroupStructure();
869 if ( ( _nGroup
< 0 ) || ( _nGroup
>= (sal_Int32
)maGroups
.size() ) )
871 OSL_TRACE( "ControlModelContainerBase::getGroup: invalid argument and I am not allowed to throw an exception!" );
872 _rGroup
.realloc( 0 );
877 AllGroups::const_iterator aGroupPos
= maGroups
.begin() + _nGroup
;
878 _rGroup
.realloc( aGroupPos
->size() );
880 ::std::copy( aGroupPos
->begin(), aGroupPos
->end(), _rGroup
.getArray() );
881 // give the group a name
882 _rName
= OUString::number( _nGroup
);
887 void SAL_CALL
ControlModelContainerBase::getGroupByName( const OUString
& _rName
, Sequence
< Reference
< XControlModel
> >& _rGroup
) throw (RuntimeException
, std::exception
)
889 SolarMutexGuard aGuard
;
892 getGroup( _rName
.toInt32( ), _rGroup
, sDummyName
);
896 void SAL_CALL
ControlModelContainerBase::addChangesListener( const Reference
< XChangesListener
>& _rxListener
) throw (RuntimeException
, std::exception
)
898 maChangeListeners
.addInterface( _rxListener
);
902 void SAL_CALL
ControlModelContainerBase::removeChangesListener( const Reference
< XChangesListener
>& _rxListener
) throw (RuntimeException
, std::exception
)
904 maChangeListeners
.removeInterface( _rxListener
);
908 void ControlModelContainerBase::implNotifyTabModelChange( const OUString
& _rAccessor
)
910 // multiplex to our change listeners:
913 aEvent
.Source
= *this;
914 aEvent
.Base
<<= aEvent
.Source
; // the "base of the changes root" is also ourself
915 aEvent
.Changes
.realloc( 1 ); // exactly one change
916 aEvent
.Changes
[ 0 ].Accessor
<<= _rAccessor
;
919 Sequence
< Reference
< XInterface
> > aChangeListeners( maChangeListeners
.getElements() );
920 const Reference
< XInterface
>* pListener
= aChangeListeners
.getConstArray();
921 const Reference
< XInterface
>* pListenerEnd
= aChangeListeners
.getConstArray() + aChangeListeners
.getLength();
922 for ( ; pListener
!= pListenerEnd
; ++pListener
)
924 if ( pListener
->is() )
925 static_cast< XChangesListener
* >( pListener
->get() )->changesOccurred( aEvent
);
931 void ControlModelContainerBase::implUpdateGroupStructure()
933 if ( mbGroupsUpToDate
)
937 // conditions for a group:
938 // * all elements of the group are radio buttons
939 // * all elements of the group are on the same dialog page
940 // * in the overall control order (determined by the tab index), all elements are subsequent
944 Sequence
< Reference
< XControlModel
> > aControlModels
= getControlModels();
945 const Reference
< XControlModel
>* pControlModels
= aControlModels
.getConstArray();
946 const Reference
< XControlModel
>* pControlModelsEnd
= pControlModels
+ aControlModels
.getLength();
948 // in extreme we have as much groups as controls
949 maGroups
.reserve( aControlModels
.getLength() );
951 GroupingMachineState eState
= eLookingForGroup
; // the current state of our machine
952 Reference
< XServiceInfo
> xModelSI
; // for checking for a radion button
953 AllGroups::iterator aCurrentGroup
= maGroups
.end(); // the group which we're currently building
954 sal_Int32 nCurrentGroupStep
= -1; // the step which all controls of the current group belong to
955 bool bIsRadioButton
; // is it a radio button?
957 #if OSL_DEBUG_LEVEL > 1
958 ::std::vector
< OUString
> aCurrentGroupLabels
;
961 for ( ; pControlModels
!= pControlModelsEnd
; ++pControlModels
)
963 // we'll need this in every state
964 xModelSI
.set(*pControlModels
, css::uno::UNO_QUERY
);
965 bIsRadioButton
= xModelSI
.is() && xModelSI
->supportsService( "com.sun.star.awt.UnoControlRadioButtonModel" );
969 case eLookingForGroup
:
971 if ( !bIsRadioButton
)
972 // this is no radio button -> still looking for the beginning of a group
974 // the current model is a radio button
975 // -> we found the beginning of a new group
976 // create the place for this group
977 size_t nGroups
= maGroups
.size();
978 maGroups
.resize( nGroups
+ 1 );
979 aCurrentGroup
= maGroups
.begin() + nGroups
;
980 // and add the (only, til now) member
981 aCurrentGroup
->push_back( *pControlModels
);
983 // get the step which all controls of this group now have to belong to
984 nCurrentGroupStep
= lcl_getDialogStep( *pControlModels
);
985 // new state: looking for further members
986 eState
= eExpandingGroup
;
988 #if OSL_DEBUG_LEVEL > 1
989 Reference
< XPropertySet
> xModelProps( *pControlModels
, UNO_QUERY
);
991 if ( xModelProps
.is() && xModelProps
->getPropertySetInfo().is() && xModelProps
->getPropertySetInfo()->hasPropertyByName("Label") )
992 xModelProps
->getPropertyValue("Label") >>= sLabel
;
993 aCurrentGroupLabels
.push_back( sLabel
);
998 case eExpandingGroup
:
1000 if ( !bIsRadioButton
)
1001 { // no radio button -> the group is done
1002 aCurrentGroup
= maGroups
.end();
1003 eState
= eLookingForGroup
;
1004 #if OSL_DEBUG_LEVEL > 1
1005 aCurrentGroupLabels
.clear();
1010 // it is a radio button - is it on the proper page?
1011 const sal_Int32 nThisModelStep
= lcl_getDialogStep( *pControlModels
);
1012 if ( ( nThisModelStep
== nCurrentGroupStep
) // the current button is on the same dialog page
1013 || ( 0 == nThisModelStep
) // the current button appears on all pages
1016 // -> it belongs to the same group
1017 aCurrentGroup
->push_back( *pControlModels
);
1018 // state still is eExpandingGroup - we're looking for further elements
1019 eState
= eExpandingGroup
;
1021 #if OSL_DEBUG_LEVEL > 1
1022 Reference
< XPropertySet
> xModelProps( *pControlModels
, UNO_QUERY
);
1024 if ( xModelProps
.is() && xModelProps
->getPropertySetInfo().is() && xModelProps
->getPropertySetInfo()->hasPropertyByName("Label") )
1025 xModelProps
->getPropertyValue("Label") >>= sLabel
;
1026 aCurrentGroupLabels
.push_back( sLabel
);
1031 // it's a radio button, but on a different page
1032 // -> we open a new group for it
1034 // close the old group
1035 aCurrentGroup
= maGroups
.end();
1036 #if OSL_DEBUG_LEVEL > 1
1037 aCurrentGroupLabels
.clear();
1041 size_t nGroups
= maGroups
.size();
1042 maGroups
.resize( nGroups
+ 1 );
1043 aCurrentGroup
= maGroups
.begin() + nGroups
;
1044 // and add the (only, til now) member
1045 aCurrentGroup
->push_back( *pControlModels
);
1047 nCurrentGroupStep
= nThisModelStep
;
1049 // state is the same: we still are looking for further elements of the current group
1050 eState
= eExpandingGroup
;
1051 #if OSL_DEBUG_LEVEL > 1
1052 Reference
< XPropertySet
> xModelProps( *pControlModels
, UNO_QUERY
);
1054 if ( xModelProps
.is() && xModelProps
->getPropertySetInfo().is() && xModelProps
->getPropertySetInfo()->hasPropertyByName("Label") )
1055 xModelProps
->getPropertyValue("Label") >>= sLabel
;
1056 aCurrentGroupLabels
.push_back( sLabel
);
1063 mbGroupsUpToDate
= true;
1067 void SAL_CALL
ControlModelContainerBase::propertyChange( const PropertyChangeEvent
& _rEvent
) throw (RuntimeException
, std::exception
)
1069 SolarMutexGuard aGuard
;
1071 DBG_ASSERT( _rEvent
.PropertyName
== "TabIndex",
1072 "ControlModelContainerBase::propertyChange: not listening for this property!" );
1074 // the accessor for the changed element
1076 UnoControlModelHolderList::const_iterator aPos
=
1078 maModels
.begin(), maModels
.end(),
1079 CompareControlModel( Reference
< XControlModel
>( _rEvent
.Source
, UNO_QUERY
) )
1081 OSL_ENSURE( maModels
.end() != aPos
, "ControlModelContainerBase::propertyChange: don't know this model!" );
1082 if ( maModels
.end() != aPos
)
1083 sAccessor
= aPos
->second
;
1085 // our groups are not up-to-date
1086 mbGroupsUpToDate
= false;
1089 implNotifyTabModelChange( sAccessor
);
1093 void SAL_CALL
ControlModelContainerBase::disposing( const EventObject
& /*rEvent*/ ) throw (RuntimeException
, std::exception
)
1098 void ControlModelContainerBase::startControlListening( const Reference
< XControlModel
>& _rxChildModel
)
1100 SolarMutexGuard aGuard
;
1102 Reference
< XPropertySet
> xModelProps( _rxChildModel
, UNO_QUERY
);
1103 Reference
< XPropertySetInfo
> xPSI
;
1104 if ( xModelProps
.is() )
1105 xPSI
= xModelProps
->getPropertySetInfo();
1107 if ( xPSI
.is() && xPSI
->hasPropertyByName( getTabIndexPropertyName() ) )
1108 xModelProps
->addPropertyChangeListener( getTabIndexPropertyName(), this );
1112 void ControlModelContainerBase::stopControlListening( const Reference
< XControlModel
>& _rxChildModel
)
1114 SolarMutexGuard aGuard
;
1116 Reference
< XPropertySet
> xModelProps( _rxChildModel
, UNO_QUERY
);
1117 Reference
< XPropertySetInfo
> xPSI
;
1118 if ( xModelProps
.is() )
1119 xPSI
= xModelProps
->getPropertySetInfo();
1121 if ( xPSI
.is() && xPSI
->hasPropertyByName( getTabIndexPropertyName() ) )
1122 xModelProps
->removePropertyChangeListener( getTabIndexPropertyName(), this );
1126 // = class ResourceListener
1129 ResourceListener::ResourceListener(
1130 const Reference
< util::XModifyListener
>& rListener
) :
1132 m_xListener( rListener
),
1133 m_bListening( false )
1137 ResourceListener::~ResourceListener()
1142 Any SAL_CALL
ResourceListener::queryInterface( const Type
& rType
)
1143 throw ( RuntimeException
, std::exception
)
1145 Any a
= ::cppu::queryInterface(
1147 static_cast< XModifyListener
* >( this ),
1148 static_cast< XEventListener
* >( this ));
1153 return OWeakObject::queryInterface( rType
);
1156 void SAL_CALL
ResourceListener::acquire() throw ()
1158 OWeakObject::acquire();
1161 void SAL_CALL
ResourceListener::release() throw ()
1163 OWeakObject::release();
1166 void ResourceListener::startListening(
1167 const Reference
< resource::XStringResourceResolver
>& rResource
)
1169 Reference
< util::XModifyBroadcaster
> xModifyBroadcaster( rResource
, UNO_QUERY
);
1173 ::osl::ResettableGuard
< ::osl::Mutex
> aGuard( m_aMutex
);
1174 bool bListening( m_bListening
);
1175 bool bResourceSet( m_xResource
.is() );
1179 if ( bListening
&& bResourceSet
)
1184 m_xResource
= rResource
;
1189 Reference
< util::XModifyListener
> xThis( static_cast<OWeakObject
*>( this ), UNO_QUERY
);
1190 if ( xModifyBroadcaster
.is() )
1194 xModifyBroadcaster
->addModifyListener( xThis
);
1197 ::osl::ResettableGuard
< ::osl::Mutex
> aGuard( m_aMutex
);
1198 m_bListening
= true;
1201 catch (const RuntimeException
&)
1205 catch (const Exception
&)
1211 void ResourceListener::stopListening()
1213 Reference
< util::XModifyBroadcaster
> xModifyBroadcaster
;
1216 ::osl::ResettableGuard
< ::osl::Mutex
> aGuard( m_aMutex
);
1217 if ( m_bListening
&& m_xResource
.is() )
1218 xModifyBroadcaster
= Reference
< util::XModifyBroadcaster
>( m_xResource
, UNO_QUERY
);
1222 Reference
< util::XModifyListener
> xThis( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
1223 if ( xModifyBroadcaster
.is() )
1229 m_bListening
= false;
1230 m_xResource
.clear();
1234 xModifyBroadcaster
->removeModifyListener( xThis
);
1236 catch (const RuntimeException
&)
1240 catch (const Exception
&)
1247 void SAL_CALL
ResourceListener::modified(
1248 const lang::EventObject
& aEvent
)
1249 throw ( RuntimeException
, std::exception
)
1251 Reference
< util::XModifyListener
> xListener
;
1254 ::osl::ResettableGuard
< ::osl::Mutex
> aGuard( m_aMutex
);
1255 xListener
= m_xListener
;
1259 if ( xListener
.is() )
1263 xListener
->modified( aEvent
);
1265 catch (const RuntimeException
&)
1269 catch (const Exception
&)
1276 void SAL_CALL
ResourceListener::disposing(
1277 const EventObject
& Source
)
1278 throw ( RuntimeException
, std::exception
)
1280 Reference
< lang::XEventListener
> xListener
;
1281 Reference
< resource::XStringResourceResolver
> xResource
;
1284 ::osl::ResettableGuard
< ::osl::Mutex
> aGuard( m_aMutex
);
1285 Reference
< XInterface
> xIfacRes( m_xResource
, UNO_QUERY
);
1286 Reference
< XInterface
> xIfacList( m_xListener
, UNO_QUERY
);
1290 if ( Source
.Source
== xIfacRes
)
1294 m_bListening
= false;
1295 xResource
= m_xResource
;
1296 xListener
= Reference
< lang::XEventListener
>( m_xListener
, UNO_QUERY
);
1297 m_xResource
.clear();
1301 if ( xListener
.is() )
1305 xListener
->disposing( Source
);
1307 catch (const RuntimeException
&)
1311 catch (const Exception
&)
1316 else if ( Source
.Source
== xIfacList
)
1320 m_bListening
= false;
1321 xListener
= Reference
< lang::XEventListener
>( m_xListener
, UNO_QUERY
);
1322 xResource
= m_xResource
;
1323 m_xResource
.clear();
1324 m_xListener
.clear();
1328 // Remove ourself as listener from resource resolver
1329 Reference
< util::XModifyBroadcaster
> xModifyBroadcaster( xResource
, UNO_QUERY
);
1330 Reference
< util::XModifyListener
> xThis( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
1331 if ( xModifyBroadcaster
.is() )
1335 xModifyBroadcaster
->removeModifyListener( xThis
);
1337 catch (const RuntimeException
&)
1341 catch (const Exception
&)
1350 // class DialogContainerControl
1352 ControlContainerBase::ControlContainerBase( const Reference
< XComponentContext
>& rxContext
)
1353 :ContainerControl_IBase()
1354 ,m_xContext(rxContext
)
1355 ,mbSizeModified(false)
1356 ,mbPosModified(false)
1358 maComponentInfos
.nWidth
= 280;
1359 maComponentInfos
.nHeight
= 400;
1360 mxListener
= new ResourceListener( Reference
< util::XModifyListener
>(
1361 static_cast< OWeakObject
* >( this ), UNO_QUERY
));
1364 ControlContainerBase::~ControlContainerBase()
1368 void ControlContainerBase::createPeer( const Reference
< XToolkit
> & rxToolkit
, const Reference
< XWindowPeer
> & rParentPeer
) throw(RuntimeException
, std::exception
)
1370 SolarMutexGuard aGuard
;
1371 UnoControlContainer::createPeer( rxToolkit
, rParentPeer
);
1374 void ControlContainerBase::ImplInsertControl( Reference
< XControlModel
>& rxModel
, const OUString
& rName
)
1376 Reference
< XPropertySet
> xP( rxModel
, UNO_QUERY
);
1379 xP
->getPropertyValue( GetPropertyName( BASEPROPERTY_DEFAULTCONTROL
) ) >>= aDefCtrl
;
1380 Reference
< XControl
> xCtrl( m_xContext
->getServiceManager()->createInstanceWithContext(aDefCtrl
, m_xContext
), UNO_QUERY
);
1382 DBG_ASSERT( xCtrl
.is(), "ControlContainerBase::ImplInsertControl: could not create the control!" );
1385 xCtrl
->setModel( rxModel
);
1386 addControl( rName
, xCtrl
);
1387 // will implicitly call addingControl, where we can add the PropertiesChangeListener to the model
1388 // (which we formerly did herein)
1389 // 08.01.2001 - 96008 - fs@openoffice.org
1391 ImplSetPosSize( xCtrl
);
1395 void ControlContainerBase::ImplRemoveControl( Reference
< XControlModel
>& rxModel
)
1397 Sequence
< Reference
< XControl
> > aControls
= getControls();
1398 Reference
< XControl
> xCtrl
= StdTabController::FindControl( aControls
, rxModel
);
1401 removeControl( xCtrl
);
1406 catch (const Exception
&)
1408 DBG_UNHANDLED_EXCEPTION();
1413 void ControlContainerBase::ImplSetPosSize( Reference
< XControl
>& rxCtrl
)
1415 Reference
< XPropertySet
> xP( rxCtrl
->getModel(), UNO_QUERY
);
1417 sal_Int32 nX
= 0, nY
= 0, nWidth
= 0, nHeight
= 0;
1418 xP
->getPropertyValue("PositionX") >>= nX
;
1419 xP
->getPropertyValue("PositionY") >>= nY
;
1420 xP
->getPropertyValue("Width") >>= nWidth
;
1421 xP
->getPropertyValue("Height") >>= nHeight
;
1422 MapMode
aMode( MAP_APPFONT
);
1423 OutputDevice
*pOutDev
= Application::GetDefaultDevice();
1426 ::Size
aTmp( nX
, nY
);
1427 aTmp
= pOutDev
->LogicToPixel( aTmp
, aMode
);
1430 aTmp
= ::Size( nWidth
, nHeight
);
1431 aTmp
= pOutDev
->LogicToPixel( aTmp
, aMode
);
1432 nWidth
= aTmp
.Width();
1433 nHeight
= aTmp
.Height();
1437 Reference
< XWindowPeer
> xPeer
= ImplGetCompatiblePeer( true );
1438 Reference
< XDevice
> xD( xPeer
, UNO_QUERY
);
1440 SimpleFontMetric aFM
;
1442 Any aVal
= ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_FONTDESCRIPTOR
) );
1444 if ( !aFD
.StyleName
.isEmpty() )
1446 Reference
< XFont
> xFont
= xD
->getFont( aFD
);
1447 aFM
= xFont
->getFontMetric();
1451 Reference
< XGraphics
> xG
= xD
->createGraphics();
1452 aFM
= xG
->getFontMetric();
1455 sal_Int16 nH
= aFM
.Ascent
+ aFM
.Descent
;
1456 sal_Int16 nW
= nH
/2; // calculate avarage width?!
1467 Reference
< XWindow
> xW( rxCtrl
, UNO_QUERY
);
1468 xW
->setPosSize( nX
, nY
, nWidth
, nHeight
, PosSize::POSSIZE
);
1471 void ControlContainerBase::dispose() throw(RuntimeException
, std::exception
)
1474 aEvt
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
1475 // Notify our listener helper about dispose
1478 SolarMutexClearableGuard aGuard
;
1479 Reference
< XEventListener
> xListener( mxListener
, UNO_QUERY
);
1484 if ( xListener
.is() )
1485 xListener
->disposing( aEvt
);
1486 UnoControlContainer::dispose();
1489 void SAL_CALL
ControlContainerBase::disposing(
1490 const EventObject
& Source
)
1491 throw(RuntimeException
, std::exception
)
1493 UnoControlContainer::disposing( Source
);
1496 sal_Bool
ControlContainerBase::setModel( const Reference
< XControlModel
>& rxModel
) throw(RuntimeException
, std::exception
)
1498 SolarMutexGuard aGuard
;
1500 // destroy the old tab controller, if existent
1501 if ( mxTabController
.is() )
1503 mxTabController
->setModel( NULL
); // just to be sure, should not be necessary
1504 removeTabController( mxTabController
);
1505 ::comphelper::disposeComponent( mxTabController
); // just to be sure, should not be necessary
1506 mxTabController
.clear();
1509 if ( getModel().is() )
1511 Sequence
< Reference
< XControl
> > aControls
= getControls();
1512 const Reference
< XControl
>* pCtrls
= aControls
.getConstArray();
1513 const Reference
< XControl
>* pCtrlsEnd
= pCtrls
+ aControls
.getLength();
1515 for ( ; pCtrls
< pCtrlsEnd
; ++pCtrls
)
1516 removeControl( *pCtrls
);
1517 // will implicitly call removingControl, which will remove the PropertyChangeListener
1518 // (which we formerly did herein)
1519 // 08.01.2001 - 96008 - fs@openoffice.org
1521 Reference
< XContainer
> xC( getModel(), UNO_QUERY
);
1523 xC
->removeContainerListener( this );
1525 Reference
< XChangesNotifier
> xChangeNotifier( getModel(), UNO_QUERY
);
1526 if ( xChangeNotifier
.is() )
1527 xChangeNotifier
->removeChangesListener( this );
1530 bool bRet
= UnoControl::setModel( rxModel
);
1532 if ( getModel().is() )
1534 Reference
< XNameAccess
> xNA( getModel(), UNO_QUERY
);
1537 Sequence
< OUString
> aNames
= xNA
->getElementNames();
1538 const OUString
* pNames
= aNames
.getConstArray();
1539 sal_uInt32 nCtrls
= aNames
.getLength();
1541 Reference
< XControlModel
> xCtrlModel
;
1542 for( sal_uInt32 n
= 0; n
< nCtrls
; ++n
, ++pNames
)
1544 xNA
->getByName( *pNames
) >>= xCtrlModel
;
1545 ImplInsertControl( xCtrlModel
, *pNames
);
1549 Reference
< XContainer
> xC( getModel(), UNO_QUERY
);
1551 xC
->addContainerListener( this );
1553 Reference
< XChangesNotifier
> xChangeNotifier( getModel(), UNO_QUERY
);
1554 if ( xChangeNotifier
.is() )
1555 xChangeNotifier
->addChangesListener( this );
1558 Reference
< XTabControllerModel
> xTabbing( getModel(), UNO_QUERY
);
1559 if ( xTabbing
.is() )
1561 mxTabController
= new StdTabController
;
1562 mxTabController
->setModel( xTabbing
);
1563 addTabController( mxTabController
);
1565 ImplStartListingForResourceEvents();
1569 void ControlContainerBase::setDesignMode( sal_Bool bOn
) throw(RuntimeException
, std::exception
)
1571 SolarMutexGuard aGuard
;
1573 UnoControl::setDesignMode( bOn
);
1575 Sequence
< Reference
< XControl
> > xCtrls
= getControls();
1576 sal_Int32 nControls
= xCtrls
.getLength();
1577 Reference
< XControl
>* pControls
= xCtrls
.getArray();
1578 for ( sal_Int32 n
= 0; n
< nControls
; n
++ )
1579 pControls
[n
]->setDesignMode( bOn
);
1581 // #109067# in design mode the tab controller is not notified about
1582 // tab index changes, therefore the tab order must be activated
1583 // when switching from design mode to live mode
1584 if ( mxTabController
.is() && !bOn
)
1585 mxTabController
->activateTabOrder();
1588 void ControlContainerBase::elementInserted( const ContainerEvent
& Event
) throw(RuntimeException
, std::exception
)
1590 SolarMutexGuard aGuard
;
1592 Reference
< XControlModel
> xModel
;
1595 Event
.Accessor
>>= aName
;
1596 Event
.Element
>>= xModel
;
1597 ENSURE_OR_RETURN_VOID( xModel
.is(), "ControlContainerBase::elementInserted: illegal element!" );
1600 ImplInsertControl( xModel
, aName
);
1602 catch (const RuntimeException
&)
1606 catch (const Exception
&)
1608 DBG_UNHANDLED_EXCEPTION();
1612 void ControlContainerBase::elementRemoved( const ContainerEvent
& Event
) throw(RuntimeException
, std::exception
)
1614 SolarMutexGuard aGuard
;
1616 Reference
< XControlModel
> xModel
;
1617 Event
.Element
>>= xModel
;
1618 ENSURE_OR_RETURN_VOID( xModel
.is(), "ControlContainerBase::elementRemoved: illegal element!" );
1621 ImplRemoveControl( xModel
);
1623 catch (const RuntimeException
&)
1627 catch (const Exception
&)
1629 DBG_UNHANDLED_EXCEPTION();
1633 void ControlContainerBase::elementReplaced( const ContainerEvent
& Event
) throw(RuntimeException
, std::exception
)
1635 SolarMutexGuard aGuard
;
1637 Reference
< XControlModel
> xModel
;
1638 Event
.ReplacedElement
>>= xModel
;
1641 OSL_ENSURE( xModel
.is(), "ControlContainerBase::elementReplaced: invalid ReplacedElement!" );
1643 ImplRemoveControl( xModel
);
1645 catch (const RuntimeException
&)
1649 catch (const Exception
&)
1651 DBG_UNHANDLED_EXCEPTION();
1655 Event
.Accessor
>>= aName
;
1656 Event
.Element
>>= xModel
;
1657 ENSURE_OR_RETURN_VOID( xModel
.is(), "ControlContainerBase::elementReplaced: invalid new element!" );
1660 ImplInsertControl( xModel
, aName
);
1662 catch (const RuntimeException
&)
1666 catch (const Exception
&)
1668 DBG_UNHANDLED_EXCEPTION();
1672 // XPropertiesChangeListener
1673 void ControlContainerBase::ImplModelPropertiesChanged( const Sequence
< PropertyChangeEvent
>& rEvents
) throw(RuntimeException
)
1675 if( !isDesignMode() && !mbCreatingCompatiblePeer
)
1677 OUString
s1( "PositionX" );
1678 OUString
s2( "PositionY" );
1679 OUString
s3( "Width" );
1680 OUString
s4( "Height" );
1682 sal_Int32 nLen
= rEvents
.getLength();
1683 for( sal_Int32 i
= 0; i
< nLen
; i
++ )
1685 const PropertyChangeEvent
& rEvt
= rEvents
.getConstArray()[i
];
1686 Reference
< XControlModel
> xModel( rEvt
.Source
, UNO_QUERY
);
1687 bool bOwnModel
= (XControlModel
*)xModel
.get() == (XControlModel
*)getModel().get();
1688 if ( ( rEvt
.PropertyName
== s1
) ||
1689 ( rEvt
.PropertyName
== s2
) ||
1690 ( rEvt
.PropertyName
== s3
) ||
1691 ( rEvt
.PropertyName
== s4
) )
1695 if ( !mbPosModified
&& !mbSizeModified
)
1697 // Don't set new pos/size if we get new values from window listener
1698 Reference
< XControl
> xThis( (XAggregation
*)(::cppu::OWeakAggObject
*)this, UNO_QUERY
);
1699 ImplSetPosSize( xThis
);
1704 Sequence
<Reference
<XControl
> > aControlSequence(getControls());
1705 Reference
<XControl
> aControlRef( StdTabController::FindControl( aControlSequence
, xModel
) );
1706 ImplSetPosSize( aControlRef
);
1713 UnoControlContainer::ImplModelPropertiesChanged( rEvents
);
1716 void ControlContainerBase::addingControl( const Reference
< XControl
>& _rxControl
)
1718 SolarMutexGuard aGuard
;
1719 UnoControlContainer::addingControl( _rxControl
);
1721 if ( _rxControl
.is() )
1723 Reference
< XMultiPropertySet
> xProps( _rxControl
->getModel(), UNO_QUERY
);
1726 Sequence
< OUString
> aNames( 4 );
1727 OUString
* pNames
= aNames
.getArray();
1728 *pNames
++ = "PositionX";
1729 *pNames
++ = "PositionY";
1730 *pNames
++ = "Width";
1731 *pNames
++ = "Height";
1733 xProps
->addPropertiesChangeListener( aNames
, this );
1738 void ControlContainerBase::removingControl( const Reference
< XControl
>& _rxControl
)
1740 SolarMutexGuard aGuard
;
1741 UnoControlContainer::removingControl( _rxControl
);
1743 if ( _rxControl
.is() )
1745 Reference
< XMultiPropertySet
> xProps( _rxControl
->getModel(), UNO_QUERY
);
1747 xProps
->removePropertiesChangeListener( this );
1752 void SAL_CALL
ControlContainerBase::changesOccurred( const ChangesEvent
& ) throw (RuntimeException
, std::exception
)
1754 SolarMutexGuard aGuard
;
1755 // a tab controller model may have changed
1757 // #109067# in design mode don't notify the tab controller
1758 // about tab index changes
1759 if ( mxTabController
.is() && !mbDesignMode
)
1760 mxTabController
->activateTabOrder();
1762 static void lcl_ApplyResolverToNestedContainees( const Reference
< resource::XStringResourceResolver
>& xStringResourceResolver
, const Reference
< XControlContainer
>& xContainer
)
1764 OUString
aPropName( PROPERTY_RESOURCERESOLVER
);
1766 Any xNewStringResourceResolver
; xNewStringResourceResolver
<<= xStringResourceResolver
;
1768 Sequence
< OUString
> aPropNames(1);
1769 aPropNames
[0] = aPropName
;
1771 const Sequence
< Reference
< awt::XControl
> > aSeq
= xContainer
->getControls();
1772 for ( sal_Int32 i
= 0; i
< aSeq
.getLength(); i
++ )
1774 Reference
< XControl
> xControl( aSeq
[i
] );
1775 Reference
< XPropertySet
> xPropertySet
;
1777 if ( xControl
.is() )
1778 xPropertySet
= Reference
< XPropertySet
>( xControl
->getModel(), UNO_QUERY
);
1780 if ( !xPropertySet
.is() )
1785 Reference
< resource::XStringResourceResolver
> xCurrStringResourceResolver
;
1786 Any aOldValue
= xPropertySet
->getPropertyValue( aPropName
);
1787 if ( ( aOldValue
>>= xCurrStringResourceResolver
)
1788 && ( xStringResourceResolver
== xCurrStringResourceResolver
)
1791 Reference
< XMultiPropertySet
> xMultiPropSet( xPropertySet
, UNO_QUERY
);
1792 Reference
< XPropertiesChangeListener
> xListener( xPropertySet
, UNO_QUERY
);
1793 xMultiPropSet
->firePropertiesChangeEvent( aPropNames
, xListener
);
1796 xPropertySet
->setPropertyValue( aPropName
, xNewStringResourceResolver
);
1798 catch (const Exception
&)
1802 uno::Reference
< XControlContainer
> xNestedContainer( xControl
, uno::UNO_QUERY
);
1803 if ( xNestedContainer
.is() )
1804 lcl_ApplyResolverToNestedContainees( xStringResourceResolver
, xNestedContainer
);
1809 void ControlContainerBase::ImplStartListingForResourceEvents()
1811 Reference
< resource::XStringResourceResolver
> xStringResourceResolver
;
1813 ImplGetPropertyValue( PROPERTY_RESOURCERESOLVER
) >>= xStringResourceResolver
;
1815 // Add our helper as listener to retrieve notifications about changes
1816 Reference
< util::XModifyListener
> rListener( mxListener
);
1817 ResourceListener
* pResourceListener
= static_cast< ResourceListener
* >( rListener
.get() );
1819 // resource listener will stop listening if resolver reference is empty
1820 if ( pResourceListener
)
1821 pResourceListener
->startListening( xStringResourceResolver
);
1822 ImplUpdateResourceResolver();
1825 void ControlContainerBase::ImplUpdateResourceResolver()
1827 OUString
aPropName( PROPERTY_RESOURCERESOLVER
);
1828 Reference
< resource::XStringResourceResolver
> xStringResourceResolver
;
1830 ImplGetPropertyValue( aPropName
) >>= xStringResourceResolver
;
1831 if ( !xStringResourceResolver
.is() )
1834 lcl_ApplyResolverToNestedContainees( xStringResourceResolver
, this );
1836 // propagate resource resolver changes to language dependent props of the dialog
1837 Reference
< XPropertySet
> xPropertySet( getModel(), UNO_QUERY
);
1838 if ( xPropertySet
.is() )
1840 Reference
< XMultiPropertySet
> xMultiPropSet( xPropertySet
, UNO_QUERY
);
1841 Reference
< XPropertiesChangeListener
> xListener( xPropertySet
, UNO_QUERY
);
1842 xMultiPropSet
->firePropertiesChangeEvent( lcl_getLanguageDependentProperties(), xListener
);
1846 //// ----------------------------------------------------
1847 //// Helper Method to convert relative url to physical location
1848 //// ----------------------------------------------------
1850 OUString
getPhysicalLocation( const ::com::sun::star::uno::Any
& rbase
, const ::com::sun::star::uno::Any
& rUrl
)
1853 OUString baseLocation
;
1856 rbase
>>= baseLocation
;
1859 OUString
absoluteURL( url
);
1860 if ( !url
.isEmpty() )
1862 INetURLObject
urlObj(baseLocation
);
1863 urlObj
.removeSegment();
1864 baseLocation
= urlObj
.GetMainURL( INetURLObject::NO_DECODE
);
1866 const INetURLObject
protocolCheck( url
);
1867 const INetProtocol protocol
= protocolCheck
.GetProtocol();
1868 if ( protocol
== INetProtocol::NotValid
)
1870 OUString testAbsoluteURL
;
1871 if ( ::osl::FileBase::E_None
== ::osl::FileBase::getAbsoluteFileURL( baseLocation
, url
, testAbsoluteURL
) )
1872 absoluteURL
= testAbsoluteURL
;
1880 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
)
1882 if ( Operation
< Insert
|| Operation
> Remove
)
1883 throw IllegalArgumentException();
1885 if ( xAllChildren
.is() )
1887 if ( Operation
== Remove
)
1889 Reference
< XControlModel
> xOldModel( xAllChildren
->getByName( aName
), UNO_QUERY
);
1890 xAllChildren
->removeByName( aName
);
1892 Reference
< XNameContainer
> xChildContainer( xOldModel
, UNO_QUERY
);
1893 if ( xChildContainer
.is() )
1895 Reference
< XPropertySet
> xProps( xChildContainer
, UNO_QUERY
);
1896 // container control is being removed from this container, reset the
1897 // global list of containees
1899 xProps
->setPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES
), uno::makeAny( uno::Reference
< XNameContainer
>() ) );
1900 Sequence
< OUString
> aChildNames
= xChildContainer
->getElementNames();
1901 for ( sal_Int32 index
=0; index
< aChildNames
.getLength(); ++index
)
1902 updateUserFormChildren( xAllChildren
, aChildNames
[ index
], Operation
, Reference
< XControlModel
> () );
1905 else if ( Operation
== Insert
)
1907 xAllChildren
->insertByName( aName
, uno::makeAny( xTarget
) );
1908 Reference
< XNameContainer
> xChildContainer( xTarget
, UNO_QUERY
);
1909 if ( xChildContainer
.is() )
1911 // container control is being added from this container, reset the
1912 // global list of containees to point to the correct global list
1913 Reference
< XPropertySet
> xProps( xChildContainer
, UNO_QUERY
);
1915 xProps
->setPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES
), uno::makeAny( xAllChildren
) );
1916 Sequence
< OUString
> aChildNames
= xChildContainer
->getElementNames();
1917 for ( sal_Int32 index
=0; index
< aChildNames
.getLength(); ++index
)
1919 Reference
< XControlModel
> xChildTarget( xChildContainer
->getByName( aChildNames
[ index
] ), UNO_QUERY
);
1920 updateUserFormChildren( xAllChildren
, aChildNames
[ index
], Operation
, xChildTarget
);
1926 throw IllegalArgumentException();
1929 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */