/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_extensions.hxx"
#include "composeduiupdate.hxx"

/** === begin UNO includes === **/
#include <com/sun/star/inspection/XObjectInspectorUI.hpp>
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/inspection/PropertyLineElement.hpp>
/** === end UNO includes === **/
#include <osl/mutex.hxx>
#include <rtl/ref.hxx>

#include <algorithm>

//........................................................................
namespace pcr
{
//........................................................................

    /** === begin UNO using === **/
    using ::com::sun::star::uno::Exception;
    using ::com::sun::star::lang::DisposedException;
    using ::com::sun::star::lang::NullPointerException;
    using ::com::sun::star::inspection::XPropertyHandler;
    using ::com::sun::star::uno::Reference;
    using ::com::sun::star::inspection::XObjectInspectorUI;
    using ::com::sun::star::inspection::XPropertyControl;
    using ::com::sun::star::uno::RuntimeException;
    using ::com::sun::star::lang::NoSupportException;
    using ::com::sun::star::inspection::XPropertyControlObserver;
    /** === end UNO using === **/

    namespace PropertyLineElement = ::com::sun::star::inspection::PropertyLineElement;

    //====================================================================
	//= helper
	//====================================================================
    namespace
    {
        struct HandlerLess : public ::std::binary_function  <	Reference< XPropertyHandler >
									                        ,   Reference< XPropertyHandler >
									                        ,	bool
                                                            >
        {
	        bool operator()( const Reference< XPropertyHandler >& lhs, const Reference< XPropertyHandler >& rhs) const
	        {
		        return lhs.get() < rhs.get();
            }
        };

        //================================================================
        typedef ::std::set< ::rtl::OUString >       StringBag;
        typedef ::std::map< sal_Int16, StringBag >  MapIntToStringBag;
    }

    //====================================================================
	//= callbacks for CachedInspectorUI
	//====================================================================
    typedef void (ComposedPropertyUIUpdate::*FNotifySingleUIChange)();

    //====================================================================
	//= CachedInspectorUI
	//====================================================================
    typedef ::cppu::WeakImplHelper1 <   ::com::sun::star::inspection::XObjectInspectorUI
                                    >   CachedInspectorUI_Base;
    struct CachedInspectorUI : public CachedInspectorUI_Base
    {
    private:
        ::osl::Mutex            m_aMutex;
        oslInterlockedCount     m_refCount;
        bool                    m_bDisposed;
        ComposedPropertyUIUpdate&
                                m_rMaster;
        FNotifySingleUIChange   m_pUIChangeNotification;

        // enablePropertyUI cache
        StringBag               aEnabledProperties;
        StringBag               aDisabledProperties;

        // show/hidePropertyUI cache
        StringBag               aShownProperties;
        StringBag               aHiddenProperties;

        // rebuildPropertyUI cache
        StringBag               aRebuiltProperties;

        // showCategory cache
        StringBag               aShownCategories;
        StringBag               aHiddenCategories;

        // enablePropertyUIElements cache
        MapIntToStringBag       aEnabledElements;
        MapIntToStringBag       aDisabledElements;

    public:
        typedef StringBag& (CachedInspectorUI::*FGetStringBag)();

        // enablePropertyUI cache
        StringBag&  getEnabledProperties()          { return aEnabledProperties; }
        StringBag&  getDisabledProperties()         { return aDisabledProperties; }

        // show/hidePropertyUI cache
        StringBag&  getShownProperties()            { return aShownProperties; }
        StringBag&  getHiddenProperties()           { return aHiddenProperties; }

        // rebuildPropertyUI cache
        StringBag&  getRebuiltProperties()          { return aRebuiltProperties; }

        // showCategory cache
        StringBag&  getShownCategories()            { return aShownCategories; }
        StringBag&  getHiddenCategories()           { return aHiddenCategories; }

        // enablePropertyUIElements
        StringBag&  getEnabledInputControls()       { return aEnabledElements[ PropertyLineElement::InputControl ]; }
        StringBag&  getDisabledInputControls()      { return aDisabledElements[ PropertyLineElement::InputControl ]; }
        StringBag&  getEnabledPrimaryButtons()      { return aEnabledElements[ PropertyLineElement::PrimaryButton ]; }
        StringBag&  getDisabledPrimaryButtons()     { return aDisabledElements[ PropertyLineElement::PrimaryButton ]; }
        StringBag&  getEnabledSecondaryButtons()    { return aEnabledElements[ PropertyLineElement::SecondaryButton ]; }
        StringBag&  getDisabledSecondaryButtons()   { return aDisabledElements[ PropertyLineElement::SecondaryButton ]; }

