/**************************************************************
 * 
 * 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_framework.hxx"

#include <imagemanagerimpl.hxx>
#include <threadhelp/resetableguard.hxx>
#include <xml/imagesconfiguration.hxx>
#include <uiconfiguration/graphicnameaccess.hxx>
#include <services.h>

#include "properties.h"

//_________________________________________________________________________________________________________________
//	interface includes
//_________________________________________________________________________________________________________________
#include <com/sun/star/ui/UIElementType.hpp>
#include <com/sun/star/ui/ConfigurationEvent.hpp>
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/io/XStream.hpp>
#include <com/sun/star/ui/ImageType.hpp>

//_________________________________________________________________________________________________________________
//	other includes
//_________________________________________________________________________________________________________________

#include <vcl/svapp.hxx>
#include <rtl/ustrbuf.hxx>
#include <osl/mutex.hxx>
#include <comphelper/sequence.hxx>
#include <tools/urlobj.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <vcl/pngread.hxx>
#include <vcl/pngwrite.hxx>
#include <rtl/logfile.hxx>
#include "svtools/miscopt.hxx"

//_________________________________________________________________________________________________________________
//	namespaces
//_________________________________________________________________________________________________________________

using ::rtl::OUString;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::XInterface;
using ::com::sun::star::uno::Exception;
using ::com::sun::star::uno::RuntimeException;
using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::uno::Any;
using ::com::sun::star::uno::makeAny;
using ::com::sun::star::graphic::XGraphic;
using namespace ::com::sun::star;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::embed;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::ui;
using namespace ::cppu;

// Image sizes for our toolbars/menus
const sal_Int32 IMAGE_SIZE_NORMAL         = 16;
const sal_Int32 IMAGE_SIZE_LARGE          = 26;
const sal_Int16 MAX_IMAGETYPE_VALUE       = ::com::sun::star::ui::ImageType::COLOR_HIGHCONTRAST|
                                            ::com::sun::star::ui::ImageType::SIZE_LARGE;

static const char   IMAGE_FOLDER[]        = "images";
static const char   BITMAPS_FOLDER[]      = "Bitmaps";
static const char   IMAGE_EXTENSION[]     = ".png";

static const char*  IMAGELIST_XML_FILE[]  =
{
    "sc_imagelist.xml",
    "lc_imagelist.xml",
    "sch_imagelist.xml",
    "lch_imagelist.xml"
};

static const char*  BITMAP_FILE_NAMES[]   =
{
    "sc_userimages.png",
    "lc_userimages.png",
    "sch_userimages.png",
    "lch_userimages.png"
};

namespace framework
{
    static char ModuleImageList[] = "private:resource/images/moduleimages";
    static osl::Mutex*          pImageListWrapperMutex = 0;
    static GlobalImageList*     pGlobalImageList = 0;
    static const char* ImageType_Prefixes[ImageType_COUNT] =
    {
        "res/commandimagelist/sc_",
        "res/commandimagelist/lc_",
        "res/commandimagelist/sch_",
        "res/commandimagelist/lch_"
    };

typedef GraphicNameAccess CmdToXGraphicNameAccess;

static osl::Mutex& getGlobalImageListMutex()
{
    if ( pImageListWrapperMutex == 0 )
    {
        osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ;
        if ( pImageListWrapperMutex == 0 )
            pImageListWrapperMutex = new osl::Mutex;
    }

    return *pImageListWrapperMutex;
}

static GlobalImageList* getGlobalImageList( const uno::Reference< XMultiServiceFactory >& rServiceManager )
{
    osl::MutexGuard guard( getGlobalImageListMutex() );

    if ( pGlobalImageList == 0 )
        pGlobalImageList = new GlobalImageList( rServiceManager );

    return pGlobalImageList;
}

static rtl::OUString getCanonicalName( const rtl::OUString& rFileName )
{
    bool               bRemoveSlash( true );
    sal_Int32          nLength = rFileName.getLength();
    const sal_Unicode* pString = rFileName.getStr();

    rtl::OUStringBuffer aBuf( nLength );
    for ( sal_Int32 i = 0; i < nLength; i++ )
    {
        const sal_Unicode c = pString[i];
        switch ( c )
        {
            // map forbidden characters to escape
            case '/' : if ( !bRemoveSlash )
                         aBuf.appendAscii( "%2f" ); 
                       break;
            case '\\': aBuf.appendAscii( "%5c" ); bRemoveSlash = false; break;
            case ':' : aBuf.appendAscii( "%3a" ); bRemoveSlash = false; break;
            case '*' : aBuf.appendAscii( "%2a" ); bRemoveSlash = false; break;
            case '?' : aBuf.appendAscii( "%3f" ); bRemoveSlash = false; break;
            case '<' : aBuf.appendAscii( "%3c" ); bRemoveSlash = false; break;
            case '>' : aBuf.appendAscii( "%3e" ); bRemoveSlash = false; break;
            case '|' : aBuf.appendAscii( "%7c" ); bRemoveSlash = false; break;
            default: aBuf.append( c ); bRemoveSlash = false; 
        }
    }
    return aBuf.makeStringAndClear();
}

//_________________________________________________________________________________________________________________

CmdImageList::CmdImageList( const uno::Reference< XMultiServiceFactory >& rServiceManager, const rtl::OUString& aModuleIdentifier ) :
    m_bVectorInit( sal_False ),
    m_aModuleIdentifier( aModuleIdentifier ),
    m_xServiceManager( rServiceManager ),
    m_nSymbolsStyle( SvtMiscOptions().GetCurrentSymbolsStyle() )
{
    for ( sal_Int32 n=0; n < ImageType_COUNT; n++ )
        m_pImageList[n] = 0;
}

CmdImageList::~CmdImageList()
{
    for ( sal_Int32 n=0; n < ImageType_COUNT; n++ )
        delete m_pImageList[n];
}

void CmdImageList::impl_fillCommandToImageNameMap()
{
    RTL_LOGFILE_CONTEXT( aLog, "framework: CmdImageList::impl_fillCommandToImageNameMap" );

    if ( !m_bVectorInit )
    {
        const rtl::OUString aCommandImageList( RTL_CONSTASCII_USTRINGPARAM( UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDIMAGELIST ));
        Sequence< OUString > aCmdImageSeq;
        uno::Reference< XNameAccess > xCmdDesc( m_xServiceManager->createInstance(
                                                SERVICENAME_UICOMMANDDESCRIPTION ),
                                            UNO_QUERY );

        if ( m_aModuleIdentifier.getLength() > 0 )
        {
            // If we have a module identifier - use to retrieve the command image name list from it.
            // Otherwise we will use the global command image list
            try
            {
                xCmdDesc->getByName( m_aModuleIdentifier ) >>= xCmdDesc;
                if ( xCmdDesc.is() )
                    xCmdDesc->getByName( aCommandImageList ) >>= aCmdImageSeq;
            }
            catch ( NoSuchElementException& )
            {
                // Module unknown we will work with an empty command image list!
                return;
            }
        }

        if ( xCmdDesc.is() )
        {
            try
            {
                xCmdDesc->getByName( aCommandImageList ) >>= aCmdImageSeq;
            }
            catch ( NoSuchElementException& )
            {
            }
            catch ( WrappedTargetException& )
            {
            }
        }

        // We have to map commands which uses special characters like '/',':','?','\','<'.'>','|'
        String aExt = String::CreateFromAscii( IMAGE_EXTENSION );
        m_aImageCommandNameVector.resize(aCmdImageSeq.getLength() );
        m_aImageNameVector.resize( aCmdImageSeq.getLength() );

        ::std::copy( aCmdImageSeq.getConstArray(),
                     aCmdImageSeq.getConstArray()+aCmdImageSeq.getLength(),
                     m_aImageCommandNameVector.begin() );

        // Create a image name vector that must be provided to the vcl imagelist. We also need
        // a command to image name map to speed up access time for image retrieval.
        OUString aUNOString( RTL_CONSTASCII_USTRINGPARAM( ".uno:" ));
        String   aEmptyString;
        const sal_uInt32 nCount = m_aImageCommandNameVector.size();
		for ( sal_uInt32 i = 0; i < nCount; i++ )
        {
            OUString aCommandName( m_aImageCommandNameVector[i] );
            String   aImageName;
            
            if ( aCommandName.indexOf( aUNOString ) != 0 )
            {
                INetURLObject aUrlObject( aCommandName, INetURLObject::ENCODE_ALL );
                aImageName = aUrlObject.GetURLPath();
                aImageName = getCanonicalName( aImageName ); // convert to valid filename
            }
            else
            {
                // just remove the schema 
                if ( aCommandName.getLength() > 5 )
                    aImageName = aCommandName.copy( 5 );
                else
                    aImageName = aEmptyString;
                
                // Search for query part. 
                sal_Int32 nIndex = aImageName.Search( '?' );
                if ( nIndex != STRING_NOTFOUND )
                    aImageName = getCanonicalName( aImageName ); // convert to valid filename
            }
            // Image names are not case-dependent. Always use lower case characters to
            // reflect this.
            aImageName += aExt;
            aImageName.ToLowerAscii();
            
            m_aImageNameVector[i] = aImageName;
            m_aCommandToImageNameMap.insert( CommandToImageNameMap::value_type( aCommandName, aImageName ));
        }

        m_bVectorInit = sal_True;
    }
}

ImageList* CmdImageList::impl_getImageList( sal_Int16 nImageType )
{
    SvtMiscOptions aMiscOptions;

    sal_Int16 nSymbolsStyle = aMiscOptions.GetCurrentSymbolsStyle();
    if ( nSymbolsStyle != m_nSymbolsStyle )
    {
        m_nSymbolsStyle = nSymbolsStyle;
        for ( sal_Int32 n=0; n < ImageType_COUNT; n++ )
            delete m_pImageList[n], m_pImageList[n] = NULL;
    }

    if ( !m_pImageList[nImageType] )
    {
        m_pImageList[nImageType] = new ImageList( m_aImageNameVector,
                                                  OUString::createFromAscii( ImageType_Prefixes[nImageType] ) );
    }

    return m_pImageList[nImageType];
}

std::vector< ::rtl::OUString >& CmdImageList::impl_getImageNameVector()
{
    return m_aImageNameVector;
}

std::vector< rtl::OUString >& CmdImageList::impl_getImageCommandNameVector()
{
    return m_aImageCommandNameVector;
}

Image CmdImageList::getImageFromCommandURL( sal_Int16 nImageType, const rtl::OUString& rCommandURL )
{
    impl_fillCommandToImageNameMap();
    CommandToImageNameMap::const_iterator pIter = m_aCommandToImageNameMap.find( rCommandURL );
    if ( pIter != m_aCommandToImageNameMap.end() )
    {
        ImageList* pImageList = impl_getImageList( nImageType );
        return pImageList->GetImage( pIter->second );
    }

    return Image();
}

bool CmdImageList::hasImage( sal_Int16 /*nImageType*/, const rtl::OUString& rCommandURL )
{
    impl_fillCommandToImageNameMap();
    CommandToImageNameMap::const_iterator pIter = m_aCommandToImageNameMap.find( rCommandURL );
    if ( pIter != m_aCommandToImageNameMap.end() )
        return true;
    else
        return false;
}

