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