    public:
        CachedInspectorUI( ComposedPropertyUIUpdate& _rMaster, FNotifySingleUIChange _pUIChangeNotification );

        /// disposes the instance
        void dispose();

        // XObjectInspectorUI overridables
        virtual void SAL_CALL enablePropertyUI( const ::rtl::OUString& _rPropertyName, ::sal_Bool _bEnable ) throw (RuntimeException);
        virtual void SAL_CALL enablePropertyUIElements( const ::rtl::OUString& _rPropertyName, ::sal_Int16 _nElements, ::sal_Bool _bEnable ) throw (RuntimeException);
        virtual void SAL_CALL rebuildPropertyUI( const ::rtl::OUString& _rPropertyName ) throw (RuntimeException);
        virtual void SAL_CALL showPropertyUI( const ::rtl::OUString& _rPropertyName ) throw (RuntimeException);
        virtual void SAL_CALL hidePropertyUI( const ::rtl::OUString& _rPropertyName ) throw (RuntimeException);
        virtual void SAL_CALL showCategory( const ::rtl::OUString& _rCategory, ::sal_Bool _bShow ) throw (RuntimeException);
        virtual Reference< XPropertyControl > SAL_CALL getPropertyControl( const ::rtl::OUString& _rPropertyName ) throw (RuntimeException);
        virtual void SAL_CALL registerControlObserver( const Reference< XPropertyControlObserver >& Observer ) throw (RuntimeException);
        virtual void SAL_CALL revokeControlObserver( const Reference< XPropertyControlObserver >& Observer ) throw (RuntimeException);
        virtual void SAL_CALL setHelpSectionText( const ::rtl::OUString& _HelpText ) throw (NoSupportException, RuntimeException);

        // UNOCompatibleNonUNOReference overridables
		virtual void SAL_CALL acquire() throw();
		virtual void SAL_CALL release() throw();

    protected:
        ~CachedInspectorUI();

        /// determines whether the instance is already disposed
        inline bool isDisposed() const { return m_bDisposed; }

        /// throws an exception if the component is already disposed
        void checkDisposed() const;

    private:
        void    impl_markElementEnabledOrDisabled( const ::rtl::OUString& _rPropertyName, sal_Int16 _nElementIdOrZero, sal_Bool _bEnable );

        /** calls <member>m_pUIChangeNotification</member> at <member>m_rMaster</member>
        */
        void    impl_notifySingleUIChange() const;

    private:
        CachedInspectorUI( const CachedInspectorUI& );              // never implemented
        CachedInspectorUI& operator=( const CachedInspectorUI& );   // never implemented

    private:
        class MethodGuard;
        friend class MethodGuard;
        class MethodGuard : public ::osl::MutexGuard
        {
        public:
            MethodGuard( CachedInspectorUI& rInstance )
                : ::osl::MutexGuard( rInstance.m_aMutex )
            {
                rInstance.checkDisposed();
            }
        };
    };

    //----------------------------------------------------------------
    CachedInspectorUI::CachedInspectorUI( ComposedPropertyUIUpdate& _rMaster, FNotifySingleUIChange _pUIChangeNotification )
        :m_refCount( 0 )
        ,m_bDisposed( false )
        ,m_rMaster( _rMaster )
        ,m_pUIChangeNotification( _pUIChangeNotification )
    {
    }

    //----------------------------------------------------------------
    CachedInspectorUI::~CachedInspectorUI()
    {
    }

    //----------------------------------------------------------------
    void CachedInspectorUI::dispose()
    {
        ::osl::MutexGuard aGuard( m_aMutex );
        m_bDisposed = true;

        clearContainer( aEnabledProperties );
        clearContainer( aDisabledProperties );
        clearContainer( aRebuiltProperties );
        clearContainer( aShownProperties );
        clearContainer( aHiddenProperties );
        clearContainer( aShownCategories );
        clearContainer( aHiddenCategories );
        clearContainer( aEnabledElements );
        clearContainer( aDisabledElements );
    }

    //----------------------------------------------------------------
    void SAL_CALL CachedInspectorUI::acquire() throw()
    {
        osl_incrementInterlockedCount( &m_refCount );
    }

    //----------------------------------------------------------------
    void SAL_CALL CachedInspectorUI::release() throw()
    {
        if ( 0 == osl_decrementInterlockedCount( &m_refCount ) )
            delete this;
    }


	//----------------------------------------------------------------
    void CachedInspectorUI::checkDisposed() const
    {
        if ( isDisposed() )
            throw DisposedException();
    }

    //----------------------------------------------------------------
    namespace
    {
        void lcl_markStringKeyPositiveOrNegative( const ::rtl::OUString& _rKeyName, StringBag& _rPositives, StringBag& _rNegatives, sal_Bool _bMarkPositive )
        {
            if ( _bMarkPositive )
            {
                _rPositives.insert( _rKeyName );
                // if the same key has been remember as in the "negative" list before, clear this information, since it's overruled
                _rNegatives.erase( _rKeyName );
            }
            else
                _rNegatives.insert( _rKeyName );
        }
    }

    //----------------------------------------------------------------
    void CachedInspectorUI::enablePropertyUI( const ::rtl::OUString& _rPropertyName, sal_Bool _bEnable ) throw (RuntimeException)
    {
        MethodGuard aGuard( *this );
        if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
            return;

        lcl_markStringKeyPositiveOrNegative( _rPropertyName, aEnabledProperties, aDisabledProperties, _bEnable );
        impl_notifySingleUIChange();
    }

    //----------------------------------------------------------------
    void CachedInspectorUI::impl_markElementEnabledOrDisabled( const ::rtl::OUString& _rPropertyName, sal_Int16 _nElementIdOrZero, sal_Bool _bEnable )
    {
        if ( _nElementIdOrZero == 0 )
            return;

        lcl_markStringKeyPositiveOrNegative(
            _rPropertyName,
            aEnabledElements[ _nElementIdOrZero ],
            aDisabledElements[ _nElementIdOrZero ],
            _bEnable
        );
    }

    //----------------------------------------------------------------
    void CachedInspectorUI::impl_notifySingleUIChange() const
    {
        (m_rMaster.*m_pUIChangeNotification)();
    }

    //----------------------------------------------------------------
    void CachedInspectorUI::enablePropertyUIElements( const ::rtl::OUString& _rPropertyName, sal_Int16 _nElements, sal_Bool _bEnable ) throw (RuntimeException)
    {
        MethodGuard aGuard( *this );
        if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
            return;

        impl_markElementEnabledOrDisabled( _rPropertyName, _nElements & PropertyLineElement::InputControl,    _bEnable );
        impl_markElementEnabledOrDisabled( _rPropertyName, _nElements & PropertyLineElement::PrimaryButton,   _bEnable );
        impl_markElementEnabledOrDisabled( _rPropertyName, _nElements & PropertyLineElement::SecondaryButton, _bEnable );

        impl_notifySingleUIChange();
    }

    //----------------------------------------------------------------
    void CachedInspectorUI::rebuildPropertyUI( const ::rtl::OUString& _rPropertyName ) throw (RuntimeException)
    {
        MethodGuard aGuard( *this );
        if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
            return;

        aRebuiltProperties.insert( _rPropertyName );

        impl_notifySingleUIChange();
    }

    //----------------------------------------------------------------
    void CachedInspectorUI::showPropertyUI( const ::rtl::OUString& _rPropertyName ) throw (RuntimeException)
    {
        MethodGuard aGuard( *this );
        if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
            return;

        aShownProperties.insert( _rPropertyName );
        // if the same category has been hidden before, clear this information, since it's overruled
        aHiddenProperties.erase( _rPropertyName );

        impl_notifySingleUIChange();
    }

    //----------------------------------------------------------------
    void CachedInspectorUI::hidePropertyUI( const ::rtl::OUString& _rPropertyName ) throw (RuntimeException)
    {
        MethodGuard aGuard( *this );
        if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
            return;

        aHiddenProperties.insert( _rPropertyName );
        impl_notifySingleUIChange();
    }

    //----------------------------------------------------------------
    void CachedInspectorUI::showCategory( const ::rtl::OUString& _rCategory, sal_Bool _bShow ) throw (RuntimeException)
    {
        MethodGuard aGuard( *this );

        lcl_markStringKeyPositiveOrNegative( _rCategory, aShownCategories, aHiddenCategories, _bShow );
        impl_notifySingleUIChange();
    }

    //----------------------------------------------------------------
    Reference< XPropertyControl > SAL_CALL CachedInspectorUI::getPropertyControl( const ::rtl::OUString& _rPropertyName ) throw (RuntimeException)
    {
        MethodGuard aGuard( *this );
        if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
            return Reference< XPropertyControl >();

        return m_rMaster.getDelegatorUI()->getPropertyControl( _rPropertyName );
    }

    //--------------------------------------------------------------------
    void SAL_CALL CachedInspectorUI::registerControlObserver( const Reference< XPropertyControlObserver >& _Observer ) throw (RuntimeException)
    {
        OSL_ENSURE( false, "CachedInspectorUI::registerControlObserver: not expected to be called!" );
            // CachedInspectorUI is used as context for the controls, and we don't expect them to
            // register listeners themself
        m_rMaster.getDelegatorUI()->registerControlObserver( _Observer );
    }
    
    //--------------------------------------------------------------------
    void SAL_CALL CachedInspectorUI::revokeControlObserver( const Reference< XPropertyControlObserver >& _Observer ) throw (RuntimeException)
    {
        OSL_ENSURE( false, "CachedInspectorUI::revokeControlObserver: not expected to be called!" );
            // CachedInspectorUI is used as context for the controls, and we don't expect them to
            // register listeners themself
        m_rMaster.getDelegatorUI()->revokeControlObserver( _Observer );
    }

    //----------------------------------------------------------------
    void SAL_CALL CachedInspectorUI::setHelpSectionText( const ::rtl::OUString& _HelpText ) throw (NoSupportException, RuntimeException)
    {
        m_rMaster.getDelegatorUI()->setHelpSectionText( _HelpText );
    }

    //====================================================================
	//= HandlerMap
	//====================================================================
    typedef ::std::map  <   Reference< XPropertyHandler >
                        ,   ::rtl::Reference< CachedInspectorUI >
                        ,   HandlerLess
                        >   ImplMapHandlerToUI;
    struct MapHandlerToUI
    {
        ImplMapHandlerToUI aHandlers;
    };

    //====================================================================
	//= ComposedPropertyUIUpdate
	//====================================================================
	//----------------------------------------------------------------
    ComposedPropertyUIUpdate::ComposedPropertyUIUpdate( const Reference< XObjectInspectorUI >& _rxDelegatorUI,
        IPropertyExistenceCheck* _pPropertyCheck )
        :m_pCollectedUIs( new MapHandlerToUI )
        ,m_xDelegatorUI( _rxDelegatorUI )
        ,m_nSuspendCounter( 0 )
        ,m_pPropertyCheck( _pPropertyCheck )
    {
        if ( !m_xDelegatorUI.is() )
            throw NullPointerException();
    }

	//----------------------------------------------------------------
    ComposedPropertyUIUpdate::~ComposedPropertyUIUpdate( )
    {
    }

	//----------------------------------------------------------------
    Reference< XObjectInspectorUI > ComposedPropertyUIUpdate::getUIForPropertyHandler( const Reference< XPropertyHandler >& _rxHandler )
    {
        impl_checkDisposed();

        ::rtl::Reference< CachedInspectorUI >& rUI = m_pCollectedUIs->aHandlers[ _rxHandler ];
        if ( !rUI.is() )
            rUI = new CachedInspectorUI( *this, &ComposedPropertyUIUpdate::callback_inspectorUIChanged_throw );
        return rUI.get();
    }

	//----------------------------------------------------------------
    namespace
    {
        //============================================================
	    //= StringBagCollector
	    //============================================================
        /** an STL-compatible structure which collects strings from a CachedInspectorUI instances
        */
        struct StringBagCollector : public ::std::unary_function< ImplMapHandlerToUI::value_type, void >
        {
        private:
            StringBag&                      m_rBag;
            CachedInspectorUI::FGetStringBag  m_pGetter;

