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