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