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