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 : #include <com/sun/star/awt/XControlContainer.hpp>
21 : #include <com/sun/star/awt/WindowAttribute.hpp>
22 : #include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
23 : #include <com/sun/star/awt/PosSize.hpp>
24 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
25 : #include <com/sun/star/beans/PropertyValue.hpp>
26 : #include <com/sun/star/resource/XStringResourceResolver.hpp>
27 : #include <toolkit/controls/unocontrol.hxx>
28 : #include <toolkit/helper/vclunohelper.hxx>
29 : #include <cppuhelper/typeprovider.hxx>
30 : #include <rtl/uuid.h>
31 : #include <osl/mutex.hxx>
32 : #include <tools/date.hxx>
33 : #include <tools/debug.hxx>
34 : #include <tools/diagnose_ex.h>
35 : #include <vcl/svapp.hxx>
36 : #include <vcl/wrkwin.hxx>
37 : #include <comphelper/stl_types.hxx>
38 : #include <comphelper/processfactory.hxx>
39 : #include <toolkit/helper/property.hxx>
40 : #include <toolkit/helper/servicenames.hxx>
41 : #include <toolkit/helper/vclunohelper.hxx>
42 : #include <toolkit/awt/vclxwindow.hxx>
43 : #include <vcl/svapp.hxx>
44 : #include <osl/mutex.hxx>
45 : #include <toolkit/controls/accessiblecontrolcontext.hxx>
46 : #include <comphelper/container.hxx>
47 :
48 : #include <algorithm>
49 : #include <set>
50 :
51 : using namespace ::com::sun::star;
52 : using namespace ::com::sun::star::uno;
53 : using namespace ::com::sun::star::awt;
54 : using namespace ::com::sun::star::beans;
55 : using namespace ::com::sun::star::lang;
56 : using namespace ::com::sun::star::util;
57 :
58 : using ::com::sun::star::accessibility::XAccessibleContext;
59 : using ::com::sun::star::accessibility::XAccessible;
60 :
61 : struct LanguageDependentProp
62 : {
63 : const char* pPropName;
64 : sal_Int32 nPropNameLength;
65 : };
66 :
67 : static const LanguageDependentProp aLanguageDependentProp[] =
68 : {
69 : { "Text", 4 },
70 : { "Label", 5 },
71 : { "Title", 5 },
72 : { "HelpText", 8 },
73 : { "CurrencySymbol", 14 },
74 : { "StringItemList", 14 },
75 : { 0, 0 }
76 : };
77 :
78 9 : static Sequence< ::rtl::OUString> lcl_ImplGetPropertyNames( const Reference< XMultiPropertySet > & rxModel )
79 : {
80 9 : Sequence< ::rtl::OUString> aNames;
81 9 : Reference< XPropertySetInfo > xPSInf = rxModel->getPropertySetInfo();
82 : DBG_ASSERT( xPSInf.is(), "UpdateFromModel: No PropertySetInfo!" );
83 9 : if ( xPSInf.is() )
84 : {
85 9 : Sequence< Property> aProps = xPSInf->getProperties();
86 9 : sal_Int32 nLen = aProps.getLength();
87 9 : aNames = Sequence< ::rtl::OUString>( nLen );
88 9 : ::rtl::OUString* pNames = aNames.getArray();
89 9 : const Property* pProps = aProps.getConstArray();
90 90 : for ( sal_Int32 n = 0; n < nLen; ++n, ++pProps, ++pNames)
91 90 : *pNames = pProps->Name;
92 : }
93 9 : return aNames;
94 : }
95 :
96 : // ====================================================
97 : class VclListenerLock
98 : {
99 : private:
100 : VCLXWindow* m_pLockWindow;
101 :
102 : public:
103 0 : inline VclListenerLock( VCLXWindow* _pLockWindow )
104 0 : :m_pLockWindow( _pLockWindow )
105 : {
106 0 : if ( m_pLockWindow )
107 0 : m_pLockWindow->suspendVclEventListening( );
108 0 : }
109 0 : inline ~VclListenerLock( )
110 : {
111 0 : if ( m_pLockWindow )
112 0 : m_pLockWindow->resumeVclEventListening( );
113 0 : }
114 :
115 : private:
116 : VclListenerLock(); // never implemented
117 : VclListenerLock( const VclListenerLock& ); // never implemented
118 : VclListenerLock& operator=( const VclListenerLock& ); // never implemented
119 : };
120 :
121 : typedef ::std::map< ::rtl::OUString, sal_Int32 > MapString2Int;
122 2 : struct UnoControl_Data
123 : {
124 : MapString2Int aSuspendedPropertyNotifications;
125 : /// true if and only if our model has a property ResourceResolver
126 : bool bLocalizationSupport;
127 :
128 9 : UnoControl_Data()
129 : :aSuspendedPropertyNotifications()
130 9 : ,bLocalizationSupport( false )
131 : {
132 9 : }
133 : };
134 :
135 : // ----------------------------------------------------
136 : // class UnoControl
137 : // ----------------------------------------------------
138 : DBG_NAME( UnoControl )
139 0 : UnoControl::UnoControl()
140 : :maContext( ::comphelper::getProcessServiceFactory() )
141 : ,maDisposeListeners( *this )
142 : ,maWindowListeners( *this )
143 : ,maFocusListeners( *this )
144 : ,maKeyListeners( *this )
145 : ,maMouseListeners( *this )
146 : ,maMouseMotionListeners( *this )
147 : ,maPaintListeners( *this )
148 0 : ,maModeChangeListeners( GetMutex() )
149 0 : ,mpData( new UnoControl_Data )
150 : {
151 : DBG_CTOR( UnoControl, NULL );
152 : OSL_ENSURE( false, "UnoControl::UnoControl: not implemented. Well, not really." );
153 : // just implemented to let the various FooImplInheritanceHelper compile, you should use the
154 : // version taking a service factory
155 0 : }
156 :
157 9 : UnoControl::UnoControl( const Reference< XMultiServiceFactory >& i_factory )
158 : : maContext( i_factory )
159 : , maDisposeListeners( *this )
160 : , maWindowListeners( *this )
161 : , maFocusListeners( *this )
162 : , maKeyListeners( *this )
163 : , maMouseListeners( *this )
164 : , maMouseMotionListeners( *this )
165 : , maPaintListeners( *this )
166 9 : , maModeChangeListeners( GetMutex() )
167 18 : , mpData( new UnoControl_Data )
168 : {
169 : DBG_CTOR( UnoControl, NULL );
170 9 : mbDisposePeer = sal_True;
171 9 : mbRefeshingPeer = sal_False;
172 9 : mbCreatingPeer = sal_False;
173 9 : mbCreatingCompatiblePeer = sal_False;
174 9 : mbDesignMode = sal_False;
175 9 : }
176 :
177 4 : UnoControl::~UnoControl()
178 : {
179 2 : DELETEZ( mpData );
180 : DBG_DTOR( UnoControl, NULL );
181 2 : }
182 :
183 0 : ::rtl::OUString UnoControl::GetComponentServiceName()
184 : {
185 0 : return ::rtl::OUString();
186 : }
187 :
188 0 : Reference< XWindowPeer > UnoControl::ImplGetCompatiblePeer( sal_Bool bAcceptExistingPeer )
189 : {
190 : DBG_ASSERT( !mbCreatingCompatiblePeer, "ImplGetCompatiblePeer - rekursive?" );
191 :
192 0 : mbCreatingCompatiblePeer = sal_True;
193 :
194 0 : Reference< XWindowPeer > xCompatiblePeer;
195 :
196 0 : if ( bAcceptExistingPeer )
197 0 : xCompatiblePeer = getPeer();
198 :
199 0 : if ( !xCompatiblePeer.is() )
200 : {
201 : // Create the pair as invisible
202 0 : sal_Bool bVis = maComponentInfos.bVisible;
203 0 : if( bVis )
204 0 : maComponentInfos.bVisible = sal_False;
205 :
206 0 : Reference< XWindowPeer > xCurrentPeer = getPeer();
207 0 : setPeer( NULL );
208 :
209 : // queryInterface ourself, to allow aggregation
210 0 : Reference< XControl > xMe;
211 0 : OWeakAggObject::queryInterface( ::getCppuType( &xMe ) ) >>= xMe;
212 :
213 0 : Window* pParentWindow( NULL );
214 : {
215 0 : SolarMutexGuard aGuard;
216 0 : pParentWindow = dynamic_cast< Window* >( Application::GetDefaultDevice() );
217 0 : ENSURE_OR_THROW( pParentWindow != NULL, "could obtain a default parent window!" );
218 : }
219 : try
220 : {
221 0 : xMe->createPeer( NULL, pParentWindow->GetComponentInterface( sal_True ) );
222 : }
223 0 : catch( const Exception& )
224 : {
225 0 : mbCreatingCompatiblePeer = sal_False;
226 0 : throw;
227 : }
228 0 : xCompatiblePeer = getPeer();
229 0 : setPeer( xCurrentPeer );
230 :
231 0 : if ( xCompatiblePeer.is() && mxGraphics.is() )
232 : {
233 0 : Reference< XView > xPeerView( xCompatiblePeer, UNO_QUERY );
234 0 : if ( xPeerView.is() )
235 0 : xPeerView->setGraphics( mxGraphics );
236 : }
237 :
238 0 : if( bVis )
239 0 : maComponentInfos.bVisible = sal_True;
240 : }
241 :
242 0 : mbCreatingCompatiblePeer = sal_False;
243 :
244 0 : return xCompatiblePeer;
245 : }
246 :
247 0 : bool UnoControl::ImplCheckLocalize( ::rtl::OUString& _rPossiblyLocalizable )
248 : {
249 0 : if ( !mpData->bLocalizationSupport
250 0 : || ( _rPossiblyLocalizable.isEmpty() )
251 0 : || ( _rPossiblyLocalizable[0] != '&' )
252 : // TODO: make this reasonable. At the moment, everything which by accident starts with a & is considered
253 : // localizable, which is probably wrong.
254 : )
255 0 : return false;
256 :
257 : try
258 : {
259 0 : Reference< XPropertySet > xPropSet( mxModel, UNO_QUERY_THROW );
260 : Reference< resource::XStringResourceResolver > xStringResourceResolver(
261 0 : xPropSet->getPropertyValue( ::rtl::OUString( "ResourceResolver" ) ),
262 : UNO_QUERY
263 0 : );
264 0 : if ( xStringResourceResolver.is() )
265 : {
266 0 : ::rtl::OUString aLocalizationKey( _rPossiblyLocalizable.copy( 1 ) );
267 0 : _rPossiblyLocalizable = xStringResourceResolver->resolveString( aLocalizationKey );
268 0 : return true;
269 0 : }
270 : }
271 0 : catch( const Exception& )
272 : {
273 : DBG_UNHANDLED_EXCEPTION();
274 : }
275 0 : return false;
276 : }
277 :
278 0 : void UnoControl::ImplSetPeerProperty( const ::rtl::OUString& rPropName, const Any& rVal )
279 : {
280 : // since a change made in propertiesChange, we can't be sure that this is called with an valid getPeer(),
281 : // this assumption may be false in some (seldom) multi-threading scenarios (cause propertiesChange
282 : // releases our mutex before calling here in)
283 : // That's why this additional check
284 :
285 0 : if ( mxVclWindowPeer.is() )
286 : {
287 0 : Any aConvertedValue( rVal );
288 :
289 0 : if ( mpData->bLocalizationSupport )
290 : {
291 : // We now support a mapping for language dependent properties. This is the
292 : // central method to implement it.
293 0 : if (( rPropName.equalsAsciiL( "Text", 4 )) ||
294 0 : ( rPropName.equalsAsciiL( "Label", 5 )) ||
295 0 : ( rPropName.equalsAsciiL( "Title", 5 )) ||
296 0 : ( rPropName.equalsAsciiL( "HelpText", 8 )) ||
297 0 : ( rPropName.equalsAsciiL( "CurrencySymbol", 14 )) ||
298 0 : ( rPropName.equalsAsciiL( "StringItemList", 14 )) )
299 : {
300 0 : ::rtl::OUString aValue;
301 0 : uno::Sequence< rtl::OUString > aSeqValue;
302 0 : if ( aConvertedValue >>= aValue )
303 : {
304 0 : if ( ImplCheckLocalize( aValue ) )
305 0 : aConvertedValue <<= aValue;
306 : }
307 0 : else if ( aConvertedValue >>= aSeqValue )
308 : {
309 0 : for ( sal_Int32 i = 0; i < aSeqValue.getLength(); i++ )
310 0 : ImplCheckLocalize( aSeqValue[i] );
311 0 : aConvertedValue <<= aSeqValue;
312 0 : }
313 : }
314 : }
315 :
316 0 : mxVclWindowPeer->setProperty( rPropName, aConvertedValue );
317 : }
318 0 : }
319 :
320 0 : void UnoControl::PrepareWindowDescriptor( WindowDescriptor& )
321 : {
322 0 : }
323 :
324 0 : Reference< XWindow > UnoControl::getParentPeer() const
325 : {
326 0 : Reference< XWindow > xPeer;
327 0 : if( mxContext.is() )
328 : {
329 0 : Reference< XControl > xContComp( mxContext, UNO_QUERY );
330 0 : if ( xContComp.is() )
331 : {
332 0 : Reference< XWindowPeer > xP = xContComp->getPeer();
333 0 : if ( xP.is() )
334 0 : xP->queryInterface( ::getCppuType((const Reference< XWindow >*)0) ) >>= xPeer;
335 0 : }
336 : }
337 0 : return xPeer;
338 : }
339 :
340 0 : void UnoControl::updateFromModel()
341 : {
342 : // Read default properties and hand over to peer
343 0 : if( getPeer().is() )
344 : {
345 0 : Reference< XMultiPropertySet > xPropSet( mxModel, UNO_QUERY );
346 0 : if( xPropSet.is() )
347 : {
348 0 : Sequence< ::rtl::OUString> aNames = lcl_ImplGetPropertyNames( xPropSet );
349 0 : xPropSet->firePropertiesChangeEvent( aNames, this );
350 0 : }
351 : }
352 0 : }
353 :
354 :
355 : // XTypeProvider
356 0 : IMPL_IMPLEMENTATION_ID( UnoControl )
357 :
358 2 : void UnoControl::disposeAccessibleContext()
359 : {
360 2 : Reference< XComponent > xContextComp( maAccessibleContext.get(), UNO_QUERY );
361 2 : if ( xContextComp.is() )
362 : {
363 0 : maAccessibleContext = NULL;
364 : try
365 : {
366 0 : xContextComp->removeEventListener( this );
367 0 : xContextComp->dispose();
368 : }
369 0 : catch( const Exception& )
370 : {
371 : OSL_FAIL( "UnoControl::disposeAccessibleContext: could not dispose my AccessibleContext!" );
372 : }
373 2 : }
374 2 : }
375 :
376 2 : void UnoControl::dispose( ) throw(RuntimeException)
377 : {
378 2 : Reference< XWindowPeer > xPeer;
379 : {
380 2 : ::osl::MutexGuard aGuard( GetMutex() );
381 2 : if( mbDisposePeer )
382 : {
383 0 : xPeer = mxPeer;
384 : }
385 2 : setPeer( NULL );
386 : }
387 2 : if( xPeer.is() )
388 : {
389 0 : xPeer->dispose();
390 : }
391 :
392 : // dispose and release our AccessibleContext
393 2 : disposeAccessibleContext();
394 :
395 2 : EventObject aDisposeEvent;
396 2 : aDisposeEvent.Source = static_cast< XAggregation* >( this );
397 :
398 2 : maDisposeListeners.disposeAndClear( aDisposeEvent );
399 2 : maWindowListeners.disposeAndClear( aDisposeEvent );
400 2 : maFocusListeners.disposeAndClear( aDisposeEvent );
401 2 : maKeyListeners.disposeAndClear( aDisposeEvent );
402 2 : maMouseListeners.disposeAndClear( aDisposeEvent );
403 2 : maMouseMotionListeners.disposeAndClear( aDisposeEvent );
404 2 : maPaintListeners.disposeAndClear( aDisposeEvent );
405 2 : maModeChangeListeners.disposeAndClear( aDisposeEvent );
406 :
407 : // release Model again
408 2 : setModel( Reference< XControlModel > () );
409 2 : setContext( Reference< XInterface > () );
410 2 : }
411 :
412 0 : void UnoControl::addEventListener( const Reference< XEventListener >& rxListener ) throw(RuntimeException)
413 : {
414 0 : ::osl::MutexGuard aGuard( GetMutex() );
415 :
416 0 : maDisposeListeners.addInterface( rxListener );
417 0 : }
418 :
419 0 : void UnoControl::removeEventListener( const Reference< XEventListener >& rxListener ) throw(RuntimeException)
420 : {
421 0 : ::osl::MutexGuard aGuard( GetMutex() );
422 :
423 0 : maDisposeListeners.removeInterface( rxListener );
424 0 : }
425 :
426 0 : sal_Bool UnoControl::requiresNewPeer( const ::rtl::OUString& /* _rPropertyName */ ) const
427 : {
428 0 : return sal_False;
429 : }
430 :
431 : // XPropertiesChangeListener
432 0 : void UnoControl::propertiesChange( const Sequence< PropertyChangeEvent >& rEvents ) throw(RuntimeException)
433 : {
434 0 : Sequence< PropertyChangeEvent > aEvents( rEvents );
435 : {
436 0 : ::osl::MutexGuard aGuard( GetMutex() );
437 :
438 0 : if ( !mpData->aSuspendedPropertyNotifications.empty() )
439 : {
440 : // strip the property which we are currently updating (somewhere up the stack)
441 0 : PropertyChangeEvent* pEvents = aEvents.getArray();
442 0 : PropertyChangeEvent* pEventsEnd = pEvents + aEvents.getLength();
443 0 : for ( ; pEvents < pEventsEnd; )
444 0 : if ( mpData->aSuspendedPropertyNotifications.find( pEvents->PropertyName ) != mpData->aSuspendedPropertyNotifications.end() )
445 : {
446 0 : if ( pEvents != pEventsEnd )
447 0 : ::std::copy( pEvents + 1, pEventsEnd, pEvents );
448 0 : --pEventsEnd;
449 : }
450 : else
451 0 : ++pEvents;
452 0 : aEvents.realloc( pEventsEnd - aEvents.getConstArray() );
453 :
454 0 : if ( !aEvents.getLength() )
455 0 : return;
456 0 : }
457 : }
458 :
459 0 : ImplModelPropertiesChanged( aEvents );
460 : }
461 :
462 0 : void UnoControl::ImplLockPropertyChangeNotification( const ::rtl::OUString& rPropertyName, bool bLock )
463 : {
464 0 : MapString2Int::iterator pos = mpData->aSuspendedPropertyNotifications.find( rPropertyName );
465 0 : if ( bLock )
466 : {
467 0 : if ( pos == mpData->aSuspendedPropertyNotifications.end() )
468 0 : pos = mpData->aSuspendedPropertyNotifications.insert( MapString2Int::value_type( rPropertyName, 0 ) ).first;
469 0 : ++pos->second;
470 : }
471 : else
472 : {
473 : OSL_ENSURE( pos != mpData->aSuspendedPropertyNotifications.end(), "UnoControl::ImplLockPropertyChangeNotification: property not locked!" );
474 0 : if ( pos != mpData->aSuspendedPropertyNotifications.end() )
475 : {
476 : OSL_ENSURE( pos->second > 0, "UnoControl::ImplLockPropertyChangeNotification: invalid suspension counter!" );
477 0 : if ( 0 == --pos->second )
478 0 : mpData->aSuspendedPropertyNotifications.erase( pos );
479 : }
480 : }
481 0 : }
482 :
483 0 : void UnoControl::ImplLockPropertyChangeNotifications( const Sequence< ::rtl::OUString >& rPropertyNames, bool bLock )
484 : {
485 0 : for ( const ::rtl::OUString* pPropertyName = rPropertyNames.getConstArray();
486 0 : pPropertyName != rPropertyNames.getConstArray() + rPropertyNames.getLength();
487 : ++pPropertyName
488 : )
489 0 : ImplLockPropertyChangeNotification( *pPropertyName, bLock );
490 0 : }
491 :
492 0 : void UnoControl::ImplModelPropertiesChanged( const Sequence< PropertyChangeEvent >& rEvents )
493 : {
494 0 : ::osl::ClearableGuard< ::osl::Mutex > aGuard( GetMutex() );
495 :
496 0 : if( getPeer().is() )
497 : {
498 : DECLARE_STL_VECTOR( PropertyValue, PropertyValueVector);
499 0 : PropertyValueVector aPeerPropertiesToSet;
500 0 : sal_Int32 nIndependentPos = 0;
501 0 : bool bResourceResolverSet( false );
502 : // position where to insert the independent properties into aPeerPropertiesToSet,
503 : // dependent ones are inserted at the end of the vector
504 :
505 0 : sal_Bool bNeedNewPeer = sal_False;
506 : // some properties require a re-creation of the peer, 'cause they can't be changed on the fly
507 :
508 0 : Reference< XControlModel > xOwnModel( getModel(), UNO_QUERY );
509 : // our own model for comparison
510 0 : Reference< XPropertySet > xPS( xOwnModel, UNO_QUERY );
511 0 : Reference< XPropertySetInfo > xPSI( xPS->getPropertySetInfo(), UNO_QUERY );
512 : OSL_ENSURE( xPSI.is(), "UnoControl::ImplModelPropertiesChanged: should have property set meta data!" );
513 :
514 0 : const PropertyChangeEvent* pEvents = rEvents.getConstArray();
515 :
516 0 : sal_Int32 nLen = rEvents.getLength();
517 0 : aPeerPropertiesToSet.reserve(nLen);
518 :
519 0 : for( sal_Int32 i = 0; i < nLen; ++i, ++pEvents )
520 : {
521 0 : Reference< XControlModel > xModel( pEvents->Source, UNO_QUERY );
522 0 : sal_Bool bOwnModel = xModel.get() == xOwnModel.get();
523 0 : if ( !bOwnModel )
524 0 : continue;
525 :
526 : // Detect changes on our resource resolver which invalidates
527 : // automatically some language dependent properties.
528 0 : if ( pEvents->PropertyName.equalsAsciiL( "ResourceResolver", 16 ))
529 : {
530 0 : Reference< resource::XStringResourceResolver > xStrResolver;
531 0 : if ( pEvents->NewValue >>= xStrResolver )
532 0 : bResourceResolverSet = xStrResolver.is();
533 : }
534 :
535 0 : sal_uInt16 nPType = GetPropertyId( pEvents->PropertyName );
536 0 : if ( mbDesignMode && mbDisposePeer && !mbRefeshingPeer && !mbCreatingPeer )
537 : {
538 : // if we're in design mode, then some properties can change which
539 : // require creating a *new* peer (since these properties cannot
540 : // be switched at existing peers)
541 0 : if ( nPType )
542 : bNeedNewPeer = ( nPType == BASEPROPERTY_BORDER )
543 : || ( nPType == BASEPROPERTY_MULTILINE )
544 : || ( nPType == BASEPROPERTY_DROPDOWN )
545 : || ( nPType == BASEPROPERTY_HSCROLL )
546 : || ( nPType == BASEPROPERTY_VSCROLL )
547 : || ( nPType == BASEPROPERTY_AUTOHSCROLL )
548 : || ( nPType == BASEPROPERTY_AUTOVSCROLL )
549 : || ( nPType == BASEPROPERTY_ORIENTATION )
550 : || ( nPType == BASEPROPERTY_SPIN )
551 : || ( nPType == BASEPROPERTY_ALIGN )
552 0 : || ( nPType == BASEPROPERTY_PAINTTRANSPARENT );
553 : else
554 0 : bNeedNewPeer = requiresNewPeer( pEvents->PropertyName );
555 :
556 0 : if ( bNeedNewPeer )
557 : break;
558 : }
559 :
560 0 : if ( nPType && ( nLen > 1 ) && DoesDependOnOthers( nPType ) )
561 : {
562 : // Add properties with dependencies on other properties last
563 : // since they're dependent on properties added later (such as
564 : // VALUE dependency on VALUEMIN/MAX)
565 0 : aPeerPropertiesToSet.push_back(PropertyValue(pEvents->PropertyName, 0, pEvents->NewValue, PropertyState_DIRECT_VALUE));
566 : }
567 : else
568 : {
569 0 : if ( bResourceResolverSet )
570 : {
571 : // The resource resolver property change should be one of the first ones.
572 : // All language dependent properties are dependent on this property.
573 : // As BASEPROPERTY_NATIVE_WIDGET_LOOK is not dependent on resource
574 : // resolver. We don't need to handle a special order for these two props.
575 : aPeerPropertiesToSet.insert(
576 : aPeerPropertiesToSet.begin(),
577 0 : PropertyValue( pEvents->PropertyName, 0, pEvents->NewValue, PropertyState_DIRECT_VALUE ) );
578 0 : ++nIndependentPos;
579 : }
580 0 : else if ( nPType == BASEPROPERTY_NATIVE_WIDGET_LOOK )
581 : {
582 : // since *a lot* of other properties might be overruled by this one, we need
583 : // a special handling:
584 : // NativeWidgetLook needs to be set first: If it is set to ON, all other
585 : // properties describing the look (e.g. BackgroundColor) are ignored, anyway.
586 : // If it is switched OFF, then we need to do it first because else it will
587 : // overrule other look-related properties, and re-initialize them from system
588 : // defaults.
589 : aPeerPropertiesToSet.insert(
590 : aPeerPropertiesToSet.begin(),
591 0 : PropertyValue( pEvents->PropertyName, 0, pEvents->NewValue, PropertyState_DIRECT_VALUE ) );
592 0 : ++nIndependentPos;
593 : }
594 : else
595 : {
596 : aPeerPropertiesToSet.insert(aPeerPropertiesToSet.begin() + nIndependentPos,
597 0 : PropertyValue(pEvents->PropertyName, 0, pEvents->NewValue, PropertyState_DIRECT_VALUE));
598 0 : ++nIndependentPos;
599 : }
600 : }
601 0 : }
602 :
603 0 : Reference< XWindow > xParent = getParentPeer();
604 0 : Reference< XControl > xThis( (XAggregation*)(::cppu::OWeakAggObject*)this, UNO_QUERY );
605 : // call createPeer via a interface got from queryInterface, so the aggregating class can intercept it
606 :
607 : DBG_ASSERT( !bNeedNewPeer || xParent.is(), "Need new peer, but don't have a parent!" );
608 :
609 : // Check if we have to update language dependent properties
610 0 : if ( !bNeedNewPeer && bResourceResolverSet )
611 : {
612 : // Add language dependent properties into the peer property set.
613 : // Our resource resolver has been changed and we must be sure
614 : // that language dependent props use the new resolver.
615 0 : const LanguageDependentProp* pLangDepProp = aLanguageDependentProp;
616 0 : while ( pLangDepProp->pPropName != 0 )
617 : {
618 0 : bool bMustBeInserted( true );
619 0 : for ( sal_uInt32 i = 0; i < aPeerPropertiesToSet.size(); i++ )
620 : {
621 0 : if ( aPeerPropertiesToSet[i].Name.equalsAsciiL(
622 0 : pLangDepProp->pPropName, pLangDepProp->nPropNameLength ))
623 : {
624 0 : bMustBeInserted = false;
625 0 : break;
626 : }
627 : }
628 :
629 0 : if ( bMustBeInserted )
630 : {
631 : // Add language dependent props at the end
632 0 : ::rtl::OUString aPropName( ::rtl::OUString::createFromAscii( pLangDepProp->pPropName ));
633 0 : if ( xPSI.is() && xPSI->hasPropertyByName( aPropName ) )
634 : {
635 : aPeerPropertiesToSet.push_back(
636 0 : PropertyValue( aPropName, 0, xPS->getPropertyValue( aPropName ), PropertyState_DIRECT_VALUE ) );
637 0 : }
638 : }
639 :
640 0 : ++pLangDepProp;
641 : }
642 : }
643 0 : aGuard.clear();
644 :
645 : // clear the guard before creating a new peer - as usual, our peer implementations use the SolarMutex
646 :
647 0 : if (bNeedNewPeer && xParent.is())
648 : {
649 0 : SolarMutexGuard aVclGuard;
650 : // and now this is the final withdrawal:
651 : // I have no other idea than locking the SolarMutex here ....
652 : // I really hate the fact that VCL is not theadsafe ....
653 :
654 : // Doesn't work for Container!
655 0 : getPeer()->dispose();
656 0 : mxPeer.clear();
657 0 : mxVclWindowPeer = NULL;
658 0 : mbRefeshingPeer = sal_True;
659 0 : Reference< XWindowPeer > xP( xParent, UNO_QUERY );
660 0 : xThis->createPeer( Reference< XToolkit > (), xP );
661 0 : mbRefeshingPeer = sal_False;
662 0 : aPeerPropertiesToSet.clear();
663 : }
664 :
665 : // lock the multiplexing of VCL events to our UNO listeners
666 : // this is for compatibility reasons: in OOo 1.0.x, changes which were done at the
667 : // model did not cause the listeners of the controls/peers to be called
668 : // Since the implementations for the listeners changed a lot towards 1.1, this
669 : // would not be the case anymore, if we would not do this listener-lock below
670 : // #i14703#
671 0 : Window* pVclPeer = VCLUnoHelper::GetWindow( getPeer() );
672 0 : VCLXWindow* pPeer = pVclPeer ? pVclPeer->GetWindowPeer() : NULL;
673 0 : VclListenerLock aNoVclEventMultiplexing( pPeer );
674 :
675 : // setting peer properties may result in an attemp to acquire the solar mutex, 'cause the peers
676 : // usually don't have an own mutex but use the SolarMutex instead.
677 : // To prevent deadlocks resulting from this, we do this without our own mutex locked
678 0 : PropertyValueVectorIterator aEnd = aPeerPropertiesToSet.end();
679 0 : for ( PropertyValueVectorIterator aLoop = aPeerPropertiesToSet.begin();
680 : aLoop != aEnd;
681 : ++aLoop
682 : )
683 : {
684 0 : ImplSetPeerProperty( aLoop->Name, aLoop->Value );
685 0 : }
686 0 : }
687 0 : }
688 :
689 0 : void UnoControl::disposing( const EventObject& rEvt ) throw(RuntimeException)
690 : {
691 0 : ::osl::ClearableMutexGuard aGuard( GetMutex() );
692 : // do not compare differing types in case of multible inheritance
693 :
694 0 : if ( maAccessibleContext.get() == rEvt.Source )
695 : {
696 : // just in case the context is disposed, but not released - ensure that we do not re-use it in the future
697 0 : maAccessibleContext = NULL;
698 : }
699 0 : else if( mxModel.get() == Reference< XControlModel >(rEvt.Source,UNO_QUERY).get() )
700 : {
701 : // #62337# if the model dies, it does not make sense for us to live ...
702 0 : Reference< XControl > xThis = this;
703 :
704 0 : aGuard.clear();
705 0 : xThis->dispose();
706 :
707 : DBG_ASSERT( !mxModel.is(), "UnoControl::disposing: invalid dispose behaviour!" );
708 0 : mxModel.clear();
709 0 : }
710 0 : }
711 :
712 :
713 0 : void SAL_CALL UnoControl::setOutputSize( const awt::Size& aSize ) throw (RuntimeException)
714 : {
715 0 : Reference< XWindow2 > xPeerWindow;
716 : {
717 0 : ::osl::MutexGuard aGuard( GetMutex() );
718 0 : xPeerWindow = xPeerWindow.query( getPeer() );
719 : }
720 :
721 0 : if ( xPeerWindow.is() )
722 0 : xPeerWindow->setOutputSize( aSize );
723 0 : }
724 :
725 : namespace
726 : {
727 : template < typename RETVALTYPE >
728 0 : RETVALTYPE lcl_askPeer( const uno::Reference< awt::XWindowPeer >& _rxPeer, RETVALTYPE (SAL_CALL XWindow2::*_pMethod)(), RETVALTYPE _aDefault )
729 : {
730 0 : RETVALTYPE aReturn( _aDefault );
731 :
732 0 : Reference< XWindow2 > xPeerWindow( _rxPeer, UNO_QUERY );
733 0 : if ( xPeerWindow.is() )
734 0 : aReturn = (xPeerWindow.get()->*_pMethod)();
735 :
736 0 : return aReturn;
737 : }
738 : }
739 :
740 0 : awt::Size SAL_CALL UnoControl::getOutputSize( ) throw (RuntimeException)
741 : {
742 0 : return lcl_askPeer( getPeer(), &XWindow2::getOutputSize, awt::Size() );
743 : }
744 :
745 0 : ::sal_Bool SAL_CALL UnoControl::isVisible( ) throw (RuntimeException)
746 : {
747 0 : return lcl_askPeer( getPeer(), &XWindow2::isVisible, maComponentInfos.bVisible );
748 : }
749 :
750 0 : ::sal_Bool SAL_CALL UnoControl::isActive( ) throw (RuntimeException)
751 : {
752 0 : return lcl_askPeer( getPeer(), &XWindow2::isActive, sal_False );
753 : }
754 :
755 0 : ::sal_Bool SAL_CALL UnoControl::isEnabled( ) throw (RuntimeException)
756 : {
757 0 : return lcl_askPeer( getPeer(), &XWindow2::isEnabled, maComponentInfos.bEnable );
758 : }
759 :
760 0 : ::sal_Bool SAL_CALL UnoControl::hasFocus( ) throw (RuntimeException)
761 : {
762 0 : return lcl_askPeer( getPeer(), &XWindow2::hasFocus, sal_False );
763 : }
764 :
765 : // XWindow
766 0 : void UnoControl::setPosSize( sal_Int32 X, sal_Int32 Y, sal_Int32 Width, sal_Int32 Height, sal_Int16 Flags ) throw(RuntimeException)
767 : {
768 0 : Reference< XWindow > xWindow;
769 : {
770 0 : ::osl::MutexGuard aGuard( GetMutex() );
771 :
772 0 : if ( Flags & awt::PosSize::X )
773 0 : maComponentInfos.nX = X;
774 0 : if ( Flags & awt::PosSize::Y )
775 0 : maComponentInfos.nY = Y;
776 0 : if ( Flags & awt::PosSize::WIDTH )
777 0 : maComponentInfos.nWidth = Width;
778 0 : if ( Flags & awt::PosSize::HEIGHT )
779 0 : maComponentInfos.nHeight = Height;
780 0 : maComponentInfos.nFlags |= Flags;
781 :
782 0 : xWindow = xWindow.query( getPeer() );
783 : }
784 :
785 0 : if( xWindow.is() )
786 0 : xWindow->setPosSize( X, Y, Width, Height, Flags );
787 0 : }
788 :
789 0 : awt::Rectangle UnoControl::getPosSize( ) throw(RuntimeException)
790 : {
791 0 : awt::Rectangle aRect( maComponentInfos.nX, maComponentInfos.nY, maComponentInfos.nWidth, maComponentInfos.nHeight);
792 0 : Reference< XWindow > xWindow;
793 :
794 : {
795 0 : ::osl::MutexGuard aGuard( GetMutex() );
796 0 : xWindow = xWindow.query( getPeer() );
797 : }
798 :
799 0 : if( xWindow.is() )
800 0 : aRect = xWindow->getPosSize();
801 0 : return aRect;
802 : }
803 :
804 0 : void UnoControl::setVisible( sal_Bool bVisible ) throw(RuntimeException)
805 : {
806 0 : Reference< XWindow > xWindow;
807 : {
808 0 : ::osl::MutexGuard aGuard( GetMutex() );
809 :
810 : // Visible status is handled by View
811 0 : maComponentInfos.bVisible = bVisible;
812 0 : xWindow = xWindow.query( getPeer() );
813 : }
814 0 : if ( xWindow.is() )
815 0 : xWindow->setVisible( bVisible );
816 0 : }
817 :
818 0 : void UnoControl::setEnable( sal_Bool bEnable ) throw(RuntimeException)
819 : {
820 0 : Reference< XWindow > xWindow;
821 : {
822 0 : ::osl::MutexGuard aGuard( GetMutex() );
823 :
824 : // Enable status is handled by View
825 0 : maComponentInfos.bEnable = bEnable;
826 0 : xWindow = xWindow.query( getPeer() );
827 : }
828 0 : if ( xWindow.is() )
829 0 : xWindow->setEnable( bEnable );
830 0 : }
831 :
832 0 : void UnoControl::setFocus( ) throw(RuntimeException)
833 : {
834 0 : Reference< XWindow > xWindow;
835 : {
836 0 : ::osl::MutexGuard aGuard( GetMutex() );
837 0 : xWindow = xWindow.query( getPeer() );
838 : }
839 0 : if ( xWindow.is() )
840 0 : xWindow->setFocus();
841 0 : }
842 :
843 0 : void UnoControl::addWindowListener( const Reference< XWindowListener >& rxListener ) throw(RuntimeException)
844 : {
845 0 : Reference< XWindow > xPeerWindow;
846 : {
847 0 : ::osl::MutexGuard aGuard( GetMutex() );
848 0 : maWindowListeners.addInterface( rxListener );
849 0 : if ( maWindowListeners.getLength() == 1 )
850 0 : xPeerWindow = xPeerWindow.query( getPeer() );
851 : }
852 0 : if ( xPeerWindow.is() )
853 0 : xPeerWindow->addWindowListener( &maWindowListeners );
854 0 : }
855 :
856 0 : void UnoControl::removeWindowListener( const Reference< XWindowListener >& rxListener ) throw(RuntimeException)
857 : {
858 0 : Reference< XWindow > xPeerWindow;
859 : {
860 0 : ::osl::MutexGuard aGuard( GetMutex() );
861 0 : if ( maWindowListeners.getLength() == 1 )
862 0 : xPeerWindow = xPeerWindow.query( getPeer() );
863 0 : maWindowListeners.removeInterface( rxListener );
864 : }
865 0 : if ( xPeerWindow.is() )
866 0 : xPeerWindow->removeWindowListener( &maWindowListeners );
867 0 : }
868 :
869 0 : void UnoControl::addFocusListener( const Reference< XFocusListener >& rxListener ) throw(RuntimeException)
870 : {
871 0 : Reference< XWindow > xPeerWindow;
872 : {
873 0 : ::osl::MutexGuard aGuard( GetMutex() );
874 0 : maFocusListeners.addInterface( rxListener );
875 0 : if ( maFocusListeners.getLength() == 1 )
876 0 : xPeerWindow = xPeerWindow.query( getPeer() );
877 : }
878 0 : if ( xPeerWindow.is() )
879 0 : xPeerWindow->addFocusListener( &maFocusListeners );
880 0 : }
881 :
882 0 : void UnoControl::removeFocusListener( const Reference< XFocusListener >& rxListener ) throw(RuntimeException)
883 : {
884 0 : Reference< XWindow > xPeerWindow;
885 : {
886 0 : ::osl::MutexGuard aGuard( GetMutex() );
887 0 : if ( maFocusListeners.getLength() == 1 )
888 0 : xPeerWindow = xPeerWindow.query( getPeer() );
889 0 : maFocusListeners.removeInterface( rxListener );
890 : }
891 0 : if ( xPeerWindow.is() )
892 0 : xPeerWindow->removeFocusListener( &maFocusListeners );
893 0 : }
894 :
895 0 : void UnoControl::addKeyListener( const Reference< XKeyListener >& rxListener ) throw(RuntimeException)
896 : {
897 0 : Reference< XWindow > xPeerWindow;
898 : {
899 0 : ::osl::MutexGuard aGuard( GetMutex() );
900 0 : maKeyListeners.addInterface( rxListener );
901 0 : if ( maKeyListeners.getLength() == 1 )
902 0 : xPeerWindow = xPeerWindow.query( getPeer() );
903 : }
904 0 : if ( xPeerWindow.is() )
905 0 : xPeerWindow->addKeyListener( &maKeyListeners);
906 0 : }
907 :
908 0 : void UnoControl::removeKeyListener( const Reference< XKeyListener >& rxListener ) throw(RuntimeException)
909 : {
910 0 : Reference< XWindow > xPeerWindow;
911 : {
912 0 : ::osl::MutexGuard aGuard( GetMutex() );
913 0 : if ( maKeyListeners.getLength() == 1 )
914 0 : xPeerWindow = xPeerWindow.query( getPeer() );
915 0 : maKeyListeners.removeInterface( rxListener );
916 : }
917 0 : if ( xPeerWindow.is() )
918 0 : xPeerWindow->removeKeyListener( &maKeyListeners);
919 0 : }
920 :
921 0 : void UnoControl::addMouseListener( const Reference< XMouseListener >& rxListener ) throw(RuntimeException)
922 : {
923 0 : Reference< XWindow > xPeerWindow;
924 : {
925 0 : ::osl::MutexGuard aGuard( GetMutex() );
926 0 : maMouseListeners.addInterface( rxListener );
927 0 : if ( maMouseListeners.getLength() == 1 )
928 0 : xPeerWindow = xPeerWindow.query( getPeer() );
929 : }
930 0 : if ( xPeerWindow.is() )
931 0 : xPeerWindow->addMouseListener( &maMouseListeners);
932 0 : }
933 :
934 0 : void UnoControl::removeMouseListener( const Reference< XMouseListener >& rxListener ) throw(RuntimeException)
935 : {
936 0 : Reference< XWindow > xPeerWindow;
937 : {
938 0 : ::osl::MutexGuard aGuard( GetMutex() );
939 0 : if ( maMouseListeners.getLength() == 1 )
940 0 : xPeerWindow = xPeerWindow.query( getPeer() );
941 0 : maMouseListeners.removeInterface( rxListener );
942 : }
943 0 : if ( xPeerWindow.is() )
944 0 : xPeerWindow->removeMouseListener( &maMouseListeners );
945 0 : }
946 :
947 0 : void UnoControl::addMouseMotionListener( const Reference< XMouseMotionListener >& rxListener ) throw(RuntimeException)
948 : {
949 0 : Reference< XWindow > xPeerWindow;
950 : {
951 0 : ::osl::MutexGuard aGuard( GetMutex() );
952 0 : maMouseMotionListeners.addInterface( rxListener );
953 0 : if ( maMouseMotionListeners.getLength() == 1 )
954 0 : xPeerWindow = xPeerWindow.query( getPeer() );
955 : }
956 0 : if ( xPeerWindow.is() )
957 0 : xPeerWindow->addMouseMotionListener( &maMouseMotionListeners);
958 0 : }
959 :
960 0 : void UnoControl::removeMouseMotionListener( const Reference< XMouseMotionListener >& rxListener ) throw(RuntimeException)
961 : {
962 0 : Reference< XWindow > xPeerWindow;
963 : {
964 0 : ::osl::MutexGuard aGuard( GetMutex() );
965 0 : if ( maMouseMotionListeners.getLength() == 1 )
966 0 : xPeerWindow = xPeerWindow.query( getPeer() );
967 0 : maMouseMotionListeners.removeInterface( rxListener );
968 : }
969 0 : if ( xPeerWindow.is() )
970 0 : xPeerWindow->removeMouseMotionListener( &maMouseMotionListeners );
971 0 : }
972 :
973 0 : void UnoControl::addPaintListener( const Reference< XPaintListener >& rxListener ) throw(RuntimeException)
974 : {
975 0 : Reference< XWindow > xPeerWindow;
976 : {
977 0 : ::osl::MutexGuard aGuard( GetMutex() );
978 0 : maPaintListeners.addInterface( rxListener );
979 0 : if ( maPaintListeners.getLength() == 1 )
980 0 : xPeerWindow = xPeerWindow.query( getPeer() );
981 : }
982 0 : if ( xPeerWindow.is() )
983 0 : xPeerWindow->addPaintListener( &maPaintListeners);
984 0 : }
985 :
986 0 : void UnoControl::removePaintListener( const Reference< XPaintListener >& rxListener ) throw(RuntimeException)
987 : {
988 0 : Reference< XWindow > xPeerWindow;
989 : {
990 0 : ::osl::MutexGuard aGuard( GetMutex() );
991 0 : if ( maPaintListeners.getLength() == 1 )
992 0 : xPeerWindow = xPeerWindow.query( getPeer() );
993 0 : maPaintListeners.removeInterface( rxListener );
994 : }
995 0 : if ( xPeerWindow.is() )
996 0 : xPeerWindow->removePaintListener( &maPaintListeners );
997 0 : }
998 :
999 : // XView
1000 0 : sal_Bool UnoControl::setGraphics( const Reference< XGraphics >& rDevice ) throw(RuntimeException)
1001 : {
1002 0 : Reference< XView > xView;
1003 : {
1004 0 : ::osl::MutexGuard aGuard( GetMutex() );
1005 :
1006 0 : mxGraphics = rDevice;
1007 0 : xView = xView.query( getPeer() );
1008 : }
1009 0 : return xView.is() ? xView->setGraphics( rDevice ) : sal_True;
1010 : }
1011 :
1012 0 : Reference< XGraphics > UnoControl::getGraphics( ) throw(RuntimeException)
1013 : {
1014 0 : return mxGraphics;
1015 : }
1016 :
1017 0 : awt::Size UnoControl::getSize( ) throw(RuntimeException)
1018 : {
1019 0 : ::osl::MutexGuard aGuard( GetMutex() );
1020 0 : return awt::Size( maComponentInfos.nWidth, maComponentInfos.nHeight );
1021 : }
1022 :
1023 0 : void UnoControl::draw( sal_Int32 x, sal_Int32 y ) throw(RuntimeException)
1024 : {
1025 0 : Reference< XWindowPeer > xDrawPeer;
1026 0 : Reference< XView > xDrawPeerView;
1027 :
1028 0 : bool bDisposeDrawPeer( false );
1029 : {
1030 0 : ::osl::MutexGuard aGuard( GetMutex() );
1031 :
1032 0 : xDrawPeer = ImplGetCompatiblePeer( sal_True );
1033 0 : bDisposeDrawPeer = xDrawPeer.is() && ( xDrawPeer != getPeer() );
1034 :
1035 0 : xDrawPeerView.set( xDrawPeer, UNO_QUERY );
1036 0 : DBG_ASSERT( xDrawPeerView.is(), "UnoControl::draw: no peer!" );
1037 : }
1038 :
1039 0 : if ( xDrawPeerView.is() )
1040 : {
1041 0 : Reference< XVclWindowPeer > xWindowPeer;
1042 0 : xWindowPeer.set( xDrawPeer, UNO_QUERY );
1043 0 : if ( xWindowPeer.is() )
1044 0 : xWindowPeer->setDesignMode( mbDesignMode );
1045 0 : xDrawPeerView->draw( x, y );
1046 : }
1047 :
1048 0 : if ( bDisposeDrawPeer )
1049 0 : xDrawPeer->dispose();
1050 0 : }
1051 :
1052 0 : void UnoControl::setZoom( float fZoomX, float fZoomY ) throw(RuntimeException)
1053 : {
1054 0 : Reference< XView > xView;
1055 : {
1056 0 : ::osl::MutexGuard aGuard( GetMutex() );
1057 :
1058 0 : maComponentInfos.nZoomX = fZoomX;
1059 0 : maComponentInfos.nZoomY = fZoomY;
1060 :
1061 0 : xView = xView.query( getPeer() );
1062 : }
1063 0 : if ( xView.is() )
1064 0 : xView->setZoom( fZoomX, fZoomY );
1065 0 : }
1066 :
1067 : // XControl
1068 2 : void UnoControl::setContext( const Reference< XInterface >& rxContext ) throw(RuntimeException)
1069 : {
1070 2 : ::osl::MutexGuard aGuard( GetMutex() );
1071 :
1072 2 : mxContext = rxContext;
1073 2 : }
1074 :
1075 9 : Reference< XInterface > UnoControl::getContext( ) throw(RuntimeException)
1076 : {
1077 9 : ::osl::MutexGuard aGuard( GetMutex() );
1078 :
1079 9 : return mxContext;
1080 : }
1081 :
1082 0 : void UnoControl::peerCreated()
1083 : {
1084 0 : Reference< XWindow > xWindow( getPeer(), UNO_QUERY );
1085 0 : if ( !xWindow.is() )
1086 0 : return;
1087 :
1088 0 : if ( maWindowListeners.getLength() )
1089 0 : xWindow->addWindowListener( &maWindowListeners );
1090 :
1091 0 : if ( maFocusListeners.getLength() )
1092 0 : xWindow->addFocusListener( &maFocusListeners );
1093 :
1094 0 : if ( maKeyListeners.getLength() )
1095 0 : xWindow->addKeyListener( &maKeyListeners );
1096 :
1097 0 : if ( maMouseListeners.getLength() )
1098 0 : xWindow->addMouseListener( &maMouseListeners );
1099 :
1100 0 : if ( maMouseMotionListeners.getLength() )
1101 0 : xWindow->addMouseMotionListener( &maMouseMotionListeners );
1102 :
1103 0 : if ( maPaintListeners.getLength() )
1104 0 : xWindow->addPaintListener( &maPaintListeners );
1105 : }
1106 :
1107 0 : void UnoControl::createPeer( const Reference< XToolkit >& rxToolkit, const Reference< XWindowPeer >& rParentPeer ) throw(RuntimeException)
1108 : {
1109 0 : ::osl::ClearableMutexGuard aGuard( GetMutex() );
1110 0 : if ( !mxModel.is() )
1111 : {
1112 0 : RuntimeException aException;
1113 0 : aException.Message = ::rtl::OUString("createPeer: no model!");
1114 0 : aException.Context = (XAggregation*)(::cppu::OWeakAggObject*)this;
1115 0 : throw( aException );
1116 : }
1117 :
1118 0 : if( !getPeer().is() )
1119 : {
1120 0 : mbCreatingPeer = sal_True;
1121 :
1122 : WindowClass eType;
1123 0 : Reference< XToolkit > xToolkit = rxToolkit;
1124 0 : if( rParentPeer.is() && mxContext.is() )
1125 : {
1126 : // kein TopWindow
1127 0 : if ( !xToolkit.is() )
1128 0 : xToolkit = rParentPeer->getToolkit();
1129 0 : Any aAny = OWeakAggObject::queryInterface( ::getCppuType((const Reference< XControlContainer>*)0) );
1130 0 : Reference< XControlContainer > xC;
1131 0 : aAny >>= xC;
1132 0 : if( xC.is() )
1133 : // It's a container
1134 0 : eType = WindowClass_CONTAINER;
1135 : else
1136 0 : eType = WindowClass_SIMPLE;
1137 : }
1138 : else
1139 : { // This is only correct for Top Window
1140 0 : if( rParentPeer.is() )
1141 : {
1142 0 : if ( !xToolkit.is() )
1143 0 : xToolkit = rParentPeer->getToolkit();
1144 0 : eType = WindowClass_CONTAINER;
1145 : }
1146 : else
1147 : {
1148 0 : if ( !xToolkit.is() )
1149 0 : xToolkit = VCLUnoHelper::CreateToolkit();
1150 0 : eType = WindowClass_TOP;
1151 : }
1152 : }
1153 0 : WindowDescriptor aDescr;
1154 0 : aDescr.Type = eType;
1155 0 : aDescr.WindowServiceName = GetComponentServiceName();
1156 0 : aDescr.Parent = rParentPeer;
1157 0 : aDescr.Bounds = getPosSize();
1158 0 : aDescr.WindowAttributes = 0;
1159 :
1160 : // Border
1161 0 : Reference< XPropertySet > xPSet( mxModel, UNO_QUERY );
1162 0 : Reference< XPropertySetInfo > xInfo = xPSet->getPropertySetInfo();
1163 :
1164 0 : Any aVal;
1165 0 : ::rtl::OUString aPropName = GetPropertyName( BASEPROPERTY_BORDER );
1166 0 : if ( xInfo->hasPropertyByName( aPropName ) )
1167 : {
1168 0 : aVal = xPSet->getPropertyValue( aPropName );
1169 0 : sal_Int16 n = sal_Int16();
1170 0 : if ( aVal >>= n )
1171 : {
1172 0 : if ( n )
1173 0 : aDescr.WindowAttributes |= WindowAttribute::BORDER;
1174 : else
1175 0 : aDescr.WindowAttributes |= VclWindowPeerAttribute::NOBORDER;
1176 : }
1177 : }
1178 :
1179 : // DESKTOP_AS_PARENT
1180 0 : if ( aDescr.Type == WindowClass_TOP )
1181 : {
1182 0 : aPropName = GetPropertyName( BASEPROPERTY_DESKTOP_AS_PARENT );
1183 0 : if ( xInfo->hasPropertyByName( aPropName ) )
1184 : {
1185 0 : aVal = xPSet->getPropertyValue( aPropName );
1186 0 : sal_Bool b = sal_Bool();
1187 0 : if ( ( aVal >>= b ) && b)
1188 0 : aDescr.ParentIndex = -1;
1189 : }
1190 : }
1191 : // Moveable
1192 0 : aPropName = GetPropertyName( BASEPROPERTY_MOVEABLE );
1193 0 : if ( xInfo->hasPropertyByName( aPropName ) )
1194 : {
1195 0 : aVal = xPSet->getPropertyValue( aPropName );
1196 0 : sal_Bool b = sal_Bool();
1197 0 : if ( ( aVal >>= b ) && b)
1198 0 : aDescr.WindowAttributes |= WindowAttribute::MOVEABLE;
1199 : }
1200 :
1201 : // Closeable
1202 0 : aPropName = GetPropertyName( BASEPROPERTY_CLOSEABLE );
1203 0 : if ( xInfo->hasPropertyByName( aPropName ) )
1204 : {
1205 0 : aVal = xPSet->getPropertyValue( aPropName );
1206 0 : sal_Bool b = sal_Bool();
1207 0 : if ( ( aVal >>= b ) && b)
1208 0 : aDescr.WindowAttributes |= WindowAttribute::CLOSEABLE;
1209 : }
1210 :
1211 : // Dropdown
1212 0 : aPropName = GetPropertyName( BASEPROPERTY_DROPDOWN );
1213 0 : if ( xInfo->hasPropertyByName( aPropName ) )
1214 : {
1215 0 : aVal = xPSet->getPropertyValue( aPropName );
1216 0 : sal_Bool b = sal_Bool();
1217 0 : if ( ( aVal >>= b ) && b)
1218 0 : aDescr.WindowAttributes |= VclWindowPeerAttribute::DROPDOWN;
1219 : }
1220 :
1221 : // Spin
1222 0 : aPropName = GetPropertyName( BASEPROPERTY_SPIN );
1223 0 : if ( xInfo->hasPropertyByName( aPropName ) )
1224 : {
1225 0 : aVal = xPSet->getPropertyValue( aPropName );
1226 0 : sal_Bool b = sal_Bool();
1227 0 : if ( ( aVal >>= b ) && b)
1228 0 : aDescr.WindowAttributes |= VclWindowPeerAttribute::SPIN;
1229 : }
1230 :
1231 : // HScroll
1232 0 : aPropName = GetPropertyName( BASEPROPERTY_HSCROLL );
1233 0 : if ( xInfo->hasPropertyByName( aPropName ) )
1234 : {
1235 0 : aVal = xPSet->getPropertyValue( aPropName );
1236 0 : sal_Bool b = sal_Bool();
1237 0 : if ( ( aVal >>= b ) && b)
1238 0 : aDescr.WindowAttributes |= VclWindowPeerAttribute::HSCROLL;
1239 : }
1240 :
1241 : // VScroll
1242 0 : aPropName = GetPropertyName( BASEPROPERTY_VSCROLL );
1243 0 : if ( xInfo->hasPropertyByName( aPropName ) )
1244 : {
1245 0 : aVal = xPSet->getPropertyValue( aPropName );
1246 0 : sal_Bool b = sal_Bool();
1247 0 : if ( ( aVal >>= b ) && b)
1248 0 : aDescr.WindowAttributes |= VclWindowPeerAttribute::VSCROLL;
1249 : }
1250 :
1251 : // AutoHScroll
1252 0 : aPropName = GetPropertyName( BASEPROPERTY_AUTOHSCROLL );
1253 0 : if ( xInfo->hasPropertyByName( aPropName ) )
1254 : {
1255 0 : aVal = xPSet->getPropertyValue( aPropName );
1256 0 : sal_Bool b = sal_Bool();
1257 0 : if ( ( aVal >>= b ) && b)
1258 0 : aDescr.WindowAttributes |= VclWindowPeerAttribute::AUTOHSCROLL;
1259 : }
1260 :
1261 : // AutoVScroll
1262 0 : aPropName = GetPropertyName( BASEPROPERTY_AUTOVSCROLL );
1263 0 : if ( xInfo->hasPropertyByName( aPropName ) )
1264 : {
1265 0 : aVal = xPSet->getPropertyValue( aPropName );
1266 0 : sal_Bool b = sal_Bool();
1267 0 : if ( ( aVal >>= b ) && b)
1268 0 : aDescr.WindowAttributes |= VclWindowPeerAttribute::AUTOVSCROLL;
1269 : }
1270 :
1271 : //added for issue79712
1272 : //NoLabel
1273 0 : aPropName = GetPropertyName( BASEPROPERTY_NOLABEL );
1274 0 : if ( xInfo->hasPropertyByName( aPropName ) )
1275 : {
1276 0 : aVal = xPSet->getPropertyValue( aPropName );
1277 0 : sal_Bool b = sal_Bool();
1278 0 : if ( ( aVal >>=b ) && b )
1279 0 : aDescr.WindowAttributes |= VclWindowPeerAttribute::NOLABEL;
1280 : }
1281 : //issue79712 ends
1282 :
1283 : // Align
1284 0 : aPropName = GetPropertyName( BASEPROPERTY_ALIGN );
1285 0 : if ( xInfo->hasPropertyByName( aPropName ) )
1286 : {
1287 0 : aVal = xPSet->getPropertyValue( aPropName );
1288 0 : sal_Int16 n = sal_Int16();
1289 0 : if ( aVal >>= n )
1290 : {
1291 0 : if ( n == PROPERTY_ALIGN_LEFT )
1292 0 : aDescr.WindowAttributes |= VclWindowPeerAttribute::LEFT;
1293 0 : else if ( n == PROPERTY_ALIGN_CENTER )
1294 0 : aDescr.WindowAttributes |= VclWindowPeerAttribute::CENTER;
1295 : else
1296 0 : aDescr.WindowAttributes |= VclWindowPeerAttribute::RIGHT;
1297 : }
1298 : }
1299 :
1300 : // Allow derivates to manipulate attributes
1301 0 : PrepareWindowDescriptor(aDescr);
1302 :
1303 : // create the peer
1304 0 : setPeer( xToolkit->createWindow( aDescr ) );
1305 :
1306 : // release the mutex guard (and work with copies of our members)
1307 : // this is necessary as our peer may lock the SolarMutex (actually, all currently known peers do), so calling
1308 : // into the peer with our own mutex locked may cause deadlocks
1309 : // (We _really_ need peers which do not use the SolarMutex. It's really pissing me off that from time to
1310 : // time deadlocks pop up because the low-level components like our peers use a mutex which ususally
1311 : // is locked at the top of the stack (it protects the global message looping). This is always dangerous, and
1312 : // can not always be solved by tampering with other mutexes.
1313 : // Unfortunately, the VCL used in the peers is not threadsafe, and by definition needs a locked SolarMutex.)
1314 : // 82300 - 12/21/00 - FS
1315 0 : UnoControlComponentInfos aComponentInfos(maComponentInfos);
1316 0 : sal_Bool bDesignMode(mbDesignMode);
1317 :
1318 0 : Reference< XGraphics > xGraphics( mxGraphics );
1319 0 : Reference< XView > xView ( getPeer(), UNO_QUERY_THROW );
1320 0 : Reference< XWindow > xWindow ( getPeer(), UNO_QUERY_THROW );
1321 :
1322 0 : aGuard.clear();
1323 :
1324 : // the updateFromModel is done without a locked mutex, too.
1325 : // The reason is that the only thing this method does is firing property changes, and this in general has
1326 : // to be done without locked mutexes (as every notification to external listeners).
1327 : // 82300 - 12/21/00 - FS
1328 0 : updateFromModel();
1329 :
1330 0 : xView->setZoom( aComponentInfos.nZoomX, aComponentInfos.nZoomY );
1331 :
1332 0 : setPosSize( aComponentInfos.nX, aComponentInfos.nY, aComponentInfos.nWidth, aComponentInfos.nHeight, aComponentInfos.nFlags );
1333 :
1334 0 : if( aComponentInfos.bVisible && !bDesignMode )
1335 : // Show only after setting the data
1336 0 : xWindow->setVisible( aComponentInfos.bVisible );
1337 :
1338 0 : if( !aComponentInfos.bEnable )
1339 0 : xWindow->setEnable( aComponentInfos.bEnable );
1340 :
1341 0 : xView->setGraphics( xGraphics );
1342 :
1343 0 : peerCreated();
1344 :
1345 0 : mbCreatingPeer = sal_False;
1346 0 : }
1347 0 : }
1348 :
1349 9 : Reference< XWindowPeer > UnoControl::getPeer() throw(RuntimeException)
1350 : {
1351 9 : ::osl::MutexGuard aGuard( GetMutex() );
1352 9 : return mxPeer;
1353 : }
1354 :
1355 11 : sal_Bool UnoControl::setModel( const Reference< XControlModel >& rxModel ) throw(RuntimeException)
1356 : {
1357 11 : ::osl::MutexGuard aGuard( GetMutex() );
1358 :
1359 11 : Reference< XMultiPropertySet > xPropSet( mxModel, UNO_QUERY );
1360 :
1361 : // query for the XPropertiesChangeListener - our delegator is allowed to overwrite this interface
1362 11 : Reference< XPropertiesChangeListener > xListener;
1363 11 : queryInterface( ::getCppuType( &xListener ) ) >>= xListener;
1364 :
1365 11 : if( xPropSet.is() )
1366 2 : xPropSet->removePropertiesChangeListener( xListener );
1367 :
1368 11 : mpData->bLocalizationSupport = false;
1369 11 : mxModel = rxModel;
1370 :
1371 11 : if( mxModel.is() )
1372 : {
1373 : try
1374 : {
1375 9 : xPropSet.set( mxModel, UNO_QUERY_THROW );
1376 9 : Reference< XPropertySetInfo > xPSI( xPropSet->getPropertySetInfo(), UNO_SET_THROW );
1377 :
1378 9 : Sequence< ::rtl::OUString> aNames = lcl_ImplGetPropertyNames( xPropSet );
1379 9 : xPropSet->addPropertiesChangeListener( aNames, xListener );
1380 :
1381 9 : mpData->bLocalizationSupport = xPSI->hasPropertyByName( ::rtl::OUString( "ResourceResolver" ) );
1382 : }
1383 0 : catch( const Exception& )
1384 : {
1385 : DBG_UNHANDLED_EXCEPTION();
1386 0 : mxModel.clear();
1387 : }
1388 : }
1389 :
1390 11 : return mxModel.is();
1391 : }
1392 :
1393 0 : Reference< XControlModel > UnoControl::getModel( ) throw(RuntimeException)
1394 : {
1395 0 : return mxModel;
1396 : }
1397 :
1398 0 : Reference< XView > UnoControl::getView( ) throw(RuntimeException)
1399 : {
1400 0 : return static_cast< XView* >( this );
1401 : }
1402 :
1403 0 : void UnoControl::setDesignMode( sal_Bool bOn ) throw(RuntimeException)
1404 : {
1405 0 : ModeChangeEvent aModeChangeEvent;
1406 :
1407 0 : Reference< XWindow > xWindow;
1408 : {
1409 0 : ::osl::MutexGuard aGuard( GetMutex() );
1410 0 : if ( bOn == mbDesignMode )
1411 0 : return;
1412 :
1413 : // remember this
1414 0 : mbDesignMode = bOn;
1415 0 : xWindow = xWindow.query( getPeer() );
1416 : // dispose our current AccessibleContext, if we have one
1417 : // (changing the design mode implies having a new implementation for this context,
1418 : // so the old one must be declared DEFUNC)
1419 0 : disposeAccessibleContext();
1420 :
1421 0 : aModeChangeEvent.Source = *this;
1422 0 : aModeChangeEvent.NewMode = mbDesignMode ? ::rtl::OUString("design") : ::rtl::OUString("alive" );
1423 : }
1424 :
1425 : // ajust the visibility of our window
1426 0 : if ( xWindow.is() )
1427 0 : xWindow->setVisible( !bOn );
1428 :
1429 : // and notify our mode listeners
1430 0 : maModeChangeListeners.notifyEach( &XModeChangeListener::modeChanged, aModeChangeEvent );
1431 : }
1432 :
1433 0 : sal_Bool UnoControl::isDesignMode( ) throw(RuntimeException)
1434 : {
1435 0 : return mbDesignMode;
1436 : }
1437 :
1438 0 : sal_Bool UnoControl::isTransparent( ) throw(RuntimeException)
1439 : {
1440 0 : return sal_False;
1441 : }
1442 :
1443 : // XServiceInfo
1444 0 : ::rtl::OUString UnoControl::getImplementationName( ) throw(RuntimeException)
1445 : {
1446 : OSL_FAIL( "This method should be overloaded!" );
1447 0 : return ::rtl::OUString();
1448 : }
1449 :
1450 0 : sal_Bool UnoControl::supportsService( const ::rtl::OUString& rServiceName ) throw(RuntimeException)
1451 : {
1452 0 : ::osl::MutexGuard aGuard( GetMutex() );
1453 :
1454 0 : Sequence< ::rtl::OUString > aSNL = getSupportedServiceNames();
1455 0 : const ::rtl::OUString* pArray = aSNL.getConstArray();
1456 0 : const ::rtl::OUString* pArrayEnd = aSNL.getConstArray() + aSNL.getLength();
1457 0 : for (; pArray != pArrayEnd; ++pArray )
1458 0 : if( *pArray == rServiceName )
1459 0 : break;
1460 :
1461 0 : return pArray != pArrayEnd;
1462 : }
1463 :
1464 0 : Sequence< ::rtl::OUString > UnoControl::getSupportedServiceNames( ) throw(RuntimeException)
1465 : {
1466 0 : ::rtl::OUString sName( "com.sun.star.awt.UnoControl" );
1467 0 : return Sequence< ::rtl::OUString >( &sName, 1 );
1468 : }
1469 :
1470 : // ------------------------------------------------------------------------
1471 0 : Reference< XAccessibleContext > SAL_CALL UnoControl::getAccessibleContext( ) throw (RuntimeException)
1472 : {
1473 : // creation of the context will certainly require the SolarMutex ...
1474 0 : SolarMutexGuard aSolarGuard;
1475 0 : ::osl::MutexGuard aGuard( GetMutex() );
1476 :
1477 0 : Reference< XAccessibleContext > xCurrentContext( maAccessibleContext.get(), UNO_QUERY );
1478 0 : if ( !xCurrentContext.is() )
1479 : {
1480 0 : if ( !mbDesignMode )
1481 : { // in alive mode, use the AccessibleContext of the peer
1482 0 : Reference< XAccessible > xPeerAcc( getPeer(), UNO_QUERY );
1483 0 : if ( xPeerAcc.is() )
1484 0 : xCurrentContext = xPeerAcc->getAccessibleContext( );
1485 : }
1486 : else
1487 : // in design mode, use a fallback
1488 0 : xCurrentContext = ::toolkit::OAccessibleControlContext::create( this );
1489 :
1490 : DBG_ASSERT( xCurrentContext.is(), "UnoControl::getAccessibleContext: invalid context (invalid peer?)!" );
1491 0 : maAccessibleContext = xCurrentContext;
1492 :
1493 : // get notified when the context is disposed
1494 0 : Reference< XComponent > xContextComp( xCurrentContext, UNO_QUERY );
1495 0 : if ( xContextComp.is() )
1496 0 : xContextComp->addEventListener( this );
1497 : // In an ideal world, this is not necessary - there the object would be released as soon as it has been
1498 : // disposed, and thus our weak reference would be empty, too.
1499 : // But 'til this ideal world comes (means 'til we do never have any refcount/lifetime bugs anymore), we
1500 : // need to listen for disposal and reset our weak reference then.
1501 : }
1502 :
1503 0 : return xCurrentContext;
1504 : }
1505 :
1506 0 : void SAL_CALL UnoControl::addModeChangeListener( const Reference< XModeChangeListener >& _rxListener ) throw (RuntimeException)
1507 : {
1508 0 : ::osl::MutexGuard aGuard( GetMutex() );
1509 0 : maModeChangeListeners.addInterface( _rxListener );
1510 0 : }
1511 :
1512 0 : void SAL_CALL UnoControl::removeModeChangeListener( const Reference< XModeChangeListener >& _rxListener ) throw (RuntimeException)
1513 : {
1514 0 : ::osl::MutexGuard aGuard( GetMutex() );
1515 0 : maModeChangeListeners.removeInterface( _rxListener );
1516 0 : }
1517 :
1518 0 : void SAL_CALL UnoControl::addModeChangeApproveListener( const Reference< XModeChangeApproveListener >& ) throw (NoSupportException, RuntimeException)
1519 : {
1520 0 : throw NoSupportException( );
1521 : }
1522 :
1523 0 : void SAL_CALL UnoControl::removeModeChangeApproveListener( const Reference< XModeChangeApproveListener >& ) throw (NoSupportException, RuntimeException)
1524 : {
1525 0 : throw NoSupportException( );
1526 : }
1527 :
1528 : //----------------------------------------------------------------------------------------------------------------------
1529 0 : awt::Point SAL_CALL UnoControl::convertPointToLogic( const awt::Point& i_Point, ::sal_Int16 i_TargetUnit ) throw (IllegalArgumentException, RuntimeException)
1530 : {
1531 0 : Reference< XUnitConversion > xPeerConversion;
1532 : {
1533 0 : ::osl::MutexGuard aGuard( GetMutex() );
1534 0 : xPeerConversion = xPeerConversion.query( getPeer() );
1535 : }
1536 0 : if ( xPeerConversion.is() )
1537 0 : return xPeerConversion->convertPointToLogic( i_Point, i_TargetUnit );
1538 0 : return awt::Point( );
1539 : }
1540 :
1541 : //----------------------------------------------------------------------------------------------------------------------
1542 0 : awt::Point SAL_CALL UnoControl::convertPointToPixel( const awt::Point& i_Point, ::sal_Int16 i_SourceUnit ) throw (IllegalArgumentException, RuntimeException)
1543 : {
1544 0 : Reference< XUnitConversion > xPeerConversion;
1545 : {
1546 0 : ::osl::MutexGuard aGuard( GetMutex() );
1547 0 : xPeerConversion = xPeerConversion.query( getPeer() );
1548 : }
1549 0 : if ( xPeerConversion.is() )
1550 0 : return xPeerConversion->convertPointToPixel( i_Point, i_SourceUnit );
1551 0 : return awt::Point( );
1552 : }
1553 :
1554 : //----------------------------------------------------------------------------------------------------------------------
1555 0 : awt::Size SAL_CALL UnoControl::convertSizeToLogic( const awt::Size& i_Size, ::sal_Int16 i_TargetUnit ) throw (IllegalArgumentException, RuntimeException)
1556 : {
1557 0 : Reference< XUnitConversion > xPeerConversion;
1558 : {
1559 0 : ::osl::MutexGuard aGuard( GetMutex() );
1560 0 : xPeerConversion = xPeerConversion.query( getPeer() );
1561 : }
1562 0 : if ( xPeerConversion.is() )
1563 0 : return xPeerConversion->convertSizeToLogic( i_Size, i_TargetUnit );
1564 0 : return awt::Size( );
1565 : }
1566 :
1567 : //----------------------------------------------------------------------------------------------------------------------
1568 0 : awt::Size SAL_CALL UnoControl::convertSizeToPixel( const awt::Size& i_Size, ::sal_Int16 i_SourceUnit ) throw (IllegalArgumentException, RuntimeException)
1569 : {
1570 0 : Reference< XUnitConversion > xPeerConversion;
1571 : {
1572 0 : ::osl::MutexGuard aGuard( GetMutex() );
1573 0 : xPeerConversion = xPeerConversion.query( getPeer() );
1574 : }
1575 0 : if ( xPeerConversion.is() )
1576 0 : return xPeerConversion->convertSizeToPixel( i_Size, i_SourceUnit );
1577 0 : return awt::Size( );
1578 : }
1579 :
1580 : //----------------------------------------------------------------------------------------------------------------------
1581 0 : uno::Reference< awt::XStyleSettings > SAL_CALL UnoControl::getStyleSettings() throw (RuntimeException)
1582 : {
1583 0 : Reference< awt::XStyleSettingsSupplier > xPeerSupplier;
1584 : {
1585 0 : ::osl::MutexGuard aGuard( GetMutex() );
1586 0 : xPeerSupplier = xPeerSupplier.query( getPeer() );
1587 : }
1588 0 : if ( xPeerSupplier.is() )
1589 0 : return xPeerSupplier->getStyleSettings();
1590 0 : return NULL;
1591 : }
1592 :
1593 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|