        public:
            StringBagCollector( StringBag& _rBag, CachedInspectorUI::FGetStringBag _pGetter ) :m_rBag( _rBag ), m_pGetter( _pGetter ) { }

            void operator()( const ImplMapHandlerToUI::value_type& _rUI )
            {
                StringBag& rBag( ((_rUI.second.get())->*m_pGetter)() );
                m_rBag.insert( rBag.begin(), rBag.end() );
            }

            static void collectAll( StringBag& _rAll, const ImplMapHandlerToUI& _rMap, CachedInspectorUI::FGetStringBag _pGetter )
            {
                ::std::for_each( _rMap.begin(), _rMap.end(), StringBagCollector( _rAll, _pGetter ) );
            }
        };

        //============================================================
	    //= StringBagClearer
	    //============================================================
        /** an STL-compatible structure which cleans a certain string bag in a CachedInspectorUI instances
        */
        struct StringBagClearer : public ::std::unary_function< ImplMapHandlerToUI::value_type, void >
        {
        private:
            CachedInspectorUI::FGetStringBag  m_pGetter;

        public:
            StringBagClearer( CachedInspectorUI::FGetStringBag _pGetter ) :m_pGetter( _pGetter ) { }

            void operator()( const ImplMapHandlerToUI::value_type& _rUI )
            {
                clearContainer( ((_rUI.second.get())->*m_pGetter)() );
            }

            static void clearAll( const ImplMapHandlerToUI& _rMap, CachedInspectorUI::FGetStringBag _pGetter )
            {
                ::std::for_each( _rMap.begin(), _rMap.end(), StringBagClearer( _pGetter ) );
            }
        };

        //============================================================
	    //= FPropertyUISetter
	    //============================================================
        /** a typedef for a ->XObjectInspectorUI member function taking a string
        */
        typedef void ( SAL_CALL XObjectInspectorUI::*FPropertyUISetter )( const ::rtl::OUString& );

        //============================================================
	    //= PropertyUIOperator
	    //============================================================
        /** an STL-compatible struct which calls a certain member method (taking a string) at a
            given ->XObjectInspectorUI instance
        */
        struct PropertyUIOperator : public ::std::unary_function< ::rtl::OUString, void >
        {
        private:
            Reference< XObjectInspectorUI > m_xUpdater;
            FPropertyUISetter               m_pSetter;

        public:
            PropertyUIOperator( const Reference< XObjectInspectorUI >& _rxInspectorUI, FPropertyUISetter _pSetter )
                :m_xUpdater( _rxInspectorUI )
                ,m_pSetter( _pSetter )
            {
            }

            void operator()( const ::rtl::OUString& _rPropertyName )
            {
                ((m_xUpdater.get())->*m_pSetter)( _rPropertyName );
            }

            static void forEach( const StringBag& _rProperties, const Reference< XObjectInspectorUI >& _rxDelegatorUI, FPropertyUISetter _pSetter )
            {
                ::std::for_each( _rProperties.begin(), _rProperties.end(), PropertyUIOperator( _rxDelegatorUI, _pSetter ) );
            }
        };

        //============================================================
	    //= IStringKeyBooleanUIUpdate
	    //============================================================
        /** an interface which encapsulates access to a single aspect of the ->XObjectInspectorUI,
            where this aspect is given by a string key, and has a boolean value.
        */
        class IStringKeyBooleanUIUpdate
        {
        public:
            virtual void updateUIForKey( const ::rtl::OUString& _rKey, sal_Bool _bFlag ) const = 0;

            virtual ~IStringKeyBooleanUIUpdate() { }
        };

        //============================================================
	    //= FPropertyUIFlagSetter
	    //============================================================
        /** an implementation of the ->IStringKeyBooleanUIUpdate interface which,
            for a fixed ->XObjectInspectorUI instance and a fixed UI element (->PropertyLineElement),
            updates this element for a given property with a given boolean flag
            (->XObjectInspectorUI::enablePropertyUIElements)
        */
        class EnablePropertyUIElement : public IStringKeyBooleanUIUpdate
        {
        private:
            Reference< XObjectInspectorUI > m_xUIUpdate;
            sal_Int16                       m_nElement;

        public:
            EnablePropertyUIElement( const Reference< XObjectInspectorUI >& _rxUIUpdate, sal_Int16 _nElement )
                :m_xUIUpdate( _rxUIUpdate )
                ,m_nElement( _nElement )
            {
            }
            // IStringKeyBooleanUIUpdate
            virtual void updateUIForKey( const ::rtl::OUString& _rKey, sal_Bool _bFlag ) const;
        };

        //............................................................
        void EnablePropertyUIElement::updateUIForKey( const ::rtl::OUString& _rKey, sal_Bool _bFlag ) const
        {
            m_xUIUpdate->enablePropertyUIElements( _rKey, m_nElement, _bFlag );
        }

        //============================================================
	    //= FPropertyUIFlagSetter
	    //============================================================
        /** a ->XObjectInspectorUI method taking a string and a boolean
        */
        typedef void ( SAL_CALL XObjectInspectorUI::*FPropertyUIFlagSetter )( const ::rtl::OUString&, sal_Bool );

        //============================================================
	    //= DefaultStringKeyBooleanUIUpdate
	    //============================================================
        /** an implementaiton of the ->IStringKeyBooleanUIUpdate interface which calls
            am arbitrary ->XObjectInspectorUI method taking a string and a boolean flag
        */
        class DefaultStringKeyBooleanUIUpdate : public IStringKeyBooleanUIUpdate
        {
        private:
            Reference< XObjectInspectorUI > m_xUIUpdate;
            FPropertyUIFlagSetter           m_pSetter;

        public:
            DefaultStringKeyBooleanUIUpdate( const Reference< XObjectInspectorUI >& _rxUIUpdate, FPropertyUIFlagSetter _pSetter );
            // IStringKeyBooleanUIUpdate
            virtual void updateUIForKey( const ::rtl::OUString& _rKey, sal_Bool _bFlag ) const;
        };

        //............................................................
        DefaultStringKeyBooleanUIUpdate::DefaultStringKeyBooleanUIUpdate( const Reference< XObjectInspectorUI >& _rxUIUpdate, FPropertyUIFlagSetter _pSetter )
            :m_xUIUpdate( _rxUIUpdate )
            ,m_pSetter( _pSetter )
        {
        }

        //............................................................
        void DefaultStringKeyBooleanUIUpdate::updateUIForKey( const ::rtl::OUString& _rKey, sal_Bool _bFlag ) const
        {
            ((m_xUIUpdate.get())->*m_pSetter)( _rKey, _bFlag );
        }

        //============================================================
	    //= BooleanUIAspectUpdate
	    //============================================================
        /** an STL-compatible structure which applies a ->IStringKeyBooleanUIUpdate::updateUIForKey
            operation with a fixed boolean value, for a given string value
        */
        struct BooleanUIAspectUpdate : public ::std::unary_function< ::rtl::OUString, void >
        {
        private:
            const IStringKeyBooleanUIUpdate&    m_rUpdater;
            sal_Bool                            m_bFlag;

        public:
            BooleanUIAspectUpdate( const IStringKeyBooleanUIUpdate& _rUpdater, sal_Bool _bFlag )
                :m_rUpdater( _rUpdater )
                ,m_bFlag( _bFlag )
            {
            }

            void operator()( const ::rtl::OUString& _rPropertyName )
            {
                m_rUpdater.updateUIForKey( _rPropertyName, m_bFlag );
            }

            static void forEach( const StringBag& _rProperties, const IStringKeyBooleanUIUpdate& _rUpdater, sal_Bool _bFlag )
            {
                ::std::for_each( _rProperties.begin(), _rProperties.end(), BooleanUIAspectUpdate( _rUpdater, _bFlag ) );
            }
        };

        //============================================================
	    //= BooleanUIAspectUpdate
	    //============================================================
        /** an STL-compatible structure subtracting a given string from a fixed ->StringBag
        */
        struct StringBagComplement : public ::std::unary_function< ::rtl::OUString, void >
        {
        private:
            StringBag&  m_rMinuend;

        public:
            StringBagComplement( StringBag& _rMinuend ) :m_rMinuend( _rMinuend ) { }

            void operator()( const ::rtl::OUString& _rPropertyToSubtract )
            {
                m_rMinuend.erase( _rPropertyToSubtract );
            }

            static void subtract( StringBag& _rMinuend, const StringBag& _rSubtrahend )
            {
                ::std::for_each( _rSubtrahend.begin(), _rSubtrahend.end(), StringBagComplement( _rMinuend ) );
            }
        };

        //============================================================
	    //= BooleanUIAspectUpdate
	    //============================================================
        void lcl_fireUIStateFlag(
                const IStringKeyBooleanUIUpdate& _rUIUpdate,
                const ImplMapHandlerToUI& _rHandlerUIs,
                CachedInspectorUI::FGetStringBag _pGetPositives,
                CachedInspectorUI::FGetStringBag _pGetNegatives
            )
        {
            // all strings which are in the "positive" list of one handler
            StringBag aAllPositives;
            StringBagCollector::collectAll( aAllPositives, _rHandlerUIs, _pGetPositives );

            // all strings which are in the "negative" list of one handler
            StringBag aAllNegatives;
            StringBagCollector::collectAll( aAllNegatives, _rHandlerUIs, _pGetNegatives );

            // propagate the "negative" flags to the delegator UI
            BooleanUIAspectUpdate::forEach( aAllNegatives, _rUIUpdate, sal_False );

            // propagate the "positive" flags to the delegator UI, for all elements where _no_
            // "negative" flag exists
            StringBagComplement::subtract( aAllPositives, aAllNegatives );
            BooleanUIAspectUpdate::forEach( aAllPositives, _rUIUpdate, sal_True );

            // the "positive" request can be cleared no, only negative requests
            // (such as "disable a property" or "hide a category") need to be preserved for the next round
            StringBagClearer::clearAll( _rHandlerUIs, _pGetPositives );
        }
    }

	//----------------------------------------------------------------
    void ComposedPropertyUIUpdate::impl_fireEnablePropertyUI_throw()
    {
        lcl_fireUIStateFlag(
            DefaultStringKeyBooleanUIUpdate( m_xDelegatorUI, &XObjectInspectorUI::enablePropertyUI ),
            m_pCollectedUIs->aHandlers,
            &CachedInspectorUI::getEnabledProperties,
            &CachedInspectorUI::getDisabledProperties
        );
    }

	//----------------------------------------------------------------
    void ComposedPropertyUIUpdate::impl_fireRebuildPropertyUI_throw()
    {
        // collect all properties for which a rebuild request has been made
        StringBag aAllRebuilt;
        StringBagCollector::collectAll( aAllRebuilt, m_pCollectedUIs->aHandlers, &CachedInspectorUI::getRebuiltProperties );

        // rebuild all those properties
        PropertyUIOperator::forEach( aAllRebuilt, m_xDelegatorUI, &XObjectInspectorUI::rebuildPropertyUI );

        // clear the "properties to rebuild" at all handlers, since the request has been fulfilled now.
        StringBagClearer::clearAll( m_pCollectedUIs->aHandlers, &CachedInspectorUI::getRebuiltProperties );
    }

	//----------------------------------------------------------------
    void ComposedPropertyUIUpdate::impl_fireShowHidePropertyUI_throw()
    {
        // all properties which have been shown by at least one handler
        StringBag aAllShown;
        StringBagCollector::collectAll( aAllShown, m_pCollectedUIs->aHandlers, &CachedInspectorUI::getShownProperties );
        // all properties which have been hidden by at least one handler
        StringBag aAllHidden;
        StringBagCollector::collectAll( aAllHidden, m_pCollectedUIs->aHandlers, &CachedInspectorUI::getHiddenProperties );

        // hide properties as necessary
        PropertyUIOperator::forEach( aAllHidden, m_xDelegatorUI, &XObjectInspectorUI::hidePropertyUI );

        // for those properties which are hidden, ignore all "show" requests which other handlers might have had
        StringBagComplement::subtract( aAllShown, aAllHidden );

        // show properties
        PropertyUIOperator::forEach( aAllShown, m_xDelegatorUI, &XObjectInspectorUI::showPropertyUI );
    }

	//----------------------------------------------------------------
    void ComposedPropertyUIUpdate::impl_fireShowCategory_throw()
    {
        lcl_fireUIStateFlag(
            DefaultStringKeyBooleanUIUpdate( m_xDelegatorUI, &XObjectInspectorUI::showCategory ),
            m_pCollectedUIs->aHandlers,
            &CachedInspectorUI::getShownCategories,
            &CachedInspectorUI::getHiddenCategories
        );
    }

	//----------------------------------------------------------------
    void ComposedPropertyUIUpdate::impl_fireEnablePropertyUIElements_throw()
    {
        lcl_fireUIStateFlag(
            EnablePropertyUIElement( m_xDelegatorUI, PropertyLineElement::InputControl ),
            m_pCollectedUIs->aHandlers,
            &CachedInspectorUI::getEnabledInputControls,
            &CachedInspectorUI::getDisabledInputControls
        );

        lcl_fireUIStateFlag(
            EnablePropertyUIElement( m_xDelegatorUI, PropertyLineElement::PrimaryButton ),
            m_pCollectedUIs->aHandlers,
            &CachedInspectorUI::getEnabledPrimaryButtons,
            &CachedInspectorUI::getDisabledPrimaryButtons
        );

        lcl_fireUIStateFlag(
            EnablePropertyUIElement( m_xDelegatorUI, PropertyLineElement::SecondaryButton ),
            m_pCollectedUIs->aHandlers,
            &CachedInspectorUI::getEnabledSecondaryButtons,
            &CachedInspectorUI::getDisabledSecondaryButtons
        );
    }

    //--------------------------------------------------------------------
    void ComposedPropertyUIUpdate::impl_fireAll_throw()
    {
        OSL_PRECOND( !impl_isDisposed(), "ComposedPropertyUIUpdate::impl_fireAll_throw: already disposed, this will crash!" );

        impl_fireEnablePropertyUI_throw();
        impl_fireShowHidePropertyUI_throw();
        impl_fireRebuildPropertyUI_throw();
        impl_fireShowCategory_throw();
        impl_fireEnablePropertyUIElements_throw();
    }

    //--------------------------------------------------------------------
    void SAL_CALL ComposedPropertyUIUpdate::suspendAutoFire()
    {
        impl_checkDisposed();
        osl_incrementInterlockedCount( &m_nSuspendCounter );
    }

    //--------------------------------------------------------------------
    void SAL_CALL ComposedPropertyUIUpdate::resumeAutoFire()
    {
        impl_checkDisposed();
        if ( 0 == osl_decrementInterlockedCount( &m_nSuspendCounter ) )
            impl_fireAll_throw();
    }

	//----------------------------------------------------------------
    void ComposedPropertyUIUpdate::impl_checkDisposed() const
    {
        if ( impl_isDisposed() )
            throw DisposedException();
    }

	//----------------------------------------------------------------
    void ComposedPropertyUIUpdate::callback_inspectorUIChanged_throw()
    {
        if ( 0 == m_nSuspendCounter )
            impl_fireAll_throw();
    }

	//----------------------------------------------------------------
    Reference< XObjectInspectorUI > ComposedPropertyUIUpdate::getDelegatorUI() const
    {
        impl_checkDisposed();
        return m_xDelegatorUI;
    }

    //----------------------------------------------------------------
    void SAL_CALL ComposedPropertyUIUpdate::dispose()
    {
        if ( impl_isDisposed() )
            return;

        OSL_ENSURE( m_nSuspendCounter == 0, "ComposedPropertyUIUpdate::dispose: still suspended, the changes will be lost!" );

        for ( ImplMapHandlerToUI::const_iterator singleUI = m_pCollectedUIs->aHandlers.begin();
              singleUI != m_pCollectedUIs->aHandlers.end();
              ++singleUI
            )
        {
            singleUI->second->dispose();
        }
        m_pCollectedUIs.reset();
        m_xDelegatorUI.set( NULL );
    }

    //----------------------------------------------------------------
    bool ComposedPropertyUIUpdate::shouldContinuePropertyHandling( const ::rtl::OUString& _rName ) const
    {
        if ( !m_pPropertyCheck )
            return true;
        if ( m_pPropertyCheck->hasPropertyByName( _rName ) )
            return true;
        return false;
    }

//........................................................................
} // namespace pcr
//........................................................................

