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