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