::std::vector< rtl::OUString >& CmdImageList::getImageNames()
{
    return impl_getImageNameVector();
}

::std::vector< rtl::OUString >& CmdImageList::getImageCommandNames()
{
    return impl_getImageCommandNameVector();
}

//_________________________________________________________________________________________________________________

GlobalImageList::GlobalImageList( const uno::Reference< XMultiServiceFactory >& rServiceManager ) :
    CmdImageList( rServiceManager, rtl::OUString() ),
    m_nRefCount( 0 )
{
}

GlobalImageList::~GlobalImageList()
{
}

Image GlobalImageList::getImageFromCommandURL( sal_Int16 nImageType, const rtl::OUString& rCommandURL )
{
    osl::MutexGuard guard( getGlobalImageListMutex() );
    return CmdImageList::getImageFromCommandURL( nImageType, rCommandURL );
}

bool GlobalImageList::hasImage( sal_Int16 nImageType, const rtl::OUString& rCommandURL )
{
    osl::MutexGuard guard( getGlobalImageListMutex() );
    return CmdImageList::hasImage( nImageType, rCommandURL );
}

::std::vector< rtl::OUString >& GlobalImageList::getImageNames()
{
    osl::MutexGuard guard( getGlobalImageListMutex() );
    return impl_getImageNameVector();
}

::std::vector< rtl::OUString >& GlobalImageList::getImageCommandNames()
{
    osl::MutexGuard guard( getGlobalImageListMutex() );
    return impl_getImageCommandNameVector();
}

oslInterlockedCount GlobalImageList::acquire()
{
    osl_incrementInterlockedCount( &m_nRefCount );
    return m_nRefCount;
}

oslInterlockedCount GlobalImageList::release()
{
    osl::MutexGuard guard( getGlobalImageListMutex() );

    if ( !osl_decrementInterlockedCount( &m_nRefCount ))
    {
        oslInterlockedCount nCount( m_nRefCount );
        // remove global pointer as we destroy the object now
        pGlobalImageList = 0;
		delete this;
        return nCount;
    }

    return m_nRefCount;
}

