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 111 : static Sequence< ::rtl::OUString> lcl_ImplGetPropertyNames( const Reference< XMultiPropertySet > & rxModel )
79 : {
80 111 : Sequence< ::rtl::OUString> aNames;
81 111 : Reference< XPropertySetInfo > xPSInf = rxModel->getPropertySetInfo();
82 : DBG_ASSERT( xPSInf.is(), "UpdateFromModel: No PropertySetInfo!" );
83 111 : if ( xPSInf.is() )
84 : {
85 111 : Sequence< Property> aProps = xPSInf->getProperties();
86 111 : sal_Int32 nLen = aProps.getLength();
87 111 : aNames = Sequence< ::rtl::OUString>( nLen );
88 111 : ::rtl::OUString* pNames = aNames.getArray();
89 111 : const Property* pProps = aProps.getConstArray();
90 3066 : for ( sal_Int32 n = 0; n < nLen; ++n, ++pProps, ++pNames)
91 3066 : *pNames = pProps->Name;
92 : }
93 111 : return aNames;
94 : }
95 :
96 : // ====================================================
97 : class VclListenerLock
98 : {
99 : private:
100 : VCLXWindow* m_pLockWindow;
101 :
102 : public:
103 12 : inline VclListenerLock( VCLXWindow* _pLockWindow )
104 12 : :m_pLockWindow( _pLockWindow )
105 : {
106 12 : if ( m_pLockWindow )
107 12 : m_pLockWindow->suspendVclEventListening( );
108 12 : }
109 12 : inline ~VclListenerLock( )
110 : {
111 12 : if ( m_pLockWindow )
112 12 : m_pLockWindow->resumeVclEventListening( );
113 12 : }
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 65 : struct UnoControl_Data
123 : {
124 : MapString2Int aSuspendedPropertyNotifications;
125 : /// true if and only if our model has a property ResourceResolver
126 : bool bLocalizationSupport;
127 :
128 99 : UnoControl_Data()
129 : :aSuspendedPropertyNotifications()
130 99 : ,bLocalizationSupport( false )
131 : {
132 99 : }
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 99 : 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 99 : , maModeChangeListeners( GetMutex() )
167 198 : , mpData( new UnoControl_Data )
168 : {
169 : DBG_CTOR( UnoControl, NULL );
170 99 : mbDisposePeer = sal_True;
171 99 : mbRefeshingPeer = sal_False;
172 99 : mbCreatingPeer = sal_False;
173 99 : mbCreatingCompatiblePeer = sal_False;
174 99 : mbDesignMode = sal_False;
175 99 : }
176 :
177 130 : UnoControl::~UnoControl()
178 : {
179 65 : DELETEZ( mpData );
180 : DBG_DTOR( UnoControl, NULL );
181 65 : }
182 :
183 0 : ::rtl::OUString UnoControl::GetComponentServiceName()
184 : {
185 0 : return ::rtl::OUString();
186 : }
187 :
188 2 : Reference< XWindowPeer > UnoControl::ImplGetCompatiblePeer( sal_Bool bAcceptExistingPeer )
189 : {
190 : DBG_ASSERT( !mbCreatingCompatiblePeer, "ImplGetCompatiblePeer - rekursive?" );
191 :
192 2 : mbCreatingCompatiblePeer = sal_True;
193 :
194 2 : Reference< XWindowPeer > xCompatiblePeer;
195 :
196 2 : if ( bAcceptExistingPeer )
197 2 : xCompatiblePeer = getPeer();
198 :
199 2 : if ( !xCompatiblePeer.is() )
200 : {
201 : // Create the pair as invisible
202 2 : sal_Bool bVis = maComponentInfos.bVisible;
203 2 : if( bVis )
204 2 : maComponentInfos.bVisible = sal_False;
205 :
206 2 : Reference< XWindowPeer > xCurrentPeer = getPeer();
207 2 : setPeer( NULL );
208 :
209 : // queryInterface ourself, to allow aggregation
210 2 : Reference< XControl > xMe;
211 2 : OWeakAggObject::queryInterface( ::getCppuType( &xMe ) ) >>= xMe;
212 :
213 2 : Window* pParentWindow( NULL );
214 : {
215 2 : SolarMutexGuard aGuard;
216 2 : pParentWindow = dynamic_cast< Window* >( Application::GetDefaultDevice() );
217 2 : ENSURE_OR_THROW( pParentWindow != NULL, "could obtain a default parent window!" );
218 : }
219 : try
220 : {
221 2 : xMe->createPeer( NULL, pParentWindow->GetComponentInterface( sal_True ) );
222 : }
223 0 : catch( const Exception& )
224 : {
225 0 : mbCreatingCompatiblePeer = sal_False;
226 0 : throw;
227 : }
228 2 : xCompatiblePeer = getPeer();
229 2 : setPeer( xCurrentPeer );
230 :
231 2 : if ( xCompatiblePeer.is() && mxGraphics.is() )
232 : {
233 2 : Reference< XView > xPeerView( xCompatiblePeer, UNO_QUERY );
234 2 : if ( xPeerView.is() )
235 2 : xPeerView->setGraphics( mxGraphics );
236 : }
237 :
238 2 : if( bVis )
239 2 : maComponentInfos.bVisible = sal_True;
240 : }
241 :
242 2 : mbCreatingCompatiblePeer = sal_False;
243 :
244 2 : return xCompatiblePeer;
245 : }
246 :
247 6 : bool UnoControl::ImplCheckLocalize( ::rtl::OUString& _rPossiblyLocalizable )
248 : {
249 6 : 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 6 : 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 1080 : 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 1080 : if ( mxVclWindowPeer.is() )
286 : {
287 1080 : Any aConvertedValue( rVal );
288 :
289 1080 : 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 1080 : mxVclWindowPeer->setProperty( rPropName, aConvertedValue );
317 : }
318 1080 : }
319 :
320 12 : void UnoControl::PrepareWindowDescriptor( WindowDescriptor& )
321 : {
322 12 : }
323 :
324 12 : Reference< XWindow > UnoControl::getParentPeer() const
325 : {
326 12 : Reference< XWindow > xPeer;
327 12 : if( mxContext.is() )
328 : {
329 10 : Reference< XControl > xContComp( mxContext, UNO_QUERY );
330 10 : if ( xContComp.is() )
331 : {
332 10 : Reference< XWindowPeer > xP = xContComp->getPeer();
333 10 : if ( xP.is() )
334 10 : xP->queryInterface( ::getCppuType((const Reference< XWindow >*)0) ) >>= xPeer;
335 10 : }
336 : }
337 12 : return xPeer;
338 : }
339 :
340 12 : void UnoControl::updateFromModel()
341 : {
342 : // Read default properties and hand over to peer
343 12 : if( getPeer().is() )
344 : {
345 12 : Reference< XMultiPropertySet > xPropSet( mxModel, UNO_QUERY );
346 12 : if( xPropSet.is() )
347 : {
348 12 : Sequence< ::rtl::OUString> aNames = lcl_ImplGetPropertyNames( xPropSet );
349 12 : xPropSet->firePropertiesChangeEvent( aNames, this );
350 12 : }
351 : }
352 12 : }
353 :
354 :
355 : // XTypeProvider
356 0 : IMPL_IMPLEMENTATION_ID( UnoControl )
357 :
358 67 : void UnoControl::disposeAccessibleContext()
359 : {
360 67 : Reference< XComponent > xContextComp( maAccessibleContext.get(), UNO_QUERY );
361 67 : 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 67 : }
374 67 : }
375 :
376 65 : void UnoControl::dispose( ) throw(RuntimeException)
377 : {
378 65 : Reference< XWindowPeer > xPeer;
379 : {
380 65 : ::osl::MutexGuard aGuard( GetMutex() );
381 65 : if( mbDisposePeer )
382 : {
383 8 : xPeer = mxPeer;
384 : }
385 65 : setPeer( NULL );
386 : }
387 65 : if( xPeer.is() )
388 : {
389 6 : xPeer->dispose();
390 : }
391 :
392 : // dispose and release our AccessibleContext
393 65 : disposeAccessibleContext();
394 :
395 65 : EventObject aDisposeEvent;
396 65 : aDisposeEvent.Source = static_cast< XAggregation* >( this );
397 :
398 65 : maDisposeListeners.disposeAndClear( aDisposeEvent );
399 65 : maWindowListeners.disposeAndClear( aDisposeEvent );
400 65 : maFocusListeners.disposeAndClear( aDisposeEvent );
401 65 : maKeyListeners.disposeAndClear( aDisposeEvent );
402 65 : maMouseListeners.disposeAndClear( aDisposeEvent );
403 65 : maMouseMotionListeners.disposeAndClear( aDisposeEvent );
404 65 : maPaintListeners.disposeAndClear( aDisposeEvent );
405 65 : maModeChangeListeners.disposeAndClear( aDisposeEvent );
406 :
407 : // release Model again
408 65 : setModel( Reference< XControlModel > () );
409 65 : setContext( Reference< XInterface > () );
410 65 : }
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 12 : void UnoControl::propertiesChange( const Sequence< PropertyChangeEvent >& rEvents ) throw(RuntimeException)
433 : {
434 12 : Sequence< PropertyChangeEvent > aEvents( rEvents );
435 : {
436 12 : ::osl::MutexGuard aGuard( GetMutex() );
437 :
438 12 : 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 12 : return;
456 12 : }
457 : }
458 :
459 12 : 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 12 : void UnoControl::ImplModelPropertiesChanged( const Sequence< PropertyChangeEvent >& rEvents )
493 : {
494 12 : ::osl::ClearableGuard< ::osl::Mutex > aGuard( GetMutex() );
495 :
496 12 : if( getPeer().is() )
497 : {
498 : DECLARE_STL_VECTOR( PropertyValue, PropertyValueVector);
499 12 : PropertyValueVector aPeerPropertiesToSet;
500 12 : sal_Int32 nIndependentPos = 0;
501 12 : 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 12 : 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 12 : Reference< XControlModel > xOwnModel( getModel(), UNO_QUERY );
509 : // our own model for comparison
510 12 : Reference< XPropertySet > xPS( xOwnModel, UNO_QUERY );
511 12 : Reference< XPropertySetInfo > xPSI( xPS->getPropertySetInfo(), UNO_QUERY );
512 : OSL_ENSURE( xPSI.is(), "UnoControl::ImplModelPropertiesChanged: should have property set meta data!" );
513 :
514 12 : const PropertyChangeEvent* pEvents = rEvents.getConstArray();
515 :
516 12 : sal_Int32 nLen = rEvents.getLength();
517 12 : aPeerPropertiesToSet.reserve(nLen);
518 :
519 1098 : for( sal_Int32 i = 0; i < nLen; ++i, ++pEvents )
520 : {
521 1086 : Reference< XControlModel > xModel( pEvents->Source, UNO_QUERY );
522 1086 : sal_Bool bOwnModel = xModel.get() == xOwnModel.get();
523 1086 : if ( !bOwnModel )
524 0 : continue;
525 :
526 : // Detect changes on our resource resolver which invalidates
527 : // automatically some language dependent properties.
528 1086 : 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 1086 : sal_uInt16 nPType = GetPropertyId( pEvents->PropertyName );
536 1086 : 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 1086 : 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 12 : aPeerPropertiesToSet.push_back(PropertyValue(pEvents->PropertyName, 0, pEvents->NewValue, PropertyState_DIRECT_VALUE));
566 : }
567 : else
568 : {
569 1074 : 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 1074 : 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 12 : PropertyValue( pEvents->PropertyName, 0, pEvents->NewValue, PropertyState_DIRECT_VALUE ) );
592 12 : ++nIndependentPos;
593 : }
594 : else
595 : {
596 : aPeerPropertiesToSet.insert(aPeerPropertiesToSet.begin() + nIndependentPos,
597 1062 : PropertyValue(pEvents->PropertyName, 0, pEvents->NewValue, PropertyState_DIRECT_VALUE));
598 1062 : ++nIndependentPos;
599 : }
600 : }
601 1086 : }
602 :
603 12 : Reference< XWindow > xParent = getParentPeer();
604 12 : 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 12 : 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 12 : aGuard.clear();
644 :
645 : // clear the guard before creating a new peer - as usual, our peer implementations use the SolarMutex
646 :
647 12 : 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 12 : Window* pVclPeer = VCLUnoHelper::GetWindow( getPeer() );
672 12 : VCLXWindow* pPeer = pVclPeer ? pVclPeer->GetWindowPeer() : NULL;
673 12 : 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 12 : PropertyValueVectorIterator aEnd = aPeerPropertiesToSet.end();
679 1098 : for ( PropertyValueVectorIterator aLoop = aPeerPropertiesToSet.begin();
680 : aLoop != aEnd;
681 : ++aLoop
682 : )
683 : {
684 1086 : ImplSetPeerProperty( aLoop->Name, aLoop->Value );
685 12 : }
686 12 : }
687 12 : }
688 :
689 14 : void UnoControl::disposing( const EventObject& rEvt ) throw(RuntimeException)
690 : {
691 14 : ::osl::ClearableMutexGuard aGuard( GetMutex() );
692 : // do not compare differing types in case of multible inheritance
693 :
694 14 : 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 14 : 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 14 : }
710 14 : }
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 108 : RETVALTYPE lcl_askPeer( const uno::Reference< awt::XWindowPeer >& _rxPeer, RETVALTYPE (SAL_CALL XWindow2::*_pMethod)(), RETVALTYPE _aDefault )
729 : {
730 108 : RETVALTYPE aReturn( _aDefault );
731 :
732 108 : Reference< XWindow2 > xPeerWindow( _rxPeer, UNO_QUERY );
733 108 : if ( xPeerWindow.is() )
734 102 : aReturn = (xPeerWindow.get()->*_pMethod)();
735 :
736 108 : 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 108 : ::sal_Bool SAL_CALL UnoControl::isVisible( ) throw (RuntimeException)
746 : {
747 108 : 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 24 : void UnoControl::setPosSize( sal_Int32 X, sal_Int32 Y, sal_Int32 Width, sal_Int32 Height, sal_Int16 Flags ) throw(RuntimeException)
767 : {
768 24 : Reference< XWindow > xWindow;
769 : {
770 24 : ::osl::MutexGuard aGuard( GetMutex() );
771 :
772 24 : if ( Flags & awt::PosSize::X )
773 24 : maComponentInfos.nX = X;
774 24 : if ( Flags & awt::PosSize::Y )
775 24 : maComponentInfos.nY = Y;
776 24 : if ( Flags & awt::PosSize::WIDTH )
777 24 : maComponentInfos.nWidth = Width;
778 24 : if ( Flags & awt::PosSize::HEIGHT )
779 24 : maComponentInfos.nHeight = Height;
780 24 : maComponentInfos.nFlags |= Flags;
781 :
782 24 : xWindow = xWindow.query( getPeer() );
783 : }
784 :
785 24 : if( xWindow.is() )
786 12 : xWindow->setPosSize( X, Y, Width, Height, Flags );
787 24 : }
788 :
789 208 : awt::Rectangle UnoControl::getPosSize( ) throw(RuntimeException)
790 : {
791 208 : awt::Rectangle aRect( maComponentInfos.nX, maComponentInfos.nY, maComponentInfos.nWidth, maComponentInfos.nHeight);
792 208 : Reference< XWindow > xWindow;
793 :
794 : {
795 208 : ::osl::MutexGuard aGuard( GetMutex() );
796 208 : xWindow = xWindow.query( getPeer() );
797 : }
798 :
799 208 : if( xWindow.is() )
800 184 : aRect = xWindow->getPosSize();
801 208 : return aRect;
802 : }
803 :
804 10 : void UnoControl::setVisible( sal_Bool bVisible ) throw(RuntimeException)
805 : {
806 10 : Reference< XWindow > xWindow;
807 : {
808 10 : ::osl::MutexGuard aGuard( GetMutex() );
809 :
810 : // Visible status is handled by View
811 10 : maComponentInfos.bVisible = bVisible;
812 10 : xWindow = xWindow.query( getPeer() );
813 : }
814 10 : if ( xWindow.is() )
815 0 : xWindow->setVisible( bVisible );
816 10 : }
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 12 : void UnoControl::addWindowListener( const Reference< XWindowListener >& rxListener ) throw(RuntimeException)
844 : {
845 12 : Reference< XWindow > xPeerWindow;
846 : {
847 12 : ::osl::MutexGuard aGuard( GetMutex() );
848 12 : maWindowListeners.addInterface( rxListener );
849 12 : if ( maWindowListeners.getLength() == 1 )
850 12 : xPeerWindow = xPeerWindow.query( getPeer() );
851 : }
852 12 : if ( xPeerWindow.is() )
853 10 : xPeerWindow->addWindowListener( &maWindowListeners );
854 12 : }
855 :
856 8 : void UnoControl::removeWindowListener( const Reference< XWindowListener >& rxListener ) throw(RuntimeException)
857 : {
858 8 : Reference< XWindow > xPeerWindow;
859 : {
860 8 : ::osl::MutexGuard aGuard( GetMutex() );
861 8 : if ( maWindowListeners.getLength() == 1 )
862 8 : xPeerWindow = xPeerWindow.query( getPeer() );
863 8 : maWindowListeners.removeInterface( rxListener );
864 : }
865 8 : if ( xPeerWindow.is() )
866 6 : xPeerWindow->removeWindowListener( &maWindowListeners );
867 8 : }
868 :
869 16 : void UnoControl::addFocusListener( const Reference< XFocusListener >& rxListener ) throw(RuntimeException)
870 : {
871 16 : Reference< XWindow > xPeerWindow;
872 : {
873 16 : ::osl::MutexGuard aGuard( GetMutex() );
874 16 : maFocusListeners.addInterface( rxListener );
875 16 : if ( maFocusListeners.getLength() == 1 )
876 12 : xPeerWindow = xPeerWindow.query( getPeer() );
877 : }
878 16 : if ( xPeerWindow.is() )
879 6 : xPeerWindow->addFocusListener( &maFocusListeners );
880 16 : }
881 :
882 6 : void UnoControl::removeFocusListener( const Reference< XFocusListener >& rxListener ) throw(RuntimeException)
883 : {
884 6 : Reference< XWindow > xPeerWindow;
885 : {
886 6 : ::osl::MutexGuard aGuard( GetMutex() );
887 6 : if ( maFocusListeners.getLength() == 1 )
888 6 : xPeerWindow = xPeerWindow.query( getPeer() );
889 6 : maFocusListeners.removeInterface( rxListener );
890 : }
891 6 : if ( xPeerWindow.is() )
892 6 : xPeerWindow->removeFocusListener( &maFocusListeners );
893 6 : }
894 :
895 6 : void UnoControl::addKeyListener( const Reference< XKeyListener >& rxListener ) throw(RuntimeException)
896 : {
897 6 : Reference< XWindow > xPeerWindow;
898 : {
899 6 : ::osl::MutexGuard aGuard( GetMutex() );
900 6 : maKeyListeners.addInterface( rxListener );
901 6 : if ( maKeyListeners.getLength() == 1 )
902 6 : xPeerWindow = xPeerWindow.query( getPeer() );
903 : }
904 6 : if ( xPeerWindow.is() )
905 0 : xPeerWindow->addKeyListener( &maKeyListeners);
906 6 : }
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 14 : void UnoControl::addMouseListener( const Reference< XMouseListener >& rxListener ) throw(RuntimeException)
922 : {
923 14 : Reference< XWindow > xPeerWindow;
924 : {
925 14 : ::osl::MutexGuard aGuard( GetMutex() );
926 14 : maMouseListeners.addInterface( rxListener );
927 14 : if ( maMouseListeners.getLength() == 1 )
928 10 : xPeerWindow = xPeerWindow.query( getPeer() );
929 : }
930 14 : if ( xPeerWindow.is() )
931 10 : xPeerWindow->addMouseListener( &maMouseListeners);
932 14 : }
933 :
934 10 : void UnoControl::removeMouseListener( const Reference< XMouseListener >& rxListener ) throw(RuntimeException)
935 : {
936 10 : Reference< XWindow > xPeerWindow;
937 : {
938 10 : ::osl::MutexGuard aGuard( GetMutex() );
939 10 : if ( maMouseListeners.getLength() == 1 )
940 6 : xPeerWindow = xPeerWindow.query( getPeer() );
941 10 : maMouseListeners.removeInterface( rxListener );
942 : }
943 10 : if ( xPeerWindow.is() )
944 6 : xPeerWindow->removeMouseListener( &maMouseListeners );
945 10 : }
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 40 : sal_Bool UnoControl::setGraphics( const Reference< XGraphics >& rDevice ) throw(RuntimeException)
1001 : {
1002 40 : Reference< XView > xView;
1003 : {
1004 40 : ::osl::MutexGuard aGuard( GetMutex() );
1005 :
1006 40 : mxGraphics = rDevice;
1007 40 : xView = xView.query( getPeer() );
1008 : }
1009 40 : return xView.is() ? xView->setGraphics( rDevice ) : sal_True;
1010 : }
1011 :
1012 20 : Reference< XGraphics > UnoControl::getGraphics( ) throw(RuntimeException)
1013 : {
1014 20 : 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 2 : void UnoControl::draw( sal_Int32 x, sal_Int32 y ) throw(RuntimeException)
1024 : {
1025 2 : Reference< XWindowPeer > xDrawPeer;
1026 2 : Reference< XView > xDrawPeerView;
1027 :
1028 2 : bool bDisposeDrawPeer( false );
1029 : {
1030 2 : ::osl::MutexGuard aGuard( GetMutex() );
1031 :
1032 2 : xDrawPeer = ImplGetCompatiblePeer( sal_True );
1033 2 : bDisposeDrawPeer = xDrawPeer.is() && ( xDrawPeer != getPeer() );
1034 :
1035 2 : xDrawPeerView.set( xDrawPeer, UNO_QUERY );
1036 2 : DBG_ASSERT( xDrawPeerView.is(), "UnoControl::draw: no peer!" );
1037 : }
1038 :
1039 2 : if ( xDrawPeerView.is() )
1040 : {
1041 2 : Reference< XVclWindowPeer > xWindowPeer;
1042 2 : xWindowPeer.set( xDrawPeer, UNO_QUERY );
1043 2 : if ( xWindowPeer.is() )
1044 2 : xWindowPeer->setDesignMode( mbDesignMode );
1045 2 : xDrawPeerView->draw( x, y );
1046 : }
1047 :
1048 2 : if ( bDisposeDrawPeer )
1049 2 : xDrawPeer->dispose();
1050 2 : }
1051 :
1052 196 : void UnoControl::setZoom( float fZoomX, float fZoomY ) throw(RuntimeException)
1053 : {
1054 196 : Reference< XView > xView;
1055 : {
1056 196 : ::osl::MutexGuard aGuard( GetMutex() );
1057 :
1058 196 : maComponentInfos.nZoomX = fZoomX;
1059 196 : maComponentInfos.nZoomY = fZoomY;
1060 :
1061 196 : xView = xView.query( getPeer() );
1062 : }
1063 196 : if ( xView.is() )
1064 184 : xView->setZoom( fZoomX, fZoomY );
1065 196 : }
1066 :
1067 : // XControl
1068 81 : void UnoControl::setContext( const Reference< XInterface >& rxContext ) throw(RuntimeException)
1069 : {
1070 81 : ::osl::MutexGuard aGuard( GetMutex() );
1071 :
1072 81 : mxContext = rxContext;
1073 81 : }
1074 :
1075 87 : Reference< XInterface > UnoControl::getContext( ) throw(RuntimeException)
1076 : {
1077 87 : ::osl::MutexGuard aGuard( GetMutex() );
1078 :
1079 87 : return mxContext;
1080 : }
1081 :
1082 12 : void UnoControl::peerCreated()
1083 : {
1084 12 : Reference< XWindow > xWindow( getPeer(), UNO_QUERY );
1085 12 : if ( !xWindow.is() )
1086 12 : return;
1087 :
1088 12 : if ( maWindowListeners.getLength() )
1089 2 : xWindow->addWindowListener( &maWindowListeners );
1090 :
1091 12 : if ( maFocusListeners.getLength() )
1092 6 : xWindow->addFocusListener( &maFocusListeners );
1093 :
1094 12 : if ( maKeyListeners.getLength() )
1095 6 : xWindow->addKeyListener( &maKeyListeners );
1096 :
1097 12 : if ( maMouseListeners.getLength() )
1098 0 : xWindow->addMouseListener( &maMouseListeners );
1099 :
1100 12 : if ( maMouseMotionListeners.getLength() )
1101 0 : xWindow->addMouseMotionListener( &maMouseMotionListeners );
1102 :
1103 12 : if ( maPaintListeners.getLength() )
1104 0 : xWindow->addPaintListener( &maPaintListeners );
1105 : }
1106 :
1107 12 : void UnoControl::createPeer( const Reference< XToolkit >& rxToolkit, const Reference< XWindowPeer >& rParentPeer ) throw(RuntimeException)
1108 : {
1109 12 : ::osl::ClearableMutexGuard aGuard( GetMutex() );
1110 12 : 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 12 : if( !getPeer().is() )
1119 : {
1120 12 : mbCreatingPeer = sal_True;
1121 :
1122 : WindowClass eType;
1123 12 : Reference< XToolkit > xToolkit = rxToolkit;
1124 12 : if( rParentPeer.is() && mxContext.is() )
1125 : {
1126 : // kein TopWindow
1127 10 : if ( !xToolkit.is() )
1128 10 : xToolkit = rParentPeer->getToolkit();
1129 10 : Any aAny = OWeakAggObject::queryInterface( ::getCppuType((const Reference< XControlContainer>*)0) );
1130 10 : Reference< XControlContainer > xC;
1131 10 : aAny >>= xC;
1132 10 : if( xC.is() )
1133 : // It's a container
1134 0 : eType = WindowClass_CONTAINER;
1135 : else
1136 10 : eType = WindowClass_SIMPLE;
1137 : }
1138 : else
1139 : { // This is only correct for Top Window
1140 2 : if( rParentPeer.is() )
1141 : {
1142 2 : if ( !xToolkit.is() )
1143 2 : xToolkit = rParentPeer->getToolkit();
1144 2 : 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 12 : WindowDescriptor aDescr;
1154 12 : aDescr.Type = eType;
1155 12 : aDescr.WindowServiceName = GetComponentServiceName();
1156 12 : aDescr.Parent = rParentPeer;
1157 12 : aDescr.Bounds = getPosSize();
1158 12 : aDescr.WindowAttributes = 0;
1159 :
1160 : // Border
1161 12 : Reference< XPropertySet > xPSet( mxModel, UNO_QUERY );
1162 12 : Reference< XPropertySetInfo > xInfo = xPSet->getPropertySetInfo();
1163 :
1164 12 : Any aVal;
1165 12 : ::rtl::OUString aPropName = GetPropertyName( BASEPROPERTY_BORDER );
1166 12 : if ( xInfo->hasPropertyByName( aPropName ) )
1167 : {
1168 6 : aVal = xPSet->getPropertyValue( aPropName );
1169 6 : sal_Int16 n = sal_Int16();
1170 6 : if ( aVal >>= n )
1171 : {
1172 6 : if ( n )
1173 6 : aDescr.WindowAttributes |= WindowAttribute::BORDER;
1174 : else
1175 0 : aDescr.WindowAttributes |= VclWindowPeerAttribute::NOBORDER;
1176 : }
1177 : }
1178 :
1179 : // DESKTOP_AS_PARENT
1180 12 : 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 12 : aPropName = GetPropertyName( BASEPROPERTY_MOVEABLE );
1193 12 : 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 12 : aPropName = GetPropertyName( BASEPROPERTY_CLOSEABLE );
1203 12 : 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 12 : aPropName = GetPropertyName( BASEPROPERTY_DROPDOWN );
1213 12 : 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 12 : aPropName = GetPropertyName( BASEPROPERTY_SPIN );
1223 12 : 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 12 : aPropName = GetPropertyName( BASEPROPERTY_HSCROLL );
1233 12 : if ( xInfo->hasPropertyByName( aPropName ) )
1234 : {
1235 6 : aVal = xPSet->getPropertyValue( aPropName );
1236 6 : sal_Bool b = sal_Bool();
1237 6 : if ( ( aVal >>= b ) && b)
1238 0 : aDescr.WindowAttributes |= VclWindowPeerAttribute::HSCROLL;
1239 : }
1240 :
1241 : // VScroll
1242 12 : aPropName = GetPropertyName( BASEPROPERTY_VSCROLL );
1243 12 : if ( xInfo->hasPropertyByName( aPropName ) )
1244 : {
1245 6 : aVal = xPSet->getPropertyValue( aPropName );
1246 6 : sal_Bool b = sal_Bool();
1247 6 : if ( ( aVal >>= b ) && b)
1248 0 : aDescr.WindowAttributes |= VclWindowPeerAttribute::VSCROLL;
1249 : }
1250 :
1251 : // AutoHScroll
1252 12 : aPropName = GetPropertyName( BASEPROPERTY_AUTOHSCROLL );
1253 12 : 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 12 : aPropName = GetPropertyName( BASEPROPERTY_AUTOVSCROLL );
1263 12 : 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 12 : aPropName = GetPropertyName( BASEPROPERTY_NOLABEL );
1274 12 : 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 12 : aPropName = GetPropertyName( BASEPROPERTY_ALIGN );
1285 12 : if ( xInfo->hasPropertyByName( aPropName ) )
1286 : {
1287 12 : aVal = xPSet->getPropertyValue( aPropName );
1288 12 : sal_Int16 n = sal_Int16();
1289 12 : if ( aVal >>= n )
1290 : {
1291 12 : if ( n == PROPERTY_ALIGN_LEFT )
1292 6 : aDescr.WindowAttributes |= VclWindowPeerAttribute::LEFT;
1293 6 : else if ( n == PROPERTY_ALIGN_CENTER )
1294 6 : aDescr.WindowAttributes |= VclWindowPeerAttribute::CENTER;
1295 : else
1296 0 : aDescr.WindowAttributes |= VclWindowPeerAttribute::RIGHT;
1297 : }
1298 : }
1299 :
1300 : // Allow derivates to manipulate attributes
1301 12 : PrepareWindowDescriptor(aDescr);
1302 :
1303 : // create the peer
1304 12 : 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 12 : UnoControlComponentInfos aComponentInfos(maComponentInfos);
1316 12 : sal_Bool bDesignMode(mbDesignMode);
1317 :
1318 12 : Reference< XGraphics > xGraphics( mxGraphics );
1319 12 : Reference< XView > xView ( getPeer(), UNO_QUERY_THROW );
1320 12 : Reference< XWindow > xWindow ( getPeer(), UNO_QUERY_THROW );
1321 :
1322 12 : 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 12 : updateFromModel();
1329 :
1330 12 : xView->setZoom( aComponentInfos.nZoomX, aComponentInfos.nZoomY );
1331 :
1332 12 : setPosSize( aComponentInfos.nX, aComponentInfos.nY, aComponentInfos.nWidth, aComponentInfos.nHeight, aComponentInfos.nFlags );
1333 :
1334 12 : if( aComponentInfos.bVisible && !bDesignMode )
1335 : // Show only after setting the data
1336 10 : xWindow->setVisible( aComponentInfos.bVisible );
1337 :
1338 12 : if( !aComponentInfos.bEnable )
1339 0 : xWindow->setEnable( aComponentInfos.bEnable );
1340 :
1341 12 : xView->setGraphics( xGraphics );
1342 :
1343 12 : peerCreated();
1344 :
1345 12 : mbCreatingPeer = sal_False;
1346 12 : }
1347 12 : }
1348 :
1349 1018 : Reference< XWindowPeer > UnoControl::getPeer() throw(RuntimeException)
1350 : {
1351 1018 : ::osl::MutexGuard aGuard( GetMutex() );
1352 1018 : return mxPeer;
1353 : }
1354 :
1355 164 : sal_Bool UnoControl::setModel( const Reference< XControlModel >& rxModel ) throw(RuntimeException)
1356 : {
1357 164 : ::osl::MutexGuard aGuard( GetMutex() );
1358 :
1359 164 : Reference< XMultiPropertySet > xPropSet( mxModel, UNO_QUERY );
1360 :
1361 : // query for the XPropertiesChangeListener - our delegator is allowed to overwrite this interface
1362 164 : Reference< XPropertiesChangeListener > xListener;
1363 164 : queryInterface( ::getCppuType( &xListener ) ) >>= xListener;
1364 :
1365 164 : if( xPropSet.is() )
1366 65 : xPropSet->removePropertiesChangeListener( xListener );
1367 :
1368 164 : mpData->bLocalizationSupport = false;
1369 164 : mxModel = rxModel;
1370 :
1371 164 : if( mxModel.is() )
1372 : {
1373 : try
1374 : {
1375 99 : xPropSet.set( mxModel, UNO_QUERY_THROW );
1376 99 : Reference< XPropertySetInfo > xPSI( xPropSet->getPropertySetInfo(), UNO_SET_THROW );
1377 :
1378 99 : Sequence< ::rtl::OUString> aNames = lcl_ImplGetPropertyNames( xPropSet );
1379 99 : xPropSet->addPropertiesChangeListener( aNames, xListener );
1380 :
1381 99 : 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 164 : return mxModel.is();
1391 : }
1392 :
1393 154 : Reference< XControlModel > UnoControl::getModel( ) throw(RuntimeException)
1394 : {
1395 154 : return mxModel;
1396 : }
1397 :
1398 0 : Reference< XView > UnoControl::getView( ) throw(RuntimeException)
1399 : {
1400 0 : return static_cast< XView* >( this );
1401 : }
1402 :
1403 12 : void UnoControl::setDesignMode( sal_Bool bOn ) throw(RuntimeException)
1404 : {
1405 12 : ModeChangeEvent aModeChangeEvent;
1406 :
1407 12 : Reference< XWindow > xWindow;
1408 : {
1409 12 : ::osl::MutexGuard aGuard( GetMutex() );
1410 12 : if ( bOn == mbDesignMode )
1411 12 : return;
1412 :
1413 : // remember this
1414 2 : mbDesignMode = bOn;
1415 2 : 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 2 : disposeAccessibleContext();
1420 :
1421 2 : aModeChangeEvent.Source = *this;
1422 2 : aModeChangeEvent.NewMode = mbDesignMode ? ::rtl::OUString("design") : ::rtl::OUString("alive" );
1423 : }
1424 :
1425 : // ajust the visibility of our window
1426 2 : if ( xWindow.is() )
1427 0 : xWindow->setVisible( !bOn );
1428 :
1429 : // and notify our mode listeners
1430 2 : maModeChangeListeners.notifyEach( &XModeChangeListener::modeChanged, aModeChangeEvent );
1431 : }
1432 :
1433 78 : sal_Bool UnoControl::isDesignMode( ) throw(RuntimeException)
1434 : {
1435 78 : 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 12 : void SAL_CALL UnoControl::addModeChangeListener( const Reference< XModeChangeListener >& _rxListener ) throw (RuntimeException)
1507 : {
1508 12 : ::osl::MutexGuard aGuard( GetMutex() );
1509 12 : maModeChangeListeners.addInterface( _rxListener );
1510 12 : }
1511 :
1512 8 : void SAL_CALL UnoControl::removeModeChangeListener( const Reference< XModeChangeListener >& _rxListener ) throw (RuntimeException)
1513 : {
1514 8 : ::osl::MutexGuard aGuard( GetMutex() );
1515 8 : maModeChangeListeners.removeInterface( _rxListener );
1516 8 : }
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: */
|