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 68 : FindControlModel( const OUString& _rName ) : m_rName( _rName ) { }
133 :
134 98 : bool operator()( const ControlModelContainerBase::UnoControlModelHolder& _rCompare )
135 : {
136 98 : 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 122 : static const OUString& getTabIndexPropertyName( )
198 : {
199 122 : static const OUString s_sTabIndexProperty( "TabIndex" );
200 122 : 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 14 : ControlModelContainerBase::ControlModelContainerBase( const Reference< XComponentContext >& rxContext )
214 : :ControlModelContainer_IBase( rxContext )
215 : ,maContainerListeners( *this )
216 14 : ,maChangeListeners ( GetMutex() )
217 : ,mbGroupsUpToDate( false )
218 : ,m_bEnabled( true )
219 28 : ,m_nTabPageId(0)
220 : {
221 14 : }
222 :
223 1 : ControlModelContainerBase::ControlModelContainerBase( const ControlModelContainerBase& rModel )
224 : : ControlModelContainer_IBase( rModel )
225 : , maContainerListeners( *this )
226 1 : , maChangeListeners ( GetMutex() )
227 : , mbGroupsUpToDate( false )
228 : , m_bEnabled( rModel.m_bEnabled )
229 2 : , m_nTabPageId( rModel.m_nTabPageId )
230 : {
231 1 : }
232 :
233 10 : ControlModelContainerBase::~ControlModelContainerBase()
234 : {
235 5 : maModels.clear();
236 5 : mbGroupsUpToDate = false;
237 5 : }
238 :
239 30 : Any ControlModelContainerBase::ImplGetDefaultValue( sal_uInt16 nPropId ) const
240 : {
241 30 : Any aAny;
242 :
243 30 : switch ( nPropId )
244 : {
245 : case BASEPROPERTY_DEFAULTCONTROL:
246 0 : aAny <<= OUString::createFromAscii( szServiceName_UnoControlDialog );
247 0 : break;
248 : default:
249 30 : aAny = UnoControlModel::ImplGetDefaultValue( nPropId );
250 : }
251 :
252 30 : 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 5 : void SAL_CALL ControlModelContainerBase::dispose( ) throw(RuntimeException, std::exception)
267 : {
268 :
269 : // tell our listeners
270 : {
271 5 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
272 :
273 10 : EventObject aDisposeEvent;
274 5 : aDisposeEvent.Source = static_cast< XAggregation* >( static_cast< ::cppu::OWeakAggObject* >( this ) );
275 :
276 5 : maContainerListeners.disposeAndClear( aDisposeEvent );
277 10 : maChangeListeners.disposeAndClear( aDisposeEvent );
278 : }
279 :
280 :
281 : // call the base class
282 5 : 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 5 : ::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 5 : );
294 :
295 : // now dispose
296 5 : ::std::for_each( aChildModels.begin(), aChildModels.end(), DisposeControlModel() );
297 5 : aChildModels.clear();
298 :
299 5 : mbGroupsUpToDate = false;
300 5 : }
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 1 : 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 1 : );
315 1 : }
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 68 : ControlModelContainerBase::UnoControlModelHolderList::iterator ControlModelContainerBase::ImplFindElement( const OUString& rName )
326 : {
327 68 : return ::std::find_if( maModels.begin(), maModels.end(), FindControlModel( rName ) );
328 : }
329 :
330 : // ::XMultiServiceFactory
331 53 : Reference< XInterface > ControlModelContainerBase::createInstance( const OUString& aServiceSpecifier ) throw(Exception, RuntimeException, std::exception)
332 : {
333 53 : SolarMutexGuard aGuard;
334 :
335 53 : OGeometryControlModel_Base* pNewModel = NULL;
336 :
337 53 : if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlEditModel ) )
338 5 : pNewModel = new OGeometryControlModel< UnoControlEditModel >( m_xContext );
339 48 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlFormattedFieldModel ) )
340 1 : pNewModel = new OGeometryControlModel< UnoControlFormattedFieldModel >( m_xContext);
341 47 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlFileControlModel ) )
342 1 : pNewModel = new OGeometryControlModel< UnoControlFileControlModel >( m_xContext );
343 46 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlButtonModel ) )
344 6 : pNewModel = new OGeometryControlModel< UnoControlButtonModel >( m_xContext );
345 40 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlImageControlModel ) )
346 1 : pNewModel = new OGeometryControlModel< UnoControlImageControlModel >( m_xContext );
347 39 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlRadioButtonModel ) )
348 1 : pNewModel = new OGeometryControlModel< UnoControlRadioButtonModel >( m_xContext );
349 38 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlCheckBoxModel ) )
350 3 : pNewModel = new OGeometryControlModel< UnoControlCheckBoxModel >( m_xContext );
351 35 : else if ( aServiceSpecifier.equalsAscii( szServiceName_UnoControlFixedHyperlinkModel ) )
352 0 : pNewModel = new OGeometryControlModel< UnoControlFixedHyperlinkModel >( m_xContext );
353 35 : else if ( aServiceSpecifier.equalsAscii( szServiceName_UnoControlFixedTextModel ) )
354 0 : pNewModel = new OGeometryControlModel< UnoControlFixedTextModel >( m_xContext );
355 35 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlGroupBoxModel ) )
356 1 : pNewModel = new OGeometryControlModel< UnoControlGroupBoxModel >( m_xContext );
357 34 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlListBoxModel ) )
358 1 : pNewModel = new OGeometryControlModel< UnoControlListBoxModel >( m_xContext );
359 33 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlComboBoxModel ) )
360 1 : pNewModel = new OGeometryControlModel< UnoControlComboBoxModel >( m_xContext );
361 32 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlDateFieldModel ) )
362 1 : pNewModel = new OGeometryControlModel< UnoControlDateFieldModel >( m_xContext );
363 31 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlTimeFieldModel ) )
364 1 : pNewModel = new OGeometryControlModel< UnoControlTimeFieldModel >( m_xContext );
365 30 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlNumericFieldModel ) )
366 1 : pNewModel = new OGeometryControlModel< UnoControlNumericFieldModel >( m_xContext );
367 29 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlCurrencyFieldModel ) )
368 1 : pNewModel = new OGeometryControlModel< UnoControlCurrencyFieldModel >( m_xContext );
369 28 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlPatternFieldModel ) )
370 1 : pNewModel = new OGeometryControlModel< UnoControlPatternFieldModel >( m_xContext );
371 27 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlProgressBarModel ) )
372 1 : pNewModel = new OGeometryControlModel< UnoControlProgressBarModel >( m_xContext );
373 26 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlScrollBarModel ) )
374 1 : pNewModel = new OGeometryControlModel< UnoControlScrollBarModel >( m_xContext );
375 25 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlFixedLineModel ) )
376 1 : pNewModel = new OGeometryControlModel< UnoControlFixedLineModel >( m_xContext );
377 24 : else if ( aServiceSpecifier.equalsAscii( szServiceName2_UnoControlRoadmapModel ) )
378 1 : pNewModel = new OGeometryControlModel< UnoControlRoadmapModel >( m_xContext );
379 23 : else if ( aServiceSpecifier.equalsAscii( szServiceName_TreeControlModel ) )
380 1 : pNewModel = new OGeometryControlModel< UnoTreeModel >( m_xContext );
381 22 : else if ( aServiceSpecifier.equalsAscii( szServiceName_GridControlModel ) )
382 2 : pNewModel = new OGeometryControlModel< UnoGridModel >( m_xContext );
383 20 : else if ( aServiceSpecifier == "com.sun.star.awt.tab.UnoControlTabPageContainerModel" )
384 1 : pNewModel = new OGeometryControlModel< UnoControlTabPageContainerModel >( m_xContext );
385 19 : else if ( aServiceSpecifier.equalsAscii( szServiceName_UnoMultiPageModel ) )
386 1 : pNewModel = new OGeometryControlModel< UnoMultiPageModel >( m_xContext );
387 18 : else if ( aServiceSpecifier == "com.sun.star.awt.tab.UnoControlTabPageModel" )
388 1 : pNewModel = new OGeometryControlModel< UnoControlTabPageModel >( m_xContext );
389 17 : else if ( aServiceSpecifier.equalsAscii( szServiceName_UnoPageModel ) )
390 0 : pNewModel = new OGeometryControlModel< UnoPageModel >( m_xContext );
391 17 : else if ( aServiceSpecifier.equalsAscii( szServiceName_UnoFrameModel ) )
392 1 : pNewModel = new OGeometryControlModel< UnoFrameModel >( m_xContext );
393 :
394 53 : if ( !pNewModel )
395 : {
396 16 : Reference< XInterface > xObject = m_xContext->getServiceManager()->createInstanceWithContext(aServiceSpecifier, m_xContext);
397 32 : Reference< XServiceInfo > xSI( xObject, UNO_QUERY );
398 32 : Reference< XCloneable > xCloneAccess( xSI, UNO_QUERY );
399 32 : Reference< XAggregation > xAgg( xCloneAccess, UNO_QUERY );
400 16 : if ( xAgg.is() )
401 : {
402 16 : if ( xSI->supportsService("com.sun.star.awt.UnoControlModel") )
403 : {
404 : // release 3 of the 4 references we have to the object
405 16 : xAgg.clear();
406 16 : xSI.clear();
407 16 : xObject.clear();
408 :
409 16 : pNewModel = new OCommonGeometryControlModel( xCloneAccess, aServiceSpecifier );
410 : }
411 16 : }
412 : }
413 :
414 53 : Reference< XInterface > xNewModel = (::cppu::OWeakObject*)pNewModel;
415 53 : 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 1 : Sequence< OUString > ControlModelContainerBase::getAvailableServiceNames() throw(RuntimeException, std::exception)
428 : {
429 : static Sequence< OUString >* pNamesSeq = NULL;
430 1 : if ( !pNamesSeq )
431 : {
432 1 : pNamesSeq = new Sequence< OUString >( 26 );
433 1 : OUString* pNames = pNamesSeq->getArray();
434 1 : pNames[0] = OUString::createFromAscii( szServiceName2_UnoControlEditModel );
435 1 : pNames[1] = OUString::createFromAscii( szServiceName2_UnoControlFormattedFieldModel );
436 1 : pNames[2] = OUString::createFromAscii( szServiceName2_UnoControlFileControlModel );
437 1 : pNames[3] = OUString::createFromAscii( szServiceName2_UnoControlButtonModel );
438 1 : pNames[4] = OUString::createFromAscii( szServiceName2_UnoControlImageControlModel );
439 1 : pNames[5] = OUString::createFromAscii( szServiceName2_UnoControlRadioButtonModel );
440 1 : pNames[6] = OUString::createFromAscii( szServiceName2_UnoControlCheckBoxModel );
441 1 : pNames[7] = OUString::createFromAscii( szServiceName2_UnoControlFixedTextModel );
442 1 : pNames[8] = OUString::createFromAscii( szServiceName2_UnoControlGroupBoxModel );
443 1 : pNames[9] = OUString::createFromAscii( szServiceName2_UnoControlListBoxModel );
444 1 : pNames[10] = OUString::createFromAscii( szServiceName2_UnoControlComboBoxModel );
445 1 : pNames[11] = OUString::createFromAscii( szServiceName2_UnoControlDateFieldModel );
446 1 : pNames[12] = OUString::createFromAscii( szServiceName2_UnoControlTimeFieldModel );
447 1 : pNames[13] = OUString::createFromAscii( szServiceName2_UnoControlNumericFieldModel );
448 1 : pNames[14] = OUString::createFromAscii( szServiceName2_UnoControlCurrencyFieldModel );
449 1 : pNames[15] = OUString::createFromAscii( szServiceName2_UnoControlPatternFieldModel );
450 1 : pNames[16] = OUString::createFromAscii( szServiceName2_UnoControlProgressBarModel );
451 1 : pNames[17] = OUString::createFromAscii( szServiceName2_UnoControlScrollBarModel );
452 1 : pNames[18] = OUString::createFromAscii( szServiceName2_UnoControlFixedLineModel );
453 1 : pNames[19] = OUString::createFromAscii( szServiceName2_UnoControlRoadmapModel );
454 1 : pNames[20] = OUString::createFromAscii( szServiceName_TreeControlModel );
455 1 : pNames[21] = OUString::createFromAscii( szServiceName_GridControlModel );
456 1 : pNames[22] = OUString( "com.sun.star.awt.tab.UnoControlTabPageContainerModel");
457 1 : pNames[23] = OUString( "com.sun.star.awt.tab.UnoControlTabPageModel" );
458 1 : pNames[24] = OUString::createFromAscii( szServiceName_UnoMultiPageModel );
459 1 : pNames[25] = OUString::createFromAscii( szServiceName_UnoFrameModel );
460 : }
461 1 : return *pNamesSeq;
462 : }
463 :
464 : // XContainer
465 8 : void ControlModelContainerBase::addContainerListener( const Reference< XContainerListener >& l ) throw(RuntimeException, std::exception)
466 : {
467 8 : maContainerListeners.addInterface( l );
468 8 : }
469 :
470 3 : void ControlModelContainerBase::removeContainerListener( const Reference< XContainerListener >& l ) throw(RuntimeException, std::exception)
471 : {
472 3 : maContainerListeners.removeInterface( l );
473 3 : }
474 :
475 : // XElementAcces
476 1 : Type ControlModelContainerBase::getElementType() throw(RuntimeException, std::exception)
477 : {
478 1 : Type aType = getCppuType( ( Reference< XControlModel>* ) NULL );
479 1 : return aType;
480 : }
481 :
482 1 : sal_Bool ControlModelContainerBase::hasElements() throw(RuntimeException, std::exception)
483 : {
484 1 : return !maModels.empty();
485 : }
486 :
487 : // XNameContainer, XNameReplace, XNameAccess
488 4 : void ControlModelContainerBase::replaceByName( const OUString& aName, const Any& aElement ) throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException, std::exception)
489 : {
490 4 : SolarMutexGuard aGuard;
491 :
492 8 : Reference< XControlModel > xNewModel;
493 4 : aElement >>= xNewModel;
494 4 : if ( !xNewModel.is() )
495 0 : lcl_throwIllegalArgumentException();
496 :
497 4 : UnoControlModelHolderList::iterator aElementPos = ImplFindElement( aName );
498 4 : 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 8 : Reference< XNameContainer > xAllChildren( getPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ) ), UNO_QUERY );
507 4 : if ( xAllChildren.is() )
508 : {
509 : // remove old control ( and children ) from global list of containees
510 4 : updateUserFormChildren( xAllChildren, aName, Remove, uno::Reference< XControlModel >() );
511 : // Add new control ( and containees if they exist )
512 4 : updateUserFormChildren( xAllChildren, aName, Insert, xNewModel );
513 : }
514 : // stop listening at the old model
515 4 : stopControlListening( aElementPos->first );
516 8 : Reference< XControlModel > xReplaced( aElementPos->first );
517 : // remember the new model, and start listening
518 4 : aElementPos->first = xNewModel;
519 4 : startControlListening( xNewModel );
520 :
521 8 : ContainerEvent aEvent;
522 4 : aEvent.Source = *this;
523 4 : aEvent.Element = aElement;
524 4 : aEvent.ReplacedElement <<= xReplaced;
525 4 : aEvent.Accessor <<= aName;
526 :
527 : // notify the container listener
528 4 : maContainerListeners.elementReplaced( aEvent );
529 :
530 : // our "tab controller model" has potentially changed -> notify this
531 8 : implNotifyTabModelChange( aName );
532 4 : }
533 :
534 25 : Any ControlModelContainerBase::getByName( const OUString& aName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException, std::exception)
535 : {
536 25 : UnoControlModelHolderList::iterator aElementPos = ImplFindElement( aName );
537 25 : if ( maModels.end() == aElementPos )
538 1 : lcl_throwNoSuchElementException();
539 :
540 24 : return makeAny( aElementPos->first );
541 : }
542 :
543 23 : Sequence< OUString > ControlModelContainerBase::getElementNames() throw(RuntimeException, std::exception)
544 : {
545 23 : 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 23 : );
552 :
553 23 : return aNames;
554 : }
555 :
556 10 : sal_Bool ControlModelContainerBase::hasByName( const OUString& aName ) throw(RuntimeException, std::exception)
557 : {
558 10 : return maModels.end() != ImplFindElement( aName );
559 : }
560 :
561 26 : void ControlModelContainerBase::insertByName( const OUString& aName, const Any& aElement ) throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException, std::exception)
562 : {
563 26 : SolarMutexGuard aGuard;
564 :
565 52 : Reference< XControlModel > xM;
566 26 : aElement >>= xM;
567 :
568 26 : if ( xM.is() )
569 : {
570 25 : Reference< beans::XPropertySet > xProps( xM, UNO_QUERY );
571 25 : if ( xProps.is() )
572 : {
573 :
574 25 : Reference< beans::XPropertySetInfo > xPropInfo = xProps.get()->getPropertySetInfo();
575 :
576 50 : OUString sImageSourceProperty = GetPropertyName( BASEPROPERTY_IMAGEURL );
577 25 : if ( xPropInfo.get()->hasPropertyByName( sImageSourceProperty ) && ImplHasProperty(BASEPROPERTY_DIALOGSOURCEURL) )
578 : {
579 9 : Any aUrl = xProps.get()->getPropertyValue( sImageSourceProperty );
580 :
581 : OUString absoluteUrl =
582 18 : getPhysicalLocation( getPropertyValue( GetPropertyName( BASEPROPERTY_DIALOGSOURCEURL ) ), aUrl );
583 :
584 9 : aUrl <<= absoluteUrl;
585 :
586 18 : xProps.get()->setPropertyValue( sImageSourceProperty , aUrl );
587 25 : }
588 25 : }
589 : }
590 :
591 :
592 :
593 26 : if ( aName.isEmpty() || !xM.is() )
594 1 : lcl_throwIllegalArgumentException();
595 :
596 25 : UnoControlModelHolderList::iterator aElementPos = ImplFindElement( aName );
597 25 : if ( maModels.end() != aElementPos )
598 1 : 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 48 : Reference< XNameContainer > xAllChildren( getPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ) ), UNO_QUERY );
608 :
609 24 : if ( xAllChildren.is() )
610 24 : updateUserFormChildren( xAllChildren, aName, Insert, xM );
611 24 : maModels.push_back( UnoControlModelHolder( xM, aName ) );
612 24 : mbGroupsUpToDate = false;
613 24 : startControlListening( xM );
614 :
615 48 : ContainerEvent aEvent;
616 24 : aEvent.Source = *this;
617 24 : aEvent.Element <<= aElement;
618 24 : aEvent.Accessor <<= aName;
619 24 : maContainerListeners.elementInserted( aEvent );
620 :
621 : // our "tab controller model" has potentially changed -> notify this
622 50 : implNotifyTabModelChange( aName );
623 24 : }
624 :
625 4 : void ControlModelContainerBase::removeByName( const OUString& aName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException, std::exception)
626 : {
627 4 : SolarMutexGuard aGuard;
628 :
629 4 : UnoControlModelHolderList::iterator aElementPos = ImplFindElement( aName );
630 4 : if ( maModels.end() == aElementPos )
631 1 : 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 6 : Reference< XNameContainer > xAllChildren( getPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ) ), UNO_QUERY );
639 3 : if ( xAllChildren.is() )
640 3 : updateUserFormChildren( xAllChildren, aName, Remove, uno::Reference< XControlModel >() );
641 :
642 6 : ContainerEvent aEvent;
643 3 : aEvent.Source = *this;
644 3 : aEvent.Element <<= aElementPos->first;
645 3 : aEvent.Accessor <<= aName;
646 3 : maContainerListeners.elementRemoved( aEvent );
647 :
648 3 : stopControlListening( aElementPos->first );
649 6 : Reference< XPropertySet > xPS( aElementPos->first, UNO_QUERY );
650 3 : maModels.erase( aElementPos );
651 3 : mbGroupsUpToDate = false;
652 :
653 3 : if ( xPS.is() )
654 : {
655 : try
656 : {
657 3 : 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 7 : implNotifyTabModelChange( aName );
667 3 : }
668 :
669 :
670 6 : sal_Bool SAL_CALL ControlModelContainerBase::getGroupControl( ) throw (RuntimeException, std::exception)
671 : {
672 6 : 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 18 : Sequence< Reference< XControlModel > > SAL_CALL ControlModelContainerBase::getControlModels( ) throw (RuntimeException, std::exception)
720 : {
721 18 : SolarMutexGuard aGuard;
722 :
723 36 : MapIndexToModel aSortedModels;
724 : // will be the sorted container of all models which have a tab index property
725 36 : ::std::vector< Reference< XControlModel > > aUnindexedModels;
726 : // will be the container of all models which do not have a tab index property
727 :
728 18 : UnoControlModelHolderList::const_iterator aLoop = maModels.begin();
729 44 : for ( ; aLoop != maModels.end(); ++aLoop )
730 : {
731 26 : Reference< XControlModel > xModel( aLoop->first );
732 :
733 : // see if the model has a TabIndex property
734 52 : Reference< XPropertySet > xControlProps( xModel, UNO_QUERY );
735 52 : Reference< XPropertySetInfo > xPSI;
736 26 : if ( xControlProps.is() )
737 26 : xPSI = xControlProps->getPropertySetInfo( );
738 : DBG_ASSERT( xPSI.is(), "ControlModelContainerBase::getControlModels: invalid child model!" );
739 :
740 : // has it?
741 26 : if ( xPSI.is() && xPSI->hasPropertyByName( getTabIndexPropertyName() ) )
742 : { // yes
743 26 : sal_Int32 nTabIndex = -1;
744 26 : xControlProps->getPropertyValue( getTabIndexPropertyName() ) >>= nTabIndex;
745 :
746 26 : 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 26 : }
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 18 : 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 18 : );
762 :
763 36 : 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 1 : static sal_Int32 lcl_getDialogStep( const Reference< XControlModel >& _rxModel )
843 : {
844 1 : sal_Int32 nStep = 0;
845 : try
846 : {
847 1 : Reference< XPropertySet > xModelProps( _rxModel, UNO_QUERY );
848 1 : 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 1 : return nStep;
855 : }
856 : }
857 :
858 :
859 6 : sal_Int32 SAL_CALL ControlModelContainerBase::getGroupCount( ) throw (RuntimeException, std::exception)
860 : {
861 6 : SolarMutexGuard aGuard;
862 :
863 6 : implUpdateGroupStructure();
864 :
865 6 : return maGroups.size();
866 : }
867 :
868 :
869 1 : void SAL_CALL ControlModelContainerBase::getGroup( sal_Int32 _nGroup, Sequence< Reference< XControlModel > >& _rGroup, OUString& _rName ) throw (RuntimeException, std::exception)
870 : {
871 1 : SolarMutexGuard aGuard;
872 :
873 1 : implUpdateGroupStructure();
874 :
875 1 : 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 1 : AllGroups::const_iterator aGroupPos = maGroups.begin() + _nGroup;
884 1 : _rGroup.realloc( aGroupPos->size() );
885 : // copy the models
886 1 : ::std::copy( aGroupPos->begin(), aGroupPos->end(), _rGroup.getArray() );
887 : // give the group a name
888 1 : _rName = OUString::number( _nGroup );
889 1 : }
890 1 : }
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 7 : void SAL_CALL ControlModelContainerBase::addChangesListener( const Reference< XChangesListener >& _rxListener ) throw (RuntimeException, std::exception)
903 : {
904 7 : maChangeListeners.addInterface( _rxListener );
905 7 : }
906 :
907 :
908 2 : void SAL_CALL ControlModelContainerBase::removeChangesListener( const Reference< XChangesListener >& _rxListener ) throw (RuntimeException, std::exception)
909 : {
910 2 : maChangeListeners.removeInterface( _rxListener );
911 2 : }
912 :
913 :
914 31 : void ControlModelContainerBase::implNotifyTabModelChange( const OUString& _rAccessor )
915 : {
916 : // multiplex to our change listeners:
917 : // the changes event
918 31 : ChangesEvent aEvent;
919 31 : aEvent.Source = *this;
920 31 : aEvent.Base <<= aEvent.Source; // the "base of the changes root" is also ourself
921 31 : aEvent.Changes.realloc( 1 ); // exactly one change
922 31 : aEvent.Changes[ 0 ].Accessor <<= _rAccessor;
923 :
924 :
925 62 : Sequence< Reference< XInterface > > aChangeListeners( maChangeListeners.getElements() );
926 31 : const Reference< XInterface >* pListener = aChangeListeners.getConstArray();
927 31 : const Reference< XInterface >* pListenerEnd = aChangeListeners.getConstArray() + aChangeListeners.getLength();
928 42 : for ( ; pListener != pListenerEnd; ++pListener )
929 : {
930 11 : if ( pListener->is() )
931 11 : static_cast< XChangesListener* >( pListener->get() )->changesOccurred( aEvent );
932 31 : }
933 31 : }
934 :
935 :
936 :
937 7 : void ControlModelContainerBase::implUpdateGroupStructure()
938 : {
939 7 : if ( mbGroupsUpToDate )
940 : // nothing to do
941 9 : 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 5 : maGroups.clear();
949 :
950 5 : Sequence< Reference< XControlModel > > aControlModels = getControlModels();
951 5 : const Reference< XControlModel >* pControlModels = aControlModels.getConstArray();
952 5 : const Reference< XControlModel >* pControlModelsEnd = pControlModels + aControlModels.getLength();
953 :
954 : // in extreme we have as much groups as controls
955 5 : maGroups.reserve( aControlModels.getLength() );
956 :
957 5 : GroupingMachineState eState = eLookingForGroup; // the current state of our machine
958 10 : Reference< XServiceInfo > xModelSI; // for checking for a radion button
959 5 : AllGroups::iterator aCurrentGroup = maGroups.end(); // the group which we're currently building
960 5 : 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 12 : for ( ; pControlModels != pControlModelsEnd; ++pControlModels )
968 : {
969 : // we'll need this in every state
970 7 : xModelSI = xModelSI.query( *pControlModels );
971 7 : bIsRadioButton = xModelSI.is() && xModelSI->supportsService( OUString::createFromAscii( szServiceName2_UnoControlRadioButtonModel ) );
972 :
973 7 : switch ( eState )
974 : {
975 : case eLookingForGroup:
976 : {
977 6 : if ( !bIsRadioButton )
978 : // this is no radio button -> still looking for the beginning of a group
979 5 : 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 1 : size_t nGroups = maGroups.size();
984 1 : maGroups.resize( nGroups + 1 );
985 1 : aCurrentGroup = maGroups.begin() + nGroups;
986 : // and add the (only, til now) member
987 1 : aCurrentGroup->push_back( *pControlModels );
988 :
989 : // get the step which all controls of this group now have to belong to
990 1 : nCurrentGroupStep = lcl_getDialogStep( *pControlModels );
991 : // new state: looking for further members
992 1 : 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 1 : break;
1003 :
1004 : case eExpandingGroup:
1005 : {
1006 1 : if ( !bIsRadioButton )
1007 : { // no radio button -> the group is done
1008 1 : aCurrentGroup = maGroups.end();
1009 1 : eState = eLookingForGroup;
1010 : #if OSL_DEBUG_LEVEL > 1
1011 : aCurrentGroupLabels.clear();
1012 : #endif
1013 1 : 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 10 : 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 28 : void ControlModelContainerBase::startControlListening( const Reference< XControlModel >& _rxChildModel )
1105 : {
1106 28 : SolarMutexGuard aGuard;
1107 :
1108 56 : Reference< XPropertySet > xModelProps( _rxChildModel, UNO_QUERY );
1109 56 : Reference< XPropertySetInfo > xPSI;
1110 28 : if ( xModelProps.is() )
1111 28 : xPSI = xModelProps->getPropertySetInfo();
1112 :
1113 28 : if ( xPSI.is() && xPSI->hasPropertyByName( getTabIndexPropertyName() ) )
1114 56 : xModelProps->addPropertyChangeListener( getTabIndexPropertyName(), this );
1115 28 : }
1116 :
1117 :
1118 7 : void ControlModelContainerBase::stopControlListening( const Reference< XControlModel >& _rxChildModel )
1119 : {
1120 7 : SolarMutexGuard aGuard;
1121 :
1122 14 : Reference< XPropertySet > xModelProps( _rxChildModel, UNO_QUERY );
1123 14 : Reference< XPropertySetInfo > xPSI;
1124 7 : if ( xModelProps.is() )
1125 7 : xPSI = xModelProps->getPropertySetInfo();
1126 :
1127 7 : if ( xPSI.is() && xPSI->hasPropertyByName( getTabIndexPropertyName() ) )
1128 14 : xModelProps->removePropertyChangeListener( getTabIndexPropertyName(), this );
1129 7 : }
1130 :
1131 :
1132 : // = class ResourceListener
1133 :
1134 :
1135 8 : ResourceListener::ResourceListener(
1136 : const Reference< util::XModifyListener >& rListener ) :
1137 : OWeakObject(),
1138 : m_xListener( rListener ),
1139 8 : m_bListening( false )
1140 : {
1141 8 : }
1142 :
1143 4 : ResourceListener::~ResourceListener()
1144 : {
1145 4 : }
1146 :
1147 : // XInterface
1148 18 : 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 18 : static_cast< XEventListener* >( this ));
1155 :
1156 18 : if ( a.hasValue() )
1157 18 : return a;
1158 :
1159 0 : return OWeakObject::queryInterface( rType );
1160 : }
1161 :
1162 58 : void SAL_CALL ResourceListener::acquire() throw ()
1163 : {
1164 58 : OWeakObject::acquire();
1165 58 : }
1166 :
1167 52 : void SAL_CALL ResourceListener::release() throw ()
1168 : {
1169 52 : OWeakObject::release();
1170 52 : }
1171 :
1172 14 : void ResourceListener::startListening(
1173 : const Reference< resource::XStringResourceResolver >& rResource )
1174 : {
1175 14 : Reference< util::XModifyBroadcaster > xModifyBroadcaster( rResource, UNO_QUERY );
1176 :
1177 : {
1178 : // --- SAFE ---
1179 14 : ::osl::ResettableGuard < ::osl::Mutex > aGuard( m_aMutex );
1180 14 : bool bListening( m_bListening );
1181 14 : bool bResourceSet( m_xResource.is() );
1182 14 : aGuard.clear();
1183 : // --- SAFE ---
1184 :
1185 14 : if ( bListening && bResourceSet )
1186 0 : stopListening();
1187 :
1188 : // --- SAFE ---
1189 14 : aGuard.reset();
1190 14 : m_xResource = rResource;
1191 14 : aGuard.clear();
1192 : // --- SAFE ---
1193 : }
1194 :
1195 28 : Reference< util::XModifyListener > xThis( static_cast<OWeakObject*>( this ), UNO_QUERY );
1196 14 : 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 14 : }
1215 14 : }
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 2 : void SAL_CALL ResourceListener::disposing(
1283 : const EventObject& Source )
1284 : throw ( RuntimeException, std::exception )
1285 : {
1286 2 : Reference< lang::XEventListener > xListener;
1287 4 : Reference< resource::XStringResourceResolver > xResource;
1288 :
1289 : // --- SAFE ---
1290 4 : ::osl::ResettableGuard < ::osl::Mutex > aGuard( m_aMutex );
1291 4 : Reference< XInterface > xIfacRes( m_xResource, UNO_QUERY );
1292 4 : Reference< XInterface > xIfacList( m_xListener, UNO_QUERY );
1293 2 : aGuard.clear();
1294 : // --- SAFE ---
1295 :
1296 2 : 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 2 : else if ( Source.Source == xIfacList )
1323 : {
1324 : // --- SAFE ---
1325 2 : aGuard.reset();
1326 2 : m_bListening = false;
1327 2 : xListener = Reference< lang::XEventListener >( m_xListener, UNO_QUERY );
1328 2 : xResource = m_xResource;
1329 2 : m_xResource.clear();
1330 2 : m_xListener.clear();
1331 2 : aGuard.clear();
1332 : // --- SAFE ---
1333 :
1334 : // Remove ourself as listener from resource resolver
1335 2 : Reference< util::XModifyBroadcaster > xModifyBroadcaster( xResource, UNO_QUERY );
1336 4 : Reference< util::XModifyListener > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1337 2 : 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 2 : }
1351 2 : }
1352 2 : }
1353 :
1354 :
1355 :
1356 : // class DialogContainerControl
1357 :
1358 8 : ControlContainerBase::ControlContainerBase( const Reference< XComponentContext >& rxContext )
1359 : :ContainerControl_IBase()
1360 : ,m_xContext(rxContext)
1361 : ,mbSizeModified(false)
1362 8 : ,mbPosModified(false)
1363 : {
1364 8 : maComponentInfos.nWidth = 280;
1365 8 : maComponentInfos.nHeight = 400;
1366 24 : mxListener = new ResourceListener( Reference< util::XModifyListener >(
1367 16 : static_cast< OWeakObject* >( this ), UNO_QUERY ));
1368 8 : }
1369 :
1370 1 : ControlContainerBase::~ControlContainerBase()
1371 : {
1372 1 : }
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 20 : void ControlContainerBase::ImplInsertControl( Reference< XControlModel >& rxModel, const OUString& rName )
1381 : {
1382 20 : Reference< XPropertySet > xP( rxModel, UNO_QUERY );
1383 :
1384 40 : OUString aDefCtrl;
1385 20 : xP->getPropertyValue( GetPropertyName( BASEPROPERTY_DEFAULTCONTROL ) ) >>= aDefCtrl;
1386 40 : 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 20 : if ( xCtrl.is() )
1390 : {
1391 20 : xCtrl->setModel( rxModel );
1392 20 : 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 20 : ImplSetPosSize( xCtrl );
1398 20 : }
1399 20 : }
1400 :
1401 7 : void ControlContainerBase::ImplRemoveControl( Reference< XControlModel >& rxModel )
1402 : {
1403 7 : Sequence< Reference< XControl > > aControls = getControls();
1404 14 : Reference< XControl > xCtrl = StdTabController::FindControl( aControls, rxModel );
1405 7 : if ( xCtrl.is() )
1406 : {
1407 7 : removeControl( xCtrl );
1408 : try
1409 : {
1410 7 : xCtrl->dispose();
1411 : }
1412 0 : catch (const Exception&)
1413 : {
1414 : DBG_UNHANDLED_EXCEPTION();
1415 : }
1416 7 : }
1417 7 : }
1418 :
1419 49 : void ControlContainerBase::ImplSetPosSize( Reference< XControl >& rxCtrl )
1420 : {
1421 49 : Reference< XPropertySet > xP( rxCtrl->getModel(), UNO_QUERY );
1422 :
1423 49 : sal_Int32 nX = 0, nY = 0, nWidth = 0, nHeight = 0;
1424 49 : xP->getPropertyValue("PositionX") >>= nX;
1425 49 : xP->getPropertyValue("PositionY") >>= nY;
1426 49 : xP->getPropertyValue("Width") >>= nWidth;
1427 49 : xP->getPropertyValue("Height") >>= nHeight;
1428 98 : MapMode aMode( MAP_APPFONT );
1429 49 : OutputDevice*pOutDev = Application::GetDefaultDevice();
1430 49 : if ( pOutDev )
1431 : {
1432 49 : ::Size aTmp( nX, nY );
1433 49 : aTmp = pOutDev->LogicToPixel( aTmp, aMode );
1434 49 : nX = aTmp.Width();
1435 49 : nY = aTmp.Height();
1436 49 : aTmp = ::Size( nWidth, nHeight );
1437 49 : aTmp = pOutDev->LogicToPixel( aTmp, aMode );
1438 49 : nWidth = aTmp.Width();
1439 49 : 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 98 : Reference < XWindow > xW( rxCtrl, UNO_QUERY );
1474 98 : xW->setPosSize( nX, nY, nWidth, nHeight, PosSize::POSSIZE );
1475 49 : }
1476 :
1477 3 : void ControlContainerBase::dispose() throw(RuntimeException, std::exception)
1478 : {
1479 3 : EventObject aEvt;
1480 3 : aEvt.Source = static_cast< ::cppu::OWeakObject* >( this );
1481 : // Notify our listener helper about dispose
1482 : // --- SAFE ---
1483 :
1484 6 : SolarMutexClearableGuard aGuard;
1485 6 : Reference< XEventListener > xListener( mxListener, UNO_QUERY );
1486 3 : mxListener.clear();
1487 3 : aGuard.clear();
1488 : // --- SAFE ---
1489 :
1490 3 : if ( xListener.is() )
1491 2 : xListener->disposing( aEvt );
1492 6 : UnoControlContainer::dispose();
1493 3 : }
1494 :
1495 4 : void SAL_CALL ControlContainerBase::disposing(
1496 : const EventObject& Source )
1497 : throw(RuntimeException, std::exception)
1498 : {
1499 4 : UnoControlContainer::disposing( Source );
1500 4 : }
1501 :
1502 10 : sal_Bool ControlContainerBase::setModel( const Reference< XControlModel >& rxModel ) throw(RuntimeException, std::exception)
1503 : {
1504 10 : SolarMutexGuard aGuard;
1505 :
1506 : // destroy the old tab controller, if existent
1507 10 : if ( mxTabController.is() )
1508 : {
1509 2 : mxTabController->setModel( NULL ); // just to be sure, should not be necessary
1510 2 : removeTabController( mxTabController );
1511 2 : ::comphelper::disposeComponent( mxTabController ); // just to be sure, should not be necessary
1512 2 : mxTabController.clear();
1513 : }
1514 :
1515 10 : if ( getModel().is() )
1516 : {
1517 2 : Sequence< Reference< XControl > > aControls = getControls();
1518 2 : const Reference< XControl >* pCtrls = aControls.getConstArray();
1519 2 : const Reference< XControl >* pCtrlsEnd = pCtrls + aControls.getLength();
1520 :
1521 2 : 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 4 : Reference< XContainer > xC( getModel(), UNO_QUERY );
1528 2 : if ( xC.is() )
1529 2 : xC->removeContainerListener( this );
1530 :
1531 4 : Reference< XChangesNotifier > xChangeNotifier( getModel(), UNO_QUERY );
1532 2 : if ( xChangeNotifier.is() )
1533 4 : xChangeNotifier->removeChangesListener( this );
1534 : }
1535 :
1536 10 : bool bRet = UnoControl::setModel( rxModel );
1537 :
1538 10 : if ( getModel().is() )
1539 : {
1540 7 : Reference< XNameAccess > xNA( getModel(), UNO_QUERY );
1541 7 : if ( xNA.is() )
1542 : {
1543 7 : Sequence< OUString > aNames = xNA->getElementNames();
1544 7 : const OUString* pNames = aNames.getConstArray();
1545 7 : sal_uInt32 nCtrls = aNames.getLength();
1546 :
1547 14 : Reference< XControlModel > xCtrlModel;
1548 19 : for( sal_uInt32 n = 0; n < nCtrls; ++n, ++pNames )
1549 : {
1550 12 : xNA->getByName( *pNames ) >>= xCtrlModel;
1551 12 : ImplInsertControl( xCtrlModel, *pNames );
1552 7 : }
1553 : }
1554 :
1555 14 : Reference< XContainer > xC( getModel(), UNO_QUERY );
1556 7 : if ( xC.is() )
1557 7 : xC->addContainerListener( this );
1558 :
1559 14 : Reference< XChangesNotifier > xChangeNotifier( getModel(), UNO_QUERY );
1560 7 : if ( xChangeNotifier.is() )
1561 14 : xChangeNotifier->addChangesListener( this );
1562 : }
1563 :
1564 20 : Reference< XTabControllerModel > xTabbing( getModel(), UNO_QUERY );
1565 10 : if ( xTabbing.is() )
1566 : {
1567 7 : mxTabController = new StdTabController;
1568 7 : mxTabController->setModel( xTabbing );
1569 7 : addTabController( mxTabController );
1570 : }
1571 10 : ImplStartListingForResourceEvents();
1572 :
1573 20 : 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 4 : void ControlContainerBase::elementInserted( const ContainerEvent& Event ) throw(RuntimeException, std::exception)
1595 : {
1596 4 : SolarMutexGuard aGuard;
1597 :
1598 8 : Reference< XControlModel > xModel;
1599 8 : OUString aName;
1600 :
1601 4 : Event.Accessor >>= aName;
1602 4 : Event.Element >>= xModel;
1603 8 : ENSURE_OR_RETURN_VOID( xModel.is(), "ControlContainerBase::elementInserted: illegal element!" );
1604 : try
1605 : {
1606 4 : 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 4 : }
1616 : }
1617 :
1618 3 : void ControlContainerBase::elementRemoved( const ContainerEvent& Event ) throw(RuntimeException, std::exception)
1619 : {
1620 3 : SolarMutexGuard aGuard;
1621 :
1622 6 : Reference< XControlModel > xModel;
1623 3 : Event.Element >>= xModel;
1624 6 : ENSURE_OR_RETURN_VOID( xModel.is(), "ControlContainerBase::elementRemoved: illegal element!" );
1625 : try
1626 : {
1627 3 : ImplRemoveControl( xModel );
1628 : }
1629 0 : catch (const RuntimeException&)
1630 : {
1631 0 : throw;
1632 : }
1633 0 : catch (const Exception&)
1634 : {
1635 : DBG_UNHANDLED_EXCEPTION();
1636 3 : }
1637 : }
1638 :
1639 4 : void ControlContainerBase::elementReplaced( const ContainerEvent& Event ) throw(RuntimeException, std::exception)
1640 : {
1641 4 : SolarMutexGuard aGuard;
1642 :
1643 8 : Reference< XControlModel > xModel;
1644 4 : Event.ReplacedElement >>= xModel;
1645 : try
1646 : {
1647 : OSL_ENSURE( xModel.is(), "ControlContainerBase::elementReplaced: invalid ReplacedElement!" );
1648 4 : if ( xModel.is() )
1649 4 : 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 8 : OUString aName;
1661 4 : Event.Accessor >>= aName;
1662 4 : Event.Element >>= xModel;
1663 8 : ENSURE_OR_RETURN_VOID( xModel.is(), "ControlContainerBase::elementReplaced: invalid new element!" );
1664 : try
1665 : {
1666 4 : 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 4 : }
1676 : }
1677 :
1678 : // XPropertiesChangeListener
1679 247 : void ControlContainerBase::ImplModelPropertiesChanged( const Sequence< PropertyChangeEvent >& rEvents ) throw(RuntimeException)
1680 : {
1681 247 : if( !isDesignMode() && !mbCreatingCompatiblePeer )
1682 : {
1683 247 : OUString s1( "PositionX" );
1684 494 : OUString s2( "PositionY" );
1685 494 : OUString s3( "Width" );
1686 494 : OUString s4( "Height" );
1687 :
1688 247 : sal_Int32 nLen = rEvents.getLength();
1689 621 : for( sal_Int32 i = 0; i < nLen; i++ )
1690 : {
1691 404 : const PropertyChangeEvent& rEvt = rEvents.getConstArray()[i];
1692 404 : Reference< XControlModel > xModel( rEvt.Source, UNO_QUERY );
1693 404 : bool bOwnModel = (XControlModel*)xModel.get() == (XControlModel*)getModel().get();
1694 1206 : if ( ( rEvt.PropertyName == s1 ) ||
1695 790 : ( rEvt.PropertyName == s2 ) ||
1696 1182 : ( rEvt.PropertyName == s3 ) ||
1697 386 : ( rEvt.PropertyName == s4 ) )
1698 : {
1699 30 : if ( bOwnModel )
1700 : {
1701 30 : if ( !mbPosModified && !mbSizeModified )
1702 : {
1703 : // Don't set new pos/size if we get new values from window listener
1704 29 : Reference< XControl > xThis( (XAggregation*)(::cppu::OWeakAggObject*)this, UNO_QUERY );
1705 29 : 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 30 : break;
1715 : }
1716 621 : }
1717 : }
1718 :
1719 247 : UnoControlContainer::ImplModelPropertiesChanged( rEvents );
1720 247 : }
1721 :
1722 21 : void ControlContainerBase::addingControl( const Reference< XControl >& _rxControl )
1723 : {
1724 21 : SolarMutexGuard aGuard;
1725 21 : UnoControlContainer::addingControl( _rxControl );
1726 :
1727 21 : if ( _rxControl.is() )
1728 : {
1729 21 : Reference< XMultiPropertySet > xProps( _rxControl->getModel(), UNO_QUERY );
1730 21 : if ( xProps.is() )
1731 : {
1732 21 : Sequence< OUString > aNames( 4 );
1733 21 : OUString* pNames = aNames.getArray();
1734 21 : *pNames++ = "PositionX";
1735 21 : *pNames++ = "PositionY";
1736 21 : *pNames++ = "Width";
1737 21 : *pNames++ = "Height";
1738 :
1739 21 : xProps->addPropertiesChangeListener( aNames, this );
1740 21 : }
1741 21 : }
1742 21 : }
1743 :
1744 9 : void ControlContainerBase::removingControl( const Reference< XControl >& _rxControl )
1745 : {
1746 9 : SolarMutexGuard aGuard;
1747 9 : UnoControlContainer::removingControl( _rxControl );
1748 :
1749 9 : if ( _rxControl.is() )
1750 : {
1751 9 : Reference< XMultiPropertySet > xProps( _rxControl->getModel(), UNO_QUERY );
1752 9 : if ( xProps.is() )
1753 9 : xProps->removePropertiesChangeListener( this );
1754 9 : }
1755 :
1756 9 : }
1757 :
1758 11 : void SAL_CALL ControlContainerBase::changesOccurred( const ChangesEvent& ) throw (RuntimeException, std::exception)
1759 : {
1760 11 : 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 11 : if ( mxTabController.is() && !mbDesignMode )
1766 11 : mxTabController->activateTabOrder();
1767 11 : }
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 20 : void ControlContainerBase::ImplStartListingForResourceEvents()
1816 : {
1817 20 : Reference< resource::XStringResourceResolver > xStringResourceResolver;
1818 :
1819 20 : ImplGetPropertyValue( PROPERTY_RESOURCERESOLVER ) >>= xStringResourceResolver;
1820 :
1821 : // Add our helper as listener to retrieve notifications about changes
1822 40 : Reference< util::XModifyListener > rListener( mxListener );
1823 20 : ResourceListener* pResourceListener = static_cast< ResourceListener* >( rListener.get() );
1824 :
1825 : // resource listener will stop listening if resolver reference is empty
1826 20 : if ( pResourceListener )
1827 14 : pResourceListener->startListening( xStringResourceResolver );
1828 40 : ImplUpdateResourceResolver();
1829 20 : }
1830 :
1831 20 : void ControlContainerBase::ImplUpdateResourceResolver()
1832 : {
1833 20 : OUString aPropName( PROPERTY_RESOURCERESOLVER );
1834 20 : Reference< resource::XStringResourceResolver > xStringResourceResolver;
1835 :
1836 20 : ImplGetPropertyValue( aPropName ) >>= xStringResourceResolver;
1837 20 : if ( !xStringResourceResolver.is() )
1838 40 : 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 11 : OUString getPhysicalLocation( const ::com::sun::star::uno::Any& rbase, const ::com::sun::star::uno::Any& rUrl )
1857 : {
1858 :
1859 11 : OUString baseLocation;
1860 22 : OUString url;
1861 :
1862 11 : rbase >>= baseLocation;
1863 11 : rUrl >>= url;
1864 :
1865 11 : OUString absoluteURL( url );
1866 11 : if ( !url.isEmpty() )
1867 : {
1868 2 : INetURLObject urlObj(baseLocation);
1869 2 : urlObj.removeSegment();
1870 2 : baseLocation = urlObj.GetMainURL( INetURLObject::NO_DECODE );
1871 :
1872 4 : const INetURLObject protocolCheck( url );
1873 2 : const INetProtocol protocol = protocolCheck.GetProtocol();
1874 2 : if ( protocol == INET_PROT_NOT_VALID )
1875 : {
1876 2 : OUString testAbsoluteURL;
1877 2 : if ( ::osl::FileBase::E_None == ::osl::FileBase::getAbsoluteFileURL( baseLocation, url, testAbsoluteURL ) )
1878 0 : absoluteURL = testAbsoluteURL;
1879 2 : }
1880 : }
1881 :
1882 22 : return absoluteURL;
1883 : }
1884 :
1885 : void
1886 35 : 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 35 : if ( Operation < Insert || Operation > Remove )
1889 0 : throw IllegalArgumentException();
1890 :
1891 35 : if ( xAllChildren.is() )
1892 : {
1893 35 : if ( Operation == Remove )
1894 : {
1895 7 : Reference< XControlModel > xOldModel( xAllChildren->getByName( aName ), UNO_QUERY );
1896 7 : xAllChildren->removeByName( aName );
1897 :
1898 14 : Reference< XNameContainer > xChildContainer( xOldModel, UNO_QUERY );
1899 7 : 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 7 : }
1910 : }
1911 28 : else if ( Operation == Insert )
1912 : {
1913 28 : xAllChildren->insertByName( aName, uno::makeAny( xTarget ) );
1914 28 : Reference< XNameContainer > xChildContainer( xTarget, UNO_QUERY );
1915 28 : 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 28 : }
1929 : }
1930 : }
1931 : else
1932 0 : throw IllegalArgumentException();
1933 548 : }
1934 :
1935 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|