static sal_Bool implts_checkAndScaleGraphic( uno::Reference< XGraphic >& rOutGraphic, const uno::Reference< XGraphic >& rInGraphic, sal_Int16 nImageType )
{
    static Size   aNormSize( IMAGE_SIZE_NORMAL, IMAGE_SIZE_NORMAL );
    static Size   aLargeSize( IMAGE_SIZE_LARGE, IMAGE_SIZE_LARGE );

    if ( !rInGraphic.is() )
    {
        rOutGraphic = Image().GetXGraphic();
        return sal_False;
    }

    // Check size and scale it
    Image  aImage( rInGraphic );
    Size   aSize = aImage.GetSizePixel();
    bool   bMustScale( false );

    if (( nImageType == ImageType_Color_Large ) ||
        ( nImageType == ImageType_HC_Large ))
        bMustScale = ( aSize != aLargeSize );
    else
        bMustScale = ( aSize != aNormSize );

    if ( bMustScale )
    {
        BitmapEx aBitmap = aImage.GetBitmapEx();
        aBitmap.Scale( aNormSize );
        aImage = Image( aBitmap );
        rOutGraphic = aImage.GetXGraphic();
    }
    else
        rOutGraphic = rInGraphic;
    return sal_True;
}

static sal_Int16 implts_convertImageTypeToIndex( sal_Int16 nImageType )
{
    sal_Int16 nIndex( 0 );
    if ( nImageType & ::com::sun::star::ui::ImageType::SIZE_LARGE )
        nIndex += 1;
    if ( nImageType & ::com::sun::star::ui::ImageType::COLOR_HIGHCONTRAST )
        nIndex += 2;
    return nIndex;
}

ImageList* ImageManagerImpl::implts_getUserImageList( ImageType nImageType )
{
    ResetableGuard aGuard( m_aLock );
    if ( !m_pUserImageList[nImageType] )
        implts_loadUserImages( nImageType, m_xUserImageStorage, m_xUserBitmapsStorage );

    return m_pUserImageList[nImageType];
}

void ImageManagerImpl::implts_initialize()
{
    // Initialize the top-level structures with the storage data
    if ( m_xUserConfigStorage.is() )
    {
        long nModes = m_bReadOnly ? ElementModes::READ : ElementModes::READWRITE;

        try
        {
            m_xUserImageStorage = m_xUserConfigStorage->openStorageElement( OUString::createFromAscii( IMAGE_FOLDER ),
                                                                            nModes );
            if ( m_xUserImageStorage.is() )
            {
                m_xUserBitmapsStorage = m_xUserImageStorage->openStorageElement( OUString::createFromAscii( BITMAPS_FOLDER ),
                                                                                 nModes );
            }
        }
        catch ( com::sun::star::container::NoSuchElementException& )
        {
        }
        catch ( ::com::sun::star::embed::InvalidStorageException& )
        {
        }
        catch ( ::com::sun::star::lang::IllegalArgumentException& )
        {
        }
        catch ( ::com::sun::star::io::IOException& )
        {
        }
        catch ( ::com::sun::star::embed::StorageWrappedTargetException& )
        {
        }
    }
}

sal_Bool ImageManagerImpl::implts_loadUserImages(
    ImageType nImageType,
    const uno::Reference< XStorage >& xUserImageStorage,
    const uno::Reference< XStorage >& xUserBitmapsStorage )
{
    ResetableGuard aGuard( m_aLock );

    if ( xUserImageStorage.is() && xUserBitmapsStorage.is() )
    {
        try
        {
            uno::Reference< XStream > xStream = xUserImageStorage->openStreamElement( rtl::OUString::createFromAscii( IMAGELIST_XML_FILE[nImageType] ),
                                                                                      ElementModes::READ );
            uno::Reference< XInputStream > xInputStream = xStream->getInputStream();

            ImageListsDescriptor aUserImageListInfo;
            ImagesConfiguration::LoadImages( m_xServiceManager,
                                             xInputStream,
                                             aUserImageListInfo );
            if (( aUserImageListInfo.pImageList != 0 ) &&
                ( aUserImageListInfo.pImageList->Count() > 0 ))
            {
                ImageListItemDescriptor* pList = aUserImageListInfo.pImageList->GetObject(0);
                sal_Int32 nCount = pList->pImageItemList->Count();
                std::vector< OUString > aUserImagesVector;
                aUserImagesVector.reserve(nCount);
                for ( sal_uInt16 i=0; i < nCount; i++ )
                {
                    const ImageItemDescriptor* pItem = pList->pImageItemList->GetObject(i);
                    aUserImagesVector.push_back( pItem->aCommandURL );
                }

                uno::Reference< XStream > xBitmapStream = xUserBitmapsStorage->openStreamElement(
                                                        rtl::OUString::createFromAscii( BITMAP_FILE_NAMES[nImageType] ),
                                                        ElementModes::READ );

                if ( xBitmapStream.is() )
                {
                    SvStream* pSvStream( 0 );
		            BitmapEx aUserBitmap;
		            {
		                pSvStream = utl::UcbStreamHelper::CreateStream( xBitmapStream );
		                vcl::PNGReader aPngReader( *pSvStream );
		                aUserBitmap = aPngReader.Read();
		            }
                    delete pSvStream;

                    // Delete old image list and create a new one from the read bitmap
                    delete m_pUserImageList[nImageType];
                    m_pUserImageList[nImageType] = new ImageList();
					m_pUserImageList[nImageType]->InsertFromHorizontalStrip
						( aUserBitmap, aUserImagesVector );
                    return sal_True;
                }
            }
        }
        catch ( com::sun::star::container::NoSuchElementException& )
        {
        }
        catch ( ::com::sun::star::embed::InvalidStorageException& )
        {
        }
        catch ( ::com::sun::star::lang::IllegalArgumentException& )
        {
        }
        catch ( ::com::sun::star::io::IOException& )
        {
        }
        catch ( ::com::sun::star::embed::StorageWrappedTargetException& )
        {
        }
    }

    // Destroy old image list - create a new empty one
    delete m_pUserImageList[nImageType];
    m_pUserImageList[nImageType] = new ImageList;

    return sal_True;
}

