Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / toolkit / source / controls / unocontrol.cxx
blob011aa72e08df2c112e57cc59c542fdcf0dcde8da
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <com/sun/star/awt/XControlContainer.hpp>
23 #include <com/sun/star/awt/WindowAttribute.hpp>
24 #include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
25 #include <com/sun/star/awt/PosSize.hpp>
26 #include <com/sun/star/beans/PropertyValue.hpp>
27 #include <com/sun/star/lang/NoSupportException.hpp>
28 #include <com/sun/star/resource/XStringResourceResolver.hpp>
29 #include <toolkit/controls/unocontrol.hxx>
30 #include <toolkit/helper/vclunohelper.hxx>
31 #include <cppuhelper/supportsservice.hxx>
32 #include <cppuhelper/typeprovider.hxx>
33 #include <rtl/uuid.h>
34 #include <osl/mutex.hxx>
35 #include <tools/date.hxx>
36 #include <tools/debug.hxx>
37 #include <tools/diagnose_ex.h>
38 #include <vcl/svapp.hxx>
39 #include <vcl/wrkwin.hxx>
40 #include <toolkit/helper/property.hxx>
41 #include <toolkit/helper/servicenames.hxx>
42 #include <toolkit/awt/vclxwindow.hxx>
43 #include <toolkit/controls/accessiblecontrolcontext.hxx>
45 #include <algorithm>
46 #include <map>
47 #include <set>
48 #include <vector>
50 using namespace ::com::sun::star;
51 using namespace ::com::sun::star::uno;
52 using namespace ::com::sun::star::awt;
53 using namespace ::com::sun::star::beans;
54 using namespace ::com::sun::star::lang;
55 using namespace ::com::sun::star::util;
57 using ::com::sun::star::accessibility::XAccessibleContext;
58 using ::com::sun::star::accessibility::XAccessible;
60 struct LanguageDependentProp
62 const char* pPropName;
63 sal_Int32 nPropNameLength;
66 static const LanguageDependentProp aLanguageDependentProp[] =
68 { "Text", 4 },
69 { "Label", 5 },
70 { "Title", 5 },
71 { "HelpText", 8 },
72 { "CurrencySymbol", 14 },
73 { "StringItemList", 14 },
74 { nullptr, 0 }
77 static Sequence< OUString> lcl_ImplGetPropertyNames( const Reference< XMultiPropertySet > & rxModel )
79 Sequence< OUString> aNames;
80 Reference< XPropertySetInfo > xPSInf = rxModel->getPropertySetInfo();
81 DBG_ASSERT( xPSInf.is(), "UpdateFromModel: No PropertySetInfo!" );
82 if ( xPSInf.is() )
84 Sequence< Property> aProps = xPSInf->getProperties();
85 sal_Int32 nLen = aProps.getLength();
86 aNames = Sequence< OUString>( nLen );
87 OUString* pNames = aNames.getArray();
88 const Property* pProps = aProps.getConstArray();
89 for ( sal_Int32 n = 0; n < nLen; ++n, ++pProps, ++pNames)
90 *pNames = pProps->Name;
92 return aNames;
96 class VclListenerLock
98 private:
99 VCLXWindow* m_pLockWindow;
101 public:
102 explicit VclListenerLock( VCLXWindow* _pLockWindow )
103 : m_pLockWindow( _pLockWindow )
105 if ( m_pLockWindow )
106 m_pLockWindow->suspendVclEventListening( );
108 ~VclListenerLock()
110 if ( m_pLockWindow )
111 m_pLockWindow->resumeVclEventListening( );
113 VclListenerLock(const VclListenerLock&) = delete;
114 VclListenerLock& operator=(const VclListenerLock&) = delete;
117 typedef ::std::map< OUString, sal_Int32 > MapString2Int;
118 struct UnoControl_Data
120 MapString2Int aSuspendedPropertyNotifications;
121 /// true if and only if our model has a property ResourceResolver
122 bool bLocalizationSupport;
124 UnoControl_Data()
125 :aSuspendedPropertyNotifications()
126 ,bLocalizationSupport( false )
131 UnoControl::UnoControl() :
132 maDisposeListeners( *this )
133 , maWindowListeners( *this )
134 , maFocusListeners( *this )
135 , maKeyListeners( *this )
136 , maMouseListeners( *this )
137 , maMouseMotionListeners( *this )
138 , maPaintListeners( *this )
139 , maModeChangeListeners( GetMutex() )
140 , mpData( new UnoControl_Data )
142 mbDisposePeer = true;
143 mbRefeshingPeer = false;
144 mbCreatingPeer = false;
145 mbCreatingCompatiblePeer = false;
146 mbDesignMode = false;
149 UnoControl::~UnoControl()
153 OUString UnoControl::GetComponentServiceName()
155 return OUString();
158 Reference< XWindowPeer > UnoControl::ImplGetCompatiblePeer()
160 DBG_ASSERT( !mbCreatingCompatiblePeer, "ImplGetCompatiblePeer - rekursive?" );
162 mbCreatingCompatiblePeer = true;
164 Reference< XWindowPeer > xCompatiblePeer = getPeer();
166 if ( !xCompatiblePeer.is() )
168 // Create the pair as invisible
169 bool bVis = maComponentInfos.bVisible;
170 if( bVis )
171 maComponentInfos.bVisible = false;
173 Reference< XWindowPeer > xCurrentPeer = getPeer();
174 setPeer( nullptr );
176 // queryInterface ourself, to allow aggregation
177 Reference< XControl > xMe;
178 OWeakAggObject::queryInterface( cppu::UnoType<decltype(xMe)>::get() ) >>= xMe;
180 vcl::Window* pParentWindow( nullptr );
182 SolarMutexGuard aGuard;
183 pParentWindow = dynamic_cast< vcl::Window* >( Application::GetDefaultDevice() );
184 ENSURE_OR_THROW( pParentWindow != nullptr, "could obtain a default parent window!" );
188 xMe->createPeer( nullptr, pParentWindow->GetComponentInterface() );
190 catch( const Exception& )
192 mbCreatingCompatiblePeer = false;
193 throw;
195 xCompatiblePeer = getPeer();
196 setPeer( xCurrentPeer );
198 if ( xCompatiblePeer.is() && mxGraphics.is() )
200 Reference< XView > xPeerView( xCompatiblePeer, UNO_QUERY );
201 if ( xPeerView.is() )
202 xPeerView->setGraphics( mxGraphics );
205 if( bVis )
206 maComponentInfos.bVisible = true;
209 mbCreatingCompatiblePeer = false;
211 return xCompatiblePeer;
214 bool UnoControl::ImplCheckLocalize( OUString& _rPossiblyLocalizable )
216 if ( !mpData->bLocalizationSupport
217 || ( _rPossiblyLocalizable.isEmpty() )
218 || ( _rPossiblyLocalizable[0] != '&' )
219 // TODO: make this reasonable. At the moment, everything which by accident starts with a & is considered
220 // localizable, which is probably wrong.
222 return false;
226 Reference< XPropertySet > xPropSet( mxModel, UNO_QUERY_THROW );
227 Reference< resource::XStringResourceResolver > xStringResourceResolver(
228 xPropSet->getPropertyValue("ResourceResolver"),
229 UNO_QUERY
231 if ( xStringResourceResolver.is() )
233 OUString aLocalizationKey( _rPossiblyLocalizable.copy( 1 ) );
234 _rPossiblyLocalizable = xStringResourceResolver->resolveString( aLocalizationKey );
235 return true;
238 catch( const Exception& )
240 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
242 return false;
245 void UnoControl::ImplSetPeerProperty( const OUString& rPropName, const Any& rVal )
247 // since a change made in propertiesChange, we can't be sure that this is called with an valid getPeer(),
248 // this assumption may be false in some (seldom) multi-threading scenarios (cause propertiesChange
249 // releases our mutex before calling here in)
250 // That's why this additional check
252 if ( mxVclWindowPeer.is() )
254 Any aConvertedValue( rVal );
256 if ( mpData->bLocalizationSupport )
258 // We now support a mapping for language dependent properties. This is the
259 // central method to implement it.
260 if( rPropName == "Text" ||
261 rPropName == "Label" ||
262 rPropName == "Title" ||
263 rPropName == "HelpText" ||
264 rPropName == "CurrencySymbol" ||
265 rPropName == "StringItemList" )
267 OUString aValue;
268 uno::Sequence< OUString > aSeqValue;
269 if ( aConvertedValue >>= aValue )
271 if ( ImplCheckLocalize( aValue ) )
272 aConvertedValue <<= aValue;
274 else if ( aConvertedValue >>= aSeqValue )
276 for ( sal_Int32 i = 0; i < aSeqValue.getLength(); i++ )
277 ImplCheckLocalize( aSeqValue[i] );
278 aConvertedValue <<= aSeqValue;
283 mxVclWindowPeer->setProperty( rPropName, aConvertedValue );
287 void UnoControl::PrepareWindowDescriptor( WindowDescriptor& )
291 Reference< XWindow > UnoControl::getParentPeer() const
293 Reference< XWindow > xPeer;
294 if( mxContext.is() )
296 Reference< XControl > xContComp( mxContext, UNO_QUERY );
297 if ( xContComp.is() )
299 Reference< XWindowPeer > xP = xContComp->getPeer();
300 if ( xP.is() )
301 xPeer.set( xP, UNO_QUERY );
304 return xPeer;
307 void UnoControl::updateFromModel()
309 // Read default properties and hand over to peer
310 if( getPeer().is() )
312 Reference< XMultiPropertySet > xPropSet( mxModel, UNO_QUERY );
313 if( xPropSet.is() )
315 Sequence< OUString> aNames = lcl_ImplGetPropertyNames( xPropSet );
316 xPropSet->firePropertiesChangeEvent( aNames, this );
322 // XTypeProvider
323 IMPL_IMPLEMENTATION_ID( UnoControl )
325 void
326 UnoControl::DisposeAccessibleContext(Reference<XComponent> const& xContextComp)
328 if (xContextComp.is())
332 xContextComp->removeEventListener( this );
333 xContextComp->dispose();
335 catch( const Exception& )
337 OSL_FAIL( "UnoControl::disposeAccessibleContext: could not dispose my AccessibleContext!" );
342 void UnoControl::dispose( )
344 Reference< XWindowPeer > xPeer;
345 Reference<XComponent> xAccessibleComp;
347 ::osl::MutexGuard aGuard( GetMutex() );
348 if( mbDisposePeer )
350 xPeer = mxPeer;
352 setPeer( nullptr );
353 xAccessibleComp.set(maAccessibleContext, UNO_QUERY);
354 maAccessibleContext.clear();
356 if( xPeer.is() )
358 xPeer->dispose();
361 // dispose our AccessibleContext - without Mutex locked
362 DisposeAccessibleContext(xAccessibleComp);
364 EventObject aDisposeEvent;
365 aDisposeEvent.Source = static_cast< XAggregation* >( this );
367 maDisposeListeners.disposeAndClear( aDisposeEvent );
368 maWindowListeners.disposeAndClear( aDisposeEvent );
369 maFocusListeners.disposeAndClear( aDisposeEvent );
370 maKeyListeners.disposeAndClear( aDisposeEvent );
371 maMouseListeners.disposeAndClear( aDisposeEvent );
372 maMouseMotionListeners.disposeAndClear( aDisposeEvent );
373 maPaintListeners.disposeAndClear( aDisposeEvent );
374 maModeChangeListeners.disposeAndClear( aDisposeEvent );
376 // release Model again
377 setModel( Reference< XControlModel > () );
378 setContext( Reference< XInterface > () );
381 void UnoControl::addEventListener( const Reference< XEventListener >& rxListener )
383 ::osl::MutexGuard aGuard( GetMutex() );
385 maDisposeListeners.addInterface( rxListener );
388 void UnoControl::removeEventListener( const Reference< XEventListener >& rxListener )
390 ::osl::MutexGuard aGuard( GetMutex() );
392 maDisposeListeners.removeInterface( rxListener );
395 bool UnoControl::requiresNewPeer( const OUString& /* _rPropertyName */ ) const
397 return false;
400 // XPropertiesChangeListener
401 void UnoControl::propertiesChange( const Sequence< PropertyChangeEvent >& rEvents )
403 Sequence< PropertyChangeEvent > aEvents( rEvents );
405 ::osl::MutexGuard aGuard( GetMutex() );
407 if ( !mpData->aSuspendedPropertyNotifications.empty() )
409 // strip the property which we are currently updating (somewhere up the stack)
410 PropertyChangeEvent* pEvents = aEvents.getArray();
411 PropertyChangeEvent* pEventsEnd = pEvents + aEvents.getLength();
412 for ( ; pEvents < pEventsEnd; )
413 if ( mpData->aSuspendedPropertyNotifications.find( pEvents->PropertyName ) != mpData->aSuspendedPropertyNotifications.end() )
415 if ( pEvents != pEventsEnd )
416 ::std::copy( pEvents + 1, pEventsEnd, pEvents );
417 --pEventsEnd;
419 else
420 ++pEvents;
421 aEvents.realloc( pEventsEnd - aEvents.getConstArray() );
423 if ( !aEvents.getLength() )
424 return;
428 ImplModelPropertiesChanged( aEvents );
431 void UnoControl::ImplLockPropertyChangeNotification( const OUString& rPropertyName, bool bLock )
433 MapString2Int::iterator pos = mpData->aSuspendedPropertyNotifications.find( rPropertyName );
434 if ( bLock )
436 if ( pos == mpData->aSuspendedPropertyNotifications.end() )
437 pos = mpData->aSuspendedPropertyNotifications.emplace( rPropertyName, 0 ).first;
438 ++pos->second;
440 else
442 OSL_ENSURE( pos != mpData->aSuspendedPropertyNotifications.end(), "UnoControl::ImplLockPropertyChangeNotification: property not locked!" );
443 if ( pos != mpData->aSuspendedPropertyNotifications.end() )
445 OSL_ENSURE( pos->second > 0, "UnoControl::ImplLockPropertyChangeNotification: invalid suspension counter!" );
446 if ( 0 == --pos->second )
447 mpData->aSuspendedPropertyNotifications.erase( pos );
452 void UnoControl::ImplLockPropertyChangeNotifications( const Sequence< OUString >& rPropertyNames, bool bLock )
454 for ( auto const & propertyName : rPropertyNames )
455 ImplLockPropertyChangeNotification( propertyName, bLock );
458 void UnoControl::ImplModelPropertiesChanged( const Sequence< PropertyChangeEvent >& rEvents )
460 ::osl::ClearableGuard< ::osl::Mutex > aGuard( GetMutex() );
462 if( !getPeer().is() )
463 return;
465 std::vector< PropertyValue > aPeerPropertiesToSet;
466 sal_Int32 nIndependentPos = 0;
467 bool bResourceResolverSet( false );
468 // position where to insert the independent properties into aPeerPropertiesToSet,
469 // dependent ones are inserted at the end of the vector
471 bool bNeedNewPeer = false;
472 // some properties require a re-creation of the peer, 'cause they can't be changed on the fly
474 Reference< XControlModel > xOwnModel( getModel(), UNO_QUERY );
475 // our own model for comparison
476 Reference< XPropertySet > xPS( xOwnModel, UNO_QUERY );
477 Reference< XPropertySetInfo > xPSI( xPS->getPropertySetInfo(), UNO_QUERY );
478 OSL_ENSURE( xPSI.is(), "UnoControl::ImplModelPropertiesChanged: should have property set meta data!" );
480 const PropertyChangeEvent* pEvents = rEvents.getConstArray();
482 sal_Int32 nLen = rEvents.getLength();
483 aPeerPropertiesToSet.reserve(nLen);
485 for( sal_Int32 i = 0; i < nLen; ++i, ++pEvents )
487 Reference< XControlModel > xModel( pEvents->Source, UNO_QUERY );
488 bool bOwnModel = xModel.get() == xOwnModel.get();
489 if ( !bOwnModel )
490 continue;
492 // Detect changes on our resource resolver which invalidates
493 // automatically some language dependent properties.
494 if ( pEvents->PropertyName == "ResourceResolver" )
496 Reference< resource::XStringResourceResolver > xStrResolver;
497 if ( pEvents->NewValue >>= xStrResolver )
498 bResourceResolverSet = xStrResolver.is();
501 sal_uInt16 nPType = GetPropertyId( pEvents->PropertyName );
502 if ( mbDesignMode && mbDisposePeer && !mbRefeshingPeer && !mbCreatingPeer )
504 // if we're in design mode, then some properties can change which
505 // require creating a *new* peer (since these properties cannot
506 // be switched at existing peers)
507 if ( nPType )
508 bNeedNewPeer = ( nPType == BASEPROPERTY_BORDER )
509 || ( nPType == BASEPROPERTY_MULTILINE )
510 || ( nPType == BASEPROPERTY_DROPDOWN )
511 || ( nPType == BASEPROPERTY_HSCROLL )
512 || ( nPType == BASEPROPERTY_VSCROLL )
513 || ( nPType == BASEPROPERTY_AUTOHSCROLL )
514 || ( nPType == BASEPROPERTY_AUTOVSCROLL )
515 || ( nPType == BASEPROPERTY_ORIENTATION )
516 || ( nPType == BASEPROPERTY_SPIN )
517 || ( nPType == BASEPROPERTY_ALIGN )
518 || ( nPType == BASEPROPERTY_PAINTTRANSPARENT );
519 else
520 bNeedNewPeer = requiresNewPeer( pEvents->PropertyName );
522 if ( bNeedNewPeer )
523 break;
526 if ( nPType && ( nLen > 1 ) && DoesDependOnOthers( nPType ) )
528 // Add properties with dependencies on other properties last
529 // since they're dependent on properties added later (such as
530 // VALUE dependency on VALUEMIN/MAX)
531 aPeerPropertiesToSet.emplace_back(pEvents->PropertyName, 0, pEvents->NewValue, PropertyState_DIRECT_VALUE);
533 else
535 if ( bResourceResolverSet )
537 // The resource resolver property change should be one of the first ones.
538 // All language dependent properties are dependent on this property.
539 // As BASEPROPERTY_NATIVE_WIDGET_LOOK is not dependent on resource
540 // resolver. We don't need to handle a special order for these two props.
541 aPeerPropertiesToSet.insert(
542 aPeerPropertiesToSet.begin(),
543 PropertyValue( pEvents->PropertyName, 0, pEvents->NewValue, PropertyState_DIRECT_VALUE ) );
544 ++nIndependentPos;
546 else if ( nPType == BASEPROPERTY_NATIVE_WIDGET_LOOK )
548 // since *a lot* of other properties might be overruled by this one, we need
549 // a special handling:
550 // NativeWidgetLook needs to be set first: If it is set to ON, all other
551 // properties describing the look (e.g. BackgroundColor) are ignored, anyway.
552 // If it is switched OFF, then we need to do it first because else it will
553 // overrule other look-related properties, and re-initialize them from system
554 // defaults.
555 aPeerPropertiesToSet.insert(
556 aPeerPropertiesToSet.begin(),
557 PropertyValue( pEvents->PropertyName, 0, pEvents->NewValue, PropertyState_DIRECT_VALUE ) );
558 ++nIndependentPos;
560 else
562 aPeerPropertiesToSet.insert(aPeerPropertiesToSet.begin() + nIndependentPos,
563 PropertyValue(pEvents->PropertyName, 0, pEvents->NewValue, PropertyState_DIRECT_VALUE));
564 ++nIndependentPos;
569 Reference< XWindow > xParent = getParentPeer();
570 Reference< XControl > xThis( static_cast<XAggregation*>(static_cast<cppu::OWeakAggObject*>(this)), UNO_QUERY );
571 // call createPeer via a interface got from queryInterface, so the aggregating class can intercept it
573 DBG_ASSERT( !bNeedNewPeer || xParent.is(), "Need new peer, but don't have a parent!" );
575 // Check if we have to update language dependent properties
576 if ( !bNeedNewPeer && bResourceResolverSet )
578 // Add language dependent properties into the peer property set.
579 // Our resource resolver has been changed and we must be sure
580 // that language dependent props use the new resolver.
581 const LanguageDependentProp* pLangDepProp = aLanguageDependentProp;
582 while ( pLangDepProp->pPropName != nullptr )
584 bool bMustBeInserted( true );
585 for (PropertyValue & i : aPeerPropertiesToSet)
587 if ( i.Name.equalsAsciiL(
588 pLangDepProp->pPropName, pLangDepProp->nPropNameLength ))
590 bMustBeInserted = false;
591 break;
595 if ( bMustBeInserted )
597 // Add language dependent props at the end
598 OUString aPropName( OUString::createFromAscii( pLangDepProp->pPropName ));
599 if ( xPSI.is() && xPSI->hasPropertyByName( aPropName ) )
601 aPeerPropertiesToSet.emplace_back( aPropName, 0, xPS->getPropertyValue( aPropName ), PropertyState_DIRECT_VALUE );
605 ++pLangDepProp;
608 aGuard.clear();
610 // clear the guard before creating a new peer - as usual, our peer implementations use the SolarMutex
612 if (bNeedNewPeer && xParent.is())
614 SolarMutexGuard aVclGuard;
615 // and now this is the final withdrawal:
616 // I have no other idea than locking the SolarMutex here....
617 // I really hate the fact that VCL is not threadsafe....
619 // Doesn't work for Container!
620 getPeer()->dispose();
621 mxPeer.clear();
622 mxVclWindowPeer = nullptr;
623 mbRefeshingPeer = true;
624 Reference< XWindowPeer > xP( xParent, UNO_QUERY );
625 xThis->createPeer( Reference< XToolkit > (), xP );
626 mbRefeshingPeer = false;
627 aPeerPropertiesToSet.clear();
630 // lock the multiplexing of VCL events to our UNO listeners
631 // this is for compatibility reasons: in OOo 1.0.x, changes which were done at the
632 // model did not cause the listeners of the controls/peers to be called
633 // Since the implementations for the listeners changed a lot towards 1.1, this
634 // would not be the case anymore, if we would not do this listener-lock below
635 // #i14703#
636 VCLXWindow* pPeer;
638 SolarMutexGuard g;
639 VclPtr<vcl::Window> pVclPeer = VCLUnoHelper::GetWindow( getPeer() );
640 pPeer = pVclPeer ? pVclPeer->GetWindowPeer() : nullptr;
642 VclListenerLock aNoVclEventMultiplexing( pPeer );
644 // setting peer properties may result in an attempt to acquire the solar mutex, 'cause the peers
645 // usually don't have an own mutex but use the SolarMutex instead.
646 // To prevent deadlocks resulting from this, we do this without our own mutex locked
647 std::vector< PropertyValue >::iterator aEnd = aPeerPropertiesToSet.end();
648 for ( std::vector< PropertyValue >::iterator aLoop = aPeerPropertiesToSet.begin();
649 aLoop != aEnd;
650 ++aLoop
653 ImplSetPeerProperty( aLoop->Name, aLoop->Value );
658 void UnoControl::disposing( const EventObject& rEvt )
660 ::osl::ClearableMutexGuard aGuard( GetMutex() );
661 // do not compare differing types in case of multiple inheritance
663 if ( maAccessibleContext.get() == rEvt.Source )
665 // just in case the context is disposed, but not released - ensure that we do not re-use it in the future
666 maAccessibleContext = nullptr;
668 else if( mxModel.get() == Reference< XControlModel >(rEvt.Source,UNO_QUERY).get() )
670 // #62337# if the model dies, it does not make sense for us to live ...
671 Reference< XControl > xThis = this;
673 aGuard.clear();
674 xThis->dispose();
676 DBG_ASSERT( !mxModel.is(), "UnoControl::disposing: invalid dispose behaviour!" );
677 mxModel.clear();
682 void SAL_CALL UnoControl::setOutputSize( const awt::Size& aSize )
684 Reference< XWindow2 > xPeerWindow;
686 ::osl::MutexGuard aGuard( GetMutex() );
687 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
690 if ( xPeerWindow.is() )
691 xPeerWindow->setOutputSize( aSize );
694 namespace
696 template < typename RETVALTYPE, typename DEFAULTTYPE >
697 RETVALTYPE lcl_askPeer( const uno::Reference< awt::XWindowPeer >& _rxPeer, RETVALTYPE (SAL_CALL XWindow2::*_pMethod)(), DEFAULTTYPE _aDefault )
699 RETVALTYPE aReturn( _aDefault );
701 Reference< XWindow2 > xPeerWindow( _rxPeer, UNO_QUERY );
702 if ( xPeerWindow.is() )
703 aReturn = (xPeerWindow.get()->*_pMethod)();
705 return aReturn;
709 awt::Size SAL_CALL UnoControl::getOutputSize( )
711 return lcl_askPeer( getPeer(), &XWindow2::getOutputSize, awt::Size() );
714 sal_Bool SAL_CALL UnoControl::isVisible( )
716 return lcl_askPeer( getPeer(), &XWindow2::isVisible, maComponentInfos.bVisible );
719 sal_Bool SAL_CALL UnoControl::isActive( )
721 return lcl_askPeer( getPeer(), &XWindow2::isActive, false );
724 sal_Bool SAL_CALL UnoControl::isEnabled( )
726 return lcl_askPeer( getPeer(), &XWindow2::isEnabled, maComponentInfos.bEnable );
729 sal_Bool SAL_CALL UnoControl::hasFocus( )
731 return lcl_askPeer( getPeer(), &XWindow2::hasFocus, false );
734 // XWindow
735 void UnoControl::setPosSize( sal_Int32 X, sal_Int32 Y, sal_Int32 Width, sal_Int32 Height, sal_Int16 Flags )
737 Reference< XWindow > xWindow;
739 ::osl::MutexGuard aGuard( GetMutex() );
741 if ( Flags & awt::PosSize::X )
742 maComponentInfos.nX = X;
743 if ( Flags & awt::PosSize::Y )
744 maComponentInfos.nY = Y;
745 if ( Flags & awt::PosSize::WIDTH )
746 maComponentInfos.nWidth = Width;
747 if ( Flags & awt::PosSize::HEIGHT )
748 maComponentInfos.nHeight = Height;
749 maComponentInfos.nFlags |= Flags;
751 xWindow.set(getPeer(), css::uno::UNO_QUERY);
754 if( xWindow.is() )
755 xWindow->setPosSize( X, Y, Width, Height, Flags );
758 awt::Rectangle UnoControl::getPosSize( )
760 awt::Rectangle aRect( maComponentInfos.nX, maComponentInfos.nY, maComponentInfos.nWidth, maComponentInfos.nHeight);
761 Reference< XWindow > xWindow;
764 ::osl::MutexGuard aGuard( GetMutex() );
765 xWindow.set(getPeer(), css::uno::UNO_QUERY);
768 if( xWindow.is() )
769 aRect = xWindow->getPosSize();
770 return aRect;
773 void UnoControl::setVisible( sal_Bool bVisible )
775 Reference< XWindow > xWindow;
777 ::osl::MutexGuard aGuard( GetMutex() );
779 // Visible status is handled by View
780 maComponentInfos.bVisible = bVisible;
781 xWindow.set(getPeer(), css::uno::UNO_QUERY);
783 if ( xWindow.is() )
784 xWindow->setVisible( bVisible );
787 void UnoControl::setEnable( sal_Bool bEnable )
789 Reference< XWindow > xWindow;
791 ::osl::MutexGuard aGuard( GetMutex() );
793 // Enable status is handled by View
794 maComponentInfos.bEnable = bEnable;
795 xWindow.set(getPeer(), css::uno::UNO_QUERY);
797 if ( xWindow.is() )
798 xWindow->setEnable( bEnable );
801 void UnoControl::setFocus( )
803 Reference< XWindow > xWindow;
805 ::osl::MutexGuard aGuard( GetMutex() );
806 xWindow.set(getPeer(), css::uno::UNO_QUERY);
808 if ( xWindow.is() )
809 xWindow->setFocus();
812 void UnoControl::addWindowListener( const Reference< XWindowListener >& rxListener )
814 Reference< XWindow > xPeerWindow;
816 ::osl::MutexGuard aGuard( GetMutex() );
817 maWindowListeners.addInterface( rxListener );
818 if ( maWindowListeners.getLength() == 1 )
819 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
821 if ( xPeerWindow.is() )
822 xPeerWindow->addWindowListener( &maWindowListeners );
825 void UnoControl::removeWindowListener( const Reference< XWindowListener >& rxListener )
827 Reference< XWindow > xPeerWindow;
829 ::osl::MutexGuard aGuard( GetMutex() );
830 if ( maWindowListeners.getLength() == 1 )
831 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
832 maWindowListeners.removeInterface( rxListener );
834 if ( xPeerWindow.is() )
835 xPeerWindow->removeWindowListener( &maWindowListeners );
838 void UnoControl::addFocusListener( const Reference< XFocusListener >& rxListener )
840 Reference< XWindow > xPeerWindow;
842 ::osl::MutexGuard aGuard( GetMutex() );
843 maFocusListeners.addInterface( rxListener );
844 if ( maFocusListeners.getLength() == 1 )
845 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
847 if ( xPeerWindow.is() )
848 xPeerWindow->addFocusListener( &maFocusListeners );
851 void UnoControl::removeFocusListener( const Reference< XFocusListener >& rxListener )
853 Reference< XWindow > xPeerWindow;
855 ::osl::MutexGuard aGuard( GetMutex() );
856 if ( maFocusListeners.getLength() == 1 )
857 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
858 maFocusListeners.removeInterface( rxListener );
860 if ( xPeerWindow.is() )
861 xPeerWindow->removeFocusListener( &maFocusListeners );
864 void UnoControl::addKeyListener( const Reference< XKeyListener >& rxListener )
866 Reference< XWindow > xPeerWindow;
868 ::osl::MutexGuard aGuard( GetMutex() );
869 maKeyListeners.addInterface( rxListener );
870 if ( maKeyListeners.getLength() == 1 )
871 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
873 if ( xPeerWindow.is() )
874 xPeerWindow->addKeyListener( &maKeyListeners);
877 void UnoControl::removeKeyListener( const Reference< XKeyListener >& rxListener )
879 Reference< XWindow > xPeerWindow;
881 ::osl::MutexGuard aGuard( GetMutex() );
882 if ( maKeyListeners.getLength() == 1 )
883 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
884 maKeyListeners.removeInterface( rxListener );
886 if ( xPeerWindow.is() )
887 xPeerWindow->removeKeyListener( &maKeyListeners);
890 void UnoControl::addMouseListener( const Reference< XMouseListener >& rxListener )
892 Reference< XWindow > xPeerWindow;
894 ::osl::MutexGuard aGuard( GetMutex() );
895 maMouseListeners.addInterface( rxListener );
896 if ( maMouseListeners.getLength() == 1 )
897 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
899 if ( xPeerWindow.is() )
900 xPeerWindow->addMouseListener( &maMouseListeners);
903 void UnoControl::removeMouseListener( const Reference< XMouseListener >& rxListener )
905 Reference< XWindow > xPeerWindow;
907 ::osl::MutexGuard aGuard( GetMutex() );
908 if ( maMouseListeners.getLength() == 1 )
909 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
910 maMouseListeners.removeInterface( rxListener );
912 if ( xPeerWindow.is() )
913 xPeerWindow->removeMouseListener( &maMouseListeners );
916 void UnoControl::addMouseMotionListener( const Reference< XMouseMotionListener >& rxListener )
918 Reference< XWindow > xPeerWindow;
920 ::osl::MutexGuard aGuard( GetMutex() );
921 maMouseMotionListeners.addInterface( rxListener );
922 if ( maMouseMotionListeners.getLength() == 1 )
923 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
925 if ( xPeerWindow.is() )
926 xPeerWindow->addMouseMotionListener( &maMouseMotionListeners);
929 void UnoControl::removeMouseMotionListener( const Reference< XMouseMotionListener >& rxListener )
931 Reference< XWindow > xPeerWindow;
933 ::osl::MutexGuard aGuard( GetMutex() );
934 if ( maMouseMotionListeners.getLength() == 1 )
935 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
936 maMouseMotionListeners.removeInterface( rxListener );
938 if ( xPeerWindow.is() )
939 xPeerWindow->removeMouseMotionListener( &maMouseMotionListeners );
942 void UnoControl::addPaintListener( const Reference< XPaintListener >& rxListener )
944 Reference< XWindow > xPeerWindow;
946 ::osl::MutexGuard aGuard( GetMutex() );
947 maPaintListeners.addInterface( rxListener );
948 if ( maPaintListeners.getLength() == 1 )
949 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
951 if ( xPeerWindow.is() )
952 xPeerWindow->addPaintListener( &maPaintListeners);
955 void UnoControl::removePaintListener( const Reference< XPaintListener >& rxListener )
957 Reference< XWindow > xPeerWindow;
959 ::osl::MutexGuard aGuard( GetMutex() );
960 if ( maPaintListeners.getLength() == 1 )
961 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
962 maPaintListeners.removeInterface( rxListener );
964 if ( xPeerWindow.is() )
965 xPeerWindow->removePaintListener( &maPaintListeners );
968 // XView
969 sal_Bool UnoControl::setGraphics( const Reference< XGraphics >& rDevice )
971 Reference< XView > xView;
973 ::osl::MutexGuard aGuard( GetMutex() );
975 mxGraphics = rDevice;
976 xView.set(getPeer(), css::uno::UNO_QUERY);
978 return !xView.is() || xView->setGraphics( rDevice );
981 Reference< XGraphics > UnoControl::getGraphics( )
983 return mxGraphics;
986 awt::Size UnoControl::getSize( )
988 ::osl::MutexGuard aGuard( GetMutex() );
989 return awt::Size( maComponentInfos.nWidth, maComponentInfos.nHeight );
992 void UnoControl::draw( sal_Int32 x, sal_Int32 y )
994 Reference< XWindowPeer > xDrawPeer;
995 Reference< XView > xDrawPeerView;
997 bool bDisposeDrawPeer( false );
999 ::osl::MutexGuard aGuard( GetMutex() );
1001 xDrawPeer = ImplGetCompatiblePeer();
1002 bDisposeDrawPeer = xDrawPeer.is() && ( xDrawPeer != getPeer() );
1004 xDrawPeerView.set( xDrawPeer, UNO_QUERY );
1005 DBG_ASSERT( xDrawPeerView.is(), "UnoControl::draw: no peer!" );
1008 if ( xDrawPeerView.is() )
1010 Reference< XVclWindowPeer > xWindowPeer;
1011 xWindowPeer.set( xDrawPeer, UNO_QUERY );
1012 if ( xWindowPeer.is() )
1013 xWindowPeer->setDesignMode( mbDesignMode );
1014 xDrawPeerView->draw( x, y );
1017 if ( bDisposeDrawPeer )
1018 xDrawPeer->dispose();
1021 void UnoControl::setZoom( float fZoomX, float fZoomY )
1023 Reference< XView > xView;
1025 ::osl::MutexGuard aGuard( GetMutex() );
1027 maComponentInfos.nZoomX = fZoomX;
1028 maComponentInfos.nZoomY = fZoomY;
1030 xView.set(getPeer(), css::uno::UNO_QUERY);
1032 if ( xView.is() )
1033 xView->setZoom( fZoomX, fZoomY );
1036 // XControl
1037 void UnoControl::setContext( const Reference< XInterface >& rxContext )
1039 ::osl::MutexGuard aGuard( GetMutex() );
1041 mxContext = rxContext;
1044 Reference< XInterface > UnoControl::getContext( )
1046 ::osl::MutexGuard aGuard( GetMutex() );
1048 return mxContext;
1051 void UnoControl::peerCreated()
1053 Reference< XWindow > xWindow( getPeer(), UNO_QUERY );
1054 if ( !xWindow.is() )
1055 return;
1057 if ( maWindowListeners.getLength() )
1058 xWindow->addWindowListener( &maWindowListeners );
1060 if ( maFocusListeners.getLength() )
1061 xWindow->addFocusListener( &maFocusListeners );
1063 if ( maKeyListeners.getLength() )
1064 xWindow->addKeyListener( &maKeyListeners );
1066 if ( maMouseListeners.getLength() )
1067 xWindow->addMouseListener( &maMouseListeners );
1069 if ( maMouseMotionListeners.getLength() )
1070 xWindow->addMouseMotionListener( &maMouseMotionListeners );
1072 if ( maPaintListeners.getLength() )
1073 xWindow->addPaintListener( &maPaintListeners );
1076 void UnoControl::createPeer( const Reference< XToolkit >& rxToolkit, const Reference< XWindowPeer >& rParentPeer )
1078 ::osl::ClearableMutexGuard aGuard( GetMutex() );
1079 if ( !mxModel.is() )
1081 RuntimeException aException;
1082 aException.Message = "createPeer: no model!";
1083 aException.Context = static_cast<XAggregation*>(static_cast<cppu::OWeakAggObject*>(this));
1084 throw aException;
1087 if( getPeer().is() )
1088 return;
1090 mbCreatingPeer = true;
1092 WindowClass eType;
1093 Reference< XToolkit > xToolkit = rxToolkit;
1094 if( rParentPeer.is() && mxContext.is() )
1096 // no TopWindow
1097 if ( !xToolkit.is() )
1098 xToolkit = rParentPeer->getToolkit();
1099 Any aAny = OWeakAggObject::queryInterface( cppu::UnoType<XControlContainer>::get());
1100 Reference< XControlContainer > xC;
1101 aAny >>= xC;
1102 if( xC.is() )
1103 // It's a container
1104 eType = WindowClass_CONTAINER;
1105 else
1106 eType = WindowClass_SIMPLE;
1108 else
1109 { // This is only correct for Top Window
1110 if( rParentPeer.is() )
1112 if ( !xToolkit.is() )
1113 xToolkit = rParentPeer->getToolkit();
1114 eType = WindowClass_CONTAINER;
1116 else
1118 if ( !xToolkit.is() )
1119 xToolkit = VCLUnoHelper::CreateToolkit();
1120 eType = WindowClass_TOP;
1123 WindowDescriptor aDescr;
1124 aDescr.Type = eType;
1125 aDescr.WindowServiceName = GetComponentServiceName();
1126 aDescr.Parent = rParentPeer;
1127 aDescr.Bounds = getPosSize();
1128 aDescr.WindowAttributes = 0;
1130 // Border
1131 Reference< XPropertySet > xPSet( mxModel, UNO_QUERY );
1132 Reference< XPropertySetInfo > xInfo = xPSet->getPropertySetInfo();
1134 Any aVal;
1135 OUString aPropName = GetPropertyName( BASEPROPERTY_BORDER );
1136 if ( xInfo->hasPropertyByName( aPropName ) )
1138 aVal = xPSet->getPropertyValue( aPropName );
1139 sal_Int16 n = sal_Int16();
1140 if ( aVal >>= n )
1142 if ( n )
1143 aDescr.WindowAttributes |= WindowAttribute::BORDER;
1144 else
1145 aDescr.WindowAttributes |= VclWindowPeerAttribute::NOBORDER;
1149 // DESKTOP_AS_PARENT
1150 if ( aDescr.Type == WindowClass_TOP )
1152 aPropName = GetPropertyName( BASEPROPERTY_DESKTOP_AS_PARENT );
1153 if ( xInfo->hasPropertyByName( aPropName ) )
1155 aVal = xPSet->getPropertyValue( aPropName );
1156 bool b = bool();
1157 if ( ( aVal >>= b ) && b)
1158 aDescr.ParentIndex = -1;
1161 // Moveable
1162 aPropName = GetPropertyName( BASEPROPERTY_MOVEABLE );
1163 if ( xInfo->hasPropertyByName( aPropName ) )
1165 aVal = xPSet->getPropertyValue( aPropName );
1166 bool b = bool();
1167 if ( ( aVal >>= b ) && b)
1168 aDescr.WindowAttributes |= WindowAttribute::MOVEABLE;
1171 // Closeable
1172 aPropName = GetPropertyName( BASEPROPERTY_CLOSEABLE );
1173 if ( xInfo->hasPropertyByName( aPropName ) )
1175 aVal = xPSet->getPropertyValue( aPropName );
1176 bool b = bool();
1177 if ( ( aVal >>= b ) && b)
1178 aDescr.WindowAttributes |= WindowAttribute::CLOSEABLE;
1181 // Dropdown
1182 aPropName = GetPropertyName( BASEPROPERTY_DROPDOWN );
1183 if ( xInfo->hasPropertyByName( aPropName ) )
1185 aVal = xPSet->getPropertyValue( aPropName );
1186 bool b = bool();
1187 if ( ( aVal >>= b ) && b)
1188 aDescr.WindowAttributes |= VclWindowPeerAttribute::DROPDOWN;
1191 // Spin
1192 aPropName = GetPropertyName( BASEPROPERTY_SPIN );
1193 if ( xInfo->hasPropertyByName( aPropName ) )
1195 aVal = xPSet->getPropertyValue( aPropName );
1196 bool b = bool();
1197 if ( ( aVal >>= b ) && b)
1198 aDescr.WindowAttributes |= VclWindowPeerAttribute::SPIN;
1201 // HScroll
1202 aPropName = GetPropertyName( BASEPROPERTY_HSCROLL );
1203 if ( xInfo->hasPropertyByName( aPropName ) )
1205 aVal = xPSet->getPropertyValue( aPropName );
1206 bool b = bool();
1207 if ( ( aVal >>= b ) && b)
1208 aDescr.WindowAttributes |= VclWindowPeerAttribute::HSCROLL;
1211 // VScroll
1212 aPropName = GetPropertyName( BASEPROPERTY_VSCROLL );
1213 if ( xInfo->hasPropertyByName( aPropName ) )
1215 aVal = xPSet->getPropertyValue( aPropName );
1216 bool b = bool();
1217 if ( ( aVal >>= b ) && b)
1218 aDescr.WindowAttributes |= VclWindowPeerAttribute::VSCROLL;
1221 // AutoHScroll
1222 aPropName = GetPropertyName( BASEPROPERTY_AUTOHSCROLL );
1223 if ( xInfo->hasPropertyByName( aPropName ) )
1225 aVal = xPSet->getPropertyValue( aPropName );
1226 bool b = bool();
1227 if ( ( aVal >>= b ) && b)
1228 aDescr.WindowAttributes |= VclWindowPeerAttribute::AUTOHSCROLL;
1231 // AutoVScroll
1232 aPropName = GetPropertyName( BASEPROPERTY_AUTOVSCROLL );
1233 if ( xInfo->hasPropertyByName( aPropName ) )
1235 aVal = xPSet->getPropertyValue( aPropName );
1236 bool b = bool();
1237 if ( ( aVal >>= b ) && b)
1238 aDescr.WindowAttributes |= VclWindowPeerAttribute::AUTOVSCROLL;
1241 //added for issue79712
1242 //NoLabel
1243 aPropName = GetPropertyName( BASEPROPERTY_NOLABEL );
1244 if ( xInfo->hasPropertyByName( aPropName ) )
1246 aVal = xPSet->getPropertyValue( aPropName );
1247 bool b = bool();
1248 if ( ( aVal >>=b ) && b )
1249 aDescr.WindowAttributes |= VclWindowPeerAttribute::NOLABEL;
1251 //issue79712 ends
1253 // Align
1254 aPropName = GetPropertyName( BASEPROPERTY_ALIGN );
1255 if ( xInfo->hasPropertyByName( aPropName ) )
1257 aVal = xPSet->getPropertyValue( aPropName );
1258 sal_Int16 n = sal_Int16();
1259 if ( aVal >>= n )
1261 if ( n == PROPERTY_ALIGN_LEFT )
1262 aDescr.WindowAttributes |= VclWindowPeerAttribute::LEFT;
1263 else if ( n == PROPERTY_ALIGN_CENTER )
1264 aDescr.WindowAttributes |= VclWindowPeerAttribute::CENTER;
1265 else
1266 aDescr.WindowAttributes |= VclWindowPeerAttribute::RIGHT;
1270 // Allow derivates to manipulate attributes
1271 PrepareWindowDescriptor(aDescr);
1273 // create the peer
1274 setPeer( xToolkit->createWindow( aDescr ) );
1276 // release the mutex guard (and work with copies of our members)
1277 // this is necessary as our peer may lock the SolarMutex (actually, all currently known peers do), so calling
1278 // into the peer with our own mutex locked may cause deadlocks
1279 // (We _really_ need peers which do not use the SolarMutex. It's really pissing me off that from time to
1280 // time deadlocks pop up because the low-level components like our peers use a mutex which usually
1281 // is locked at the top of the stack (it protects the global message looping). This is always dangerous, and
1282 // can not always be solved by tampering with other mutexes.
1283 // Unfortunately, the VCL used in the peers is not threadsafe, and by definition needs a locked SolarMutex.)
1284 // 82300 - 12/21/00 - FS
1285 UnoControlComponentInfos aComponentInfos(maComponentInfos);
1286 bool bDesignMode(mbDesignMode);
1288 Reference< XGraphics > xGraphics( mxGraphics );
1289 Reference< XView > xView ( getPeer(), UNO_QUERY_THROW );
1290 Reference< XWindow > xWindow ( getPeer(), UNO_QUERY_THROW );
1292 aGuard.clear();
1294 // the updateFromModel is done without a locked mutex, too.
1295 // The reason is that the only thing this method does is firing property changes, and this in general has
1296 // to be done without locked mutexes (as every notification to external listeners).
1297 // 82300 - 12/21/00 - FS
1298 updateFromModel();
1300 xView->setZoom( aComponentInfos.nZoomX, aComponentInfos.nZoomY );
1302 setPosSize( aComponentInfos.nX, aComponentInfos.nY, aComponentInfos.nWidth, aComponentInfos.nHeight, aComponentInfos.nFlags );
1304 if( aComponentInfos.bVisible && !bDesignMode )
1305 // Show only after setting the data
1306 xWindow->setVisible( aComponentInfos.bVisible );
1308 if( !aComponentInfos.bEnable )
1309 xWindow->setEnable( aComponentInfos.bEnable );
1311 xView->setGraphics( xGraphics );
1313 peerCreated();
1315 mbCreatingPeer = false;
1319 Reference< XWindowPeer > UnoControl::getPeer()
1321 ::osl::MutexGuard aGuard( GetMutex() );
1322 return mxPeer;
1325 sal_Bool UnoControl::setModel( const Reference< XControlModel >& rxModel )
1327 ::osl::MutexGuard aGuard( GetMutex() );
1329 Reference< XMultiPropertySet > xPropSet( mxModel, UNO_QUERY );
1331 // query for the XPropertiesChangeListener - our delegator is allowed to overwrite this interface
1332 Reference< XPropertiesChangeListener > xListener;
1333 queryInterface( cppu::UnoType<decltype(xListener)>::get() ) >>= xListener;
1335 if( xPropSet.is() )
1336 xPropSet->removePropertiesChangeListener( xListener );
1338 mpData->bLocalizationSupport = false;
1339 mxModel = rxModel;
1341 if( mxModel.is() )
1345 xPropSet.set( mxModel, UNO_QUERY_THROW );
1346 Reference< XPropertySetInfo > xPSI( xPropSet->getPropertySetInfo(), UNO_SET_THROW );
1348 Sequence< OUString> aNames = lcl_ImplGetPropertyNames( xPropSet );
1349 xPropSet->addPropertiesChangeListener( aNames, xListener );
1351 mpData->bLocalizationSupport = xPSI->hasPropertyByName("ResourceResolver");
1353 catch( const Exception& )
1355 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
1356 mxModel.clear();
1360 return mxModel.is();
1363 Reference< XControlModel > UnoControl::getModel( )
1365 return mxModel;
1368 Reference< XView > UnoControl::getView( )
1370 return static_cast< XView* >( this );
1373 void UnoControl::setDesignMode( sal_Bool bOn )
1375 ModeChangeEvent aModeChangeEvent;
1377 Reference< XWindow > xWindow;
1378 Reference<XComponent> xAccessibleComp;
1380 ::osl::MutexGuard aGuard( GetMutex() );
1381 if ( bool(bOn) == mbDesignMode )
1382 return;
1384 // remember this
1385 mbDesignMode = bOn;
1386 xWindow.set(getPeer(), css::uno::UNO_QUERY);
1388 xAccessibleComp.set(maAccessibleContext, UNO_QUERY);
1389 maAccessibleContext.clear();
1391 aModeChangeEvent.Source = *this;
1392 aModeChangeEvent.NewMode = mbDesignMode ? OUString("design") : OUString("alive" );
1395 // dispose current AccessibleContext, if we have one - without Mutex lock
1396 // (changing the design mode implies having a new implementation for this context,
1397 // so the old one must be declared DEFUNC)
1398 DisposeAccessibleContext(xAccessibleComp);
1400 // adjust the visibility of our window
1401 if ( xWindow.is() )
1402 xWindow->setVisible( !bOn );
1404 // and notify our mode listeners
1405 maModeChangeListeners.notifyEach( &XModeChangeListener::modeChanged, aModeChangeEvent );
1408 sal_Bool UnoControl::isDesignMode( )
1410 return mbDesignMode;
1413 sal_Bool UnoControl::isTransparent( )
1415 return false;
1418 // XServiceInfo
1419 OUString UnoControl::getImplementationName( )
1421 OSL_FAIL( "This method should be overridden!" );
1422 return OUString();
1425 sal_Bool UnoControl::supportsService( const OUString& rServiceName )
1427 return cppu::supportsService(this, rServiceName);
1430 Sequence< OUString > UnoControl::getSupportedServiceNames( )
1432 OUString sName( "com.sun.star.awt.UnoControl" );
1433 return Sequence< OUString >( &sName, 1 );
1437 Reference< XAccessibleContext > SAL_CALL UnoControl::getAccessibleContext( )
1439 // creation of the context will certainly require the SolarMutex ...
1440 SolarMutexGuard aSolarGuard;
1441 ::osl::MutexGuard aGuard( GetMutex() );
1443 Reference< XAccessibleContext > xCurrentContext( maAccessibleContext.get(), UNO_QUERY );
1444 if ( !xCurrentContext.is() )
1446 if ( !mbDesignMode )
1447 { // in alive mode, use the AccessibleContext of the peer
1448 Reference< XAccessible > xPeerAcc( getPeer(), UNO_QUERY );
1449 if ( xPeerAcc.is() )
1450 xCurrentContext = xPeerAcc->getAccessibleContext( );
1452 else
1453 // in design mode, use a fallback
1454 xCurrentContext = ::toolkit::OAccessibleControlContext::create( this );
1456 DBG_ASSERT( xCurrentContext.is(), "UnoControl::getAccessibleContext: invalid context (invalid peer?)!" );
1457 maAccessibleContext = xCurrentContext;
1459 // get notified when the context is disposed
1460 Reference< XComponent > xContextComp( xCurrentContext, UNO_QUERY );
1461 if ( xContextComp.is() )
1462 xContextComp->addEventListener( this );
1463 // In an ideal world, this is not necessary - there the object would be released as soon as it has been
1464 // disposed, and thus our weak reference would be empty, too.
1465 // But 'til this ideal world comes (means 'til we do never have any refcount/lifetime bugs anymore), we
1466 // need to listen for disposal and reset our weak reference then.
1469 return xCurrentContext;
1472 void SAL_CALL UnoControl::addModeChangeListener( const Reference< XModeChangeListener >& _rxListener )
1474 ::osl::MutexGuard aGuard( GetMutex() );
1475 maModeChangeListeners.addInterface( _rxListener );
1478 void SAL_CALL UnoControl::removeModeChangeListener( const Reference< XModeChangeListener >& _rxListener )
1480 ::osl::MutexGuard aGuard( GetMutex() );
1481 maModeChangeListeners.removeInterface( _rxListener );
1484 void SAL_CALL UnoControl::addModeChangeApproveListener( const Reference< XModeChangeApproveListener >& )
1486 throw NoSupportException( );
1489 void SAL_CALL UnoControl::removeModeChangeApproveListener( const Reference< XModeChangeApproveListener >& )
1491 throw NoSupportException( );
1495 awt::Point SAL_CALL UnoControl::convertPointToLogic( const awt::Point& i_Point, ::sal_Int16 i_TargetUnit )
1497 Reference< XUnitConversion > xPeerConversion;
1499 ::osl::MutexGuard aGuard( GetMutex() );
1500 xPeerConversion.set(getPeer(), css::uno::UNO_QUERY);
1502 if ( xPeerConversion.is() )
1503 return xPeerConversion->convertPointToLogic( i_Point, i_TargetUnit );
1504 return awt::Point( );
1508 awt::Point SAL_CALL UnoControl::convertPointToPixel( const awt::Point& i_Point, ::sal_Int16 i_SourceUnit )
1510 Reference< XUnitConversion > xPeerConversion;
1512 ::osl::MutexGuard aGuard( GetMutex() );
1513 xPeerConversion.set(getPeer(), css::uno::UNO_QUERY);
1515 if ( xPeerConversion.is() )
1516 return xPeerConversion->convertPointToPixel( i_Point, i_SourceUnit );
1517 return awt::Point( );
1521 awt::Size SAL_CALL UnoControl::convertSizeToLogic( const awt::Size& i_Size, ::sal_Int16 i_TargetUnit )
1523 Reference< XUnitConversion > xPeerConversion;
1525 ::osl::MutexGuard aGuard( GetMutex() );
1526 xPeerConversion.set(getPeer(), css::uno::UNO_QUERY);
1528 if ( xPeerConversion.is() )
1529 return xPeerConversion->convertSizeToLogic( i_Size, i_TargetUnit );
1530 return awt::Size( );
1534 awt::Size SAL_CALL UnoControl::convertSizeToPixel( const awt::Size& i_Size, ::sal_Int16 i_SourceUnit )
1536 Reference< XUnitConversion > xPeerConversion;
1538 ::osl::MutexGuard aGuard( GetMutex() );
1539 xPeerConversion.set(getPeer(), css::uno::UNO_QUERY);
1541 if ( xPeerConversion.is() )
1542 return xPeerConversion->convertSizeToPixel( i_Size, i_SourceUnit );
1543 return awt::Size( );
1547 uno::Reference< awt::XStyleSettings > SAL_CALL UnoControl::getStyleSettings()
1549 Reference< awt::XStyleSettingsSupplier > xPeerSupplier;
1551 ::osl::MutexGuard aGuard( GetMutex() );
1552 xPeerSupplier.set(getPeer(), css::uno::UNO_QUERY);
1554 if ( xPeerSupplier.is() )
1555 return xPeerSupplier->getStyleSettings();
1556 return nullptr;
1559 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */