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