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