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