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