xref: /AOO41X/main/toolkit/source/controls/unocontrol.cxx (revision b0724fc6948542b2496e16ea247f985ee5987cfe)
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 attemp 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 ususally
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