tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / toolkit / source / controls / unocontrol.cxx
blobf4757f5d79b64ef24a4ce9ffd80cfc1e5ca36587
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/beans/XPropertySet.hpp>
28 #include <com/sun/star/beans/XMultiPropertySet.hpp>
29 #include <com/sun/star/lang/NoSupportException.hpp>
30 #include <com/sun/star/resource/XStringResourceResolver.hpp>
31 #include <toolkit/controls/unocontrol.hxx>
32 #include <toolkit/helper/vclunohelper.hxx>
33 #include <cppuhelper/supportsservice.hxx>
34 #include <osl/mutex.hxx>
35 #include <tools/debug.hxx>
36 #include <comphelper/diagnose_ex.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/window.hxx>
39 #include <helper/property.hxx>
40 #include <toolkit/awt/vclxwindow.hxx>
41 #include <controls/accessiblecontrolcontext.hxx>
43 #include <algorithm>
44 #include <map>
45 #include <string_view>
46 #include <vector>
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;
55 using ::com::sun::star::accessibility::XAccessibleContext;
56 using ::com::sun::star::accessibility::XAccessible;
58 constexpr OUString aLanguageDependentProp[] =
60 u"Text"_ustr,
61 u"Label"_ustr,
62 u"Title"_ustr,
63 u"HelpText"_ustr,
64 u"CurrencySymbol"_ustr,
65 u"StringItemList"_ustr,
68 static Sequence< OUString> lcl_ImplGetPropertyNames( const Reference< XMultiPropertySet > & rxModel )
70 Sequence< OUString> aNames;
71 Reference< XPropertySetInfo > xPSInf = rxModel->getPropertySetInfo();
72 DBG_ASSERT( xPSInf.is(), "UpdateFromModel: No PropertySetInfo!" );
73 if ( xPSInf.is() )
75 const Sequence< Property> aProps = xPSInf->getProperties();
76 sal_Int32 nLen = aProps.getLength();
77 aNames = Sequence< OUString>( nLen );
78 std::transform(aProps.begin(), aProps.end(), aNames.getArray(),
79 [](const Property& rProp) -> OUString { return rProp.Name; });
81 return aNames;
84 namespace {
86 class VclListenerLock
88 private:
89 VCLXWindow* m_pLockWindow;
91 public:
92 explicit VclListenerLock( VCLXWindow* _pLockWindow )
93 : m_pLockWindow( _pLockWindow )
95 if ( m_pLockWindow )
96 m_pLockWindow->suspendVclEventListening( );
98 ~VclListenerLock()
100 if ( m_pLockWindow )
101 m_pLockWindow->resumeVclEventListening( );
103 VclListenerLock(const VclListenerLock&) = delete;
104 VclListenerLock& operator=(const VclListenerLock&) = delete;
109 typedef ::std::map< OUString, sal_Int32 > MapString2Int;
110 struct UnoControl_Data
112 MapString2Int aSuspendedPropertyNotifications;
113 /// true if and only if our model has a property ResourceResolver
114 bool bLocalizationSupport;
116 UnoControl_Data()
117 :bLocalizationSupport( false )
122 UnoControl::UnoControl() :
123 maDisposeListeners( *this )
124 , maWindowListeners( *this )
125 , maFocusListeners( *this )
126 , maKeyListeners( *this )
127 , maMouseListeners( *this )
128 , maMouseMotionListeners( *this )
129 , maPaintListeners( *this )
130 , maModeChangeListeners( GetMutex() )
131 , mpData( new UnoControl_Data )
133 mbDisposePeer = true;
134 mbRefreshingPeer = false;
135 mbCreatingPeer = false;
136 mbCreatingCompatiblePeer = false;
137 mbDesignMode = false;
140 UnoControl::~UnoControl()
144 OUString UnoControl::GetComponentServiceName() const
146 return OUString();
149 Reference< XVclWindowPeer > UnoControl::ImplGetCompatiblePeer()
151 DBG_ASSERT( !mbCreatingCompatiblePeer, "ImplGetCompatiblePeer - recursive?" );
153 mbCreatingCompatiblePeer = true;
155 Reference< XVclWindowPeer > xCompatiblePeer = getVclWindowPeer();
157 if ( !xCompatiblePeer.is() )
159 // Create the pair as invisible
160 bool bVis = maComponentInfos.bVisible;
161 if( bVis )
162 maComponentInfos.bVisible = false;
164 Reference< XVclWindowPeer > xCurrentPeer = getVclWindowPeer();
165 setPeer( nullptr );
167 // queryInterface ourself, to allow aggregation
168 Reference< XControl > xMe;
169 OWeakAggObject::queryInterface( cppu::UnoType<decltype(xMe)>::get() ) >>= xMe;
171 vcl::Window* pParentWindow( nullptr );
173 SolarMutexGuard aGuard;
174 auto pDefaultDevice = Application::GetDefaultDevice();
175 if (pDefaultDevice)
176 pParentWindow = pDefaultDevice->GetOwnerWindow();
177 ENSURE_OR_THROW( pParentWindow != nullptr, "could obtain a default parent window!" );
181 xMe->createPeer( nullptr, pParentWindow->GetComponentInterface() );
183 catch( const Exception& )
185 mbCreatingCompatiblePeer = false;
186 throw;
188 xCompatiblePeer = getVclWindowPeer();
189 setPeer( xCurrentPeer );
191 if ( xCompatiblePeer.is() && mxGraphics.is() )
193 Reference< XView > xPeerView( xCompatiblePeer, UNO_QUERY );
194 if ( xPeerView.is() )
195 xPeerView->setGraphics( mxGraphics );
198 if( bVis )
199 maComponentInfos.bVisible = true;
202 mbCreatingCompatiblePeer = false;
204 return xCompatiblePeer;
207 bool UnoControl::ImplCheckLocalize( OUString& _rPossiblyLocalizable )
209 if ( !mpData->bLocalizationSupport
210 || ( _rPossiblyLocalizable.isEmpty() )
211 || ( _rPossiblyLocalizable[0] != '&' )
212 // TODO: make this reasonable. At the moment, everything which by accident starts with a & is considered
213 // localizable, which is probably wrong.
215 return false;
219 Reference< XPropertySet > xPropSet( mxModel, UNO_QUERY_THROW );
220 Reference< resource::XStringResourceResolver > xStringResourceResolver(
221 xPropSet->getPropertyValue(u"ResourceResolver"_ustr),
222 UNO_QUERY
224 if ( xStringResourceResolver.is() )
226 OUString aLocalizationKey( _rPossiblyLocalizable.copy( 1 ) );
227 _rPossiblyLocalizable = xStringResourceResolver->resolveString( aLocalizationKey );
228 return true;
231 catch( const Exception& )
233 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
235 return false;
238 void UnoControl::ImplSetPeerProperty( const OUString& rPropName, const Any& rVal )
240 // since a change made in propertiesChange, we can't be sure that this is called with a valid getPeer(),
241 // this assumption may be false in some (seldom) multi-threading scenarios (cause propertiesChange
242 // releases our mutex before calling here in)
243 // That's why this additional check
245 if ( !mxVclWindowPeer.is() )
246 return;
248 Any aConvertedValue( rVal );
250 if ( mpData->bLocalizationSupport )
252 // We now support a mapping for language dependent properties. This is the
253 // central method to implement it.
254 if( rPropName == "Text" ||
255 rPropName == "Label" ||
256 rPropName == "Title" ||
257 rPropName == "HelpText" ||
258 rPropName == "CurrencySymbol" ||
259 rPropName == "StringItemList" )
261 OUString aValue;
262 uno::Sequence< OUString > aSeqValue;
263 if ( aConvertedValue >>= aValue )
265 if ( ImplCheckLocalize( aValue ) )
266 aConvertedValue <<= aValue;
268 else if ( aConvertedValue >>= aSeqValue )
270 for ( auto& rValue : asNonConstRange(aSeqValue) )
271 ImplCheckLocalize( rValue );
272 aConvertedValue <<= aSeqValue;
277 mxVclWindowPeer->setProperty( rPropName, aConvertedValue );
280 void UnoControl::PrepareWindowDescriptor( WindowDescriptor& )
284 Reference< XWindow > UnoControl::getParentPeer() const
286 Reference< XWindow > xPeer;
287 if( mxContext.is() )
289 Reference< XControl > xContComp( mxContext, UNO_QUERY );
290 if ( xContComp.is() )
292 Reference< XWindowPeer > xP = xContComp->getPeer();
293 if ( xP.is() )
294 xPeer.set( xP, UNO_QUERY );
297 return xPeer;
300 void UnoControl::updateFromModel()
302 // Read default properties and hand over to peer
303 if( getPeer().is() )
305 Reference< XMultiPropertySet > xPropSet( mxModel, UNO_QUERY );
306 if( xPropSet.is() )
308 Sequence< OUString> aNames = lcl_ImplGetPropertyNames( xPropSet );
309 xPropSet->firePropertiesChangeEvent( aNames, this );
315 // XTypeProvider
316 IMPL_IMPLEMENTATION_ID( UnoControl )
318 void
319 UnoControl::DisposeAccessibleContext(Reference<XComponent> const& xContextComp)
321 if (xContextComp.is())
325 xContextComp->removeEventListener( this );
326 xContextComp->dispose();
328 catch( const Exception& )
330 OSL_FAIL( "UnoControl::disposeAccessibleContext: could not dispose my AccessibleContext!" );
335 void UnoControl::dispose( )
337 Reference< XVclWindowPeer > xPeer;
338 Reference<XComponent> xAccessibleComp;
340 ::osl::MutexGuard aGuard( GetMutex() );
341 if( mbDisposePeer )
343 xPeer = mxVclWindowPeer;
345 setPeer( nullptr );
346 xAccessibleComp.set(maAccessibleContext, UNO_QUERY);
347 maAccessibleContext.clear();
349 if( xPeer.is() )
351 xPeer->dispose();
354 // dispose our AccessibleContext - without Mutex locked
355 DisposeAccessibleContext(xAccessibleComp);
357 EventObject aDisposeEvent;
358 aDisposeEvent.Source = static_cast< XAggregation* >( this );
360 maDisposeListeners.disposeAndClear( aDisposeEvent );
361 maWindowListeners.disposeAndClear( aDisposeEvent );
362 maFocusListeners.disposeAndClear( aDisposeEvent );
363 maKeyListeners.disposeAndClear( aDisposeEvent );
364 maMouseListeners.disposeAndClear( aDisposeEvent );
365 maMouseMotionListeners.disposeAndClear( aDisposeEvent );
366 maPaintListeners.disposeAndClear( aDisposeEvent );
367 maModeChangeListeners.disposeAndClear( aDisposeEvent );
369 // release Model again
370 setModel( Reference< XControlModel > () );
371 setContext( Reference< XInterface > () );
374 void UnoControl::addEventListener( const Reference< XEventListener >& rxListener )
376 ::osl::MutexGuard aGuard( GetMutex() );
378 maDisposeListeners.addInterface( rxListener );
381 void UnoControl::removeEventListener( const Reference< XEventListener >& rxListener )
383 ::osl::MutexGuard aGuard( GetMutex() );
385 maDisposeListeners.removeInterface( rxListener );
388 bool UnoControl::requiresNewPeer( const OUString& /* _rPropertyName */ ) const
390 return false;
393 // XPropertiesChangeListener
394 void UnoControl::propertiesChange( const Sequence< PropertyChangeEvent >& rEvents )
396 Sequence< PropertyChangeEvent > aEvents( rEvents );
398 ::osl::MutexGuard aGuard( GetMutex() );
400 if ( !mpData->aSuspendedPropertyNotifications.empty() )
402 // strip the property which we are currently updating (somewhere up the stack)
403 PropertyChangeEvent* pEvents = aEvents.getArray();
404 PropertyChangeEvent* pEventsEnd = pEvents + aEvents.getLength();
405 for ( ; pEvents < pEventsEnd; )
406 if ( mpData->aSuspendedPropertyNotifications.find( pEvents->PropertyName ) != mpData->aSuspendedPropertyNotifications.end() )
408 std::copy(pEvents + 1, pEventsEnd, pEvents);
409 --pEventsEnd;
411 else
412 ++pEvents;
413 aEvents.realloc( pEventsEnd - aEvents.getConstArray() );
415 if ( !aEvents.hasElements() )
416 return;
420 ImplModelPropertiesChanged( aEvents );
423 void UnoControl::ImplLockPropertyChangeNotification( const OUString& rPropertyName, bool bLock )
425 MapString2Int::iterator pos = mpData->aSuspendedPropertyNotifications.find( rPropertyName );
426 if ( bLock )
428 if ( pos == mpData->aSuspendedPropertyNotifications.end() )
429 pos = mpData->aSuspendedPropertyNotifications.emplace( rPropertyName, 0 ).first;
430 ++pos->second;
432 else
434 OSL_ENSURE( pos != mpData->aSuspendedPropertyNotifications.end(), "UnoControl::ImplLockPropertyChangeNotification: property not locked!" );
435 if ( pos != mpData->aSuspendedPropertyNotifications.end() )
437 OSL_ENSURE( pos->second > 0, "UnoControl::ImplLockPropertyChangeNotification: invalid suspension counter!" );
438 if ( 0 == --pos->second )
439 mpData->aSuspendedPropertyNotifications.erase( pos );
444 void UnoControl::ImplLockPropertyChangeNotifications( const Sequence< OUString >& rPropertyNames, bool bLock )
446 for ( auto const & propertyName : rPropertyNames )
447 ImplLockPropertyChangeNotification( propertyName, bLock );
450 void UnoControl::ImplModelPropertiesChanged( const Sequence< PropertyChangeEvent >& rEvents )
452 ::osl::ClearableGuard< ::osl::Mutex > aGuard( GetMutex() );
454 if( !getPeer().is() )
455 return;
457 std::vector< PropertyValue > aPeerPropertiesToSet;
458 sal_Int32 nIndependentPos = 0;
459 bool bResourceResolverSet( false );
460 // position where to insert the independent properties into aPeerPropertiesToSet,
461 // dependent ones are inserted at the end of the vector
463 bool bNeedNewPeer = false;
464 // some properties require a re-creation of the peer, 'cause they can't be changed on the fly
466 Reference< XControlModel > xOwnModel = getModel();
467 // our own model for comparison
468 Reference< XPropertySet > xPS( xOwnModel, UNO_QUERY );
469 Reference< XPropertySetInfo > xPSI = xPS->getPropertySetInfo();
470 OSL_ENSURE( xPSI.is(), "UnoControl::ImplModelPropertiesChanged: should have property set meta data!" );
472 sal_Int32 nLen = rEvents.getLength();
473 aPeerPropertiesToSet.reserve(nLen);
475 for( const PropertyChangeEvent& rEvent : rEvents )
477 Reference< XControlModel > xModel( rEvent.Source, UNO_QUERY );
478 bool bOwnModel = xModel.get() == xOwnModel.get();
479 if ( !bOwnModel )
480 continue;
482 // Detect changes on our resource resolver which invalidates
483 // automatically some language dependent properties.
484 if ( rEvent.PropertyName == "ResourceResolver" )
486 Reference< resource::XStringResourceResolver > xStrResolver;
487 if ( rEvent.NewValue >>= xStrResolver )
488 bResourceResolverSet = xStrResolver.is();
491 sal_uInt16 nPType = GetPropertyId( rEvent.PropertyName );
492 if ( mbDesignMode && mbDisposePeer && !mbRefreshingPeer && !mbCreatingPeer )
494 // if we're in design mode, then some properties can change which
495 // require creating a *new* peer (since these properties cannot
496 // be switched at existing peers)
497 if ( nPType )
498 bNeedNewPeer = ( nPType == BASEPROPERTY_BORDER )
499 || ( nPType == BASEPROPERTY_MULTILINE )
500 || ( nPType == BASEPROPERTY_DROPDOWN )
501 || ( nPType == BASEPROPERTY_HSCROLL )
502 || ( nPType == BASEPROPERTY_VSCROLL )
503 || ( nPType == BASEPROPERTY_AUTOHSCROLL )
504 || ( nPType == BASEPROPERTY_AUTOVSCROLL )
505 || ( nPType == BASEPROPERTY_ORIENTATION )
506 || ( nPType == BASEPROPERTY_SPIN )
507 || ( nPType == BASEPROPERTY_ALIGN )
508 || ( nPType == BASEPROPERTY_PAINTTRANSPARENT );
509 else
510 bNeedNewPeer = requiresNewPeer( rEvent.PropertyName );
512 if ( bNeedNewPeer )
513 break;
516 if ( nPType && ( nLen > 1 ) && DoesDependOnOthers( nPType ) )
518 // Add properties with dependencies on other properties last
519 // since they're dependent on properties added later (such as
520 // VALUE dependency on VALUEMIN/MAX)
521 aPeerPropertiesToSet.emplace_back(rEvent.PropertyName, 0, rEvent.NewValue, PropertyState_DIRECT_VALUE);
523 else
525 if ( bResourceResolverSet )
527 // The resource resolver property change should be one of the first ones.
528 // All language dependent properties are dependent on this property.
529 // As BASEPROPERTY_NATIVE_WIDGET_LOOK is not dependent on resource
530 // resolver. We don't need to handle a special order for these two props.
531 aPeerPropertiesToSet.insert(
532 aPeerPropertiesToSet.begin(),
533 PropertyValue( rEvent.PropertyName, 0, rEvent.NewValue, PropertyState_DIRECT_VALUE ) );
534 ++nIndependentPos;
536 else if ( nPType == BASEPROPERTY_NATIVE_WIDGET_LOOK )
538 // since *a lot* of other properties might be overruled by this one, we need
539 // a special handling:
540 // NativeWidgetLook needs to be set first: If it is set to ON, all other
541 // properties describing the look (e.g. BackgroundColor) are ignored, anyway.
542 // If it is switched OFF, then we need to do it first because else it will
543 // overrule other look-related properties, and re-initialize them from system
544 // defaults.
545 aPeerPropertiesToSet.insert(
546 aPeerPropertiesToSet.begin(),
547 PropertyValue( rEvent.PropertyName, 0, rEvent.NewValue, PropertyState_DIRECT_VALUE ) );
548 ++nIndependentPos;
550 else
552 aPeerPropertiesToSet.insert(aPeerPropertiesToSet.begin() + nIndependentPos,
553 PropertyValue(rEvent.PropertyName, 0, rEvent.NewValue, PropertyState_DIRECT_VALUE));
554 ++nIndependentPos;
559 Reference< XWindow > xParent = getParentPeer();
560 Reference< XControl > xThis(this);
561 // call createPeer via an interface got from queryInterface, so the aggregating class can intercept it
563 DBG_ASSERT( !bNeedNewPeer || xParent.is(), "Need new peer, but don't have a parent!" );
565 // Check if we have to update language dependent properties
566 if ( !bNeedNewPeer && bResourceResolverSet )
568 // Add language dependent properties into the peer property set.
569 // Our resource resolver has been changed and we must be sure
570 // that language dependent props use the new resolver.
572 for (const auto & rLangDepProp : aLanguageDependentProp)
574 bool bMustBeInserted( true );
575 for (const PropertyValue & i : aPeerPropertiesToSet)
577 if ( i.Name == rLangDepProp )
579 bMustBeInserted = false;
580 break;
584 if ( bMustBeInserted )
586 // Add language dependent props at the end
587 if ( xPSI.is() && xPSI->hasPropertyByName( rLangDepProp ) )
589 aPeerPropertiesToSet.emplace_back( rLangDepProp, 0, xPS->getPropertyValue( rLangDepProp ), PropertyState_DIRECT_VALUE );
594 aGuard.clear();
596 // clear the guard before creating a new peer - as usual, our peer implementations use the SolarMutex
598 if (bNeedNewPeer && xParent.is())
600 SolarMutexGuard aVclGuard;
601 // and now this is the final withdrawal:
602 // I have no other idea than locking the SolarMutex here...
603 // I really hate the fact that VCL is not threadsafe...
605 // Doesn't work for Container!
606 getPeer()->dispose();
607 mxVclWindowPeer.clear();
608 mbRefreshingPeer = true;
609 Reference< XWindowPeer > xP( xParent, UNO_QUERY );
610 xThis->createPeer( Reference< XToolkit > (), xP );
611 mbRefreshingPeer = false;
612 aPeerPropertiesToSet.clear();
615 // lock the multiplexing of VCL events to our UNO listeners
616 // this is for compatibility reasons: in OOo 1.0.x, changes which were done at the
617 // model did not cause the listeners of the controls/peers to be called
618 // Since the implementations for the listeners changed a lot towards 1.1, this
619 // would not be the case anymore, if we would not do this listener-lock below
620 // #i14703#
621 VCLXWindow* pPeer;
623 SolarMutexGuard g;
624 VclPtr<vcl::Window> pVclPeer = VCLUnoHelper::GetWindow( getPeer() );
625 pPeer = pVclPeer ? pVclPeer->GetWindowPeer() : nullptr;
627 VclListenerLock aNoVclEventMultiplexing( pPeer );
629 // setting peer properties may result in an attempt to acquire the solar mutex, 'cause the peers
630 // usually don't have an own mutex but use the SolarMutex instead.
631 // To prevent deadlocks resulting from this, we do this without our own mutex locked
632 for (const auto& rProp : aPeerPropertiesToSet)
634 ImplSetPeerProperty( rProp.Name, rProp.Value );
639 void UnoControl::disposing( const EventObject& rEvt )
641 ::osl::ClearableMutexGuard aGuard( GetMutex() );
642 // do not compare differing types in case of multiple inheritance
644 if ( maAccessibleContext.get() == rEvt.Source )
646 // just in case the context is disposed, but not released - ensure that we do not re-use it in the future
647 maAccessibleContext.clear();
649 else if( mxModel.get() == Reference< XControlModel >(rEvt.Source,UNO_QUERY).get() )
651 // #62337# if the model dies, it does not make sense for us to live ...
652 Reference< XControl > xThis = this;
654 aGuard.clear();
655 xThis->dispose();
657 DBG_ASSERT( !mxModel.is(), "UnoControl::disposing: invalid dispose behaviour!" );
658 mxModel.clear();
663 void SAL_CALL UnoControl::setOutputSize( const awt::Size& aSize )
665 Reference< XWindow2 > xPeerWindow;
667 ::osl::MutexGuard aGuard( GetMutex() );
668 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
671 if ( xPeerWindow.is() )
672 xPeerWindow->setOutputSize( aSize );
675 namespace
677 template < typename RETVALTYPE, typename DEFAULTTYPE >
678 RETVALTYPE lcl_askPeer( const uno::Reference< awt::XWindowPeer >& _rxPeer, RETVALTYPE (SAL_CALL XWindow2::*_pMethod)(), DEFAULTTYPE _aDefault )
680 RETVALTYPE aReturn( _aDefault );
682 Reference< XWindow2 > xPeerWindow( _rxPeer, UNO_QUERY );
683 if ( xPeerWindow.is() )
684 aReturn = (xPeerWindow.get()->*_pMethod)();
686 return aReturn;
690 awt::Size SAL_CALL UnoControl::getOutputSize( )
692 return lcl_askPeer( getPeer(), &XWindow2::getOutputSize, awt::Size() );
695 sal_Bool SAL_CALL UnoControl::isVisible( )
697 return lcl_askPeer( getPeer(), &XWindow2::isVisible, maComponentInfos.bVisible );
700 sal_Bool SAL_CALL UnoControl::isActive( )
702 return lcl_askPeer( getPeer(), &XWindow2::isActive, false );
705 sal_Bool SAL_CALL UnoControl::isEnabled( )
707 return lcl_askPeer( getPeer(), &XWindow2::isEnabled, maComponentInfos.bEnable );
710 sal_Bool SAL_CALL UnoControl::hasFocus( )
712 return lcl_askPeer( getPeer(), &XWindow2::hasFocus, false );
715 // XWindow
716 void UnoControl::setPosSize( sal_Int32 X, sal_Int32 Y, sal_Int32 Width, sal_Int32 Height, sal_Int16 Flags )
718 Reference< XWindow > xWindow;
720 ::osl::MutexGuard aGuard( GetMutex() );
722 if ( Flags & awt::PosSize::X )
723 maComponentInfos.nX = X;
724 if ( Flags & awt::PosSize::Y )
725 maComponentInfos.nY = Y;
726 if ( Flags & awt::PosSize::WIDTH )
727 maComponentInfos.nWidth = Width;
728 if ( Flags & awt::PosSize::HEIGHT )
729 maComponentInfos.nHeight = Height;
730 maComponentInfos.nFlags |= Flags;
732 xWindow.set(getPeer(), css::uno::UNO_QUERY);
735 if( xWindow.is() )
736 xWindow->setPosSize( X, Y, Width, Height, Flags );
739 awt::Rectangle UnoControl::getPosSize( )
741 awt::Rectangle aRect( maComponentInfos.nX, maComponentInfos.nY, maComponentInfos.nWidth, maComponentInfos.nHeight);
742 Reference< XWindow > xWindow;
745 ::osl::MutexGuard aGuard( GetMutex() );
746 xWindow.set(getPeer(), css::uno::UNO_QUERY);
749 if( xWindow.is() )
750 aRect = xWindow->getPosSize();
751 return aRect;
754 void UnoControl::setVisible( sal_Bool bVisible )
756 Reference< XWindow > xWindow;
758 ::osl::MutexGuard aGuard( GetMutex() );
760 // Visible status is handled by View
761 maComponentInfos.bVisible = bVisible;
762 xWindow.set(getPeer(), css::uno::UNO_QUERY);
764 if ( xWindow.is() )
765 xWindow->setVisible( bVisible );
768 void UnoControl::setEnable( sal_Bool bEnable )
770 Reference< XWindow > xWindow;
772 ::osl::MutexGuard aGuard( GetMutex() );
774 // Enable status is handled by View
775 maComponentInfos.bEnable = bEnable;
776 xWindow.set(getPeer(), css::uno::UNO_QUERY);
778 if ( xWindow.is() )
779 xWindow->setEnable( bEnable );
782 void UnoControl::setFocus( )
784 Reference< XWindow > xWindow;
786 ::osl::MutexGuard aGuard( GetMutex() );
787 xWindow.set(getPeer(), css::uno::UNO_QUERY);
789 if ( xWindow.is() )
790 xWindow->setFocus();
793 void UnoControl::addWindowListener( const Reference< XWindowListener >& rxListener )
795 Reference< XWindow > xPeerWindow;
797 ::osl::MutexGuard aGuard( GetMutex() );
798 maWindowListeners.addInterface( rxListener );
799 if ( maWindowListeners.getLength() == 1 )
800 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
802 if ( xPeerWindow.is() )
803 xPeerWindow->addWindowListener( &maWindowListeners );
806 void UnoControl::removeWindowListener( const Reference< XWindowListener >& rxListener )
808 Reference< XWindow > xPeerWindow;
810 ::osl::MutexGuard aGuard( GetMutex() );
811 if ( maWindowListeners.getLength() == 1 )
812 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
813 maWindowListeners.removeInterface( rxListener );
815 if ( xPeerWindow.is() )
816 xPeerWindow->removeWindowListener( &maWindowListeners );
819 void UnoControl::addFocusListener( const Reference< XFocusListener >& rxListener )
821 Reference< XWindow > xPeerWindow;
823 ::osl::MutexGuard aGuard( GetMutex() );
824 maFocusListeners.addInterface( rxListener );
825 if ( maFocusListeners.getLength() == 1 )
826 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
828 if ( xPeerWindow.is() )
829 xPeerWindow->addFocusListener( &maFocusListeners );
832 void UnoControl::removeFocusListener( const Reference< XFocusListener >& rxListener )
834 Reference< XWindow > xPeerWindow;
836 ::osl::MutexGuard aGuard( GetMutex() );
837 if ( maFocusListeners.getLength() == 1 )
838 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
839 maFocusListeners.removeInterface( rxListener );
841 if ( xPeerWindow.is() )
842 xPeerWindow->removeFocusListener( &maFocusListeners );
845 void UnoControl::addKeyListener( const Reference< XKeyListener >& rxListener )
847 Reference< XWindow > xPeerWindow;
849 ::osl::MutexGuard aGuard( GetMutex() );
850 maKeyListeners.addInterface( rxListener );
851 if ( maKeyListeners.getLength() == 1 )
852 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
854 if ( xPeerWindow.is() )
855 xPeerWindow->addKeyListener( &maKeyListeners);
858 void UnoControl::removeKeyListener( const Reference< XKeyListener >& rxListener )
860 Reference< XWindow > xPeerWindow;
862 ::osl::MutexGuard aGuard( GetMutex() );
863 if ( maKeyListeners.getLength() == 1 )
864 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
865 maKeyListeners.removeInterface( rxListener );
867 if ( xPeerWindow.is() )
868 xPeerWindow->removeKeyListener( &maKeyListeners);
871 void UnoControl::addMouseListener( const Reference< XMouseListener >& rxListener )
873 Reference< XWindow > xPeerWindow;
875 ::osl::MutexGuard aGuard( GetMutex() );
876 maMouseListeners.addInterface( rxListener );
877 if ( maMouseListeners.getLength() == 1 )
878 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
880 if ( xPeerWindow.is() )
881 xPeerWindow->addMouseListener( &maMouseListeners);
884 void UnoControl::removeMouseListener( const Reference< XMouseListener >& rxListener )
886 Reference< XWindow > xPeerWindow;
888 ::osl::MutexGuard aGuard( GetMutex() );
889 if ( maMouseListeners.getLength() == 1 )
890 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
891 maMouseListeners.removeInterface( rxListener );
893 if ( xPeerWindow.is() )
894 xPeerWindow->removeMouseListener( &maMouseListeners );
897 void UnoControl::addMouseMotionListener( const Reference< XMouseMotionListener >& rxListener )
899 Reference< XWindow > xPeerWindow;
901 ::osl::MutexGuard aGuard( GetMutex() );
902 maMouseMotionListeners.addInterface( rxListener );
903 if ( maMouseMotionListeners.getLength() == 1 )
904 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
906 if ( xPeerWindow.is() )
907 xPeerWindow->addMouseMotionListener( &maMouseMotionListeners);
910 void UnoControl::removeMouseMotionListener( const Reference< XMouseMotionListener >& rxListener )
912 Reference< XWindow > xPeerWindow;
914 ::osl::MutexGuard aGuard( GetMutex() );
915 if ( maMouseMotionListeners.getLength() == 1 )
916 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
917 maMouseMotionListeners.removeInterface( rxListener );
919 if ( xPeerWindow.is() )
920 xPeerWindow->removeMouseMotionListener( &maMouseMotionListeners );
923 void UnoControl::addPaintListener( const Reference< XPaintListener >& rxListener )
925 Reference< XWindow > xPeerWindow;
927 ::osl::MutexGuard aGuard( GetMutex() );
928 maPaintListeners.addInterface( rxListener );
929 if ( maPaintListeners.getLength() == 1 )
930 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
932 if ( xPeerWindow.is() )
933 xPeerWindow->addPaintListener( &maPaintListeners);
936 void UnoControl::removePaintListener( const Reference< XPaintListener >& rxListener )
938 Reference< XWindow > xPeerWindow;
940 ::osl::MutexGuard aGuard( GetMutex() );
941 if ( maPaintListeners.getLength() == 1 )
942 xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
943 maPaintListeners.removeInterface( rxListener );
945 if ( xPeerWindow.is() )
946 xPeerWindow->removePaintListener( &maPaintListeners );
949 // XView
950 sal_Bool UnoControl::setGraphics( const Reference< XGraphics >& rDevice )
952 Reference< XView > xView;
954 ::osl::MutexGuard aGuard( GetMutex() );
956 mxGraphics = rDevice;
957 xView.set(getPeer(), css::uno::UNO_QUERY);
959 return !xView.is() || xView->setGraphics( rDevice );
962 Reference< XGraphics > UnoControl::getGraphics( )
964 return mxGraphics;
967 awt::Size UnoControl::getSize( )
969 ::osl::MutexGuard aGuard( GetMutex() );
970 return awt::Size( maComponentInfos.nWidth, maComponentInfos.nHeight );
973 void UnoControl::draw( sal_Int32 x, sal_Int32 y )
975 Reference< XWindowPeer > xDrawPeer;
976 Reference< XView > xDrawPeerView;
978 bool bDisposeDrawPeer( false );
980 ::osl::MutexGuard aGuard( GetMutex() );
982 xDrawPeer = ImplGetCompatiblePeer();
983 bDisposeDrawPeer = xDrawPeer.is() && ( xDrawPeer != getPeer() );
985 xDrawPeerView.set( xDrawPeer, UNO_QUERY );
986 DBG_ASSERT( xDrawPeerView.is(), "UnoControl::draw: no peer!" );
989 if ( xDrawPeerView.is() )
991 Reference< XVclWindowPeer > xWindowPeer;
992 xWindowPeer.set( xDrawPeer, UNO_QUERY );
993 if ( xWindowPeer.is() )
994 xWindowPeer->setDesignMode( mbDesignMode );
995 xDrawPeerView->draw( x, y );
998 if ( bDisposeDrawPeer )
999 xDrawPeer->dispose();
1002 void UnoControl::setZoom( float fZoomX, float fZoomY )
1004 Reference< XView > xView;
1006 ::osl::MutexGuard aGuard( GetMutex() );
1008 maComponentInfos.nZoomX = fZoomX;
1009 maComponentInfos.nZoomY = fZoomY;
1011 xView.set(getPeer(), css::uno::UNO_QUERY);
1013 if ( xView.is() )
1014 xView->setZoom( fZoomX, fZoomY );
1017 // XControl
1018 void UnoControl::setContext( const Reference< XInterface >& rxContext )
1020 ::osl::MutexGuard aGuard( GetMutex() );
1022 mxContext = rxContext;
1025 Reference< XInterface > UnoControl::getContext( )
1027 ::osl::MutexGuard aGuard( GetMutex() );
1029 return mxContext;
1032 void UnoControl::peerCreated()
1034 Reference< XWindow > xWindow( getPeer(), UNO_QUERY );
1035 if ( !xWindow.is() )
1036 return;
1038 if ( maWindowListeners.getLength() )
1039 xWindow->addWindowListener( &maWindowListeners );
1041 if ( maFocusListeners.getLength() )
1042 xWindow->addFocusListener( &maFocusListeners );
1044 if ( maKeyListeners.getLength() )
1045 xWindow->addKeyListener( &maKeyListeners );
1047 if ( maMouseListeners.getLength() )
1048 xWindow->addMouseListener( &maMouseListeners );
1050 if ( maMouseMotionListeners.getLength() )
1051 xWindow->addMouseMotionListener( &maMouseMotionListeners );
1053 if ( maPaintListeners.getLength() )
1054 xWindow->addPaintListener( &maPaintListeners );
1057 void UnoControl::createPeer( const Reference< XToolkit >& rxToolkit, const Reference< XWindowPeer >& rParentPeer )
1059 ::osl::ClearableMutexGuard aGuard( GetMutex() );
1060 if ( !mxModel.is() )
1062 throw RuntimeException(u"createPeer: no model!"_ustr, getXWeak());
1065 if( getPeer().is() )
1066 return;
1068 mbCreatingPeer = true;
1070 WindowClass eType;
1071 Reference< XToolkit > xToolkit = rxToolkit;
1072 if( rParentPeer.is() && mxContext.is() )
1074 // no TopWindow
1075 if ( !xToolkit.is() )
1076 xToolkit = rParentPeer->getToolkit();
1077 Any aAny = OWeakAggObject::queryInterface( cppu::UnoType<XControlContainer>::get());
1078 Reference< XControlContainer > xC;
1079 aAny >>= xC;
1080 if( xC.is() )
1081 // It's a container
1082 eType = WindowClass_CONTAINER;
1083 else
1084 eType = WindowClass_SIMPLE;
1086 else
1087 { // This is only correct for Top Window
1088 if( rParentPeer.is() )
1090 if ( !xToolkit.is() )
1091 xToolkit = rParentPeer->getToolkit();
1092 eType = WindowClass_CONTAINER;
1094 else
1096 if ( !xToolkit.is() )
1097 xToolkit = VCLUnoHelper::CreateToolkit();
1098 eType = WindowClass_TOP;
1101 WindowDescriptor aDescr;
1102 aDescr.Type = eType;
1103 aDescr.WindowServiceName = GetComponentServiceName();
1104 aDescr.Parent = rParentPeer;
1105 aDescr.Bounds = getPosSize();
1106 aDescr.WindowAttributes = 0;
1108 // Border
1109 Reference< XPropertySet > xPSet( mxModel, UNO_QUERY );
1110 Reference< XPropertySetInfo > xInfo = xPSet->getPropertySetInfo();
1112 Any aVal;
1113 OUString aPropName = GetPropertyName( BASEPROPERTY_BORDER );
1114 if ( xInfo->hasPropertyByName( aPropName ) )
1116 aVal = xPSet->getPropertyValue( aPropName );
1117 sal_Int16 n = sal_Int16();
1118 if ( aVal >>= n )
1120 if ( n )
1121 aDescr.WindowAttributes |= WindowAttribute::BORDER;
1122 else
1123 aDescr.WindowAttributes |= VclWindowPeerAttribute::NOBORDER;
1127 // DESKTOP_AS_PARENT
1128 if ( aDescr.Type == WindowClass_TOP )
1130 aPropName = GetPropertyName( BASEPROPERTY_DESKTOP_AS_PARENT );
1131 if ( xInfo->hasPropertyByName( aPropName ) )
1133 aVal = xPSet->getPropertyValue( aPropName );
1134 bool b = bool();
1135 if ( ( aVal >>= b ) && b)
1136 aDescr.ParentIndex = -1;
1139 // Moveable
1140 aPropName = GetPropertyName( BASEPROPERTY_MOVEABLE );
1141 if ( xInfo->hasPropertyByName( aPropName ) )
1143 aVal = xPSet->getPropertyValue( aPropName );
1144 bool b = bool();
1145 if ( ( aVal >>= b ) && b)
1146 aDescr.WindowAttributes |= WindowAttribute::MOVEABLE;
1149 // Sizeable
1150 aPropName = GetPropertyName( BASEPROPERTY_SIZEABLE );
1151 if ( xInfo->hasPropertyByName( aPropName ) )
1153 aVal = xPSet->getPropertyValue( aPropName );
1154 bool b = bool();
1155 if ( ( aVal >>= b ) && b)
1156 aDescr.WindowAttributes |= WindowAttribute::SIZEABLE;
1159 // Closeable
1160 aPropName = GetPropertyName( BASEPROPERTY_CLOSEABLE );
1161 if ( xInfo->hasPropertyByName( aPropName ) )
1163 aVal = xPSet->getPropertyValue( aPropName );
1164 bool b = bool();
1165 if ( ( aVal >>= b ) && b)
1166 aDescr.WindowAttributes |= WindowAttribute::CLOSEABLE;
1169 // Dropdown
1170 aPropName = GetPropertyName( BASEPROPERTY_DROPDOWN );
1171 if ( xInfo->hasPropertyByName( aPropName ) )
1173 aVal = xPSet->getPropertyValue( aPropName );
1174 bool b = bool();
1175 if ( ( aVal >>= b ) && b)
1176 aDescr.WindowAttributes |= VclWindowPeerAttribute::DROPDOWN;
1179 // Spin
1180 aPropName = GetPropertyName( BASEPROPERTY_SPIN );
1181 if ( xInfo->hasPropertyByName( aPropName ) )
1183 aVal = xPSet->getPropertyValue( aPropName );
1184 bool b = bool();
1185 if ( ( aVal >>= b ) && b)
1186 aDescr.WindowAttributes |= VclWindowPeerAttribute::SPIN;
1189 // HScroll
1190 aPropName = GetPropertyName( BASEPROPERTY_HSCROLL );
1191 if ( xInfo->hasPropertyByName( aPropName ) )
1193 aVal = xPSet->getPropertyValue( aPropName );
1194 bool b = bool();
1195 if ( ( aVal >>= b ) && b)
1196 aDescr.WindowAttributes |= VclWindowPeerAttribute::HSCROLL;
1199 // VScroll
1200 aPropName = GetPropertyName( BASEPROPERTY_VSCROLL );
1201 if ( xInfo->hasPropertyByName( aPropName ) )
1203 aVal = xPSet->getPropertyValue( aPropName );
1204 bool b = bool();
1205 if ( ( aVal >>= b ) && b)
1206 aDescr.WindowAttributes |= VclWindowPeerAttribute::VSCROLL;
1209 // AutoHScroll
1210 aPropName = GetPropertyName( BASEPROPERTY_AUTOHSCROLL );
1211 if ( xInfo->hasPropertyByName( aPropName ) )
1213 aVal = xPSet->getPropertyValue( aPropName );
1214 bool b = bool();
1215 if ( ( aVal >>= b ) && b)
1216 aDescr.WindowAttributes |= VclWindowPeerAttribute::AUTOHSCROLL;
1219 // AutoVScroll
1220 aPropName = GetPropertyName( BASEPROPERTY_AUTOVSCROLL );
1221 if ( xInfo->hasPropertyByName( aPropName ) )
1223 aVal = xPSet->getPropertyValue( aPropName );
1224 bool b = bool();
1225 if ( ( aVal >>= b ) && b)
1226 aDescr.WindowAttributes |= VclWindowPeerAttribute::AUTOVSCROLL;
1229 //added for issue79712
1230 //NoLabel
1231 aPropName = GetPropertyName( BASEPROPERTY_NOLABEL );
1232 if ( xInfo->hasPropertyByName( aPropName ) )
1234 aVal = xPSet->getPropertyValue( aPropName );
1235 bool b = bool();
1236 if ( ( aVal >>=b ) && b )
1237 aDescr.WindowAttributes |= VclWindowPeerAttribute::NOLABEL;
1239 //issue79712 ends
1241 // Align
1242 aPropName = GetPropertyName( BASEPROPERTY_ALIGN );
1243 if ( xInfo->hasPropertyByName( aPropName ) )
1245 aVal = xPSet->getPropertyValue( aPropName );
1246 sal_Int16 n = sal_Int16();
1247 if ( aVal >>= n )
1249 if ( n == PROPERTY_ALIGN_LEFT )
1250 aDescr.WindowAttributes |= VclWindowPeerAttribute::LEFT;
1251 else if ( n == PROPERTY_ALIGN_CENTER )
1252 aDescr.WindowAttributes |= VclWindowPeerAttribute::CENTER;
1253 else
1254 aDescr.WindowAttributes |= VclWindowPeerAttribute::RIGHT;
1258 // Allow derivates to manipulate attributes
1259 PrepareWindowDescriptor(aDescr);
1261 // create the peer
1262 Reference<XWindowPeer> xTemp = xToolkit->createWindow( aDescr );
1263 mxVclWindowPeer.set(xTemp, UNO_QUERY);
1264 assert(mxVclWindowPeer);
1266 // release the mutex guard (and work with copies of our members)
1267 // this is necessary as our peer may lock the SolarMutex (actually, all currently known peers do), so calling
1268 // into the peer with our own mutex locked may cause deadlocks
1269 // (We _really_ need peers which do not use the SolarMutex. It's really pissing me off that from time to
1270 // time deadlocks pop up because the low-level components like our peers use a mutex which usually
1271 // is locked at the top of the stack (it protects the global message looping). This is always dangerous, and
1272 // can not always be solved by tampering with other mutexes.
1273 // Unfortunately, the VCL used in the peers is not threadsafe, and by definition needs a locked SolarMutex.)
1274 // 82300 - 12/21/00 - FS
1275 UnoControlComponentInfos aComponentInfos(maComponentInfos);
1276 bool bDesignMode(mbDesignMode);
1278 Reference< XGraphics > xGraphics( mxGraphics );
1279 Reference< XView > xView ( getPeer(), UNO_QUERY_THROW );
1280 Reference< XWindow > xWindow ( getPeer(), UNO_QUERY_THROW );
1282 aGuard.clear();
1284 // tdf#150886 if false use the same settings for widgets regardless of theme
1285 // for consistency of document across platforms and in pdf/print output
1286 // note: tdf#155029 do this before updateFromModel
1287 if (xInfo->hasPropertyByName(u"StandardTheme"_ustr))
1289 aVal = xPSet->getPropertyValue(u"StandardTheme"_ustr);
1290 bool bUseStandardTheme = false;
1291 aVal >>= bUseStandardTheme;
1292 if (bUseStandardTheme)
1294 VclPtr<vcl::Window> pVclPeer = VCLUnoHelper::GetWindow(getPeer());
1296 WindowBorderStyle nStyle = pVclPeer->GetBorderStyle();
1297 nStyle |= WindowBorderStyle::NONATIVEBORDER;
1298 pVclPeer->SetBorderStyle(nStyle);
1300 // KEEP IN SYNC WITH ControlCharacterDialog::translatePropertiesToItems
1301 AllSettings aAllSettings = pVclPeer->GetSettings();
1302 StyleSettings aStyleSettings = aAllSettings.GetStyleSettings();
1303 aStyleSettings.SetStandardStyles();
1304 aAllSettings.SetStyleSettings(aStyleSettings);
1305 pVclPeer->SetSettings(aAllSettings);
1309 // the updateFromModel is done without a locked mutex, too.
1310 // The reason is that the only thing this method does is firing property changes, and this in general has
1311 // to be done without locked mutexes (as every notification to external listeners).
1312 // 82300 - 12/21/00 - FS
1313 updateFromModel();
1315 xView->setZoom( aComponentInfos.nZoomX, aComponentInfos.nZoomY );
1317 setPosSize( aComponentInfos.nX, aComponentInfos.nY, aComponentInfos.nWidth, aComponentInfos.nHeight, aComponentInfos.nFlags );
1319 if( aComponentInfos.bVisible && !bDesignMode )
1320 // Show only after setting the data
1321 xWindow->setVisible( aComponentInfos.bVisible );
1323 if( !aComponentInfos.bEnable )
1324 xWindow->setEnable( aComponentInfos.bEnable );
1326 xView->setGraphics( xGraphics );
1328 peerCreated();
1330 mbCreatingPeer = false;
1334 Reference< XWindowPeer > UnoControl::getPeer()
1336 ::osl::MutexGuard aGuard( GetMutex() );
1337 return mxVclWindowPeer;
1340 Reference< XVclWindowPeer > UnoControl::getVclWindowPeer()
1342 ::osl::MutexGuard aGuard( GetMutex() );
1343 return mxVclWindowPeer;
1346 sal_Bool UnoControl::setModel( const Reference< XControlModel >& rxModel )
1348 ::osl::MutexGuard aGuard( GetMutex() );
1350 Reference< XMultiPropertySet > xPropSet( mxModel, UNO_QUERY );
1352 // query for the XPropertiesChangeListener - our delegator is allowed to overwrite this interface
1353 Reference< XPropertiesChangeListener > xListener;
1354 queryInterface( cppu::UnoType<decltype(xListener)>::get() ) >>= xListener;
1356 if( xPropSet.is() )
1357 xPropSet->removePropertiesChangeListener( xListener );
1359 mpData->bLocalizationSupport = false;
1360 mxModel = rxModel;
1362 if( mxModel.is() )
1366 xPropSet.set( mxModel, UNO_QUERY_THROW );
1367 Reference< XPropertySetInfo > xPSI( xPropSet->getPropertySetInfo(), UNO_SET_THROW );
1369 Sequence< OUString> aNames = lcl_ImplGetPropertyNames( xPropSet );
1370 xPropSet->addPropertiesChangeListener( aNames, xListener );
1372 mpData->bLocalizationSupport = xPSI->hasPropertyByName(u"ResourceResolver"_ustr);
1374 catch( const Exception& )
1376 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
1377 mxModel.clear();
1381 return mxModel.is();
1384 Reference< XControlModel > UnoControl::getModel( )
1386 return mxModel;
1389 Reference< XView > UnoControl::getView( )
1391 return static_cast< XView* >( this );
1394 void UnoControl::setDesignMode( sal_Bool bOn )
1396 ModeChangeEvent aModeChangeEvent;
1398 Reference< XWindow > xWindow;
1399 Reference<XComponent> xAccessibleComp;
1401 ::osl::MutexGuard aGuard( GetMutex() );
1402 if ( bool(bOn) == mbDesignMode )
1403 return;
1405 // remember this
1406 mbDesignMode = bOn;
1407 xWindow.set(getPeer(), css::uno::UNO_QUERY);
1409 xAccessibleComp.set(maAccessibleContext, UNO_QUERY);
1410 maAccessibleContext.clear();
1412 aModeChangeEvent.Source = *this;
1413 aModeChangeEvent.NewMode = mbDesignMode ? std::u16string_view(u"design") : std::u16string_view(u"alive" );
1416 // dispose current AccessibleContext, if we have one - without Mutex lock
1417 // (changing the design mode implies having a new implementation for this context,
1418 // so the old one must be declared DEFUNC)
1419 DisposeAccessibleContext(xAccessibleComp);
1421 // adjust the visibility of our window
1422 if ( xWindow.is() )
1423 xWindow->setVisible( !bOn );
1425 // and notify our mode listeners
1426 maModeChangeListeners.notifyEach( &XModeChangeListener::modeChanged, aModeChangeEvent );
1429 sal_Bool UnoControl::isDesignMode( )
1431 return mbDesignMode;
1434 sal_Bool UnoControl::isTransparent( )
1436 return false;
1439 // XServiceInfo
1440 OUString UnoControl::getImplementationName( )
1442 OSL_FAIL( "This method should be overridden!" );
1443 return OUString();
1446 sal_Bool UnoControl::supportsService( const OUString& rServiceName )
1448 return cppu::supportsService(this, rServiceName);
1451 Sequence< OUString > UnoControl::getSupportedServiceNames( )
1453 return { u"com.sun.star.awt.UnoControl"_ustr };
1457 Reference< XAccessibleContext > SAL_CALL UnoControl::getAccessibleContext( )
1459 // creation of the context will certainly require the SolarMutex ...
1460 SolarMutexGuard aSolarGuard;
1461 ::osl::MutexGuard aGuard( GetMutex() );
1463 Reference< XAccessibleContext > xCurrentContext( maAccessibleContext.get(), UNO_QUERY );
1464 if ( !xCurrentContext.is() )
1466 if ( !mbDesignMode )
1467 { // in alive mode, use the AccessibleContext of the peer
1468 Reference< XAccessible > xPeerAcc( getPeer(), UNO_QUERY );
1469 if ( xPeerAcc.is() )
1470 xCurrentContext = xPeerAcc->getAccessibleContext( );
1472 else
1473 // in design mode, use a fallback
1474 xCurrentContext = ::toolkit::OAccessibleControlContext::create( this );
1476 DBG_ASSERT( xCurrentContext.is(), "UnoControl::getAccessibleContext: invalid context (invalid peer?)!" );
1477 maAccessibleContext = xCurrentContext;
1479 // get notified when the context is disposed
1480 Reference< XComponent > xContextComp( xCurrentContext, UNO_QUERY );
1481 if ( xContextComp.is() )
1482 xContextComp->addEventListener( this );
1483 // In an ideal world, this is not necessary - there the object would be released as soon as it has been
1484 // disposed, and thus our weak reference would be empty, too.
1485 // But 'til this ideal world comes (means 'til we do never have any refcount/lifetime bugs anymore), we
1486 // need to listen for disposal and reset our weak reference then.
1489 return xCurrentContext;
1492 void SAL_CALL UnoControl::addModeChangeListener( const Reference< XModeChangeListener >& _rxListener )
1494 ::osl::MutexGuard aGuard( GetMutex() );
1495 maModeChangeListeners.addInterface( _rxListener );
1498 void SAL_CALL UnoControl::removeModeChangeListener( const Reference< XModeChangeListener >& _rxListener )
1500 ::osl::MutexGuard aGuard( GetMutex() );
1501 maModeChangeListeners.removeInterface( _rxListener );
1504 void SAL_CALL UnoControl::addModeChangeApproveListener( const Reference< XModeChangeApproveListener >& )
1506 throw NoSupportException( );
1509 void SAL_CALL UnoControl::removeModeChangeApproveListener( const Reference< XModeChangeApproveListener >& )
1511 throw NoSupportException( );
1515 awt::Point SAL_CALL UnoControl::convertPointToLogic( const awt::Point& i_Point, ::sal_Int16 i_TargetUnit )
1517 Reference< XUnitConversion > xPeerConversion;
1519 ::osl::MutexGuard aGuard( GetMutex() );
1520 xPeerConversion.set(getPeer(), css::uno::UNO_QUERY);
1522 if ( xPeerConversion.is() )
1523 return xPeerConversion->convertPointToLogic( i_Point, i_TargetUnit );
1524 return awt::Point( );
1528 awt::Point SAL_CALL UnoControl::convertPointToPixel( const awt::Point& i_Point, ::sal_Int16 i_SourceUnit )
1530 Reference< XUnitConversion > xPeerConversion;
1532 ::osl::MutexGuard aGuard( GetMutex() );
1533 xPeerConversion.set(getPeer(), css::uno::UNO_QUERY);
1535 if ( xPeerConversion.is() )
1536 return xPeerConversion->convertPointToPixel( i_Point, i_SourceUnit );
1537 return awt::Point( );
1541 awt::Size SAL_CALL UnoControl::convertSizeToLogic( const awt::Size& i_Size, ::sal_Int16 i_TargetUnit )
1543 Reference< XUnitConversion > xPeerConversion;
1545 ::osl::MutexGuard aGuard( GetMutex() );
1546 xPeerConversion.set(getPeer(), css::uno::UNO_QUERY);
1548 if ( xPeerConversion.is() )
1549 return xPeerConversion->convertSizeToLogic( i_Size, i_TargetUnit );
1550 return awt::Size( );
1554 awt::Size SAL_CALL UnoControl::convertSizeToPixel( const awt::Size& i_Size, ::sal_Int16 i_SourceUnit )
1556 Reference< XUnitConversion > xPeerConversion;
1558 ::osl::MutexGuard aGuard( GetMutex() );
1559 xPeerConversion.set(getPeer(), css::uno::UNO_QUERY);
1561 if ( xPeerConversion.is() )
1562 return xPeerConversion->convertSizeToPixel( i_Size, i_SourceUnit );
1563 return awt::Size( );
1567 uno::Reference< awt::XStyleSettings > SAL_CALL UnoControl::getStyleSettings()
1569 Reference< awt::XStyleSettingsSupplier > xPeerSupplier;
1571 ::osl::MutexGuard aGuard( GetMutex() );
1572 xPeerSupplier.set(getPeer(), css::uno::UNO_QUERY);
1574 if ( xPeerSupplier.is() )
1575 return xPeerSupplier->getStyleSettings();
1576 return nullptr;
1579 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */