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