sal_Bool ImageManagerImpl::implts_storeUserImages(
    ImageType nImageType,
    const uno::Reference< XStorage >& xUserImageStorage,
    const uno::Reference< XStorage >& xUserBitmapsStorage )
{
    ResetableGuard aGuard( m_aLock );

    if ( m_bModified )
    {
        ImageList* pImageList = implts_getUserImageList( nImageType );
        if ( pImageList->GetImageCount() > 0 )
        {
            ImageListsDescriptor aUserImageListInfo;
            aUserImageListInfo.pImageList = new ImageListDescriptor;

            ImageListItemDescriptor* pList = new ImageListItemDescriptor;
            aUserImageListInfo.pImageList->Insert( pList, 0 );

            pList->pImageItemList = new ImageItemListDescriptor;
            for ( sal_uInt16 i=0; i < pImageList->GetImageCount(); i++ )
            {
                ImageItemDescriptor* pItem = new ::framework::ImageItemDescriptor;

                pItem->nIndex = i;
                pItem->aCommandURL = pImageList->GetImageName( i );
                pList->pImageItemList->Insert( pItem, pList->pImageItemList->Count() );
            }

            pList->aURL = String::CreateFromAscii("Bitmaps/");
            pList->aURL += String::CreateFromAscii( BITMAP_FILE_NAMES[nImageType] );

            uno::Reference< XTransactedObject > xTransaction;
            uno::Reference< XOutputStream >     xOutputStream;
            uno::Reference< XStream > xStream = xUserImageStorage->openStreamElement( rtl::OUString::createFromAscii( IMAGELIST_XML_FILE[nImageType] ),
                                                                                      ElementModes::WRITE|ElementModes::TRUNCATE );
            if ( xStream.is() )
            {
                uno::Reference< XStream > xBitmapStream =
                    xUserBitmapsStorage->openStreamElement( rtl::OUString::createFromAscii( BITMAP_FILE_NAMES[nImageType] ),
                                                            ElementModes::WRITE|ElementModes::TRUNCATE );
                if ( xBitmapStream.is() )
                {
                    SvStream* pSvStream = utl::UcbStreamHelper::CreateStream( xBitmapStream );
                    {
                        vcl::PNGWriter aPngWriter( pImageList->GetAsHorizontalStrip() );
                        aPngWriter.Write( *pSvStream );
                    }
                    delete pSvStream;

                    // Commit user bitmaps storage
                    xTransaction = uno::Reference< XTransactedObject >( xUserBitmapsStorage, UNO_QUERY );
					if ( xTransaction.is() )
                    	xTransaction->commit();
                }

                xOutputStream = xStream->getOutputStream();
                if ( xOutputStream.is() )
                    ImagesConfiguration::StoreImages( m_xServiceManager, xOutputStream, aUserImageListInfo );

                // Commit user image storage
                xTransaction = uno::Reference< XTransactedObject >( xUserImageStorage, UNO_QUERY );
				if ( xTransaction.is() )
                	xTransaction->commit();
            }

            return sal_True;
        }
        else
        {
            // Remove the streams from the storage, if we have no data. We have to catch
            // the NoSuchElementException as it can be possible that there is no stream at all!
            try
            {
                xUserImageStorage->removeElement( rtl::OUString::createFromAscii( IMAGELIST_XML_FILE[nImageType] ));
            }
            catch ( ::com::sun::star::container::NoSuchElementException& )
            {
            }

            try
            {
                xUserBitmapsStorage->removeElement( rtl::OUString::createFromAscii( BITMAP_FILE_NAMES[nImageType] ));
            }
            catch ( ::com::sun::star::container::NoSuchElementException& )
            {
            }

            uno::Reference< XTransactedObject > xTransaction;
            
            // Commit user image storage
            xTransaction = uno::Reference< XTransactedObject >( xUserImageStorage, UNO_QUERY );
			if ( xTransaction.is() )
                xTransaction->commit();

            // Commit user bitmaps storage
            xTransaction = uno::Reference< XTransactedObject >( xUserBitmapsStorage, UNO_QUERY );
			if ( xTransaction.is() )
                xTransaction->commit();
            
            return sal_True;
        }
    }

    return sal_False;
}
const rtl::Reference< GlobalImageList >& ImageManagerImpl::implts_getGlobalImageList()
{
    ResetableGuard aGuard( m_aLock );

    if ( !m_pGlobalImageList.is() )
        m_pGlobalImageList = getGlobalImageList( m_xServiceManager );
    return m_pGlobalImageList;
}

CmdImageList* ImageManagerImpl::implts_getDefaultImageList()
{
    ResetableGuard aGuard( m_aLock );

    if ( !m_pDefaultImageList )
        m_pDefaultImageList = new CmdImageList( m_xServiceManager, m_aModuleIdentifier );

    return m_pDefaultImageList;
}

ImageManagerImpl::ImageManagerImpl( const uno::Reference< XMultiServiceFactory >& xServiceManager,const uno::Reference< XInterface >& _xOwner,bool _bUseGlobal ) :
    ThreadHelpBase( &Application::GetSolarMutex() )
    , m_xServiceManager( xServiceManager )
    , m_xOwner(_xOwner)
    , m_pDefaultImageList( 0 )
    , m_aXMLPostfix( RTL_CONSTASCII_USTRINGPARAM( ".xml" ))
    , m_aResourceString( RTL_CONSTASCII_USTRINGPARAM( ModuleImageList ))    
    , m_aListenerContainer( m_aLock.getShareableOslMutex() )
    , m_bUseGlobal(_bUseGlobal)
    , m_bReadOnly( true )
    , m_bInitialized( false )
    , m_bModified( false )
    , m_bConfigRead( false )
    , m_bDisposed( false )
{
    for ( sal_Int32 n=0; n < ImageType_COUNT; n++ )
    {
        m_pUserImageList[n] = 0;
        m_bUserImageListModified[n] = false;
    }
}

ImageManagerImpl::~ImageManagerImpl()
{
    clear();
}

