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