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