Line data Source code
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 "composeduiupdate.hxx"
21 :
22 : #include <com/sun/star/inspection/XObjectInspectorUI.hpp>
23 : #include <com/sun/star/lang/DisposedException.hpp>
24 : #include <com/sun/star/inspection/PropertyLineElement.hpp>
25 : #include <osl/mutex.hxx>
26 : #include <rtl/ref.hxx>
27 :
28 : #include <algorithm>
29 :
30 :
31 : namespace pcr
32 : {
33 :
34 :
35 : using ::com::sun::star::uno::Exception;
36 : using ::com::sun::star::lang::DisposedException;
37 : using ::com::sun::star::lang::NullPointerException;
38 : using ::com::sun::star::inspection::XPropertyHandler;
39 : using ::com::sun::star::uno::Reference;
40 : using ::com::sun::star::inspection::XObjectInspectorUI;
41 : using ::com::sun::star::inspection::XPropertyControl;
42 : using ::com::sun::star::uno::RuntimeException;
43 : using ::com::sun::star::lang::NoSupportException;
44 : using ::com::sun::star::inspection::XPropertyControlObserver;
45 :
46 : namespace PropertyLineElement = ::com::sun::star::inspection::PropertyLineElement;
47 :
48 :
49 : //= helper
50 :
51 : namespace
52 : {
53 : struct HandlerLess : public ::std::binary_function < Reference< XPropertyHandler >
54 : , Reference< XPropertyHandler >
55 : , bool
56 : >
57 : {
58 0 : bool operator()( const Reference< XPropertyHandler >& lhs, const Reference< XPropertyHandler >& rhs) const
59 : {
60 0 : return lhs.get() < rhs.get();
61 : }
62 : };
63 :
64 :
65 : typedef ::std::set< OUString > StringBag;
66 : typedef ::std::map< sal_Int16, StringBag > MapIntToStringBag;
67 : }
68 :
69 :
70 : //= callbacks for CachedInspectorUI
71 :
72 : typedef void (ComposedPropertyUIUpdate::*FNotifySingleUIChange)();
73 :
74 :
75 : //= CachedInspectorUI
76 :
77 : typedef ::cppu::WeakImplHelper1 < ::com::sun::star::inspection::XObjectInspectorUI
78 : > CachedInspectorUI_Base;
79 : struct CachedInspectorUI : public CachedInspectorUI_Base
80 : {
81 : private:
82 : ::osl::Mutex m_aMutex;
83 : oslInterlockedCount m_refCount;
84 : bool m_bDisposed;
85 : ComposedPropertyUIUpdate&
86 : m_rMaster;
87 : FNotifySingleUIChange m_pUIChangeNotification;
88 :
89 : // enablePropertyUI cache
90 : StringBag aEnabledProperties;
91 : StringBag aDisabledProperties;
92 :
93 : // show/hidePropertyUI cache
94 : StringBag aShownProperties;
95 : StringBag aHiddenProperties;
96 :
97 : // rebuildPropertyUI cache
98 : StringBag aRebuiltProperties;
99 :
100 : // showCategory cache
101 : StringBag aShownCategories;
102 : StringBag aHiddenCategories;
103 :
104 : // enablePropertyUIElements cache
105 : MapIntToStringBag aEnabledElements;
106 : MapIntToStringBag aDisabledElements;
107 :
108 : public:
109 : typedef StringBag& (CachedInspectorUI::*FGetStringBag)();
110 :
111 : // enablePropertyUI cache
112 0 : StringBag& getEnabledProperties() { return aEnabledProperties; }
113 0 : StringBag& getDisabledProperties() { return aDisabledProperties; }
114 :
115 : // show/hidePropertyUI cache
116 0 : StringBag& getShownProperties() { return aShownProperties; }
117 0 : StringBag& getHiddenProperties() { return aHiddenProperties; }
118 :
119 : // rebuildPropertyUI cache
120 0 : StringBag& getRebuiltProperties() { return aRebuiltProperties; }
121 :
122 : // showCategory cache
123 0 : StringBag& getShownCategories() { return aShownCategories; }
124 0 : StringBag& getHiddenCategories() { return aHiddenCategories; }
125 :
126 : // enablePropertyUIElements
127 0 : StringBag& getEnabledInputControls() { return aEnabledElements[ PropertyLineElement::InputControl ]; }
128 0 : StringBag& getDisabledInputControls() { return aDisabledElements[ PropertyLineElement::InputControl ]; }
129 0 : StringBag& getEnabledPrimaryButtons() { return aEnabledElements[ PropertyLineElement::PrimaryButton ]; }
130 0 : StringBag& getDisabledPrimaryButtons() { return aDisabledElements[ PropertyLineElement::PrimaryButton ]; }
131 0 : StringBag& getEnabledSecondaryButtons() { return aEnabledElements[ PropertyLineElement::SecondaryButton ]; }
132 0 : StringBag& getDisabledSecondaryButtons() { return aDisabledElements[ PropertyLineElement::SecondaryButton ]; }
133 :
134 : public:
135 : CachedInspectorUI( ComposedPropertyUIUpdate& _rMaster, FNotifySingleUIChange _pUIChangeNotification );
136 :
137 : /// disposes the instance
138 : void dispose();
139 :
140 : // XObjectInspectorUI overridables
141 : virtual void SAL_CALL enablePropertyUI( const OUString& _rPropertyName, sal_Bool _bEnable ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
142 : virtual void SAL_CALL enablePropertyUIElements( const OUString& _rPropertyName, ::sal_Int16 _nElements, sal_Bool _bEnable ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
143 : virtual void SAL_CALL rebuildPropertyUI( const OUString& _rPropertyName ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
144 : virtual void SAL_CALL showPropertyUI( const OUString& _rPropertyName ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
145 : virtual void SAL_CALL hidePropertyUI( const OUString& _rPropertyName ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
146 : virtual void SAL_CALL showCategory( const OUString& _rCategory, sal_Bool _bShow ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
147 : virtual Reference< XPropertyControl > SAL_CALL getPropertyControl( const OUString& _rPropertyName ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
148 : virtual void SAL_CALL registerControlObserver( const Reference< XPropertyControlObserver >& Observer ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
149 : virtual void SAL_CALL revokeControlObserver( const Reference< XPropertyControlObserver >& Observer ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
150 : virtual void SAL_CALL setHelpSectionText( const OUString& _HelpText ) throw (NoSupportException, RuntimeException, std::exception) SAL_OVERRIDE;
151 :
152 : // UNOCompatibleNonUNOReference overridables
153 : virtual void SAL_CALL acquire() throw() SAL_OVERRIDE;
154 : virtual void SAL_CALL release() throw() SAL_OVERRIDE;
155 :
156 : protected:
157 : virtual ~CachedInspectorUI();
158 :
159 : /// determines whether the instance is already disposed
160 0 : inline bool isDisposed() const { return m_bDisposed; }
161 :
162 : /// throws an exception if the component is already disposed
163 : void checkDisposed() const;
164 :
165 : private:
166 : void impl_markElementEnabledOrDisabled( const OUString& _rPropertyName, sal_Int16 _nElementIdOrZero, sal_Bool _bEnable );
167 :
168 : /** calls <member>m_pUIChangeNotification</member> at <member>m_rMaster</member>
169 : */
170 : void impl_notifySingleUIChange() const;
171 :
172 : private:
173 : CachedInspectorUI( const CachedInspectorUI& ); // never implemented
174 : CachedInspectorUI& operator=( const CachedInspectorUI& ); // never implemented
175 :
176 : private:
177 : class MethodGuard;
178 : friend class MethodGuard;
179 0 : class MethodGuard : public ::osl::MutexGuard
180 : {
181 : public:
182 0 : MethodGuard( CachedInspectorUI& rInstance )
183 0 : : ::osl::MutexGuard( rInstance.m_aMutex )
184 : {
185 0 : rInstance.checkDisposed();
186 0 : }
187 : };
188 : };
189 :
190 :
191 0 : CachedInspectorUI::CachedInspectorUI( ComposedPropertyUIUpdate& _rMaster, FNotifySingleUIChange _pUIChangeNotification )
192 : :m_refCount( 0 )
193 : ,m_bDisposed( false )
194 : ,m_rMaster( _rMaster )
195 0 : ,m_pUIChangeNotification( _pUIChangeNotification )
196 : {
197 0 : }
198 :
199 :
200 0 : CachedInspectorUI::~CachedInspectorUI()
201 : {
202 0 : }
203 :
204 :
205 0 : void CachedInspectorUI::dispose()
206 : {
207 0 : ::osl::MutexGuard aGuard( m_aMutex );
208 0 : m_bDisposed = true;
209 :
210 0 : clearContainer( aEnabledProperties );
211 0 : clearContainer( aDisabledProperties );
212 0 : clearContainer( aRebuiltProperties );
213 0 : clearContainer( aShownProperties );
214 0 : clearContainer( aHiddenProperties );
215 0 : clearContainer( aShownCategories );
216 0 : clearContainer( aHiddenCategories );
217 0 : clearContainer( aEnabledElements );
218 0 : clearContainer( aDisabledElements );
219 0 : }
220 :
221 :
222 0 : void SAL_CALL CachedInspectorUI::acquire() throw()
223 : {
224 0 : osl_atomic_increment( &m_refCount );
225 0 : }
226 :
227 :
228 0 : void SAL_CALL CachedInspectorUI::release() throw()
229 : {
230 0 : if ( 0 == osl_atomic_decrement( &m_refCount ) )
231 0 : delete this;
232 0 : }
233 :
234 :
235 :
236 0 : void CachedInspectorUI::checkDisposed() const
237 : {
238 0 : if ( isDisposed() )
239 0 : throw DisposedException();
240 0 : }
241 :
242 :
243 : namespace
244 : {
245 0 : void lcl_markStringKeyPositiveOrNegative( const OUString& _rKeyName, StringBag& _rPositives, StringBag& _rNegatives, sal_Bool _bMarkPositive )
246 : {
247 0 : if ( _bMarkPositive )
248 : {
249 0 : _rPositives.insert( _rKeyName );
250 : // if the same key has been remember as in the "negative" list before, clear this information, since it's overruled
251 0 : _rNegatives.erase( _rKeyName );
252 : }
253 : else
254 0 : _rNegatives.insert( _rKeyName );
255 0 : }
256 : }
257 :
258 :
259 0 : void CachedInspectorUI::enablePropertyUI( const OUString& _rPropertyName, sal_Bool _bEnable ) throw (RuntimeException, std::exception)
260 : {
261 0 : MethodGuard aGuard( *this );
262 0 : if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
263 0 : return;
264 :
265 0 : lcl_markStringKeyPositiveOrNegative( _rPropertyName, aEnabledProperties, aDisabledProperties, _bEnable );
266 0 : impl_notifySingleUIChange();
267 : }
268 :
269 :
270 0 : void CachedInspectorUI::impl_markElementEnabledOrDisabled( const OUString& _rPropertyName, sal_Int16 _nElementIdOrZero, sal_Bool _bEnable )
271 : {
272 0 : if ( _nElementIdOrZero == 0 )
273 0 : return;
274 :
275 : lcl_markStringKeyPositiveOrNegative(
276 : _rPropertyName,
277 0 : aEnabledElements[ _nElementIdOrZero ],
278 0 : aDisabledElements[ _nElementIdOrZero ],
279 : _bEnable
280 0 : );
281 : }
282 :
283 :
284 0 : void CachedInspectorUI::impl_notifySingleUIChange() const
285 : {
286 0 : (m_rMaster.*m_pUIChangeNotification)();
287 0 : }
288 :
289 :
290 0 : void CachedInspectorUI::enablePropertyUIElements( const OUString& _rPropertyName, sal_Int16 _nElements, sal_Bool _bEnable ) throw (RuntimeException, std::exception)
291 : {
292 0 : MethodGuard aGuard( *this );
293 0 : if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
294 0 : return;
295 :
296 0 : impl_markElementEnabledOrDisabled( _rPropertyName, _nElements & PropertyLineElement::InputControl, _bEnable );
297 0 : impl_markElementEnabledOrDisabled( _rPropertyName, _nElements & PropertyLineElement::PrimaryButton, _bEnable );
298 0 : impl_markElementEnabledOrDisabled( _rPropertyName, _nElements & PropertyLineElement::SecondaryButton, _bEnable );
299 :
300 0 : impl_notifySingleUIChange();
301 : }
302 :
303 :
304 0 : void CachedInspectorUI::rebuildPropertyUI( const OUString& _rPropertyName ) throw (RuntimeException, std::exception)
305 : {
306 0 : MethodGuard aGuard( *this );
307 0 : if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
308 0 : return;
309 :
310 0 : aRebuiltProperties.insert( _rPropertyName );
311 :
312 0 : impl_notifySingleUIChange();
313 : }
314 :
315 :
316 0 : void CachedInspectorUI::showPropertyUI( const OUString& _rPropertyName ) throw (RuntimeException, std::exception)
317 : {
318 0 : MethodGuard aGuard( *this );
319 0 : if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
320 0 : return;
321 :
322 0 : aShownProperties.insert( _rPropertyName );
323 : // if the same category has been hidden before, clear this information, since it's overruled
324 0 : aHiddenProperties.erase( _rPropertyName );
325 :
326 0 : impl_notifySingleUIChange();
327 : }
328 :
329 :
330 0 : void CachedInspectorUI::hidePropertyUI( const OUString& _rPropertyName ) throw (RuntimeException, std::exception)
331 : {
332 0 : MethodGuard aGuard( *this );
333 0 : if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
334 0 : return;
335 :
336 0 : aHiddenProperties.insert( _rPropertyName );
337 0 : impl_notifySingleUIChange();
338 : }
339 :
340 :
341 0 : void CachedInspectorUI::showCategory( const OUString& _rCategory, sal_Bool _bShow ) throw (RuntimeException, std::exception)
342 : {
343 0 : MethodGuard aGuard( *this );
344 :
345 0 : lcl_markStringKeyPositiveOrNegative( _rCategory, aShownCategories, aHiddenCategories, _bShow );
346 0 : impl_notifySingleUIChange();
347 0 : }
348 :
349 :
350 0 : Reference< XPropertyControl > SAL_CALL CachedInspectorUI::getPropertyControl( const OUString& _rPropertyName ) throw (RuntimeException, std::exception)
351 : {
352 0 : MethodGuard aGuard( *this );
353 0 : if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
354 0 : return Reference< XPropertyControl >();
355 :
356 0 : return m_rMaster.getDelegatorUI()->getPropertyControl( _rPropertyName );
357 : }
358 :
359 :
360 0 : void SAL_CALL CachedInspectorUI::registerControlObserver( const Reference< XPropertyControlObserver >& _Observer ) throw (RuntimeException, std::exception)
361 : {
362 : OSL_FAIL( "CachedInspectorUI::registerControlObserver: not expected to be called!" );
363 : // CachedInspectorUI is used as context for the controls, and we don't expect them to
364 : // register listeners themself
365 0 : m_rMaster.getDelegatorUI()->registerControlObserver( _Observer );
366 0 : }
367 :
368 :
369 0 : void SAL_CALL CachedInspectorUI::revokeControlObserver( const Reference< XPropertyControlObserver >& _Observer ) throw (RuntimeException, std::exception)
370 : {
371 : OSL_FAIL( "CachedInspectorUI::revokeControlObserver: not expected to be called!" );
372 : // CachedInspectorUI is used as context for the controls, and we don't expect them to
373 : // register listeners themself
374 0 : m_rMaster.getDelegatorUI()->revokeControlObserver( _Observer );
375 0 : }
376 :
377 :
378 0 : void SAL_CALL CachedInspectorUI::setHelpSectionText( const OUString& _HelpText ) throw (NoSupportException, RuntimeException, std::exception)
379 : {
380 0 : m_rMaster.getDelegatorUI()->setHelpSectionText( _HelpText );
381 0 : }
382 :
383 :
384 : //= HandlerMap
385 :
386 : typedef ::std::map < Reference< XPropertyHandler >
387 : , ::rtl::Reference< CachedInspectorUI >
388 : , HandlerLess
389 : > ImplMapHandlerToUI;
390 0 : struct MapHandlerToUI
391 : {
392 : ImplMapHandlerToUI aHandlers;
393 : };
394 :
395 :
396 : //= ComposedPropertyUIUpdate
397 :
398 :
399 0 : ComposedPropertyUIUpdate::ComposedPropertyUIUpdate( const Reference< XObjectInspectorUI >& _rxDelegatorUI,
400 : IPropertyExistenceCheck* _pPropertyCheck )
401 0 : :m_pCollectedUIs( new MapHandlerToUI )
402 : ,m_xDelegatorUI( _rxDelegatorUI )
403 : ,m_nSuspendCounter( 0 )
404 0 : ,m_pPropertyCheck( _pPropertyCheck )
405 : {
406 0 : if ( !m_xDelegatorUI.is() )
407 0 : throw NullPointerException();
408 0 : }
409 :
410 :
411 0 : ComposedPropertyUIUpdate::~ComposedPropertyUIUpdate( )
412 : {
413 0 : }
414 :
415 :
416 0 : Reference< XObjectInspectorUI > ComposedPropertyUIUpdate::getUIForPropertyHandler( const Reference< XPropertyHandler >& _rxHandler )
417 : {
418 0 : impl_checkDisposed();
419 :
420 0 : ::rtl::Reference< CachedInspectorUI >& rUI = m_pCollectedUIs->aHandlers[ _rxHandler ];
421 0 : if ( !rUI.is() )
422 0 : rUI = new CachedInspectorUI( *this, &ComposedPropertyUIUpdate::callback_inspectorUIChanged_throw );
423 0 : return rUI.get();
424 : }
425 :
426 :
427 : namespace
428 : {
429 :
430 : //= StringBagCollector
431 :
432 : /** an STL-compatible structure which collects strings from a CachedInspectorUI instances
433 : */
434 : struct StringBagCollector : public ::std::unary_function< ImplMapHandlerToUI::value_type, void >
435 : {
436 : private:
437 : StringBag& m_rBag;
438 : CachedInspectorUI::FGetStringBag m_pGetter;
439 :
440 : public:
441 0 : StringBagCollector( StringBag& _rBag, CachedInspectorUI::FGetStringBag _pGetter ) :m_rBag( _rBag ), m_pGetter( _pGetter ) { }
442 :
443 0 : void operator()( const ImplMapHandlerToUI::value_type& _rUI )
444 : {
445 0 : StringBag& rBag( ((_rUI.second.get())->*m_pGetter)() );
446 0 : m_rBag.insert( rBag.begin(), rBag.end() );
447 0 : }
448 :
449 0 : static void collectAll( StringBag& _rAll, const ImplMapHandlerToUI& _rMap, CachedInspectorUI::FGetStringBag _pGetter )
450 : {
451 0 : ::std::for_each( _rMap.begin(), _rMap.end(), StringBagCollector( _rAll, _pGetter ) );
452 0 : }
453 : };
454 :
455 :
456 : //= StringBagClearer
457 :
458 : /** an STL-compatible structure which cleans a certain string bag in a CachedInspectorUI instances
459 : */
460 : struct StringBagClearer : public ::std::unary_function< ImplMapHandlerToUI::value_type, void >
461 : {
462 : private:
463 : CachedInspectorUI::FGetStringBag m_pGetter;
464 :
465 : public:
466 0 : StringBagClearer( CachedInspectorUI::FGetStringBag _pGetter ) :m_pGetter( _pGetter ) { }
467 :
468 0 : void operator()( const ImplMapHandlerToUI::value_type& _rUI )
469 : {
470 0 : clearContainer( ((_rUI.second.get())->*m_pGetter)() );
471 0 : }
472 :
473 0 : static void clearAll( const ImplMapHandlerToUI& _rMap, CachedInspectorUI::FGetStringBag _pGetter )
474 : {
475 0 : ::std::for_each( _rMap.begin(), _rMap.end(), StringBagClearer( _pGetter ) );
476 0 : }
477 : };
478 :
479 :
480 : //= FPropertyUISetter
481 :
482 : /** a typedef for a ->XObjectInspectorUI member function taking a string
483 : */
484 : typedef void ( SAL_CALL XObjectInspectorUI::*FPropertyUISetter )( const OUString& );
485 :
486 :
487 : //= PropertyUIOperator
488 :
489 : /** an STL-compatible struct which calls a certain member method (taking a string) at a
490 : given ->XObjectInspectorUI instance
491 : */
492 0 : struct PropertyUIOperator : public ::std::unary_function< OUString, void >
493 : {
494 : private:
495 : Reference< XObjectInspectorUI > m_xUpdater;
496 : FPropertyUISetter m_pSetter;
497 :
498 : public:
499 0 : PropertyUIOperator( const Reference< XObjectInspectorUI >& _rxInspectorUI, FPropertyUISetter _pSetter )
500 : :m_xUpdater( _rxInspectorUI )
501 0 : ,m_pSetter( _pSetter )
502 : {
503 0 : }
504 :
505 0 : void operator()( const OUString& _rPropertyName )
506 : {
507 0 : ((m_xUpdater.get())->*m_pSetter)( _rPropertyName );
508 0 : }
509 :
510 0 : static void forEach( const StringBag& _rProperties, const Reference< XObjectInspectorUI >& _rxDelegatorUI, FPropertyUISetter _pSetter )
511 : {
512 0 : ::std::for_each( _rProperties.begin(), _rProperties.end(), PropertyUIOperator( _rxDelegatorUI, _pSetter ) );
513 0 : }
514 : };
515 :
516 :
517 : //= IStringKeyBooleanUIUpdate
518 :
519 : /** an interface which encapsulates access to a single aspect of the ->XObjectInspectorUI,
520 : where this aspect is given by a string key, and has a boolean value.
521 : */
522 0 : class IStringKeyBooleanUIUpdate
523 : {
524 : public:
525 : virtual void updateUIForKey( const OUString& _rKey, sal_Bool _bFlag ) const = 0;
526 :
527 0 : virtual ~IStringKeyBooleanUIUpdate() { }
528 : };
529 :
530 :
531 : //= FPropertyUIFlagSetter
532 :
533 : /** an implementation of the ->IStringKeyBooleanUIUpdate interface which,
534 : for a fixed ->XObjectInspectorUI instance and a fixed UI element (->PropertyLineElement),
535 : updates this element for a given property with a given boolean flag
536 : (->XObjectInspectorUI::enablePropertyUIElements)
537 : */
538 0 : class EnablePropertyUIElement : public IStringKeyBooleanUIUpdate
539 : {
540 : private:
541 : Reference< XObjectInspectorUI > m_xUIUpdate;
542 : sal_Int16 m_nElement;
543 :
544 : public:
545 0 : EnablePropertyUIElement( const Reference< XObjectInspectorUI >& _rxUIUpdate, sal_Int16 _nElement )
546 : :m_xUIUpdate( _rxUIUpdate )
547 0 : ,m_nElement( _nElement )
548 : {
549 0 : }
550 : // IStringKeyBooleanUIUpdate
551 : virtual void updateUIForKey( const OUString& _rKey, sal_Bool _bFlag ) const SAL_OVERRIDE;
552 : };
553 :
554 :
555 0 : void EnablePropertyUIElement::updateUIForKey( const OUString& _rKey, sal_Bool _bFlag ) const
556 : {
557 0 : m_xUIUpdate->enablePropertyUIElements( _rKey, m_nElement, _bFlag );
558 0 : }
559 :
560 :
561 : //= FPropertyUIFlagSetter
562 :
563 : /** a ->XObjectInspectorUI method taking a string and a boolean
564 : */
565 : typedef void ( SAL_CALL XObjectInspectorUI::*FPropertyUIFlagSetter )( const OUString&, sal_Bool );
566 :
567 :
568 : //= DefaultStringKeyBooleanUIUpdate
569 :
570 : /** an implementaiton of the ->IStringKeyBooleanUIUpdate interface which calls
571 : am arbitrary ->XObjectInspectorUI method taking a string and a boolean flag
572 : */
573 0 : class DefaultStringKeyBooleanUIUpdate : public IStringKeyBooleanUIUpdate
574 : {
575 : private:
576 : Reference< XObjectInspectorUI > m_xUIUpdate;
577 : FPropertyUIFlagSetter m_pSetter;
578 :
579 : public:
580 : DefaultStringKeyBooleanUIUpdate( const Reference< XObjectInspectorUI >& _rxUIUpdate, FPropertyUIFlagSetter _pSetter );
581 : // IStringKeyBooleanUIUpdate
582 : virtual void updateUIForKey( const OUString& _rKey, sal_Bool _bFlag ) const SAL_OVERRIDE;
583 : };
584 :
585 :
586 0 : DefaultStringKeyBooleanUIUpdate::DefaultStringKeyBooleanUIUpdate( const Reference< XObjectInspectorUI >& _rxUIUpdate, FPropertyUIFlagSetter _pSetter )
587 : :m_xUIUpdate( _rxUIUpdate )
588 0 : ,m_pSetter( _pSetter )
589 : {
590 0 : }
591 :
592 :
593 0 : void DefaultStringKeyBooleanUIUpdate::updateUIForKey( const OUString& _rKey, sal_Bool _bFlag ) const
594 : {
595 0 : ((m_xUIUpdate.get())->*m_pSetter)( _rKey, _bFlag );
596 0 : }
597 :
598 :
599 : //= BooleanUIAspectUpdate
600 :
601 : /** an STL-compatible structure which applies a ->IStringKeyBooleanUIUpdate::updateUIForKey
602 : operation with a fixed boolean value, for a given string value
603 : */
604 : struct BooleanUIAspectUpdate : public ::std::unary_function< OUString, void >
605 : {
606 : private:
607 : const IStringKeyBooleanUIUpdate& m_rUpdater;
608 : sal_Bool m_bFlag;
609 :
610 : public:
611 0 : BooleanUIAspectUpdate( const IStringKeyBooleanUIUpdate& _rUpdater, sal_Bool _bFlag )
612 : :m_rUpdater( _rUpdater )
613 0 : ,m_bFlag( _bFlag )
614 : {
615 0 : }
616 :
617 0 : void operator()( const OUString& _rPropertyName )
618 : {
619 0 : m_rUpdater.updateUIForKey( _rPropertyName, m_bFlag );
620 0 : }
621 :
622 0 : static void forEach( const StringBag& _rProperties, const IStringKeyBooleanUIUpdate& _rUpdater, sal_Bool _bFlag )
623 : {
624 0 : ::std::for_each( _rProperties.begin(), _rProperties.end(), BooleanUIAspectUpdate( _rUpdater, _bFlag ) );
625 0 : }
626 : };
627 :
628 :
629 : //= BooleanUIAspectUpdate
630 :
631 : /** an STL-compatible structure subtracting a given string from a fixed ->StringBag
632 : */
633 : struct StringBagComplement : public ::std::unary_function< OUString, void >
634 : {
635 : private:
636 : StringBag& m_rMinuend;
637 :
638 : public:
639 0 : StringBagComplement( StringBag& _rMinuend ) :m_rMinuend( _rMinuend ) { }
640 :
641 0 : void operator()( const OUString& _rPropertyToSubtract )
642 : {
643 0 : m_rMinuend.erase( _rPropertyToSubtract );
644 0 : }
645 :
646 0 : static void subtract( StringBag& _rMinuend, const StringBag& _rSubtrahend )
647 : {
648 0 : ::std::for_each( _rSubtrahend.begin(), _rSubtrahend.end(), StringBagComplement( _rMinuend ) );
649 0 : }
650 : };
651 :
652 :
653 : //= BooleanUIAspectUpdate
654 :
655 0 : void lcl_fireUIStateFlag(
656 : const IStringKeyBooleanUIUpdate& _rUIUpdate,
657 : const ImplMapHandlerToUI& _rHandlerUIs,
658 : CachedInspectorUI::FGetStringBag _pGetPositives,
659 : CachedInspectorUI::FGetStringBag _pGetNegatives
660 : )
661 : {
662 : // all strings which are in the "positive" list of one handler
663 0 : StringBag aAllPositives;
664 0 : StringBagCollector::collectAll( aAllPositives, _rHandlerUIs, _pGetPositives );
665 :
666 : // all strings which are in the "negative" list of one handler
667 0 : StringBag aAllNegatives;
668 0 : StringBagCollector::collectAll( aAllNegatives, _rHandlerUIs, _pGetNegatives );
669 :
670 : // propagate the "negative" flags to the delegator UI
671 0 : BooleanUIAspectUpdate::forEach( aAllNegatives, _rUIUpdate, sal_False );
672 :
673 : // propagate the "positive" flags to the delegator UI, for all elements where _no_
674 : // "negative" flag exists
675 0 : StringBagComplement::subtract( aAllPositives, aAllNegatives );
676 0 : BooleanUIAspectUpdate::forEach( aAllPositives, _rUIUpdate, sal_True );
677 :
678 : // the "positive" request can be cleared no, only negative requests
679 : // (such as "disable a property" or "hide a category") need to be preserved for the next round
680 0 : StringBagClearer::clearAll( _rHandlerUIs, _pGetPositives );
681 0 : }
682 : }
683 :
684 :
685 0 : void ComposedPropertyUIUpdate::impl_fireEnablePropertyUI_throw()
686 : {
687 : lcl_fireUIStateFlag(
688 : DefaultStringKeyBooleanUIUpdate( m_xDelegatorUI, &XObjectInspectorUI::enablePropertyUI ),
689 0 : m_pCollectedUIs->aHandlers,
690 : &CachedInspectorUI::getEnabledProperties,
691 : &CachedInspectorUI::getDisabledProperties
692 0 : );
693 0 : }
694 :
695 :
696 0 : void ComposedPropertyUIUpdate::impl_fireRebuildPropertyUI_throw()
697 : {
698 : // collect all properties for which a rebuild request has been made
699 0 : StringBag aAllRebuilt;
700 0 : StringBagCollector::collectAll( aAllRebuilt, m_pCollectedUIs->aHandlers, &CachedInspectorUI::getRebuiltProperties );
701 :
702 : // rebuild all those properties
703 0 : PropertyUIOperator::forEach( aAllRebuilt, m_xDelegatorUI, &XObjectInspectorUI::rebuildPropertyUI );
704 :
705 : // clear the "properties to rebuild" at all handlers, since the request has been fulfilled now.
706 0 : StringBagClearer::clearAll( m_pCollectedUIs->aHandlers, &CachedInspectorUI::getRebuiltProperties );
707 0 : }
708 :
709 :
710 0 : void ComposedPropertyUIUpdate::impl_fireShowHidePropertyUI_throw()
711 : {
712 : // all properties which have been shown by at least one handler
713 0 : StringBag aAllShown;
714 0 : StringBagCollector::collectAll( aAllShown, m_pCollectedUIs->aHandlers, &CachedInspectorUI::getShownProperties );
715 : // all properties which have been hidden by at least one handler
716 0 : StringBag aAllHidden;
717 0 : StringBagCollector::collectAll( aAllHidden, m_pCollectedUIs->aHandlers, &CachedInspectorUI::getHiddenProperties );
718 :
719 : // hide properties as necessary
720 0 : PropertyUIOperator::forEach( aAllHidden, m_xDelegatorUI, &XObjectInspectorUI::hidePropertyUI );
721 :
722 : // for those properties which are hidden, ignore all "show" requests which other handlers might have had
723 0 : StringBagComplement::subtract( aAllShown, aAllHidden );
724 :
725 : // show properties
726 0 : PropertyUIOperator::forEach( aAllShown, m_xDelegatorUI, &XObjectInspectorUI::showPropertyUI );
727 0 : }
728 :
729 :
730 0 : void ComposedPropertyUIUpdate::impl_fireShowCategory_throw()
731 : {
732 : lcl_fireUIStateFlag(
733 : DefaultStringKeyBooleanUIUpdate( m_xDelegatorUI, &XObjectInspectorUI::showCategory ),
734 0 : m_pCollectedUIs->aHandlers,
735 : &CachedInspectorUI::getShownCategories,
736 : &CachedInspectorUI::getHiddenCategories
737 0 : );
738 0 : }
739 :
740 :
741 0 : void ComposedPropertyUIUpdate::impl_fireEnablePropertyUIElements_throw()
742 : {
743 : lcl_fireUIStateFlag(
744 : EnablePropertyUIElement( m_xDelegatorUI, PropertyLineElement::InputControl ),
745 0 : m_pCollectedUIs->aHandlers,
746 : &CachedInspectorUI::getEnabledInputControls,
747 : &CachedInspectorUI::getDisabledInputControls
748 0 : );
749 :
750 : lcl_fireUIStateFlag(
751 : EnablePropertyUIElement( m_xDelegatorUI, PropertyLineElement::PrimaryButton ),
752 0 : m_pCollectedUIs->aHandlers,
753 : &CachedInspectorUI::getEnabledPrimaryButtons,
754 : &CachedInspectorUI::getDisabledPrimaryButtons
755 0 : );
756 :
757 : lcl_fireUIStateFlag(
758 : EnablePropertyUIElement( m_xDelegatorUI, PropertyLineElement::SecondaryButton ),
759 0 : m_pCollectedUIs->aHandlers,
760 : &CachedInspectorUI::getEnabledSecondaryButtons,
761 : &CachedInspectorUI::getDisabledSecondaryButtons
762 0 : );
763 0 : }
764 :
765 :
766 0 : void ComposedPropertyUIUpdate::impl_fireAll_throw()
767 : {
768 : OSL_PRECOND( !impl_isDisposed(), "ComposedPropertyUIUpdate::impl_fireAll_throw: already disposed, this will crash!" );
769 :
770 0 : impl_fireEnablePropertyUI_throw();
771 0 : impl_fireShowHidePropertyUI_throw();
772 0 : impl_fireRebuildPropertyUI_throw();
773 0 : impl_fireShowCategory_throw();
774 0 : impl_fireEnablePropertyUIElements_throw();
775 0 : }
776 :
777 :
778 0 : void SAL_CALL ComposedPropertyUIUpdate::suspendAutoFire()
779 : {
780 0 : impl_checkDisposed();
781 0 : osl_atomic_increment( &m_nSuspendCounter );
782 0 : }
783 :
784 :
785 0 : void SAL_CALL ComposedPropertyUIUpdate::resumeAutoFire()
786 : {
787 0 : impl_checkDisposed();
788 0 : if ( 0 == osl_atomic_decrement( &m_nSuspendCounter ) )
789 0 : impl_fireAll_throw();
790 0 : }
791 :
792 :
793 0 : void ComposedPropertyUIUpdate::impl_checkDisposed() const
794 : {
795 0 : if ( impl_isDisposed() )
796 0 : throw DisposedException();
797 0 : }
798 :
799 :
800 0 : void ComposedPropertyUIUpdate::callback_inspectorUIChanged_throw()
801 : {
802 0 : if ( 0 == m_nSuspendCounter )
803 0 : impl_fireAll_throw();
804 0 : }
805 :
806 :
807 0 : Reference< XObjectInspectorUI > ComposedPropertyUIUpdate::getDelegatorUI() const
808 : {
809 0 : impl_checkDisposed();
810 0 : return m_xDelegatorUI;
811 : }
812 :
813 :
814 0 : void SAL_CALL ComposedPropertyUIUpdate::dispose()
815 : {
816 0 : if ( impl_isDisposed() )
817 0 : return;
818 :
819 : OSL_ENSURE( m_nSuspendCounter == 0, "ComposedPropertyUIUpdate::dispose: still suspended, the changes will be lost!" );
820 :
821 0 : for ( ImplMapHandlerToUI::const_iterator singleUI = m_pCollectedUIs->aHandlers.begin();
822 0 : singleUI != m_pCollectedUIs->aHandlers.end();
823 : ++singleUI
824 : )
825 : {
826 0 : singleUI->second->dispose();
827 : }
828 0 : m_pCollectedUIs.reset();
829 0 : m_xDelegatorUI.set( NULL );
830 : }
831 :
832 :
833 0 : bool ComposedPropertyUIUpdate::shouldContinuePropertyHandling( const OUString& _rName ) const
834 : {
835 0 : if ( !m_pPropertyCheck )
836 0 : return true;
837 0 : if ( m_pPropertyCheck->hasPropertyByName( _rName ) )
838 0 : return true;
839 0 : return false;
840 : }
841 :
842 :
843 : } // namespace pcr
844 :
845 :
846 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|