void ImageManagerImpl::dispose()
{
    css::lang::EventObject aEvent( m_xOwner );
    m_aListenerContainer.disposeAndClear( aEvent );

	{
	    ResetableGuard aGuard( m_aLock );
        m_xUserConfigStorage.clear();
        m_xUserImageStorage.clear();
        m_xUserRootCommit.clear();
        m_bConfigRead = false;
        m_bModified = false;
        m_bDisposed = true;
        
        // delete user and default image list on dispose
        for ( sal_Int32 n=0; n < ImageType_COUNT; n++ )
        {
            delete m_pUserImageList[n];
            m_pUserImageList[n] = 0;
        }
        delete m_pDefaultImageList;
        m_pDefaultImageList = 0;
    }
    
}
void ImageManagerImpl::addEventListener( const uno::Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
{
    {
        ResetableGuard aGuard( m_aLock );

	    /* SAFE AREA ----------------------------------------------------------------------------------------------- */
        if ( m_bDisposed )
            throw DisposedException();
    }

    m_aListenerContainer.addInterface( ::getCppuType( ( const uno::Reference< XEventListener >* ) NULL ), xListener );
}

void ImageManagerImpl::removeEventListener( const uno::Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
{
    /* SAFE AREA ----------------------------------------------------------------------------------------------- */
    m_aListenerContainer.removeInterface( ::getCppuType( ( const uno::Reference< XEventListener >* ) NULL ), xListener );
}

// XInitialization
void ImageManagerImpl::initialize( const Sequence< Any >& aArguments )
{
    ResetableGuard aLock( m_aLock );

    if ( !m_bInitialized )
    {
        for ( sal_Int32 n = 0; n < aArguments.getLength(); n++ )
        {
            PropertyValue aPropValue;
            if ( aArguments[n] >>= aPropValue )
            {
                if ( aPropValue.Name.equalsAscii( "UserConfigStorage" ))
                {
                    aPropValue.Value >>= m_xUserConfigStorage;
                }
                else if ( aPropValue.Name.equalsAscii( "ModuleIdentifier" ))
                {
                    aPropValue.Value >>= m_aModuleIdentifier;
                }
                else if ( aPropValue.Name.equalsAscii( "UserRootCommit" ))
                {
                    aPropValue.Value >>= m_xUserRootCommit;
                }
            }
        }

        if ( m_xUserConfigStorage.is() )
        {
            uno::Reference< XPropertySet > xPropSet( m_xUserConfigStorage, UNO_QUERY );
            if ( xPropSet.is() )
            {
                long nOpenMode = 0;
                if ( xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenMode" ))) >>= nOpenMode )
                    m_bReadOnly = !( nOpenMode & ElementModes::WRITE );
            }
        }

        implts_initialize();

        m_bInitialized = true;
    }
}

// XImageManagerImpl
void ImageManagerImpl::reset()
throw (::com::sun::star::uno::RuntimeException)
{
    ResetableGuard aLock( m_aLock );

    /* SAFE AREA ----------------------------------------------------------------------------------------------- */
    if ( m_bDisposed )
        throw DisposedException();

    std::vector< OUString > aUserImageNames;

    for ( sal_Int32 i = 0; i < ImageType_COUNT; i++ )
    {
        aUserImageNames.clear();
        ImageList* pImageList = implts_getUserImageList( ImageType(i));
        pImageList->GetImageNames( aUserImageNames );

        Sequence< rtl::OUString > aRemoveList( aUserImageNames.size() );
        const sal_uInt32 nCount = aUserImageNames.size();
		for ( sal_uInt32 j = 0; j < nCount; j++ )
            aRemoveList[j] = aUserImageNames[j];

        // Remove images
        removeImages( sal_Int16( i ), aRemoveList );
        m_bUserImageListModified[i] = true;
    }

    m_bModified = sal_True;
}

Sequence< ::rtl::OUString > ImageManagerImpl::getAllImageNames( ::sal_Int16 nImageType )
throw (::com::sun::star::uno::RuntimeException)
{
    ResetableGuard aLock( m_aLock );

    /* SAFE AREA ----------------------------------------------------------------------------------------------- */
    if ( m_bDisposed )
        throw DisposedException();

    ImageNameMap aImageCmdNameMap;

    sal_Int16 nIndex = implts_convertImageTypeToIndex( nImageType );
    
    sal_uInt32 i( 0 );
    if ( m_bUseGlobal )
    {
        rtl::Reference< GlobalImageList > rGlobalImageList = implts_getGlobalImageList();
   
        const std::vector< OUString >& rGlobalImageNameVector = rGlobalImageList->getImageCommandNames();
        const sal_uInt32 nGlobalCount = rGlobalImageNameVector.size();
        for ( i = 0; i < nGlobalCount; i++ )
            aImageCmdNameMap.insert( ImageNameMap::value_type( rGlobalImageNameVector[i], sal_True ));

        const std::vector< OUString >& rModuleImageNameVector = implts_getDefaultImageList()->getImageCommandNames();
        const sal_uInt32 nModuleCount = rModuleImageNameVector.size();
        for ( i = 0; i < nModuleCount; i++ )
            aImageCmdNameMap.insert( ImageNameMap::value_type( rModuleImageNameVector[i], sal_True ));
    }

    ImageList* pImageList = implts_getUserImageList( ImageType( nIndex ));
    std::vector< OUString > rUserImageNames;
    pImageList->GetImageNames( rUserImageNames );
    const sal_uInt32 nUserCount = rUserImageNames.size();
    for ( i = 0; i < nUserCount; i++ )
        aImageCmdNameMap.insert( ImageNameMap::value_type( rUserImageNames[i], sal_True ));

    Sequence< OUString > aImageNameSeq( aImageCmdNameMap.size() );
    ImageNameMap::const_iterator pIter;
    i = 0;
    for ( pIter = aImageCmdNameMap.begin(); pIter != aImageCmdNameMap.end(); pIter++ )
        aImageNameSeq[i++] = pIter->first;

    return aImageNameSeq;
}

::sal_Bool ImageManagerImpl::hasImage( ::sal_Int16 nImageType, const ::rtl::OUString& aCommandURL )
throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
{
    ResetableGuard aLock( m_aLock );

    /* SAFE AREA ----------------------------------------------------------------------------------------------- */
    if ( m_bDisposed )
        throw DisposedException();

    if (( nImageType < 0 ) || ( nImageType > MAX_IMAGETYPE_VALUE ))
        throw IllegalArgumentException();

    sal_Int16 nIndex = implts_convertImageTypeToIndex( nImageType );
    if ( m_bUseGlobal && implts_getGlobalImageList()->hasImage( nIndex, aCommandURL ))
        return sal_True;
    else
    {
        if ( m_bUseGlobal && implts_getDefaultImageList()->hasImage( nIndex, aCommandURL ))
            return sal_True;
        else
        {
            // User layer
            ImageList* pImageList = implts_getUserImageList( ImageType( nIndex ));
            if ( pImageList )
                return ( pImageList->GetImagePos( aCommandURL ) != IMAGELIST_IMAGE_NOTFOUND );
        }
    }

    return sal_False;
}

Sequence< uno::Reference< XGraphic > > ImageManagerImpl::getImages(
    ::sal_Int16 nImageType,
    const Sequence< ::rtl::OUString >& aCommandURLSequence )
throw ( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException )
{
    ResetableGuard aLock( m_aLock );

    /* SAFE AREA ----------------------------------------------------------------------------------------------- */
    if ( m_bDisposed )
        throw DisposedException();

    if (( nImageType < 0 ) || ( nImageType > MAX_IMAGETYPE_VALUE ))
        throw IllegalArgumentException();

    Sequence< uno::Reference< XGraphic > > aGraphSeq( aCommandURLSequence.getLength() );

    const rtl::OUString* aStrArray = aCommandURLSequence.getConstArray();

    sal_Int16                         nIndex            = implts_convertImageTypeToIndex( nImageType );
    rtl::Reference< GlobalImageList > rGlobalImageList;
    CmdImageList*                     pDefaultImageList = NULL;
    if ( m_bUseGlobal )
    {
        rGlobalImageList  = implts_getGlobalImageList();
        pDefaultImageList = implts_getDefaultImageList();
    }
    ImageList*                        pUserImageList    = implts_getUserImageList( ImageType( nIndex ));

    // We have to search our image list in the following order:
    // 1. user image list (read/write)
    // 2. module image list (read)
    // 3. global image list (read)
    for ( sal_Int32 n = 0; n < aCommandURLSequence.getLength(); n++ )
    {
        Image aImage = pUserImageList->GetImage( aStrArray[n] );
        if ( !aImage && m_bUseGlobal )
        {
            aImage = pDefaultImageList->getImageFromCommandURL( nIndex, aStrArray[n] );
            if ( !aImage )
                aImage = rGlobalImageList->getImageFromCommandURL( nIndex, aStrArray[n] );
        }

        aGraphSeq[n] = aImage.GetXGraphic();
    }

    return aGraphSeq;
}

void ImageManagerImpl::replaceImages( 
    ::sal_Int16 nImageType, 
    const Sequence< ::rtl::OUString >& aCommandURLSequence, 
    const Sequence< uno::Reference< XGraphic > >& aGraphicsSequence ) 
throw ( ::com::sun::star::lang::IllegalArgumentException, 
        ::com::sun::star::lang::IllegalAccessException, 
        ::com::sun::star::uno::RuntimeException)
{
    CmdToXGraphicNameAccess* pInsertedImages( 0 );
    CmdToXGraphicNameAccess* pReplacedImages( 0 );
    
    {
        ResetableGuard aLock( m_aLock );
            
        /* SAFE AREA ----------------------------------------------------------------------------------------------- */
        if ( m_bDisposed )
            throw DisposedException();

        if (( aCommandURLSequence.getLength() != aGraphicsSequence.getLength() ) ||
            (( nImageType < 0 ) || ( nImageType > MAX_IMAGETYPE_VALUE )))
            throw IllegalArgumentException();

        if ( m_bReadOnly )
            throw IllegalAccessException();

        sal_Int16 nIndex = implts_convertImageTypeToIndex( nImageType );
        ImageList* pImageList = implts_getUserImageList( ImageType( nIndex ));
        
        uno::Reference< XGraphic > xGraphic;
        for ( sal_Int32 i = 0; i < aCommandURLSequence.getLength(); i++ )
        {
            // Check size and scale. If we don't have any graphics ignore it
            if ( !implts_checkAndScaleGraphic( xGraphic, aGraphicsSequence[i], nIndex ))
                continue;
            
            sal_uInt16 nPos = pImageList->GetImagePos( aCommandURLSequence[i] );
            if ( nPos == IMAGELIST_IMAGE_NOTFOUND )
            {
                pImageList->AddImage( aCommandURLSequence[i], xGraphic );
                if ( !pInsertedImages )
                    pInsertedImages = new CmdToXGraphicNameAccess();
                pInsertedImages->addElement( aCommandURLSequence[i], xGraphic );
            }
            else
            {
                pImageList->ReplaceImage( aCommandURLSequence[i], xGraphic );
                if ( !pReplacedImages )
                    pReplacedImages = new CmdToXGraphicNameAccess();
                pReplacedImages->addElement( aCommandURLSequence[i], xGraphic );
            }
        }

        if (( pInsertedImages != 0 ) || (  pReplacedImages != 0 ))
        {
            m_bModified = sal_True;
            m_bUserImageListModified[nIndex] = true;
        }
    }

    // Notify listeners
    if ( pInsertedImages != 0 )
    {
        ConfigurationEvent aInsertEvent;
        aInsertEvent.aInfo           <<= nImageType;
        aInsertEvent.Accessor        <<= m_xOwner;
        aInsertEvent.Source          = m_xOwner;
        aInsertEvent.ResourceURL     = m_aResourceString;
        aInsertEvent.Element         = uno::makeAny( uno::Reference< XNameAccess >( 
                                        static_cast< OWeakObject *>( pInsertedImages ), UNO_QUERY ));
        implts_notifyContainerListener( aInsertEvent, NotifyOp_Insert );
    }
    if ( pReplacedImages != 0 )
    {
        ConfigurationEvent aReplaceEvent;
        aReplaceEvent.aInfo           <<= nImageType;
        aReplaceEvent.Accessor        <<= m_xOwner;
        aReplaceEvent.Source          = m_xOwner;
        aReplaceEvent.ResourceURL     = m_aResourceString;
        aReplaceEvent.ReplacedElement = Any();
        aReplaceEvent.Element         = uno::makeAny( uno::Reference< XNameAccess >( 
                                            static_cast< OWeakObject *>( pReplacedImages ), UNO_QUERY ));
        implts_notifyContainerListener( aReplaceEvent, NotifyOp_Replace );
    }
}

void ImageManagerImpl::removeImages( ::sal_Int16 nImageType, const Sequence< ::rtl::OUString >& aCommandURLSequence ) 
throw ( ::com::sun::star::lang::IllegalArgumentException, 
        ::com::sun::star::lang::IllegalAccessException, 
        ::com::sun::star::uno::RuntimeException)
{
    CmdToXGraphicNameAccess* pRemovedImages( 0 );
    CmdToXGraphicNameAccess* pReplacedImages( 0 );

    {
        ResetableGuard aLock( m_aLock );

        /* SAFE AREA ----------------------------------------------------------------------------------------------- */
        if ( m_bDisposed )
            throw DisposedException();

        if (( nImageType < 0 ) || ( nImageType > MAX_IMAGETYPE_VALUE ))
            throw IllegalArgumentException();

        if ( m_bReadOnly )
            throw IllegalAccessException();

        sal_Int16 nIndex = implts_convertImageTypeToIndex( nImageType );
        rtl::Reference< GlobalImageList > rGlobalImageList;
        CmdImageList*                     pDefaultImageList = NULL;
        if ( m_bUseGlobal )
        {
            rGlobalImageList  = implts_getGlobalImageList();
            pDefaultImageList = implts_getDefaultImageList();
        }
        ImageList*                        pImageList        = implts_getUserImageList( ImageType( nIndex ));
        uno::Reference< XGraphic >        xEmptyGraphic( Image().GetXGraphic() );

        for ( sal_Int32 i = 0; i < aCommandURLSequence.getLength(); i++ )
        {
            sal_uInt16 nPos = pImageList->GetImagePos( aCommandURLSequence[i] );
            if ( nPos != IMAGELIST_IMAGE_NOTFOUND )
            {
                Image aImage = pImageList->GetImage( nPos );
                sal_uInt16 nId   = pImageList->GetImageId( nPos );
                pImageList->RemoveImage( nId );

                if ( m_bUseGlobal )
                {
                    // Check, if we have a image in our module/global image list. If we find one =>
                    // this is a replace instead of a remove operation!
                    Image aNewImage = pDefaultImageList->getImageFromCommandURL( nIndex, aCommandURLSequence[i] );
                    if ( !aNewImage )
                        aNewImage = rGlobalImageList->getImageFromCommandURL( nIndex, aCommandURLSequence[i] );
                    if ( !aNewImage )
                    {
                        if ( !pRemovedImages )
                            pRemovedImages = new CmdToXGraphicNameAccess();
                        pRemovedImages->addElement( aCommandURLSequence[i], xEmptyGraphic );
                    }
                    else
                    {
                        if ( !pReplacedImages )
                            pReplacedImages = new CmdToXGraphicNameAccess();
                        pReplacedImages->addElement( aCommandURLSequence[i], aNewImage.GetXGraphic() );
                    }
                } // if ( m_bUseGlobal )
                else
                {
                    if ( !pRemovedImages )
                        pRemovedImages = new CmdToXGraphicNameAccess();
                    pRemovedImages->addElement( aCommandURLSequence[i], xEmptyGraphic );
                }
            }
        }

        if (( pReplacedImages != 0 ) || ( pRemovedImages != 0 ))
        {
            m_bModified = sal_True;
            m_bUserImageListModified[nIndex] = true;
        }
    }

    // Notify listeners
    if ( pRemovedImages != 0 )
    {
        ConfigurationEvent aRemoveEvent;
        aRemoveEvent.aInfo           = uno::makeAny( nImageType );
        aRemoveEvent.Accessor        = uno::makeAny( m_xOwner );
        aRemoveEvent.Source          = m_xOwner;
        aRemoveEvent.ResourceURL     = m_aResourceString;
        aRemoveEvent.Element         = uno::makeAny( uno::Reference< XNameAccess >(
                                            static_cast< OWeakObject *>( pRemovedImages ), UNO_QUERY ));
        implts_notifyContainerListener( aRemoveEvent, NotifyOp_Remove );
    }
    if ( pReplacedImages != 0 )
    {
        ConfigurationEvent aReplaceEvent;
        aReplaceEvent.aInfo           = uno::makeAny( nImageType );
        aReplaceEvent.Accessor        = uno::makeAny( m_xOwner );
        aReplaceEvent.Source          = m_xOwner;
        aReplaceEvent.ResourceURL     = m_aResourceString;
        aReplaceEvent.ReplacedElement = Any();
        aReplaceEvent.Element         = uno::makeAny( uno::Reference< XNameAccess >(
                                            static_cast< OWeakObject *>( pReplacedImages ), UNO_QUERY ));
        implts_notifyContainerListener( aReplaceEvent, NotifyOp_Replace );
    }
}

void ImageManagerImpl::insertImages( ::sal_Int16 nImageType, const Sequence< ::rtl::OUString >& aCommandURLSequence, const Sequence< uno::Reference< XGraphic > >& aGraphicSequence ) 
throw ( ::com::sun::star::container::ElementExistException, 
        ::com::sun::star::lang::IllegalArgumentException, 
        ::com::sun::star::lang::IllegalAccessException, 
        ::com::sun::star::uno::RuntimeException)
{
    replaceImages(nImageType,aCommandURLSequence,aGraphicSequence);
}


// XUIConfigurationPersistence
void ImageManagerImpl::reload() 
throw ( ::com::sun::star::uno::Exception, 
        ::com::sun::star::uno::RuntimeException )
{
    ResetableGuard aGuard( m_aLock );

    if ( m_bDisposed )
        throw DisposedException();

    CommandMap                   aOldUserCmdImageSet;   
    std::vector< rtl::OUString > aNewUserCmdImageSet;
    
    if ( m_bModified )
    {
        for ( sal_Int16 i = 0; i < sal_Int16( ImageType_COUNT ); i++ )
        {
            if ( !m_bDisposed && m_bUserImageListModified[i] )
            {
                std::vector< rtl::OUString > aOldUserCmdImageVector;
                ImageList* pImageList = implts_getUserImageList( (ImageType)i );
                pImageList->GetImageNames( aOldUserCmdImageVector );

                // Fill hash map to speed up search afterwards
                sal_uInt32 j( 0 );
                const sal_uInt32 nOldCount = aOldUserCmdImageVector.size();
				for ( j = 0; j < nOldCount; j++ )
                    aOldUserCmdImageSet.insert( CommandMap::value_type( aOldUserCmdImageVector[j], false ));
                
                // Attention: This can make the old image list pointer invalid!
                implts_loadUserImages( (ImageType)i, m_xUserImageStorage, m_xUserBitmapsStorage );
                pImageList = implts_getUserImageList( (ImageType)i );
                pImageList->GetImageNames( aNewUserCmdImageSet );
            
                CmdToXGraphicNameAccess* pInsertedImages( 0 );
                CmdToXGraphicNameAccess* pReplacedImages( 0 );
                CmdToXGraphicNameAccess* pRemovedImages( 0 );

                const sal_uInt32 nNewCount = aNewUserCmdImageSet.size();
				for ( j = 0; j < nNewCount; j++ )
                {
                    CommandMap::iterator pIter = aOldUserCmdImageSet.find( aNewUserCmdImageSet[j] );
                    if ( pIter != aOldUserCmdImageSet.end() )
                    {
                        pIter->second = true; // mark entry as replaced
                        if ( !pReplacedImages )
                            pReplacedImages = new CmdToXGraphicNameAccess();
                        pReplacedImages->addElement( aNewUserCmdImageSet[j], 
                                                     pImageList->GetImage( aNewUserCmdImageSet[j] ).GetXGraphic() );
                    }
                    else
                    {
                        if ( !pInsertedImages )
                            pInsertedImages = new CmdToXGraphicNameAccess();
                        pInsertedImages->addElement( aNewUserCmdImageSet[j], 
                                                     pImageList->GetImage( aNewUserCmdImageSet[j] ).GetXGraphic() );
                    }
                }

                // Search map for unmarked entries => they have been removed from the user list 
                // through this reload operation. 
                // We have to search the module and global image list!
                rtl::Reference< GlobalImageList > rGlobalImageList;
                CmdImageList*                     pDefaultImageList = NULL;
                if ( m_bUseGlobal )
                {
                    rGlobalImageList  = implts_getGlobalImageList();
                    pDefaultImageList = implts_getDefaultImageList();
                }
                uno::Reference< XGraphic >        xEmptyGraphic( Image().GetXGraphic() );
                CommandMap::const_iterator        pIter = aOldUserCmdImageSet.begin();
                while ( pIter != aOldUserCmdImageSet.end() )
                {
                    if ( !pIter->second )
                    {
                        if ( m_bUseGlobal )
                        {
                            Image aImage = pDefaultImageList->getImageFromCommandURL( i, pIter->first );
                            if ( !aImage )
                                aImage = rGlobalImageList->getImageFromCommandURL( i, pIter->first );

                            if ( !aImage )
                            {
                                // No image in the module/global image list => remove user image
                                if ( !pRemovedImages )
                                    pRemovedImages = new CmdToXGraphicNameAccess();
                                pRemovedImages->addElement( pIter->first, xEmptyGraphic );
                            }
                            else
                            {
                                // Image has been found in the module/global image list => replace user image
                                if ( !pReplacedImages )
                                    pReplacedImages = new CmdToXGraphicNameAccess();
                                pReplacedImages->addElement( pIter->first, aImage.GetXGraphic() );
                            }
                        } // if ( m_bUseGlobal )
                        else
                        {
                            // No image in the user image list => remove user image
                            if ( !pRemovedImages )
                                pRemovedImages = new CmdToXGraphicNameAccess();
                            pRemovedImages->addElement( pIter->first, xEmptyGraphic );
                        }
                    }
                    ++pIter;
                }
                
                aGuard.unlock();
                
                // Now notify our listeners. Unlock mutex to prevent deadlocks
                if ( pInsertedImages != 0 )
                {
                    ConfigurationEvent aInsertEvent;
                    aInsertEvent.aInfo           = uno::makeAny( i );
                    aInsertEvent.Accessor        = uno::makeAny( m_xOwner );
                    aInsertEvent.Source          = m_xOwner;
                    aInsertEvent.ResourceURL     = m_aResourceString;
                    aInsertEvent.Element         = uno::makeAny( uno::Reference< XNameAccess >( 
                                                    static_cast< OWeakObject *>( pInsertedImages ), UNO_QUERY ));
                    implts_notifyContainerListener( aInsertEvent, NotifyOp_Insert );
                }
                if ( pReplacedImages != 0 )
                {
                    ConfigurationEvent aReplaceEvent;
                    aReplaceEvent.aInfo           = uno::makeAny( i );
                    aReplaceEvent.Accessor        = uno::makeAny( m_xOwner );
                    aReplaceEvent.Source          = m_xOwner;
                    aReplaceEvent.ResourceURL     = m_aResourceString;
                    aReplaceEvent.ReplacedElement = Any();
                    aReplaceEvent.Element         = uno::makeAny( uno::Reference< XNameAccess >( 
                                                    static_cast< OWeakObject *>( pReplacedImages ), UNO_QUERY ));
                    implts_notifyContainerListener( aReplaceEvent, NotifyOp_Replace );
                }
                if ( pRemovedImages != 0 )
                {
                    ConfigurationEvent aRemoveEvent;
                    aRemoveEvent.aInfo           = uno::makeAny( i );
                    aRemoveEvent.Accessor        = uno::makeAny( m_xOwner );
                    aRemoveEvent.Source          = m_xOwner;
                    aRemoveEvent.ResourceURL     = m_aResourceString;
                    aRemoveEvent.Element         = uno::makeAny( uno::Reference< XNameAccess >( 
                                                        static_cast< OWeakObject *>( pRemovedImages ), UNO_QUERY ));
                    implts_notifyContainerListener( aRemoveEvent, NotifyOp_Remove );
                }

                aGuard.lock();
            }
        }
    }
}

void ImageManagerImpl::store() 
throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
{
    ResetableGuard aGuard( m_aLock );

    if ( m_bDisposed )
        throw DisposedException();

    if ( m_bModified )
    {
        sal_Bool bWritten( sal_False );
        for ( sal_Int32 i = 0; i < ImageType_COUNT; i++ )
        {
            sal_Bool bSuccess = implts_storeUserImages( ImageType(i), m_xUserImageStorage, m_xUserBitmapsStorage );
            if ( bSuccess )
                bWritten = sal_True;
            m_bUserImageListModified[i] = false;
        }

        if ( bWritten && 
             m_xUserConfigStorage.is() )
        {
            uno::Reference< XTransactedObject > xUserConfigStorageCommit( m_xUserConfigStorage, UNO_QUERY );
			if ( xUserConfigStorageCommit.is() )
            	xUserConfigStorageCommit->commit();
            if ( m_xUserRootCommit.is() )
                m_xUserRootCommit->commit();
        }

        m_bModified = sal_False;
    }
}

void ImageManagerImpl::storeToStorage( const uno::Reference< XStorage >& Storage ) 
throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
{
    ResetableGuard aGuard( m_aLock );

    if ( m_bDisposed )
        throw DisposedException();

    if ( m_bModified && Storage.is() )
    {
        long nModes = ElementModes::READWRITE;

        uno::Reference< XStorage > xUserImageStorage = Storage->openStorageElement( OUString::createFromAscii( IMAGE_FOLDER ), 
                                                                                    nModes );
        if ( xUserImageStorage.is() )
        {
            uno::Reference< XStorage > xUserBitmapsStorage = xUserImageStorage->openStorageElement( OUString::createFromAscii( BITMAPS_FOLDER ),
                                                                                                    nModes );
            for ( sal_Int32 i = 0; i < ImageType_COUNT; i++ )
            {
                implts_getUserImageList( (ImageType)i );
                implts_storeUserImages( (ImageType)i, xUserImageStorage, xUserBitmapsStorage );
            }
        
            uno::Reference< XTransactedObject > xTransaction( Storage, UNO_QUERY );
			if ( xTransaction.is() )
            	xTransaction->commit();
        }
    }
}

sal_Bool ImageManagerImpl::isModified() 
throw (::com::sun::star::uno::RuntimeException)
{
    ResetableGuard aGuard( m_aLock );
    return m_bModified;
}

sal_Bool ImageManagerImpl::isReadOnly() throw (::com::sun::star::uno::RuntimeException)
{
    ResetableGuard aGuard( m_aLock );
    return m_bReadOnly;
}
// XUIConfiguration
void ImageManagerImpl::addConfigurationListener( const uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) 
throw (::com::sun::star::uno::RuntimeException)
{
    {
        ResetableGuard aGuard( m_aLock );
	
        /* SAFE AREA ----------------------------------------------------------------------------------------------- */
        if ( m_bDisposed )
            throw DisposedException();
    }
        
    m_aListenerContainer.addInterface( ::getCppuType( ( const uno::Reference< XUIConfigurationListener >* ) NULL ), xListener );
}

void ImageManagerImpl::removeConfigurationListener( const uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) 
throw (::com::sun::star::uno::RuntimeException)
{
    /* SAFE AREA ----------------------------------------------------------------------------------------------- */
    m_aListenerContainer.removeInterface( ::getCppuType( ( const uno::Reference< XUIConfigurationListener >* ) NULL ), xListener );
}


void ImageManagerImpl::implts_notifyContainerListener( const ConfigurationEvent& aEvent, NotifyOp eOp )
{
    ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( 
                                        ::getCppuType( ( const css::uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >*) NULL ) );
    if ( pContainer != NULL )
	{
        ::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
        while ( pIterator.hasMoreElements() )
        {
            try
            {
                switch ( eOp )
                {
                    case NotifyOp_Replace:
                        ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementReplaced( aEvent );
                        break;
                    case NotifyOp_Insert:
                        ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementInserted( aEvent );
                        break;
                    case NotifyOp_Remove:
                        ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementRemoved( aEvent );
                        break;
                }
            }
            catch( css::uno::RuntimeException& )
            {
                pIterator.remove();
            }
        }
	}
}
void ImageManagerImpl::clear()
{
    ResetableGuard aGuard( m_aLock );
    for ( sal_Int32 n = 0; n < ImageType_COUNT; n++ )
    {
        delete m_pUserImageList[n];
        m_pUserImageList[n] = 0;
    }
}
} // namespace framework
