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