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