diff options
Diffstat (limited to 'framework/source/uiconfiguration')
-rw-r--r-- | framework/source/uiconfiguration/globalsettings.cxx | 359 | ||||
-rw-r--r-- | framework/source/uiconfiguration/graphicnameaccess.cxx | 115 | ||||
-rw-r--r-- | framework/source/uiconfiguration/imagemanager.cxx | 257 | ||||
-rwxr-xr-x | framework/source/uiconfiguration/imagemanagerimpl.cxx | 1466 | ||||
-rwxr-xr-x | framework/source/uiconfiguration/imagemanagerimpl.hxx | 225 | ||||
-rw-r--r-- | framework/source/uiconfiguration/makefile.mk | 58 | ||||
-rw-r--r-- | framework/source/uiconfiguration/moduleimagemanager.cxx | 229 | ||||
-rw-r--r-- | framework/source/uiconfiguration/moduleuicfgsupplier.cxx | 401 | ||||
-rw-r--r-- | framework/source/uiconfiguration/moduleuiconfigurationmanager.cxx | 1615 | ||||
-rw-r--r-- | framework/source/uiconfiguration/uicategorydescription.cxx | 479 | ||||
-rw-r--r-- | framework/source/uiconfiguration/uiconfigurationmanager.cxx | 1357 | ||||
-rwxr-xr-x | framework/source/uiconfiguration/uiconfigurationmanagerimpl.cxx | 1713 | ||||
-rwxr-xr-x | framework/source/uiconfiguration/uiconfigurationmanagerimpl.hxx | 221 | ||||
-rw-r--r-- | framework/source/uiconfiguration/windowstateconfiguration.cxx | 1493 |
14 files changed, 9988 insertions, 0 deletions
diff --git a/framework/source/uiconfiguration/globalsettings.cxx b/framework/source/uiconfiguration/globalsettings.cxx new file mode 100644 index 000000000000..adca6c85a110 --- /dev/null +++ b/framework/source/uiconfiguration/globalsettings.cxx @@ -0,0 +1,359 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: globalsettings.cxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include "uiconfiguration/globalsettings.hxx" +#include <threadhelp/resetableguard.hxx> +#include "services.h" + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XContainer.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XEventListener.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ +#include <rtl/ustrbuf.hxx> +#include <rtl/instance.hxx> +#include <cppuhelper/weak.hxx> +#include <tools/debug.hxx> + +//_________________________________________________________________________________________________________________ +// Defines +//_________________________________________________________________________________________________________________ +// + +using namespace rtl; +using namespace ::com::sun::star; + +//_________________________________________________________________________________________________________________ +// Namespace +//_________________________________________________________________________________________________________________ +// + +static const char GLOBALSETTINGS_ROOT_ACCESS[] = "/org.openoffice.Office.UI.GlobalSettings/Toolbars"; + +static const char GLOBALSETTINGS_NODEREF_STATES[] = "States"; +static const char GLOBALSETTINGS_PROPERTY_LOCKED[] = "Locked"; +static const char GLOBALSETTINGS_PROPERTY_DOCKED[] = "Docked"; +static const char GLOBALSETTINGS_PROPERTY_STATESENABLED[] = "StatesEnabled"; + +namespace framework +{ + +//***************************************************************************************************************** +// Configuration access class for WindowState supplier implementation +//***************************************************************************************************************** + +class GlobalSettings_Access : public ::com::sun::star::lang::XComponent , + public ::com::sun::star::lang::XEventListener , + private ThreadHelpBase , // Struct for right initalization of mutex member! Must be first of baseclasses. + public ::cppu::OWeakObject +{ + public: + GlobalSettings_Access( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ); + virtual ~GlobalSettings_Access(); + + // XInterface, XTypeProvider, XServiceInfo + FWK_DECLARE_XINTERFACE + + // XComponent + virtual void SAL_CALL dispose() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + + // settings access + sal_Bool HasStatesInfo( GlobalSettings::UIElementType eElementType ); + sal_Bool GetStateInfo( GlobalSettings::UIElementType eElementType, GlobalSettings::StateInfo eStateInfo, ::com::sun::star::uno::Any& aValue ); + + private: + sal_Bool impl_initConfigAccess(); + + sal_Bool m_bDisposed : 1, + m_bConfigRead : 1; + rtl::OUString m_aConfigSettingsAccess; + rtl::OUString m_aNodeRefStates; + rtl::OUString m_aPropStatesEnabled; + rtl::OUString m_aPropLocked; + rtl::OUString m_aPropDocked; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xConfigAccess; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xServiceManager; +}; + + +//***************************************************************************************************************** +// XInterface +//***************************************************************************************************************** +DEFINE_XINTERFACE_2 ( GlobalSettings_Access , + OWeakObject , + DIRECT_INTERFACE ( css::lang::XComponent ), + DIRECT_INTERFACE ( css::lang::XEventListener ) + ) + +GlobalSettings_Access::GlobalSettings_Access( const css::uno::Reference< css::lang::XMultiServiceFactory >& rServiceManager ) : + ThreadHelpBase(), + m_bDisposed( sal_False ), + m_bConfigRead( sal_False ), + m_aConfigSettingsAccess( RTL_CONSTASCII_USTRINGPARAM( GLOBALSETTINGS_ROOT_ACCESS )), + m_aNodeRefStates( RTL_CONSTASCII_USTRINGPARAM( GLOBALSETTINGS_NODEREF_STATES )), + m_aPropStatesEnabled( RTL_CONSTASCII_USTRINGPARAM( GLOBALSETTINGS_PROPERTY_STATESENABLED )), + m_aPropLocked( RTL_CONSTASCII_USTRINGPARAM( GLOBALSETTINGS_PROPERTY_LOCKED )), + m_aPropDocked( RTL_CONSTASCII_USTRINGPARAM( GLOBALSETTINGS_PROPERTY_DOCKED )), + m_xServiceManager( rServiceManager ) +{ +} + +GlobalSettings_Access::~GlobalSettings_Access() +{ +} + +// XComponent +void SAL_CALL GlobalSettings_Access::dispose() +throw ( css::uno::RuntimeException ) +{ + // SAFE + ResetableGuard aLock( m_aLock ); + + m_xConfigAccess.clear(); + m_bDisposed = sal_True; +} + +void SAL_CALL GlobalSettings_Access::addEventListener( const css::uno::Reference< css::lang::XEventListener >& ) +throw (css::uno::RuntimeException) +{ +} + +void SAL_CALL GlobalSettings_Access::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& ) +throw (css::uno::RuntimeException) +{ +} + +// XEventListener +void SAL_CALL GlobalSettings_Access::disposing( const css::lang::EventObject& ) +throw (css::uno::RuntimeException) +{ + // SAFE + ResetableGuard aLock( m_aLock ); + m_xConfigAccess.clear(); +} + +// settings access +sal_Bool GlobalSettings_Access::HasStatesInfo( GlobalSettings::UIElementType eElementType ) +{ + ResetableGuard aLock( m_aLock ); + if ( eElementType == GlobalSettings::UIELEMENT_TYPE_DOCKWINDOW ) + return sal_False; + else if ( eElementType == GlobalSettings::UIELEMENT_TYPE_STATUSBAR ) + return sal_False; + + if ( m_bDisposed ) + return sal_False; + + if ( !m_bConfigRead ) + { + m_bConfigRead = sal_True; + impl_initConfigAccess(); + } + + if ( m_xConfigAccess.is() ) + { + try + { + css::uno::Any a; + sal_Bool bValue = sal_Bool(); + a = m_xConfigAccess->getByName( m_aPropStatesEnabled ); + if ( a >>= bValue ) + return bValue; + } + catch ( css::container::NoSuchElementException& ) + { + } + catch ( css::uno::Exception& ) + { + } + } + + return sal_False; +} + +sal_Bool GlobalSettings_Access::GetStateInfo( GlobalSettings::UIElementType eElementType, GlobalSettings::StateInfo eStateInfo, ::com::sun::star::uno::Any& aValue ) +{ + ResetableGuard aLock( m_aLock ); + if ( eElementType == GlobalSettings::UIELEMENT_TYPE_DOCKWINDOW ) + return sal_False; + else if ( eElementType == GlobalSettings::UIELEMENT_TYPE_STATUSBAR ) + return sal_False; + + if ( m_bDisposed ) + return sal_False; + + if ( !m_bConfigRead ) + { + m_bConfigRead = sal_True; + impl_initConfigAccess(); + } + + if ( m_xConfigAccess.is() ) + { + try + { + css::uno::Any a; + a = m_xConfigAccess->getByName( m_aNodeRefStates ); + css::uno::Reference< css::container::XNameAccess > xNameAccess; + if ( a >>= xNameAccess ) + { + if ( eStateInfo == GlobalSettings::STATEINFO_LOCKED ) + a = xNameAccess->getByName( m_aPropLocked ); + else if ( eStateInfo == GlobalSettings::STATEINFO_DOCKED ) + a = xNameAccess->getByName( m_aPropDocked ); + + aValue = a; + return sal_True; + } + } + catch ( css::container::NoSuchElementException& ) + { + } + catch ( css::uno::Exception& ) + { + } + } + + return sal_False; +} + +sal_Bool GlobalSettings_Access::impl_initConfigAccess() +{ + css::uno::Sequence< css::uno::Any > aArgs( 2 ); + css::beans::PropertyValue aPropValue; + + try + { + css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider; + if ( m_xServiceManager.is() ) + xConfigProvider = css::uno::Reference< css::lang::XMultiServiceFactory >( + m_xServiceManager->createInstance( SERVICENAME_CFGPROVIDER ), + css::uno::UNO_QUERY ); + + if ( xConfigProvider.is() ) + { + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" )); + aPropValue.Value = css::uno::makeAny( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( GLOBALSETTINGS_ROOT_ACCESS ))); + aArgs[0] = css::uno::makeAny( aPropValue ); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "lazywrite" )); + aPropValue.Value = css::uno::makeAny( sal_True ); + aArgs[1] = css::uno::makeAny( aPropValue ); + + m_xConfigAccess = css::uno::Reference< css::container::XNameAccess >( + xConfigProvider->createInstanceWithArguments( + SERVICENAME_CFGREADACCESS, aArgs ), + css::uno::UNO_QUERY ); + + css::uno::Reference< css::lang::XComponent > xComponent( xConfigProvider, css::uno::UNO_QUERY ); + if ( xComponent.is() ) + xComponent->addEventListener( + css::uno::Reference< css::lang::XEventListener >( + static_cast< cppu::OWeakObject* >( this ), + css::uno::UNO_QUERY )); + } + + return m_xConfigAccess.is(); + } + catch ( css::lang::WrappedTargetException& ) + { + } + catch ( css::uno::Exception& ) + { + } + + return sal_False; +} + +//***************************************************************************************************************** +// global class +//***************************************************************************************************************** + +struct mutexGlobalSettings : public rtl::Static< osl::Mutex, mutexGlobalSettings > {}; +static GlobalSettings_Access* pStaticSettings = 0; + +static GlobalSettings_Access* GetGlobalSettings( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rSrvMgr ) +{ + osl::MutexGuard aGuard(mutexGlobalSettings::get()); + if ( !pStaticSettings ) + pStaticSettings = new GlobalSettings_Access( rSrvMgr ); + return pStaticSettings; +} + +GlobalSettings::GlobalSettings( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rSrvMgr ) : + m_xSrvMgr( rSrvMgr ) +{ +} + +GlobalSettings::~GlobalSettings() +{ +} + +// settings access +sal_Bool GlobalSettings::HasStatesInfo( UIElementType eElementType ) +{ + GlobalSettings_Access* pSettings( GetGlobalSettings( m_xSrvMgr )); + + if ( pSettings ) + return pSettings->HasStatesInfo( eElementType ); + else + return sal_False; +} + +sal_Bool GlobalSettings::GetStateInfo( UIElementType eElementType, StateInfo eStateInfo, ::com::sun::star::uno::Any& aValue ) +{ + GlobalSettings_Access* pSettings( GetGlobalSettings( m_xSrvMgr )); + + if ( pSettings ) + return pSettings->GetStateInfo( eElementType, eStateInfo, aValue ); + else + return sal_False; +} + +} // namespace framework diff --git a/framework/source/uiconfiguration/graphicnameaccess.cxx b/framework/source/uiconfiguration/graphicnameaccess.cxx new file mode 100644 index 000000000000..f7568db1edec --- /dev/null +++ b/framework/source/uiconfiguration/graphicnameaccess.cxx @@ -0,0 +1,115 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: graphicnameaccess.cxx,v $ + * $Revision: 1.5.82.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uiconfiguration/graphicnameaccess.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#include <comphelper/sequence.hxx> + +using namespace ::com::sun::star; + +namespace framework +{ + +GraphicNameAccess::GraphicNameAccess() +{ +} + +GraphicNameAccess::~GraphicNameAccess() +{ +} + +void GraphicNameAccess::addElement( const rtl::OUString& rName, const uno::Reference< graphic::XGraphic >& rElement ) +{ + m_aNameToElementMap.insert( NameGraphicHashMap::value_type( rName, rElement )); +} + +// XNameAccess +uno::Any SAL_CALL GraphicNameAccess::getByName( const ::rtl::OUString& aName ) +throw( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + NameGraphicHashMap::const_iterator pIter = m_aNameToElementMap.find( aName ); + if ( pIter != m_aNameToElementMap.end() ) + return uno::makeAny( pIter->second ); + else + throw container::NoSuchElementException(); +} + +uno::Sequence< ::rtl::OUString > SAL_CALL GraphicNameAccess::getElementNames() +throw(::com::sun::star::uno::RuntimeException) +{ + if ( m_aSeq.getLength() == 0 ) + { + uno::Sequence< rtl::OUString > aSeq( m_aNameToElementMap.size() ); + NameGraphicHashMap::const_iterator pIter = m_aNameToElementMap.begin(); + sal_Int32 i( 0); + while ( pIter != m_aNameToElementMap.end()) + { + aSeq[i++] = pIter->first; + ++pIter; + } + m_aSeq = aSeq; + } + + return m_aSeq; +} + +sal_Bool SAL_CALL GraphicNameAccess::hasByName( const ::rtl::OUString& aName ) +throw(::com::sun::star::uno::RuntimeException) +{ + NameGraphicHashMap::const_iterator pIter = m_aNameToElementMap.find( aName ); + return ( pIter != m_aNameToElementMap.end() ); +} + +// XElementAccess +sal_Bool SAL_CALL GraphicNameAccess::hasElements() +throw( uno::RuntimeException ) +{ + return ( !m_aNameToElementMap.empty() ); +} + +uno::Type SAL_CALL GraphicNameAccess::getElementType() +throw( uno::RuntimeException ) +{ + return ::getCppuType( (const uno::Reference< graphic::XGraphic > *)NULL ); +} + +} // namespace framework diff --git a/framework/source/uiconfiguration/imagemanager.cxx b/framework/source/uiconfiguration/imagemanager.cxx new file mode 100644 index 000000000000..6844b5cb6b43 --- /dev/null +++ b/framework/source/uiconfiguration/imagemanager.cxx @@ -0,0 +1,257 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: imagemanager.cxx,v $ + * $Revision: 1.16.82.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uiconfiguration/imagemanager.hxx> +#include <threadhelp/resetableguard.hxx> +#include <xml/imagesconfiguration.hxx> +#include <uiconfiguration/graphicnameaccess.hxx> +#include <services.h> +#include "imagemanagerimpl.hxx" + +#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> + +//_________________________________________________________________________________________________________________ +// 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; + +// 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; + +namespace framework +{ + +typedef GraphicNameAccess CmdToXGraphicNameAccess; + +//***************************************************************************************************************** +// XInterface, XTypeProvider, XServiceInfo +//***************************************************************************************************************** +DEFINE_XSERVICEINFO_MULTISERVICE ( ImageManager , + ::cppu::OWeakObject , + SERVICENAME_IMAGEMANAGER , + IMPLEMENTATIONNAME_IMAGEMANAGER + ) + +DEFINE_INIT_SERVICE ( ImageManager, {} ) + +ImageManager::ImageManager( uno::Reference< XMultiServiceFactory > xServiceManager ) : + ThreadHelpBase( &Application::GetSolarMutex() ) + , m_pImpl( new ImageManagerImpl(xServiceManager,static_cast< OWeakObject* >(this),false) ) +{ +} + +ImageManager::~ImageManager() +{ + m_pImpl->clear(); +} + +// XComponent +void SAL_CALL ImageManager::dispose() throw (::com::sun::star::uno::RuntimeException) +{ + m_pImpl->dispose(); +} + +void SAL_CALL ImageManager::addEventListener( const uno::Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) +{ + m_pImpl->addEventListener(xListener); +} + +void SAL_CALL ImageManager::removeEventListener( const uno::Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) +{ + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + m_pImpl->removeEventListener(xListener); +} + +// Non-UNO methods +void ImageManager::setStorage( const uno::Reference< XStorage >& Storage ) +throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aLock( m_pImpl->m_aLock ); + + m_pImpl->m_xUserConfigStorage = Storage; + m_pImpl->implts_initialize(); +} + +// XInitialization +void SAL_CALL ImageManager::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) +{ + m_pImpl->initialize(aArguments); +} + +// XImageManager +void SAL_CALL ImageManager::reset() +throw (::com::sun::star::uno::RuntimeException) +{ + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + m_pImpl->reset(); +} + +Sequence< ::rtl::OUString > SAL_CALL ImageManager::getAllImageNames( ::sal_Int16 nImageType ) +throw (::com::sun::star::uno::RuntimeException) +{ + return m_pImpl->getAllImageNames( nImageType ); +} + +::sal_Bool SAL_CALL ImageManager::hasImage( ::sal_Int16 nImageType, const ::rtl::OUString& aCommandURL ) +throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + return m_pImpl->hasImage(nImageType,aCommandURL); +} + +Sequence< uno::Reference< XGraphic > > SAL_CALL ImageManager::getImages( + ::sal_Int16 nImageType, + const Sequence< ::rtl::OUString >& aCommandURLSequence ) +throw ( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ) +{ + return m_pImpl->getImages(nImageType,aCommandURLSequence); +} + +void SAL_CALL ImageManager::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) +{ + m_pImpl->replaceImages(nImageType,aCommandURLSequence,aGraphicsSequence); +} + +void SAL_CALL ImageManager::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) +{ + m_pImpl->removeImages(nImageType,aCommandURLSequence); +} + +void SAL_CALL ImageManager::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) +{ + m_pImpl->insertImages(nImageType,aCommandURLSequence,aGraphicSequence); +} + +// XUIConfiguration +void SAL_CALL ImageManager::addConfigurationListener( const uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) +throw (::com::sun::star::uno::RuntimeException) +{ + m_pImpl->addConfigurationListener(xListener); +} + +void SAL_CALL ImageManager::removeConfigurationListener( const uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) +throw (::com::sun::star::uno::RuntimeException) +{ + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + m_pImpl->removeConfigurationListener(xListener); +} + +// XUIConfigurationPersistence +void SAL_CALL ImageManager::reload() +throw ( ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException ) +{ + m_pImpl->reload(); +} + +void SAL_CALL ImageManager::store() +throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + m_pImpl->store(); +} + +void SAL_CALL ImageManager::storeToStorage( const uno::Reference< XStorage >& Storage ) +throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + m_pImpl->storeToStorage(Storage); +} + +sal_Bool SAL_CALL ImageManager::isModified() +throw (::com::sun::star::uno::RuntimeException) +{ + return m_pImpl->isModified(); +} + +sal_Bool SAL_CALL ImageManager::isReadOnly() throw (::com::sun::star::uno::RuntimeException) +{ + return m_pImpl->isReadOnly(); +} + +} // namespace framework diff --git a/framework/source/uiconfiguration/imagemanagerimpl.cxx b/framework/source/uiconfiguration/imagemanagerimpl.cxx new file mode 100755 index 000000000000..d46711048b11 --- /dev/null +++ b/framework/source/uiconfiguration/imagemanagerimpl.cxx @@ -0,0 +1,1466 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ImageManagerImpl.cxx,v $ + * $Revision: 1.16.82.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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 ( USHORT 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 ( USHORT 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; + + USHORT 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++ ) + { + USHORT nPos = pImageList->GetImagePos( aCommandURLSequence[i] ); + if ( nPos != IMAGELIST_IMAGE_NOTFOUND ) + { + Image aImage = pImageList->GetImage( nPos ); + USHORT 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 diff --git a/framework/source/uiconfiguration/imagemanagerimpl.hxx b/framework/source/uiconfiguration/imagemanagerimpl.hxx new file mode 100755 index 000000000000..8eea59b9236c --- /dev/null +++ b/framework/source/uiconfiguration/imagemanagerimpl.hxx @@ -0,0 +1,225 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: imagemanager.hxx,v $ + * $Revision: 1.7.82.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __FRAMEWORK_UICONFIGURATION_IMAGEMANAGERIMPL_HXX_ +#define __FRAMEWORK_UICONFIGURATION_IMAGEMANAGERIMPL_HXX_ + + +/** Attention: stl headers must(!) be included at first. Otherwhise it can make trouble + with solaris headers ... +*/ +#include <vector> +#include <list> +#include <hash_map> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <threadhelp/threadhelpbase.hxx> +#include <macros/generic.hxx> +#include <macros/xinterface.hxx> +#include <macros/xtypeprovider.hxx> +#include <macros/xserviceinfo.hxx> +#include <stdtypes.h> +#include <uiconfiguration/imagetype.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/ui/XUIConfigurationPersistence.hpp> +#include <com/sun/star/ui/XUIConfigurationStorage.hpp> +#include <com/sun/star/ui/XUIConfiguration.hpp> +#include <com/sun/star/ui/XImageManager.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/ui/ConfigurationEvent.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/ui/XImageManager.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <cppuhelper/weak.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <rtl/ustring.hxx> + +#include <vcl/image.hxx> +#include <tools/color.hxx> +#include <rtl/ref.hxx> + +#include <vector> + +namespace framework +{ + class CmdImageList + { + public: + CmdImageList( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rServiceManager, + const ::rtl::OUString& aModuleIdentifier ); + virtual ~CmdImageList(); + + virtual Image getImageFromCommandURL( sal_Int16 nImageType, const rtl::OUString& rCommandURL ); + virtual bool hasImage( sal_Int16 nImageType, const rtl::OUString& rCommandURL ); + virtual ::std::vector< rtl::OUString >& getImageNames(); + virtual ::std::vector< rtl::OUString >& getImageCommandNames(); + + protected: + void impl_fillCommandToImageNameMap(); + ImageList* impl_getImageList( sal_Int16 nImageType ); + std::vector< ::rtl::OUString >& impl_getImageNameVector(); + std::vector< ::rtl::OUString >& impl_getImageCommandNameVector(); + + private: + sal_Bool m_bVectorInit; + rtl::OUString m_aModuleIdentifier; + ImageList* m_pImageList[ImageType_COUNT]; + CommandToImageNameMap m_aCommandToImageNameMap; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xServiceManager; + ::std::vector< rtl::OUString > m_aImageNameVector; + ::std::vector< rtl::OUString > m_aImageCommandNameVector; + sal_Int16 m_nSymbolsStyle; + }; + + class GlobalImageList : public CmdImageList, public rtl::IReference + { + public: + GlobalImageList( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rServiceManager ); + virtual ~GlobalImageList(); + + virtual Image getImageFromCommandURL( sal_Int16 nImageType, const rtl::OUString& rCommandURL ); + virtual bool hasImage( sal_Int16 nImageType, const rtl::OUString& rCommandURL ); + virtual ::std::vector< rtl::OUString >& getImageNames(); + virtual ::std::vector< rtl::OUString >& getImageCommandNames(); + + // ÍReference + virtual oslInterlockedCount SAL_CALL acquire(); + virtual oslInterlockedCount SAL_CALL release(); + + private: + oslInterlockedCount m_nRefCount; + }; + + class ImageManagerImpl : public ThreadHelpBase // Struct for right initalization of mutex member! Must be first of baseclasses. + { + public: + + ImageManagerImpl(const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager + ,const com::sun::star::uno::Reference< com::sun::star::uno::XInterface >& _xOwner + ,bool _bUseGlobal); + ~ImageManagerImpl(); + + void dispose(); + void initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ); + void addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + void removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + + // XImageManager + void reset() throw (::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Sequence< ::rtl::OUString > getAllImageNames( ::sal_Int16 nImageType ) throw (::com::sun::star::uno::RuntimeException); + ::sal_Bool hasImage( ::sal_Int16 nImageType, const ::rtl::OUString& aCommandURL ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > > getImages( ::sal_Int16 nImageType, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aCommandURLSequence ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + void replaceImages( ::sal_Int16 nImageType, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aCommandURLSequence, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > >& aGraphicsSequence ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException); + void removeImages( ::sal_Int16 nImageType, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aResourceURLSequence ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException); + void insertImages( ::sal_Int16 nImageType, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aCommandURLSequence, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > >& aGraphicSequence ) throw (::com::sun::star::container::ElementExistException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException); + + // XUIConfiguration + void addConfigurationListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >& Listener ) throw (::com::sun::star::uno::RuntimeException); + void removeConfigurationListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >& Listener ) throw (::com::sun::star::uno::RuntimeException); + + // XUIConfigurationPersistence + void reload() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + void store() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + void storeToStorage( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& Storage ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + sal_Bool isModified() throw (::com::sun::star::uno::RuntimeException); + sal_Bool isReadOnly() throw (::com::sun::star::uno::RuntimeException); + + void clear(); + + typedef std::hash_map< rtl::OUString, + sal_Bool, + OUStringHashCode, + ::std::equal_to< ::rtl::OUString > > ImageNameMap; + + enum Layer + { + LAYER_DEFAULT, + LAYER_USERDEFINED, + LAYER_COUNT + }; + + enum NotifyOp + { + NotifyOp_Remove, + NotifyOp_Insert, + NotifyOp_Replace + }; + + typedef ::std::vector< ::com::sun::star::ui::ConfigurationEvent > ConfigEventNotifyContainer; + + // private methods + void implts_initialize(); + void implts_notifyContainerListener( const ::com::sun::star::ui::ConfigurationEvent& aEvent, NotifyOp eOp ); + ImageList* implts_getUserImageList( ImageType nImageType ); + sal_Bool implts_loadUserImages( ImageType nImageType, + const com::sun::star::uno::Reference< com::sun::star::embed::XStorage >& xUserImageStorage, + const com::sun::star::uno::Reference< com::sun::star::embed::XStorage >& xUserBitmapsStorage ); + sal_Bool implts_storeUserImages( ImageType nImageType, + const com::sun::star::uno::Reference< com::sun::star::embed::XStorage >& xUserImageStorage, + const com::sun::star::uno::Reference< com::sun::star::embed::XStorage >& xUserBitmapsStorage ); + const rtl::Reference< GlobalImageList >& implts_getGlobalImageList(); + CmdImageList* implts_getDefaultImageList(); + + + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > m_xUserConfigStorage; + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > m_xUserImageStorage; + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > m_xUserBitmapsStorage; + com::sun::star::uno::Reference< com::sun::star::embed::XTransactedObject > m_xUserRootCommit; + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > m_xServiceManager; + com::sun::star::uno::Reference< com::sun::star::uno::XInterface > m_xOwner; + rtl::Reference< GlobalImageList > m_pGlobalImageList; + CmdImageList* m_pDefaultImageList; + rtl::OUString m_aXMLPostfix; + rtl::OUString m_aModuleIdentifier; + rtl::OUString m_aResourceString; + ::cppu::OMultiTypeInterfaceContainerHelper m_aListenerContainer; /// container for ALL Listener + ImageList* m_pUserImageList[ImageType_COUNT]; + bool m_bUserImageListModified[ImageType_COUNT]; + bool m_bUseGlobal; + bool m_bReadOnly; + bool m_bInitialized; + bool m_bModified; + bool m_bConfigRead; + bool m_bDisposed; + }; +} + +#endif // __FRAMEWORK_UICONFIGURATION_IMAGEMANAGERIMPL_HXX_ diff --git a/framework/source/uiconfiguration/makefile.mk b/framework/source/uiconfiguration/makefile.mk new file mode 100644 index 000000000000..3ef9006072a2 --- /dev/null +++ b/framework/source/uiconfiguration/makefile.mk @@ -0,0 +1,58 @@ + +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME= framework +TARGET= fwk_uiconfiguration +USE_DEFFILE= TRUE +ENABLE_EXCEPTIONS= TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Generate ----------------------------------------------------- + +SLOFILES= \ + $(SLO)$/uiconfigurationmanager.obj \ + $(SLO)$/moduleuiconfigurationmanager.obj \ + $(SLO)$/moduleuicfgsupplier.obj \ + $(SLO)$/windowstateconfiguration.obj \ + $(SLO)$/moduleimagemanager.obj \ + $(SLO)$/imagemanager.obj \ + $(SLO)$/imagemanagerimpl.obj \ + $(SLO)$/graphicnameaccess.obj \ + $(SLO)$/uicategorydescription.obj \ + $(SLO)$/globalsettings.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/framework/source/uiconfiguration/moduleimagemanager.cxx b/framework/source/uiconfiguration/moduleimagemanager.cxx new file mode 100644 index 000000000000..8dedf0e5b033 --- /dev/null +++ b/framework/source/uiconfiguration/moduleimagemanager.cxx @@ -0,0 +1,229 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: moduleimagemanager.cxx,v $ + * $Revision: 1.21 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <rtl/logfile.hxx> +#include <uiconfiguration/moduleimagemanager.hxx> +#include <threadhelp/resetableguard.hxx> +#include <xml/imagesconfiguration.hxx> +#include <uiconfiguration/graphicnameaccess.hxx> +#include <services.h> +#include "imagemanagerimpl.hxx" + +#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> +#include <com/sun/star/uri/XUriReferenceFactory.hpp> +#include <com/sun/star/uri/XUriReference.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#include <vcl/svapp.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/mutex.hxx> +#include <osl/file.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> + +//_________________________________________________________________________________________________________________ +// 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; + +namespace framework +{ +ModuleImageManager::ModuleImageManager( uno::Reference< XMultiServiceFactory > xServiceManager ) : + ThreadHelpBase( &Application::GetSolarMutex() ) + , m_pImpl( new ImageManagerImpl(xServiceManager,static_cast< OWeakObject* >(this),true) ) +{ +} + +ModuleImageManager::~ModuleImageManager() +{ +} + +// XComponent +void SAL_CALL ModuleImageManager::dispose() throw (::com::sun::star::uno::RuntimeException) +{ + m_pImpl->dispose(); +} + +void SAL_CALL ModuleImageManager::addEventListener( const uno::Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) +{ + m_pImpl->addEventListener(xListener); +} + +void SAL_CALL ModuleImageManager::removeEventListener( const uno::Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) +{ + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + m_pImpl->removeEventListener(xListener); +} + +// XInitialization +void SAL_CALL ModuleImageManager::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) +{ + m_pImpl->initialize(aArguments); +} + +// XImageManager +void SAL_CALL ModuleImageManager::reset() +throw (::com::sun::star::uno::RuntimeException) +{ + m_pImpl->reset(); +} + +Sequence< ::rtl::OUString > SAL_CALL ModuleImageManager::getAllImageNames( ::sal_Int16 nImageType ) +throw (::com::sun::star::uno::RuntimeException) +{ + return m_pImpl->getAllImageNames( nImageType ); +} + +::sal_Bool SAL_CALL ModuleImageManager::hasImage( ::sal_Int16 nImageType, const ::rtl::OUString& aCommandURL ) +throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + return m_pImpl->hasImage(nImageType,aCommandURL); +} + +Sequence< uno::Reference< XGraphic > > SAL_CALL ModuleImageManager::getImages( + ::sal_Int16 nImageType, + const Sequence< ::rtl::OUString >& aCommandURLSequence ) +throw ( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "framework: ModuleImageManager::getImages" ); + return m_pImpl->getImages(nImageType,aCommandURLSequence); +} + +void SAL_CALL ModuleImageManager::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) +{ + m_pImpl->replaceImages(nImageType,aCommandURLSequence,aGraphicsSequence); +} + +void SAL_CALL ModuleImageManager::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) +{ + m_pImpl->removeImages(nImageType,aCommandURLSequence); +} + +void SAL_CALL ModuleImageManager::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) +{ + m_pImpl->insertImages(nImageType,aCommandURLSequence,aGraphicSequence); +} + +// XUIConfiguration +void SAL_CALL ModuleImageManager::addConfigurationListener( const uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) +throw (::com::sun::star::uno::RuntimeException) +{ + m_pImpl->addConfigurationListener(xListener); +} + +void SAL_CALL ModuleImageManager::removeConfigurationListener( const uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) +throw (::com::sun::star::uno::RuntimeException) +{ + m_pImpl->removeConfigurationListener(xListener); +} + +// XUIConfigurationPersistence +void SAL_CALL ModuleImageManager::reload() +throw ( ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException ) +{ + m_pImpl->reload(); +} + +void SAL_CALL ModuleImageManager::store() +throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + m_pImpl->store(); +} + +void SAL_CALL ModuleImageManager::storeToStorage( const uno::Reference< XStorage >& Storage ) +throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + m_pImpl->storeToStorage(Storage); +} + +sal_Bool SAL_CALL ModuleImageManager::isModified() +throw (::com::sun::star::uno::RuntimeException) +{ + return m_pImpl->isModified(); +} + +sal_Bool SAL_CALL ModuleImageManager::isReadOnly() throw (::com::sun::star::uno::RuntimeException) +{ + return m_pImpl->isReadOnly(); +} + +} // namespace framework diff --git a/framework/source/uiconfiguration/moduleuicfgsupplier.cxx b/framework/source/uiconfiguration/moduleuicfgsupplier.cxx new file mode 100644 index 000000000000..343e569a4993 --- /dev/null +++ b/framework/source/uiconfiguration/moduleuicfgsupplier.cxx @@ -0,0 +1,401 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: moduleuicfgsupplier.cxx,v $ + * $Revision: 1.12 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uiconfiguration/moduleuicfgsupplier.hxx> +#include <threadhelp/resetableguard.hxx> +#include <services.h> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/embed/XPackageStructureCreator.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <rtl/logfile.hxx> +#include <cppuhelper/implbase1.hxx> +#include <vcl/svapp.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::io; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; +using namespace com::sun::star::beans; +using namespace com::sun::star::embed; +using namespace ::com::sun::star::ui; +using namespace ::com::sun::star::frame; + +namespace framework +{ + +class RootStorageWrapper : public ::cppu::WeakImplHelper1< com::sun::star::embed::XTransactedObject > +{ + public: + // XInterface, XTypeProvider + RootStorageWrapper( const Reference< XTransactedObject >& xRootCommit ) : m_xRootCommit( xRootCommit ) {} + virtual ~RootStorageWrapper() {} + + // XTransactedObject + virtual void SAL_CALL commit() throw ( com::sun::star::io::IOException, com::sun::star::lang::WrappedTargetException ) + { + m_xRootCommit->commit(); + } + + virtual void SAL_CALL revert() throw ( com::sun::star::io::IOException, com::sun::star::lang::WrappedTargetException ) + { + m_xRootCommit->revert(); + } + + private: + Reference< XTransactedObject > m_xRootCommit; +}; + +//***************************************************************************************************************** +// XInterface, XTypeProvider, XServiceInfo +//***************************************************************************************************************** +DEFINE_XINTERFACE_4 ( ModuleUIConfigurationManagerSupplier , + OWeakObject , + DIRECT_INTERFACE( css::lang::XTypeProvider ), + DIRECT_INTERFACE( css::lang::XServiceInfo ), + DIRECT_INTERFACE( css::lang::XComponent ), + DIRECT_INTERFACE( ::com::sun::star::ui::XModuleUIConfigurationManagerSupplier ) + ) + +DEFINE_XTYPEPROVIDER_4 ( ModuleUIConfigurationManagerSupplier , + css::lang::XTypeProvider , + css::lang::XServiceInfo , + css::lang::XComponent , + ::com::sun::star::ui::XModuleUIConfigurationManagerSupplier + ) + +DEFINE_XSERVICEINFO_ONEINSTANCESERVICE ( ModuleUIConfigurationManagerSupplier , + ::cppu::OWeakObject , + SERVICENAME_MODULEUICONFIGURATIONMANAGERSUPPLIER , + IMPLEMENTATIONNAME_MODULEUICONFIGURATIONMANAGERSUPPLIER + ) + +DEFINE_INIT_SERVICE ( ModuleUIConfigurationManagerSupplier, {} ) + + +/*TODO_AS +void ModuleUIConfigurationManagerSupplier::impl_initStorages() +{ +RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ModuleUIConfigurationManagerSupplier::impl_initStorages" ); + if ( !m_bInit ) + { + RTL_LOGFILE_CONTEXT( aLog, "framework (cd100003) ::ModuleUIConfigurationManagerSupplier::impl_initStorages" ); + + rtl::OUString aFinalSlash( RTL_CONSTASCII_USTRINGPARAM( "/" )); + rtl::OUString aConfigRootFolder( RTL_CONSTASCII_USTRINGPARAM( "soffice.cfg/modules" )); + rtl::OUString aConfigSubFolder( RTL_CONSTASCII_USTRINGPARAM( "soffice.cfg/modules/soffice.cfg" )); + rtl::OUString aConfigRootFolder( RTL_CONSTASCII_USTRINGPARAM( "soffice.cfg" )); + rtl::OUString aConfigSubFolder( RTL_CONSTASCII_USTRINGPARAM( "soffice.cfg/soffice.cfg" )); + rtl::OUString aConfigFileName( RTL_CONSTASCII_USTRINGPARAM( "soffice.cfg/uiconfig.zip" )); + + Reference< XPropertySet > xPathSettings( m_xServiceManager->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.PathSettings" ))), + UNO_QUERY_THROW ); + + Any a = xPathSettings->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UIConfig" ))); + a >>= m_aDefaultConfigURL; + a = xPathSettings->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserConfig" ))); + a >>= m_aUserConfigURL; + + // Use only the first entry from "UIConfig" + sal_Int32 nIndex = m_aDefaultConfigURL.indexOf( ';' ); + if ( nIndex > 0 ) + m_aDefaultConfigURL = m_aDefaultConfigURL.copy( 0, nIndex ); + + rtl::OUString aDefaultConfigFolderURL( m_aDefaultConfigURL ); + + nIndex = m_aDefaultConfigURL.lastIndexOf( '/' ); + if (( nIndex > 0 ) && ( nIndex != ( m_aDefaultConfigURL.getLength()-1 ))) + { + m_aDefaultConfigURL += aFinalSlash; + aDefaultConfigFolderURL += aFinalSlash; + } + + nIndex = m_aUserConfigURL.lastIndexOf( '/' ); + if (( nIndex > 0 ) && ( nIndex != ( m_aUserConfigURL.getLength()-1 ))) + m_aUserConfigURL += aFinalSlash; + +// aDefaultConfigFolderURL += aConfigRootFolder; + + // Create root storages for user interface configuration data (default and customizable) + Reference< XSingleServiceFactory > xStorageFactory( m_xServiceManager->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.StorageFactory" ))), + UNO_QUERY_THROW ); + + Sequence< Any > aArgs( 2 ); + + // Default root storage (READ-ACCESS) + aArgs[0] <<= m_aDefaultConfigURL + aConfigFileName; //aConfigSubFolder; + aArgs[1] <<= ElementModes::READ; + m_xDefaultCfgRootStorage = Reference< XStorage >( xStorageFactory->createInstanceWithArguments( aArgs ), UNO_QUERY_THROW ); + + Reference < XOutputStream > xTempOut( m_xServiceManager->createInstance ( + ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), + UNO_QUERY ); + + Reference< XPackageStructureCreator > xPackageStructCreator( m_xServiceManager->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.PackageStructureCreator" ))), + UNO_QUERY_THROW ); + + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ convertToPackage" ); + xPackageStructCreator->convertToPackage( aDefaultConfigFolderURL, xTempOut ); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} convertToPackage" ); + + xTempOut->closeOutput(); + Reference< XInputStream > xTempIn( xTempOut, UNO_QUERY ); + Reference< XSeekable > xTempSeek( xTempOut, UNO_QUERY ); + + // Default root storage (READ-ACCESS) + xTempSeek->seek( 0 ); + + aArgs[0] <<= xTempIn; + aArgs[1] <<= ElementModes::READ; + m_xDefaultCfgRootStorage = Reference< XStorage >( xStorageFactory->createInstanceWithArguments( aArgs ), UNO_QUERY_THROW ); + + // Customizable root storage (READWRITE-ACCESS) + aArgs[0] <<= m_aUserConfigURL + aConfigSubFolder; + aArgs[1] <<= ElementModes::READWRITE; + m_xUserCfgRootStorage = Reference< XStorage >( xStorageFactory->createInstanceWithArguments( aArgs ), UNO_QUERY ); + + // Create wrapper object for module user interface configuration managers, so they are able to call commit/revert on + // root storage and nothing more (saftey)! + RootStorageWrapper* pUserRootStorageWrapper = new RootStorageWrapper( Reference< XTransactedObject >( m_xUserCfgRootStorage, UNO_QUERY )); + m_xUserRootCommit = Reference< XTransactedObject>( static_cast< OWeakObject *>( pUserRootStorageWrapper ), UNO_QUERY ); + } + + m_bInit = true; +} +*/ + + +ModuleUIConfigurationManagerSupplier::ModuleUIConfigurationManagerSupplier( const Reference< XMultiServiceFactory >& xServiceManager ) : + ThreadHelpBase( &Application::GetSolarMutex() ) + , m_bDisposed( false ) +//TODO_AS , m_bInit( false ) + , m_xModuleMgr( Reference< XModuleManager >( xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY )) + , m_xServiceManager( xServiceManager ) + , m_aListenerContainer( m_aLock.getShareableOslMutex() ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ModuleUIConfigurationManagerSupplier::ModuleUIConfigurationManagerSupplier" ); + // Retrieve known modules and insert them into our hash_map to speed-up access time. + Reference< XNameAccess > xNameAccess( m_xModuleMgr, UNO_QUERY ); + const Sequence< ::rtl::OUString > aNameSeq = xNameAccess->getElementNames(); + const ::rtl::OUString* pNameSeq = aNameSeq.getConstArray(); + for ( sal_Int32 n = 0; n < aNameSeq.getLength(); n++ ) + m_aModuleToModuleUICfgMgrMap.insert( ModuleToModuleCfgMgr::value_type( pNameSeq[n], Reference< XUIConfigurationManager >() )); +} + +ModuleUIConfigurationManagerSupplier::~ModuleUIConfigurationManagerSupplier() +{ + m_xUserRootCommit.clear(); + + // dispose all our module user interface configuration managers + ModuleToModuleCfgMgr::iterator pIter = m_aModuleToModuleUICfgMgrMap.begin(); + while ( pIter != m_aModuleToModuleUICfgMgrMap.end() ) + { + Reference< XComponent > xComponent( pIter->second, UNO_QUERY ); + if ( xComponent.is() ) + xComponent->dispose(); + ++pIter; + } +/*TODO_AS + // Dispose our root configuration storages + if ( m_xDefaultCfgRootStorage.is() ) + { + Reference< XComponent > xComponent( m_xDefaultCfgRootStorage, UNO_QUERY ); + xComponent->dispose(); + } + + if ( m_xUserCfgRootStorage.is() ) + { + Reference< XComponent > xComponent( m_xUserCfgRootStorage, UNO_QUERY ); + xComponent->dispose(); + } +*/ +} + +// XComponent +void SAL_CALL ModuleUIConfigurationManagerSupplier::dispose() +throw ( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ModuleUIConfigurationManagerSupplier::dispose" ); + Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY ); + + css::lang::EventObject aEvent( xThis ); + m_aListenerContainer.disposeAndClear( aEvent ); + + { + ResetableGuard aGuard( m_aLock ); + m_bDisposed = true; + } +} + +void SAL_CALL ModuleUIConfigurationManagerSupplier::addEventListener( const Reference< XEventListener >& xListener ) +throw ( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ModuleUIConfigurationManagerSupplier::addEventListener" ); + { + ResetableGuard aGuard( m_aLock ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + if ( m_bDisposed ) + throw DisposedException(); + } + + m_aListenerContainer.addInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener ); +} + +void SAL_CALL ModuleUIConfigurationManagerSupplier::removeEventListener( const Reference< XEventListener >& xListener ) +throw ( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ModuleUIConfigurationManagerSupplier::removeEventListener" ); + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener ); +} + +// XModuleUIConfigurationManagerSupplier +Reference< XUIConfigurationManager > SAL_CALL ModuleUIConfigurationManagerSupplier::getUIConfigurationManager( const ::rtl::OUString& ModuleIdentifier ) +throw ( NoSuchElementException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ModuleUIConfigurationManagerSupplier::getUIConfigurationManager" ); + ResetableGuard aGuard( m_aLock ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + if ( m_bDisposed ) + throw DisposedException(); + + ModuleToModuleCfgMgr::iterator pIter = m_aModuleToModuleUICfgMgrMap.find( ModuleIdentifier ); + if ( pIter == m_aModuleToModuleUICfgMgrMap.end() ) + throw NoSuchElementException(); +//TODO_AS impl_initStorages(); + + // Create instance on demand + if ( !pIter->second.is() ) + { + /*TODO_AS + Reference< XStorage > xDefaultConfigModuleStorage; + Reference< XStorage > xUserConfigModuleStorage; + + try + { + xDefaultConfigModuleStorage = Reference< XStorage >( m_xDefaultCfgRootStorage->openStorageElement( + sShort, ElementModes::READ ), UNO_QUERY_THROW ); + + if ( m_xUserCfgRootStorage.is() ) + { + try + { + xUserConfigModuleStorage = Reference< XStorage >( m_xUserCfgRootStorage->openStorageElement( + sShort, ElementModes::READWRITE ), UNO_QUERY ); + } + catch( ::com::sun::star::io::IOException& ) + { + try + { + xUserConfigModuleStorage = Reference< XStorage >( m_xUserCfgRootStorage->openStorageElement( + sShort, ElementModes::READ ), UNO_QUERY ); + } + catch( com::sun::star::uno::Exception& ) + { + } + } + } + } + catch ( com::sun::star::uno::Exception& ) + { + } + PropertyValue aArg; + Sequence< Any > aArgs( 5 ); + aArg.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleIdentifier" )); + aArg.Value <<= ModuleIdentifier; + aArgs[0] <<= aArg; + aArg.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultConfigStorage" )); + aArg.Value <<= xDefaultConfigModuleStorage; + aArgs[1] <<= aArg; + aArg.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserConfigStorage" )); + aArg.Value <<= xUserConfigModuleStorage; + aArgs[2] <<= aArg; + aArg.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserRootCommit" )); + aArg.Value <<= m_xUserRootCommit; + aArgs[3] <<= aArg; + */ + ::rtl::OUString sShort; + try + { + Sequence< PropertyValue > lProps; + Reference< XNameAccess > xCont(m_xModuleMgr, UNO_QUERY); + xCont->getByName(ModuleIdentifier) >>= lProps; + for (sal_Int32 i=0; i<lProps.getLength(); ++i) + { + if (lProps[i].Name.equalsAscii("ooSetupFactoryShortName")) + { + lProps[i].Value >>= sShort; + break; + } + } + } + catch( Exception& ) + { + sShort = ::rtl::OUString(); + } + + if (!sShort.getLength()) + throw NoSuchElementException(); + PropertyValue aArg; + Sequence< Any > aArgs( 2 ); + aArg.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleShortName" )); + aArg.Value <<= sShort; + aArgs[0] <<= aArg; + aArg.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleIdentifier" )); + aArg.Value <<= ModuleIdentifier; + aArgs[1] <<= aArg; + + pIter->second.set( m_xServiceManager->createInstanceWithArguments(SERVICENAME_MODULEUICONFIGURATIONMANAGER, aArgs ),UNO_QUERY ); + } + + return pIter->second; +} + +} // namespace framework + diff --git a/framework/source/uiconfiguration/moduleuiconfigurationmanager.cxx b/framework/source/uiconfiguration/moduleuiconfigurationmanager.cxx new file mode 100644 index 000000000000..663c2d0d6dd8 --- /dev/null +++ b/framework/source/uiconfiguration/moduleuiconfigurationmanager.cxx @@ -0,0 +1,1615 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: moduleuiconfigurationmanager.cxx,v $ + * $Revision: 1.19.208.2 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uiconfiguration/moduleuiconfigurationmanager.hxx> +#include <threadhelp/resetableguard.hxx> +#include <services.h> +#include <uielement/constitemcontainer.hxx> +#include <uielement/rootitemcontainer.hxx> +#include <uielement/uielementtypenames.hxx> +#include <xml/menuconfiguration.hxx> +#include <xml/toolboxconfiguration.hxx> + +#ifndef __FRAMEWORK_XML_STATUSBARCONFIGURATION_HXX_ +#include <xml/statusbarconfiguration.hxx> +#endif + +//_________________________________________________________________________________________________________________ +// 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/embed/ElementModes.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/io/XStream.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#include <vcl/svapp.hxx> +#include <rtl/ustrbuf.hxx> +#include <comphelper/sequenceashashmap.hxx> + +//_________________________________________________________________________________________________________________ +// namespaces +//_________________________________________________________________________________________________________________ + +using rtl::OUString; +using namespace com::sun::star::uno; +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; + +namespace framework +{ + +//***************************************************************************************************************** +// XInterface, XTypeProvider, XServiceInfo +//***************************************************************************************************************** +DEFINE_XINTERFACE_8 ( ModuleUIConfigurationManager , + OWeakObject , + DIRECT_INTERFACE( css::lang::XTypeProvider ), + DIRECT_INTERFACE( css::lang::XServiceInfo ), + DIRECT_INTERFACE( css::lang::XComponent ), + DIRECT_INTERFACE( css::lang::XInitialization ), + DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfiguration ), + DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationManager ), + DIRECT_INTERFACE( ::com::sun::star::ui::XModuleUIConfigurationManager ), + DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationPersistence ) + ) + +DEFINE_XTYPEPROVIDER_8 ( ModuleUIConfigurationManager , + css::lang::XTypeProvider , + css::lang::XServiceInfo , + css::lang::XComponent , + css::lang::XInitialization , + ::com::sun::star::ui::XUIConfiguration , + ::com::sun::star::ui::XUIConfigurationManager , + ::com::sun::star::ui::XModuleUIConfigurationManager , + ::com::sun::star::ui::XUIConfigurationPersistence + ) + +DEFINE_XSERVICEINFO_MULTISERVICE ( ModuleUIConfigurationManager , + ::cppu::OWeakObject , + SERVICENAME_MODULEUICONFIGURATIONMANAGER , + IMPLEMENTATIONNAME_MODULEUICONFIGURATIONMANAGER + ) + +DEFINE_INIT_SERVICE ( ModuleUIConfigurationManager, {} ) + + +// important: The order and position of the elements must match the constant +// definition of "::com::sun::star::ui::UIElementType" +static const char* UIELEMENTTYPENAMES[] = +{ + "", // Dummy value for unknown! + UIELEMENTTYPE_MENUBAR_NAME, + UIELEMENTTYPE_POPUPMENU_NAME, + UIELEMENTTYPE_TOOLBAR_NAME, + UIELEMENTTYPE_STATUSBAR_NAME, + UIELEMENTTYPE_FLOATINGWINDOW_NAME, + UIELEMENTTYPE_PROGRESSBAR_NAME +}; + +static const char RESOURCEURL_PREFIX[] = "private:resource/"; +static const sal_Int32 RESOURCEURL_PREFIX_SIZE = 17; +static const char RESOURCEURL_CUSTOM_ELEMENT[] = "custom_"; + +static sal_Int16 RetrieveTypeFromResourceURL( const rtl::OUString& aResourceURL ) +{ + + if (( aResourceURL.indexOf( OUString( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_PREFIX ))) == 0 ) && + ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE )) + { + OUString aTmpStr = aResourceURL.copy( RESOURCEURL_PREFIX_SIZE ); + sal_Int32 nIndex = aTmpStr.indexOf( '/' ); + if (( nIndex > 0 ) && ( aTmpStr.getLength() > nIndex )) + { + OUString aTypeStr( aTmpStr.copy( 0, nIndex )); + for ( int i = 0; i < UIElementType::COUNT; i++ ) + { + if ( aTypeStr.equalsAscii( UIELEMENTTYPENAMES[i] )) + return sal_Int16( i ); + } + } + } + + return UIElementType::UNKNOWN; +} + +static OUString RetrieveNameFromResourceURL( const rtl::OUString& aResourceURL ) +{ + if (( aResourceURL.indexOf( OUString( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_PREFIX ))) == 0 ) && + ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE )) + { + sal_Int32 nIndex = aResourceURL.lastIndexOf( '/' ); + if (( nIndex > 0 ) && (( nIndex+1 ) < aResourceURL.getLength())) + return aResourceURL.copy( nIndex+1 ); + } + + return OUString(); +} + +void ModuleUIConfigurationManager::impl_fillSequenceWithElementTypeInfo( UIElementInfoHashMap& aUIElementInfoCollection, sal_Int16 nElementType ) +{ + // preload list of element types on demand + impl_preloadUIElementTypeList( LAYER_USERDEFINED, nElementType ); + impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType ); + + UIElementDataHashMap& rUserElements = m_aUIElements[LAYER_USERDEFINED][nElementType].aElementsHashMap; + UIElementDataHashMap::const_iterator pUserIter = rUserElements.begin(); + + OUString aCustomUrlPrefix( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_CUSTOM_ELEMENT )); + while ( pUserIter != rUserElements.end() ) + { + sal_Int32 nIndex = pUserIter->second.aResourceURL.indexOf( aCustomUrlPrefix, RESOURCEURL_PREFIX_SIZE ); + if ( nIndex > RESOURCEURL_PREFIX_SIZE ) + { + // Performance: Retrieve user interface name only for custom user interface elements. + // It's only used by them! + UIElementData* pDataSettings = impl_findUIElementData( pUserIter->second.aResourceURL, nElementType ); + if ( pDataSettings ) + { + // Retrieve user interface name from XPropertySet interface + rtl::OUString aUIName; + Reference< XPropertySet > xPropSet( pDataSettings->xSettings, UNO_QUERY ); + if ( xPropSet.is() ) + { + Any a = xPropSet->getPropertyValue( m_aPropUIName ); + a >>= aUIName; + } + + UIElementInfo aInfo( pUserIter->second.aResourceURL, aUIName ); + aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pUserIter->second.aResourceURL, aInfo )); + } + } + else + { + // The user interface name for standard user interface elements is stored in the WindowState.xcu file + UIElementInfo aInfo( pUserIter->second.aResourceURL, OUString() ); + aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pUserIter->second.aResourceURL, aInfo )); + } + ++pUserIter; + } + + UIElementDataHashMap& rDefaultElements = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap; + UIElementDataHashMap::const_iterator pDefIter = rDefaultElements.begin(); + + while ( pDefIter != rDefaultElements.end() ) + { + UIElementInfoHashMap::const_iterator pIterInfo = aUIElementInfoCollection.find( pDefIter->second.aResourceURL ); + if ( pIterInfo == aUIElementInfoCollection.end() ) + { + sal_Int32 nIndex = pDefIter->second.aResourceURL.indexOf( aCustomUrlPrefix, RESOURCEURL_PREFIX_SIZE ); + if ( nIndex > RESOURCEURL_PREFIX_SIZE ) + { + // Performance: Retrieve user interface name only for custom user interface elements. + // It's only used by them! + UIElementData* pDataSettings = impl_findUIElementData( pDefIter->second.aResourceURL, nElementType ); + if ( pDataSettings ) + { + // Retrieve user interface name from XPropertySet interface + rtl::OUString aUIName; + Reference< XPropertySet > xPropSet( pDataSettings->xSettings, UNO_QUERY ); + if ( xPropSet.is() ) + { + Any a = xPropSet->getPropertyValue( m_aPropUIName ); + a >>= aUIName; + } + + UIElementInfo aInfo( pDefIter->second.aResourceURL, aUIName ); + aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pDefIter->second.aResourceURL, aInfo )); + } + } + else + { + // The user interface name for standard user interface elements is stored in the WindowState.xcu file + UIElementInfo aInfo( pDefIter->second.aResourceURL, OUString() ); + aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pDefIter->second.aResourceURL, aInfo )); + } + } + + ++pDefIter; + } +} + +void ModuleUIConfigurationManager::impl_preloadUIElementTypeList( Layer eLayer, sal_Int16 nElementType ) +{ + UIElementType& rElementTypeData = m_aUIElements[eLayer][nElementType]; + + if ( !rElementTypeData.bLoaded ) + { + Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage; + if ( xElementTypeStorage.is() ) + { + rtl::OUStringBuffer aBuf( RESOURCEURL_PREFIX_SIZE ); + aBuf.appendAscii( RESOURCEURL_PREFIX ); + aBuf.appendAscii( UIELEMENTTYPENAMES[ nElementType ] ); + aBuf.appendAscii( "/" ); + OUString aResURLPrefix( aBuf.makeStringAndClear() ); + + UIElementDataHashMap& rHashMap = rElementTypeData.aElementsHashMap; + Reference< XNameAccess > xNameAccess( xElementTypeStorage, UNO_QUERY ); + Sequence< OUString > aUIElementNames = xNameAccess->getElementNames(); + for ( sal_Int32 n = 0; n < aUIElementNames.getLength(); n++ ) + { + UIElementData aUIElementData; + + // Resource name must be without ".xml" + sal_Int32 nIndex = aUIElementNames[n].lastIndexOf( '.' ); + if (( nIndex > 0 ) && ( nIndex < aUIElementNames[n].getLength() )) + { + OUString aExtension( aUIElementNames[n].copy( nIndex+1 )); + OUString aUIElementName( aUIElementNames[n].copy( 0, nIndex )); + + if (( aUIElementName.getLength() > 0 ) && + ( aExtension.equalsIgnoreAsciiCaseAsciiL( "xml", 3 ))) + { + aUIElementData.aResourceURL = aResURLPrefix + aUIElementName; + aUIElementData.aName = aUIElementNames[n]; + + if ( eLayer == LAYER_USERDEFINED ) + { + aUIElementData.bModified = false; + aUIElementData.bDefault = false; + aUIElementData.bDefaultNode = false; + } + + // Create hash_map entries for all user interface elements inside the storage. We don't load the + // settings to speed up the process. + rHashMap.insert( UIElementDataHashMap::value_type( aUIElementData.aResourceURL, aUIElementData )); + } + } + } + } + } + + rElementTypeData.bLoaded = true; +} + +void ModuleUIConfigurationManager::impl_requestUIElementData( sal_Int16 nElementType, Layer eLayer, UIElementData& aUIElementData ) +{ + UIElementType& rElementTypeData = m_aUIElements[eLayer][nElementType]; + + Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage; + if ( xElementTypeStorage.is() && aUIElementData.aName.getLength() ) + { + try + { + Reference< XStream > xStream = xElementTypeStorage->openStreamElement( aUIElementData.aName, ElementModes::READ ); + Reference< XInputStream > xInputStream = xStream->getInputStream(); + + if ( xInputStream.is() ) + { + switch ( nElementType ) + { + case ::com::sun::star::ui::UIElementType::UNKNOWN: + break; + + case ::com::sun::star::ui::UIElementType::MENUBAR: + { + try + { + MenuConfiguration aMenuCfg( m_xServiceManager ); + Reference< XIndexAccess > xContainer( aMenuCfg.CreateMenuBarConfigurationFromXML( xInputStream )); + RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xContainer ); + if ( pRootItemContainer ) + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY ); + else + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( xContainer, sal_True ) ), UNO_QUERY ); + return; + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + } + break; + + case ::com::sun::star::ui::UIElementType::POPUPMENU: + { + break; + } + + case ::com::sun::star::ui::UIElementType::TOOLBAR: + { + try + { + Reference< XIndexContainer > xIndexContainer( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY ); + ToolBoxConfiguration::LoadToolBox( m_xServiceManager, xInputStream, xIndexContainer ); + RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xIndexContainer ); + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY ); + return; + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + + break; + } + + case ::com::sun::star::ui::UIElementType::STATUSBAR: + { + try + { + Reference< XIndexContainer > xIndexContainer( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY ); + StatusBarConfiguration::LoadStatusBar( m_xServiceManager, xInputStream, xIndexContainer ); + RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xIndexContainer ); + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY ); + return; + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + + break; + } + + case ::com::sun::star::ui::UIElementType::FLOATINGWINDOW: + { + break; + } + } + } + } + catch ( ::com::sun::star::embed::InvalidStorageException& ) + { + } + catch ( ::com::sun::star::lang::IllegalArgumentException& ) + { + } + catch ( ::com::sun::star::io::IOException& ) + { + } + catch ( ::com::sun::star::embed::StorageWrappedTargetException& ) + { + } + } + + // At least we provide an empty settings container! + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer() ), UNO_QUERY ); +} + +ModuleUIConfigurationManager::UIElementData* ModuleUIConfigurationManager::impl_findUIElementData( const rtl::OUString& aResourceURL, sal_Int16 nElementType, bool bLoad ) +{ + // preload list of element types on demand + impl_preloadUIElementTypeList( LAYER_USERDEFINED, nElementType ); + impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType ); + + // first try to look into our user-defined vector/hash_map combination + UIElementDataHashMap& rUserHashMap = m_aUIElements[LAYER_USERDEFINED][nElementType].aElementsHashMap; + UIElementDataHashMap::iterator pIter = rUserHashMap.find( aResourceURL ); + if ( pIter != rUserHashMap.end() ) + { + // Default data settings data must be retrieved from the default layer! + if ( !pIter->second.bDefault ) + { + if ( !pIter->second.xSettings.is() && bLoad ) + impl_requestUIElementData( nElementType, LAYER_USERDEFINED, pIter->second ); + return &(pIter->second); + } + } + + // Not successfull, we have to look into our default vector/hash_map combination + UIElementDataHashMap& rDefaultHashMap = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap; + pIter = rDefaultHashMap.find( aResourceURL ); + if ( pIter != rDefaultHashMap.end() ) + { + if ( !pIter->second.xSettings.is() && bLoad ) + impl_requestUIElementData( nElementType, LAYER_DEFAULT, pIter->second ); + return &(pIter->second); + } + + // Nothing has been found! + return NULL; +} + +void ModuleUIConfigurationManager::impl_storeElementTypeData( Reference< XStorage > xStorage, UIElementType& rElementType, bool bResetModifyState ) +{ + UIElementDataHashMap& rHashMap = rElementType.aElementsHashMap; + UIElementDataHashMap::iterator pIter = rHashMap.begin(); + + while ( pIter != rHashMap.end() ) + { + UIElementData& rElement = pIter->second; + if ( rElement.bModified ) + { + if ( rElement.bDefault ) + { + xStorage->removeElement( rElement.aName ); + rElement.bModified = sal_False; // mark as not modified + } + else + { + Reference< XStream > xStream( xStorage->openStreamElement( rElement.aName, ElementModes::WRITE|ElementModes::TRUNCATE ), UNO_QUERY ); + Reference< XOutputStream > xOutputStream( xStream->getOutputStream() ); + + if ( xOutputStream.is() ) + { + switch( rElementType.nElementType ) + { + case ::com::sun::star::ui::UIElementType::MENUBAR: + { + try + { + MenuConfiguration aMenuCfg( m_xServiceManager ); + aMenuCfg.StoreMenuBarConfigurationToXML( rElement.xSettings, xOutputStream ); + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + } + break; + + case ::com::sun::star::ui::UIElementType::TOOLBAR: + { + try + { + ToolBoxConfiguration::StoreToolBox( m_xServiceManager, xOutputStream, rElement.xSettings ); + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + } + break; + + case ::com::sun::star::ui::UIElementType::STATUSBAR: + { + try + { + StatusBarConfiguration::StoreStatusBar( m_xServiceManager, xOutputStream, rElement.xSettings ); + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + } + break; + + default: + break; + } + } + + // mark as not modified if we store to our own storage + if ( bResetModifyState ) + rElement.bModified = sal_False; + } + } + + ++pIter; + } + + // commit element type storage + Reference< XTransactedObject > xTransactedObject( xStorage, UNO_QUERY ); + if ( xTransactedObject.is() ) + xTransactedObject->commit(); + + // mark UIElementType as not modified if we store to our own storage + if ( bResetModifyState ) + rElementType.bModified = sal_False; +} + +// This is only allowed to be called on the LAYER_USER_DEFINED! +void ModuleUIConfigurationManager::impl_resetElementTypeData( + UIElementType& rUserElementType, + UIElementType& rDefaultElementType, + ConfigEventNotifyContainer& rRemoveNotifyContainer, + ConfigEventNotifyContainer& rReplaceNotifyContainer ) +{ + UIElementDataHashMap& rHashMap = rUserElementType.aElementsHashMap; + UIElementDataHashMap::iterator pIter = rHashMap.begin(); + + Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); + Reference< XInterface > xIfac( xThis, UNO_QUERY ); + Reference< XNameAccess > xDefaultNameAccess( rDefaultElementType.xStorage, UNO_QUERY ); + sal_Int16 nType = rUserElementType.nElementType; + + // Make copies of the event structures to be thread-safe. We have to unlock our mutex before calling + // our listeners! + while ( pIter != rHashMap.end() ) + { + UIElementData& rElement = pIter->second; + if ( !rElement.bDefault ) + { + if ( xDefaultNameAccess->hasByName( rElement.aName )) + { + // Replace settings with data from default layer + Reference< XIndexAccess > xOldSettings( rElement.xSettings ); + impl_requestUIElementData( nType, LAYER_DEFAULT, rElement ); + + ConfigurationEvent aReplaceEvent; + aReplaceEvent.ResourceURL = rElement.aResourceURL; + aReplaceEvent.Accessor <<= xThis; + aReplaceEvent.Source = xIfac; + aReplaceEvent.ReplacedElement <<= xOldSettings; + aReplaceEvent.Element <<= rElement.xSettings; + + rReplaceNotifyContainer.push_back( aReplaceEvent ); + + // Mark element as default and not modified. That means "not active" + // in the user layer anymore. + rElement.bModified = false; + rElement.bDefault = true; + } + else + { + // Remove user-defined settings from user layer + ConfigurationEvent aEvent; + aEvent.ResourceURL = rElement.aResourceURL; + aEvent.Accessor <<= xThis; + aEvent.Source = xIfac; + aEvent.Element <<= rElement.xSettings; + + rRemoveNotifyContainer.push_back( aEvent ); + + // Mark element as default and not modified. That means "not active" + // in the user layer anymore. + rElement.bModified = false; + rElement.bDefault = true; + } + } + + ++pIter; + } + + // Remove all settings from our user interface elements + rHashMap.clear(); +} + +void ModuleUIConfigurationManager::impl_reloadElementTypeData( + UIElementType& rUserElementType, + UIElementType& rDefaultElementType, + ConfigEventNotifyContainer& rRemoveNotifyContainer, + ConfigEventNotifyContainer& rReplaceNotifyContainer ) +{ + UIElementDataHashMap& rHashMap = rUserElementType.aElementsHashMap; + UIElementDataHashMap::iterator pIter = rHashMap.begin(); + Reference< XStorage > xUserStorage( rUserElementType.xStorage ); + Reference< XStorage > xDefaultStorage( rDefaultElementType.xStorage ); + Reference< XNameAccess > xUserNameAccess( rUserElementType.xStorage, UNO_QUERY ); + Reference< XNameAccess > xDefaultNameAccess( rDefaultElementType.xStorage, UNO_QUERY ); + + Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); + Reference< XInterface > xIfac( xThis, UNO_QUERY ); + sal_Int16 nType = rUserElementType.nElementType; + + while ( pIter != rHashMap.end() ) + { + UIElementData& rElement = pIter->second; + if ( rElement.bModified ) + { + if ( xUserNameAccess->hasByName( rElement.aName )) + { + // Replace settings with data from user layer + Reference< XIndexAccess > xOldSettings( rElement.xSettings ); + + impl_requestUIElementData( nType, LAYER_USERDEFINED, rElement ); + + ConfigurationEvent aReplaceEvent; + + aReplaceEvent.ResourceURL = rElement.aResourceURL; + aReplaceEvent.Accessor <<= xThis; + aReplaceEvent.Source = xIfac; + aReplaceEvent.ReplacedElement <<= xOldSettings; + aReplaceEvent.Element <<= rElement.xSettings; + rReplaceNotifyContainer.push_back( aReplaceEvent ); + + rElement.bModified = false; + } + else if ( xDefaultNameAccess->hasByName( rElement.aName )) + { + // Replace settings with data from default layer + Reference< XIndexAccess > xOldSettings( rElement.xSettings ); + + impl_requestUIElementData( nType, LAYER_DEFAULT, rElement ); + + ConfigurationEvent aReplaceEvent; + + aReplaceEvent.ResourceURL = rElement.aResourceURL; + aReplaceEvent.Accessor <<= xThis; + aReplaceEvent.Source = xIfac; + aReplaceEvent.ReplacedElement <<= xOldSettings; + aReplaceEvent.Element <<= rElement.xSettings; + rReplaceNotifyContainer.push_back( aReplaceEvent ); + + // Mark element as default and not modified. That means "not active" + // in the user layer anymore. + rElement.bModified = false; + rElement.bDefault = true; + } + else + { + // Element settings are not in any storage => remove + ConfigurationEvent aRemoveEvent; + + aRemoveEvent.ResourceURL = rElement.aResourceURL; + aRemoveEvent.Accessor <<= xThis; + aRemoveEvent.Source = xIfac; + aRemoveEvent.Element <<= rElement.xSettings; + + rRemoveNotifyContainer.push_back( aRemoveEvent ); + + // Mark element as default and not modified. That means "not active" + // in the user layer anymore. + rElement.bModified = false; + rElement.bDefault = true; + } + } + ++pIter; + } + + rUserElementType.bModified = sal_False; +} + +void ModuleUIConfigurationManager::impl_Initialize() +{ + // Initialize the top-level structures with the storage data + if ( m_xUserConfigStorage.is() ) + { + // Try to access our module sub folder + for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; + i++ ) + { + Reference< XStorage > xElementTypeStorage; + try + { + if ( m_pStorageHandler[i] ) + xElementTypeStorage = m_pStorageHandler[i]->getWorkingStorageUser(); + } + 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& ) + { + } + + m_aUIElements[LAYER_USERDEFINED][i].nElementType = i; + m_aUIElements[LAYER_USERDEFINED][i].bModified = false; + m_aUIElements[LAYER_USERDEFINED][i].xStorage = xElementTypeStorage; + m_aUIElements[LAYER_USERDEFINED][i].bDefaultLayer = false; + } + } + + if ( m_xDefaultConfigStorage.is() ) + { + Reference< XNameAccess > xNameAccess( m_xDefaultConfigStorage, UNO_QUERY_THROW ); + + // Try to access our module sub folder + for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; + i++ ) + { + Reference< XStorage > xElementTypeStorage; + try + { + Any a = xNameAccess->getByName( OUString::createFromAscii( UIELEMENTTYPENAMES[i] )); + a >>= xElementTypeStorage; + } + catch ( com::sun::star::container::NoSuchElementException& ) + { + } + + m_aUIElements[LAYER_DEFAULT][i].nElementType = i; + m_aUIElements[LAYER_DEFAULT][i].bModified = false; + m_aUIElements[LAYER_DEFAULT][i].xStorage = xElementTypeStorage; + m_aUIElements[LAYER_DEFAULT][i].bDefaultLayer = true; + } + } +} + +ModuleUIConfigurationManager::ModuleUIConfigurationManager( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > xServiceManager ) : + ThreadHelpBase( &Application::GetSolarMutex() ) + , m_xDefaultConfigStorage( 0 ) + , m_xUserConfigStorage( 0 ) + , m_bReadOnly( true ) + , m_bInitialized( false ) + , m_bModified( false ) + , m_bConfigRead( false ) + , m_bDisposed( false ) + , m_aXMLPostfix( RTL_CONSTASCII_USTRINGPARAM( ".xml" )) + , m_aPropUIName( RTL_CONSTASCII_USTRINGPARAM( "UIName" )) + , m_aPropResourceURL( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" )) + , m_xServiceManager( xServiceManager ) + , m_aListenerContainer( m_aLock.getShareableOslMutex() ) +{ + for ( int i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + m_pStorageHandler[i] = 0; + + // Make sure we have a default initialized entry for every layer and user interface element type! + // The following code depends on this! + m_aUIElements[LAYER_DEFAULT].resize( ::com::sun::star::ui::UIElementType::COUNT ); + m_aUIElements[LAYER_USERDEFINED].resize( ::com::sun::star::ui::UIElementType::COUNT ); +} + +ModuleUIConfigurationManager::~ModuleUIConfigurationManager() +{ + for ( int i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + delete m_pStorageHandler[i]; +} + +// XComponent +void SAL_CALL ModuleUIConfigurationManager::dispose() throw (::com::sun::star::uno::RuntimeException) +{ + Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY ); + + css::lang::EventObject aEvent( xThis ); + m_aListenerContainer.disposeAndClear( aEvent ); + + { + ResetableGuard aGuard( m_aLock ); + try + { + if ( m_xModuleImageManager.is() ) + m_xModuleImageManager->dispose(); + } + catch ( Exception& ) + { + } + + m_xModuleImageManager.clear(); + m_aUIElements[LAYER_USERDEFINED].clear(); + m_aUIElements[LAYER_DEFAULT].clear(); + m_xDefaultConfigStorage.clear(); + m_xUserConfigStorage.clear(); + m_xUserRootCommit.clear(); + m_bConfigRead = false; + m_bModified = false; + m_bDisposed = true; + } +} + +void SAL_CALL ModuleUIConfigurationManager::addEventListener( const 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 Reference< XEventListener >* ) NULL ), xListener ); +} + +void SAL_CALL ModuleUIConfigurationManager::removeEventListener( const Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) +{ + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener ); +} + +// XInitialization +void SAL_CALL ModuleUIConfigurationManager::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + if ( !m_bInitialized ) + { + ::comphelper::SequenceAsHashMap lArgs(aArguments); + m_aModuleIdentifier = lArgs.getUnpackedValueOrDefault(::rtl::OUString::createFromAscii("ModuleIdentifier"), ::rtl::OUString()); + m_aModuleShortName = lArgs.getUnpackedValueOrDefault(::rtl::OUString::createFromAscii("ModuleShortName"), ::rtl::OUString()); + + for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + { + rtl::OUString aResourceType; + if ( i == ::com::sun::star::ui::UIElementType::MENUBAR ) + aResourceType = PresetHandler::RESOURCETYPE_MENUBAR(); + else if ( i == ::com::sun::star::ui::UIElementType::TOOLBAR ) + aResourceType = PresetHandler::RESOURCETYPE_TOOLBAR(); + else if ( i == ::com::sun::star::ui::UIElementType::STATUSBAR ) + aResourceType = PresetHandler::RESOURCETYPE_STATUSBAR(); + + if ( aResourceType.getLength() > 0 ) + { + m_pStorageHandler[i] = new PresetHandler( m_xServiceManager ); + m_pStorageHandler[i]->connectToResource( PresetHandler::E_MODULES, + aResourceType, // this path wont be used later ... seee next lines! + m_aModuleShortName, + css::uno::Reference< css::embed::XStorage >()); // no document root used here! + } + } + + // initialize root storages for all resource types + m_xUserRootCommit = css::uno::Reference< css::embed::XTransactedObject >( + m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getOrCreateRootStorageUser(), css::uno::UNO_QUERY); // can be empty + m_xDefaultConfigStorage = m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getParentStorageShare( + m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getWorkingStorageShare()); + m_xUserConfigStorage = m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getParentStorageUser( + m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getWorkingStorageUser()); + + if ( m_xUserConfigStorage.is() ) + { + Reference< XPropertySet > xPropSet( m_xUserConfigStorage, UNO_QUERY ); + if ( xPropSet.is() ) + { + long nOpenMode = 0; + Any a = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenMode" ))); + if ( a >>= nOpenMode ) + m_bReadOnly = !( nOpenMode & ElementModes::WRITE ); + } + } + + impl_Initialize(); + + m_bInitialized = true; + } +} + +// XUIConfiguration +void SAL_CALL ModuleUIConfigurationManager::addConfigurationListener( const 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 Reference< XUIConfigurationListener >* ) NULL ), xListener ); +} + +void SAL_CALL ModuleUIConfigurationManager::removeConfigurationListener( const Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) +{ + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XUIConfigurationListener >* ) NULL ), xListener ); +} + + +// XUIConfigurationManager +void SAL_CALL ModuleUIConfigurationManager::reset() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + if ( m_bDisposed ) + throw DisposedException(); + + bool bResetStorage( false ); + + if ( !isReadOnly() ) + { + // Remove all elements from our user-defined storage! + try + { + for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + { + UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i]; + Reference< XStorage > xSubStorage( rElementType.xStorage, UNO_QUERY ); + + if ( xSubStorage.is() ) + { + bool bCommitSubStorage( false ); + Reference< XNameAccess > xSubStorageNameAccess( xSubStorage, UNO_QUERY ); + Sequence< OUString > aUIElementStreamNames = xSubStorageNameAccess->getElementNames(); + for ( sal_Int32 j = 0; j < aUIElementStreamNames.getLength(); j++ ) + { + xSubStorage->removeElement( aUIElementStreamNames[j] ); + bCommitSubStorage = true; + } + + if ( bCommitSubStorage ) + { + Reference< XTransactedObject > xTransactedObject( xSubStorage, UNO_QUERY ); + if ( xTransactedObject.is() ) + xTransactedObject->commit(); + m_pStorageHandler[i]->commitUserChanges(); + } + } + } + + bResetStorage = true; + + // remove settings from user defined layer and notify listener about removed settings data! + ConfigEventNotifyContainer aRemoveEventNotifyContainer; + ConfigEventNotifyContainer aReplaceEventNotifyContainer; + for ( sal_Int16 j = 1; j < ::com::sun::star::ui::UIElementType::COUNT; j++ ) + { + try + { + UIElementType& rUserElementType = m_aUIElements[LAYER_USERDEFINED][j]; + UIElementType& rDefaultElementType = m_aUIElements[LAYER_DEFAULT][j]; + + impl_resetElementTypeData( rUserElementType, rDefaultElementType, aRemoveEventNotifyContainer, aReplaceEventNotifyContainer ); + rUserElementType.bModified = sal_False; + } + catch ( Exception& ) + { + throw IOException(); + } + } + + m_bModified = sal_False; + + // Unlock mutex before notify our listeners + aGuard.unlock(); + + // Notify our listeners + sal_uInt32 k = 0; + for ( k = 0; k < aRemoveEventNotifyContainer.size(); k++ ) + implts_notifyContainerListener( aRemoveEventNotifyContainer[k], NotifyOp_Remove ); + for ( k = 0; k < aReplaceEventNotifyContainer.size(); k++ ) + implts_notifyContainerListener( aReplaceEventNotifyContainer[k], NotifyOp_Replace ); + } + catch ( ::com::sun::star::lang::IllegalArgumentException& ) + { + } + catch ( ::com::sun::star::container::NoSuchElementException& ) + { + } + catch ( ::com::sun::star::embed::InvalidStorageException& ) + { + } + catch ( ::com::sun::star::embed::StorageWrappedTargetException& ) + { + } + } +} + +Sequence< Sequence< PropertyValue > > SAL_CALL ModuleUIConfigurationManager::getUIElementsInfo( sal_Int16 ElementType ) +throw ( IllegalArgumentException, RuntimeException ) +{ + if (( ElementType < 0 ) || ( ElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + + ResetableGuard aGuard( m_aLock ); + if ( m_bDisposed ) + throw DisposedException(); + + Sequence< Sequence< PropertyValue > > aElementInfoSeq; + UIElementInfoHashMap aUIElementInfoCollection; + + if ( ElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) + { + for ( sal_Int16 i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, sal_Int16( i ) ); + } + else + impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, ElementType ); + + Sequence< PropertyValue > aUIElementInfo( 2 ); + aUIElementInfo[0].Name = m_aPropResourceURL; + aUIElementInfo[1].Name = m_aPropUIName; + + aElementInfoSeq.realloc( aUIElementInfoCollection.size() ); + UIElementInfoHashMap::const_iterator pIter = aUIElementInfoCollection.begin(); + + sal_Int32 n = 0; + while ( pIter != aUIElementInfoCollection.end() ) + { + aUIElementInfo[0].Value <<= pIter->second.aResourceURL; + aUIElementInfo[1].Value <<= pIter->second.aUIName; + aElementInfoSeq[n++] = aUIElementInfo; + ++pIter; + } + + return aElementInfoSeq; +} + +Reference< XIndexContainer > SAL_CALL ModuleUIConfigurationManager::createSettings() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + // Creates an empty item container which can be filled from outside + return Reference< XIndexContainer >( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY ); +} + +sal_Bool SAL_CALL ModuleUIConfigurationManager::hasSettings( const ::rtl::OUString& ResourceURL ) +throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false ); + if ( pDataSettings ) + return sal_True; + } + + return sal_False; +} + +Reference< XIndexAccess > SAL_CALL ModuleUIConfigurationManager::getSettings( const ::rtl::OUString& ResourceURL, sal_Bool bWriteable ) +throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType ); + if ( pDataSettings ) + { + // Create a copy of our data if someone wants to change the data. + if ( bWriteable ) + return Reference< XIndexAccess >( static_cast< OWeakObject * >( new RootItemContainer( pDataSettings->xSettings ) ), UNO_QUERY ); + else + return pDataSettings->xSettings; + } + } + + throw NoSuchElementException(); +} + +void SAL_CALL ModuleUIConfigurationManager::replaceSettings( const ::rtl::OUString& ResourceURL, const Reference< ::com::sun::star::container::XIndexAccess >& aNewData ) +throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else if ( m_bReadOnly ) + throw IllegalAccessException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType ); + if ( pDataSettings ) + { + if ( !pDataSettings->bDefaultNode ) + { + // we have a settings entry in our user-defined layer - replace + Reference< XIndexAccess > xOldSettings = pDataSettings->xSettings; + + // Create a copy of the data if the container is not const + Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY ); + if ( xReplace.is() ) + pDataSettings->xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY ); + else + pDataSettings->xSettings = aNewData; + pDataSettings->bDefault = false; + pDataSettings->bModified = true; + m_bModified = true; + + // Modify type container + UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType]; + rElementType.bModified = true; + + Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); + + // Create event to notify listener about replaced element settings + ConfigurationEvent aEvent; + Reference< XInterface > xIfac( xThis, UNO_QUERY ); + + aEvent.ResourceURL = ResourceURL; + aEvent.Accessor <<= xThis; + aEvent.Source = xIfac; + aEvent.ReplacedElement <<= xOldSettings; + aEvent.Element <<= pDataSettings->xSettings; + + aGuard.unlock(); + + implts_notifyContainerListener( aEvent, NotifyOp_Replace ); + } + else + { + // we have no settings in our user-defined layer - insert + UIElementData aUIElementData; + + aUIElementData.bDefault = false; + aUIElementData.bDefaultNode = false; + aUIElementData.bModified = true; + + // Create a copy of the data if the container is not const + Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY ); + if ( xReplace.is() ) + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY ); + else + aUIElementData.xSettings = aNewData; + aUIElementData.aName = RetrieveNameFromResourceURL( ResourceURL ) + m_aXMLPostfix; + aUIElementData.aResourceURL = ResourceURL; + m_bModified = true; + + // Modify type container + UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType]; + rElementType.bModified = true; + + UIElementDataHashMap& rElements = rElementType.aElementsHashMap; + + // Check our user element settings hash map as it can already contain settings that have been set to default! + // If no node can be found, we have to insert it. + UIElementDataHashMap::iterator pIter = rElements.find( ResourceURL ); + if ( pIter != rElements.end() ) + pIter->second = aUIElementData; + else + rElements.insert( UIElementDataHashMap::value_type( ResourceURL, aUIElementData )); + + Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); + Reference< XInterface > xIfac( xThis, UNO_QUERY ); + + // Create event to notify listener about replaced element settings + ConfigurationEvent aEvent; + + aEvent.ResourceURL = ResourceURL; + aEvent.Accessor <<= xThis; + aEvent.Source = xIfac; + aEvent.ReplacedElement <<= pDataSettings->xSettings; + aEvent.Element <<= aUIElementData.xSettings; + + aGuard.unlock(); + + implts_notifyContainerListener( aEvent, NotifyOp_Replace ); + } + } + else + throw NoSuchElementException(); + } +} + +void SAL_CALL ModuleUIConfigurationManager::removeSettings( const ::rtl::OUString& ResourceURL ) +throw ( NoSuchElementException, IllegalArgumentException, IllegalAccessException, RuntimeException) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else if ( m_bReadOnly ) + throw IllegalAccessException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType ); + if ( pDataSettings ) + { + // If element settings are default, we don't need to change anything! + if ( pDataSettings->bDefault ) + return; + else + { + Reference< XIndexAccess > xRemovedSettings = pDataSettings->xSettings; + pDataSettings->bDefault = true; + + // check if this is a default layer node + if ( !pDataSettings->bDefaultNode ) + pDataSettings->bModified = true; // we have to remove this node from the user layer! + pDataSettings->xSettings.clear(); + m_bModified = true; // user layer must be written + + // Modify type container + UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType]; + rElementType.bModified = true; + + Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); + Reference< XInterface > xIfac( xThis, UNO_QUERY ); + + // Check if we have settings in the default layer which replaces the user-defined one! + UIElementData* pDefaultDataSettings = impl_findUIElementData( ResourceURL, nElementType ); + if ( pDefaultDataSettings ) + { + // Create event to notify listener about replaced element settings + ConfigurationEvent aEvent; + + aEvent.ResourceURL = ResourceURL; + aEvent.Accessor <<= xThis; + aEvent.Source = xIfac; + aEvent.Element <<= xRemovedSettings; + aEvent.ReplacedElement <<= pDefaultDataSettings->xSettings; + + aGuard.unlock(); + + implts_notifyContainerListener( aEvent, NotifyOp_Replace ); + } + else + { + // Create event to notify listener about removed element settings + ConfigurationEvent aEvent; + + aEvent.ResourceURL = ResourceURL; + aEvent.Accessor <<= xThis; + aEvent.Source = xIfac; + aEvent.Element <<= xRemovedSettings; + + aGuard.unlock(); + + implts_notifyContainerListener( aEvent, NotifyOp_Remove ); + } + } + } + else + throw NoSuchElementException(); + } +} + +void SAL_CALL ModuleUIConfigurationManager::insertSettings( const ::rtl::OUString& NewResourceURL, const Reference< XIndexAccess >& aNewData ) +throw ( ElementExistException, IllegalArgumentException, IllegalAccessException, RuntimeException ) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( NewResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else if ( m_bReadOnly ) + throw IllegalAccessException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + UIElementData* pDataSettings = impl_findUIElementData( NewResourceURL, nElementType ); + if ( !pDataSettings ) + { + UIElementData aUIElementData; + + aUIElementData.bDefault = false; + aUIElementData.bDefaultNode = false; + aUIElementData.bModified = true; + + // Create a copy of the data if the container is not const + Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY ); + if ( xReplace.is() ) + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY ); + else + aUIElementData.xSettings = aNewData; + aUIElementData.aName = RetrieveNameFromResourceURL( NewResourceURL ) + m_aXMLPostfix; + aUIElementData.aResourceURL = NewResourceURL; + m_bModified = true; + + UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType]; + rElementType.bModified = true; + + UIElementDataHashMap& rElements = rElementType.aElementsHashMap; + rElements.insert( UIElementDataHashMap::value_type( NewResourceURL, aUIElementData )); + + Reference< XIndexAccess > xInsertSettings( aUIElementData.xSettings ); + Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); + Reference< XInterface > xIfac( xThis, UNO_QUERY ); + + // Create event to notify listener about removed element settings + ConfigurationEvent aEvent; + + aEvent.ResourceURL = NewResourceURL; + aEvent.Accessor <<= xThis; + aEvent.Source = xIfac; + aEvent.Element <<= xInsertSettings; + + aGuard.unlock(); + + implts_notifyContainerListener( aEvent, NotifyOp_Insert ); + } + else + throw ElementExistException(); + } +} + +Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getImageManager() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( !m_xModuleImageManager.is() ) + { + m_xModuleImageManager = Reference< XComponent >( static_cast< cppu::OWeakObject *>( new ModuleImageManager( m_xServiceManager )), + UNO_QUERY ); + Reference< XInitialization > xInit( m_xModuleImageManager, UNO_QUERY ); + + Sequence< Any > aPropSeq( 3 ); + PropertyValue aPropValue; + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserConfigStorage" )); + aPropValue.Value = makeAny( m_xUserConfigStorage ); + aPropSeq[0] = makeAny( aPropValue ); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleIdentifier" )); + aPropValue.Value = makeAny( m_aModuleIdentifier ); + aPropSeq[1] = makeAny( aPropValue ); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserRootCommit" )); + aPropValue.Value = makeAny( m_xUserRootCommit ); + aPropSeq[2] = makeAny( aPropValue ); + + xInit->initialize( aPropSeq ); + } + + return Reference< XInterface >( m_xModuleImageManager, UNO_QUERY ); + +// return Reference< XInterface >(); +} + +Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getShortCutManager() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + Reference< XMultiServiceFactory > xSMGR = m_xServiceManager; + ::rtl::OUString aModule = /*m_aModuleShortName*/m_aModuleIdentifier; + aGuard.unlock(); + + Reference< XInterface > xManager = xSMGR->createInstance(SERVICENAME_MODULEACCELERATORCONFIGURATION); + Reference< XInitialization > xInit (xManager, UNO_QUERY_THROW); + + PropertyValue aProp; + aProp.Name = ::rtl::OUString::createFromAscii("ModuleIdentifier"); + aProp.Value <<= aModule; + + Sequence< Any > lArgs(1); + lArgs[0] <<= aProp; + + xInit->initialize(lArgs); + + return xManager; +} + +Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getEventsManager() throw (::com::sun::star::uno::RuntimeException) +{ + return Reference< XInterface >(); +} + +// XModuleUIConfigurationManager +sal_Bool SAL_CALL ModuleUIConfigurationManager::isDefaultSettings( const ::rtl::OUString& ResourceURL ) +throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false ); + if ( pDataSettings && pDataSettings->bDefaultNode ) + return sal_True; + } + + return sal_False; +} + +Reference< XIndexAccess > SAL_CALL ModuleUIConfigurationManager::getDefaultSettings( const ::rtl::OUString& ResourceURL ) +throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + // preload list of element types on demand + impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType ); + + // Look into our default vector/hash_map combination + UIElementDataHashMap& rDefaultHashMap = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap; + UIElementDataHashMap::iterator pIter = rDefaultHashMap.find( ResourceURL ); + if ( pIter != rDefaultHashMap.end() ) + { + if ( !pIter->second.xSettings.is() ) + impl_requestUIElementData( nElementType, LAYER_DEFAULT, pIter->second ); + return pIter->second.xSettings; + } + } + + // Nothing has been found! + throw NoSuchElementException(); +} + +// XUIConfigurationPersistence +void SAL_CALL ModuleUIConfigurationManager::reload() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly ) + { + // Try to access our module sub folder + ConfigEventNotifyContainer aRemoveNotifyContainer; + ConfigEventNotifyContainer aReplaceNotifyContainer; + for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + { + try + { + UIElementType& rUserElementType = m_aUIElements[LAYER_USERDEFINED][i]; + UIElementType& rDefaultElementType = m_aUIElements[LAYER_DEFAULT][i]; + + if ( rUserElementType.bModified ) + impl_reloadElementTypeData( rUserElementType, rDefaultElementType, aRemoveNotifyContainer, aReplaceNotifyContainer ); + } + catch ( Exception& ) + { + throw IOException(); + } + } + + m_bModified = sal_False; + + // Unlock mutex before notify our listeners + aGuard.unlock(); + + // Notify our listeners + for ( sal_uInt32 j = 0; j < aRemoveNotifyContainer.size(); j++ ) + implts_notifyContainerListener( aRemoveNotifyContainer[j], NotifyOp_Remove ); + for ( sal_uInt32 k = 0; k < aReplaceNotifyContainer.size(); k++ ) + implts_notifyContainerListener( aReplaceNotifyContainer[k], NotifyOp_Replace ); + } +} + +void SAL_CALL ModuleUIConfigurationManager::store() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly ) + { + // Try to access our module sub folder + for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + { + try + { + UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i]; + Reference< XStorage > xStorage( rElementType.xStorage, UNO_QUERY ); + + if ( rElementType.bModified && xStorage.is() ) + { + impl_storeElementTypeData( xStorage, rElementType ); + m_pStorageHandler[i]->commitUserChanges(); + } + } + catch ( Exception& ) + { + throw IOException(); + } + } + + m_bModified = false; + } +} + +void SAL_CALL ModuleUIConfigurationManager::storeToStorage( const 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_xUserConfigStorage.is() && m_bModified && !m_bReadOnly ) + { + // Try to access our module sub folder + for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + { + try + { + Reference< XStorage > xElementTypeStorage( Storage->openStorageElement( + OUString::createFromAscii( UIELEMENTTYPENAMES[i] ), ElementModes::READWRITE )); + UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i]; + + if ( rElementType.bModified && xElementTypeStorage.is() ) + impl_storeElementTypeData( xElementTypeStorage, rElementType, false ); // store data to storage, but don't reset modify flag! + } + catch ( Exception& ) + { + throw IOException(); + } + } + + Reference< XTransactedObject > xTransactedObject( Storage, UNO_QUERY ); + if ( xTransactedObject.is() ) + xTransactedObject->commit(); + } +} + +sal_Bool SAL_CALL ModuleUIConfigurationManager::isModified() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + return m_bModified; +} + +sal_Bool SAL_CALL ModuleUIConfigurationManager::isReadOnly() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + return m_bReadOnly; +} + +void ModuleUIConfigurationManager::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(); + } + } + } +} + +} // namespace framework diff --git a/framework/source/uiconfiguration/uicategorydescription.cxx b/framework/source/uiconfiguration/uicategorydescription.cxx new file mode 100644 index 000000000000..a7f63db38257 --- /dev/null +++ b/framework/source/uiconfiguration/uicategorydescription.cxx @@ -0,0 +1,479 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: uicategorydescription.cxx,v $ + * $Revision: 1.8.34.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + +#ifndef __FRAMEWORK_UICONFIGURATION_UICATEGORYDESCRPTION_HXX_ +#include "uiconfiguration/uicategorydescription.hxx" +#endif +#include <threadhelp/resetableguard.hxx> +#include "services.h" + +#include "properties.h" + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XContainer.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ +#include <rtl/ustrbuf.hxx> +#include <cppuhelper/implbase2.hxx> +#include <unotools/configmgr.hxx> +#include <tools/string.hxx> + +#ifndef _VCL_MNEMONIC_HXX_ +#include <vcl/mnemonic.hxx> +#endif +#include <comphelper/sequence.hxx> +#include <rtl/logfile.hxx> + +//_________________________________________________________________________________________________________________ +// Defines +//_________________________________________________________________________________________________________________ +// + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; +using namespace ::com::sun::star::frame; + +//_________________________________________________________________________________________________________________ +// Namespace +//_________________________________________________________________________________________________________________ +// + +struct ModuleToCategory +{ + const char* pModuleId; + const char* pCommands; +}; + +static const char CATEGORY[] = "Category"; +static const char GENERIC_MODULE_NAME[] = "generic"; +static const char CONFIGURATION_ROOT_ACCESS[] = "/org.openoffice.Office.UI."; +static const char CONFIGURATION_CATEGORY_ELEMENT_ACCESS[] = "/Commands/Categories"; +static const char CONFIGURATION_PROPERTY_NAME[] = "Name"; + +namespace framework +{ + +//***************************************************************************************************************** +// Configuration access class for PopupMenuControllerFactory implementation +//***************************************************************************************************************** + +class ConfigurationAccess_UICategory : // Order is neccessary for right initialization! + private ThreadHelpBase , + public ::cppu::WeakImplHelper2<XNameAccess,XContainerListener> +{ + public: + ConfigurationAccess_UICategory( const ::rtl::OUString& aModuleName, const Reference< XNameAccess >& xGenericUICommands, const Reference< XMultiServiceFactory >& rServiceManager ); + virtual ~ConfigurationAccess_UICategory(); + + // XNameAccess + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) + throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames() + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) + throw (::com::sun::star::uno::RuntimeException); + + // XElementAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType() + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL hasElements() + throw (::com::sun::star::uno::RuntimeException); + + // container.XContainerListener + virtual void SAL_CALL elementInserted( const ContainerEvent& aEvent ) throw(RuntimeException); + virtual void SAL_CALL elementRemoved ( const ContainerEvent& aEvent ) throw(RuntimeException); + virtual void SAL_CALL elementReplaced( const ContainerEvent& aEvent ) throw(RuntimeException); + + // lang.XEventListener + virtual void SAL_CALL disposing( const EventObject& aEvent ) throw(RuntimeException); + + protected: + Any getUINameFromID( const rtl::OUString& rId ); + Any getUINameFromCache( const rtl::OUString& rId ); + Sequence< rtl::OUString > getAllIds(); + sal_Bool fillCache(); + + private: + typedef ::std::hash_map< ::rtl::OUString, + ::rtl::OUString, + OUStringHashCode, + ::std::equal_to< ::rtl::OUString > > IdToInfoCache; + + sal_Bool initializeConfigAccess(); + + rtl::OUString m_aConfigCategoryAccess; + rtl::OUString m_aPropUIName; + Reference< XNameAccess > m_xGenericUICategories; + Reference< XMultiServiceFactory > m_xServiceManager; + Reference< XMultiServiceFactory > m_xConfigProvider; + Reference< XNameAccess > m_xConfigAccess; + sal_Bool m_bConfigAccessInitialized; + sal_Bool m_bCacheFilled; + IdToInfoCache m_aIdCache; +}; + +//***************************************************************************************************************** +// XInterface, XTypeProvider +//***************************************************************************************************************** + +ConfigurationAccess_UICategory::ConfigurationAccess_UICategory( const rtl::OUString& aModuleName, const Reference< XNameAccess >& rGenericUICategories, const Reference< XMultiServiceFactory >& rServiceManager ) : + ThreadHelpBase(), + m_aConfigCategoryAccess( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_ROOT_ACCESS )), + m_aPropUIName( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_PROPERTY_NAME )), + m_xGenericUICategories( rGenericUICategories ), + m_xServiceManager( rServiceManager ), + m_bConfigAccessInitialized( sal_False ), + m_bCacheFilled( sal_False ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::ConfigurationAccess_UICategory" ); + // Create configuration hierachical access name + m_aConfigCategoryAccess += aModuleName; + m_aConfigCategoryAccess += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_CATEGORY_ELEMENT_ACCESS )); + + m_xConfigProvider = Reference< XMultiServiceFactory >( rServiceManager->createInstance(SERVICENAME_CFGPROVIDER),UNO_QUERY ); +} + +ConfigurationAccess_UICategory::~ConfigurationAccess_UICategory() +{ + // SAFE + ResetableGuard aLock( m_aLock ); + Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY ); + if ( xContainer.is() ) + xContainer->removeContainerListener( this ); +} + +// XNameAccess +Any SAL_CALL ConfigurationAccess_UICategory::getByName( const ::rtl::OUString& rId ) +throw ( NoSuchElementException, WrappedTargetException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getByName" ); + ResetableGuard aLock( m_aLock ); + if ( !m_bConfigAccessInitialized ) + { + initializeConfigAccess(); + m_bConfigAccessInitialized = sal_True; + fillCache(); + } + + // SAFE + Any a = getUINameFromID( rId ); + + if ( !a.hasValue() ) + throw NoSuchElementException(); + + return a; +} + +Sequence< ::rtl::OUString > SAL_CALL ConfigurationAccess_UICategory::getElementNames() +throw ( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getElementNames" ); + return getAllIds(); +} + +sal_Bool SAL_CALL ConfigurationAccess_UICategory::hasByName( const ::rtl::OUString& rId ) +throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::hasByName" ); + return getByName( rId ).hasValue(); +} + +// XElementAccess +Type SAL_CALL ConfigurationAccess_UICategory::getElementType() +throw ( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getElementType" ); + return( ::getCppuType( (const rtl::OUString*)NULL ) ); +} + +sal_Bool SAL_CALL ConfigurationAccess_UICategory::hasElements() +throw ( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::hasElements" ); + // There must be global categories! + return sal_True; +} + +sal_Bool ConfigurationAccess_UICategory::fillCache() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::fillCache" ); + RTL_LOGFILE_CONTEXT( aLog, "framework (cd100003) ::ConfigurationAccess_UICategory::fillCache" ); + + if ( m_bCacheFilled ) + return sal_True; + + sal_Int32 i( 0 ); + rtl::OUString aUIName; + Sequence< ::rtl::OUString > aNameSeq = m_xConfigAccess->getElementNames(); + + for ( i = 0; i < aNameSeq.getLength(); i++ ) + { + try + { + Reference< XNameAccess > xNameAccess(m_xConfigAccess->getByName( aNameSeq[i] ),UNO_QUERY); + if ( xNameAccess.is() ) + { + xNameAccess->getByName( m_aPropUIName ) >>= aUIName; + + m_aIdCache.insert( IdToInfoCache::value_type( aNameSeq[i], aUIName )); + } + } + catch ( com::sun::star::lang::WrappedTargetException& ) + { + } + catch ( com::sun::star::container::NoSuchElementException& ) + { + } + } + + m_bCacheFilled = sal_True; + + return sal_True; +} + +Any ConfigurationAccess_UICategory::getUINameFromID( const rtl::OUString& rId ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getUINameFromID" ); + Any a; + + try + { + a = getUINameFromCache( rId ); + if ( !a.hasValue() ) + { + // Try to ask our global commands configuration access + if ( m_xGenericUICategories.is() ) + { + try + { + return m_xGenericUICategories->getByName( rId ); + } + catch ( com::sun::star::lang::WrappedTargetException& ) + { + } + catch ( com::sun::star::container::NoSuchElementException& ) + { + } + } + } + } + catch( com::sun::star::container::NoSuchElementException& ) + { + } + catch ( com::sun::star::lang::WrappedTargetException& ) + { + } + + return a; +} + +Any ConfigurationAccess_UICategory::getUINameFromCache( const rtl::OUString& rId ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getUINameFromCache" ); + Any a; + + IdToInfoCache::const_iterator pIter = m_aIdCache.find( rId ); + if ( pIter != m_aIdCache.end() ) + a <<= pIter->second; + + return a; +} + +Sequence< rtl::OUString > ConfigurationAccess_UICategory::getAllIds() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::getAllIds" ); + // SAFE + ResetableGuard aLock( m_aLock ); + + if ( !m_bConfigAccessInitialized ) + { + initializeConfigAccess(); + m_bConfigAccessInitialized = sal_True; + fillCache(); + } + + if ( m_xConfigAccess.is() ) + { + Any a; + Reference< XNameAccess > xNameAccess; + + try + { + Sequence< ::rtl::OUString > aNameSeq = m_xConfigAccess->getElementNames(); + + if ( m_xGenericUICategories.is() ) + { + // Create concat list of supported user interface commands of the module + Sequence< ::rtl::OUString > aGenericNameSeq = m_xGenericUICategories->getElementNames(); + sal_uInt32 nCount1 = aNameSeq.getLength(); + sal_uInt32 nCount2 = aGenericNameSeq.getLength(); + + aNameSeq.realloc( nCount1 + nCount2 ); + ::rtl::OUString* pNameSeq = aNameSeq.getArray(); + const ::rtl::OUString* pGenericSeq = aGenericNameSeq.getConstArray(); + for ( sal_uInt32 i = 0; i < nCount2; i++ ) + pNameSeq[nCount1+i] = pGenericSeq[i]; + } + + return aNameSeq; + } + catch( com::sun::star::container::NoSuchElementException& ) + { + } + catch ( com::sun::star::lang::WrappedTargetException& ) + { + } + } + + return Sequence< rtl::OUString >(); +} + +sal_Bool ConfigurationAccess_UICategory::initializeConfigAccess() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::initializeConfigAccess" ); + Sequence< Any > aArgs( 1 ); + PropertyValue aPropValue; + + try + { + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" )); + aPropValue.Value <<= m_aConfigCategoryAccess; + aArgs[0] <<= aPropValue; + + m_xConfigAccess = Reference< XNameAccess >( m_xConfigProvider->createInstanceWithArguments(SERVICENAME_CFGREADACCESS,aArgs ),UNO_QUERY ); + if ( m_xConfigAccess.is() ) + { + // Add as container listener + Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY ); + if ( xContainer.is() ) + xContainer->addContainerListener( this ); + } + + return sal_True; + } + catch ( WrappedTargetException& ) + { + } + catch ( Exception& ) + { + } + + return sal_False; +} + +// container.XContainerListener +void SAL_CALL ConfigurationAccess_UICategory::elementInserted( const ContainerEvent& ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::elementInserted" ); +} + +void SAL_CALL ConfigurationAccess_UICategory::elementRemoved ( const ContainerEvent& ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::elementRemoved " ); +} + +void SAL_CALL ConfigurationAccess_UICategory::elementReplaced( const ContainerEvent& ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::elementReplaced" ); +} + +// lang.XEventListener +void SAL_CALL ConfigurationAccess_UICategory::disposing( const EventObject& aEvent ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_UICategory::disposing" ); + // SAFE + // remove our reference to the config access + ResetableGuard aLock( m_aLock ); + + Reference< XInterface > xIfac1( aEvent.Source, UNO_QUERY ); + Reference< XInterface > xIfac2( m_xConfigAccess, UNO_QUERY ); + if ( xIfac1 == xIfac2 ) + m_xConfigAccess.clear(); +} + +//***************************************************************************************************************** +// XInterface, XTypeProvider, XServiceInfo +//***************************************************************************************************************** +DEFINE_XSERVICEINFO_ONEINSTANCESERVICE ( UICategoryDescription , + ::cppu::OWeakObject , + SERVICENAME_UICATEGORYDESCRIPTION , + IMPLEMENTATIONNAME_UICATEGORYDESCRIPTION + ) + +DEFINE_INIT_SERVICE ( UICategoryDescription, {} ) + +UICategoryDescription::UICategoryDescription( const Reference< XMultiServiceFactory >& xServiceManager ) : + UICommandDescription(xServiceManager,true) +{ + Reference< XNameAccess > xEmpty; + rtl::OUString aGenericCategories( RTL_CONSTASCII_USTRINGPARAM( "GenericCategories" )); + m_xGenericUICommands = new ConfigurationAccess_UICategory( aGenericCategories, xEmpty, xServiceManager ); + + // insert generic categories mappings + m_aModuleToCommandFileMap.insert( ModuleToCommandFileMap::value_type( + rtl::OUString::createFromAscii( GENERIC_MODULE_NAME ), aGenericCategories )); + + UICommandsHashMap::iterator pCatIter = m_aUICommandsHashMap.find( aGenericCategories ); + if ( pCatIter != m_aUICommandsHashMap.end() ) + pCatIter->second = m_xGenericUICommands; + + impl_fillElements("ooSetupFactoryCmdCategoryConfigRef"); +} + +UICategoryDescription::~UICategoryDescription() +{ +} +Reference< XNameAccess > UICategoryDescription::impl_createConfigAccess(const ::rtl::OUString& _sName) +{ + return new ConfigurationAccess_UICategory( _sName,m_xGenericUICommands,m_xServiceManager ); +} + +} // namespace framework + diff --git a/framework/source/uiconfiguration/uiconfigurationmanager.cxx b/framework/source/uiconfiguration/uiconfigurationmanager.cxx new file mode 100644 index 000000000000..3309333fb327 --- /dev/null +++ b/framework/source/uiconfiguration/uiconfigurationmanager.cxx @@ -0,0 +1,1357 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: uiconfigurationmanager.cxx,v $ + * $Revision: 1.19 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uiconfiguration/uiconfigurationmanager.hxx> +#include <threadhelp/resetableguard.hxx> +#include <services.h> +#include <uielement/rootitemcontainer.hxx> +#include <uielement/constitemcontainer.hxx> +#include <uielement/uielementtypenames.hxx> +#include <xml/menuconfiguration.hxx> +#include <xml/toolboxconfiguration.hxx> + +#ifndef __FRAMEWORK_XML_STATUSBARCONFIGURATION_HXX_ +#include <xml/statusbarconfiguration.hxx> +#endif + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/ui/UIElementType.hpp> +#include <com/sun/star/ui/ConfigurationEvent.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#include <vcl/svapp.hxx> +#include <rtl/ustrbuf.hxx> + +//_________________________________________________________________________________________________________________ +// namespaces +//_________________________________________________________________________________________________________________ + +using namespace com::sun::star::uno; +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; + +namespace framework +{ + +//***************************************************************************************************************** +// XInterface, XTypeProvider, XServiceInfo +//***************************************************************************************************************** +DEFINE_XINTERFACE_7 ( UIConfigurationManager , + OWeakObject , + DIRECT_INTERFACE( css::lang::XTypeProvider ), + DIRECT_INTERFACE( css::lang::XServiceInfo ), + DIRECT_INTERFACE( css::lang::XComponent ), + DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfiguration ), + DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationManager ), + DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationPersistence ), + DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationStorage ) + ) + +DEFINE_XTYPEPROVIDER_7 ( UIConfigurationManager , + css::lang::XTypeProvider , + css::lang::XServiceInfo , + css::lang::XComponent , + ::com::sun::star::ui::XUIConfiguration , + ::com::sun::star::ui::XUIConfigurationManager , + ::com::sun::star::ui::XUIConfigurationPersistence , + ::com::sun::star::ui::XUIConfigurationStorage + ) + +DEFINE_XSERVICEINFO_MULTISERVICE ( UIConfigurationManager , + ::cppu::OWeakObject , + SERVICENAME_UICONFIGURATIONMANAGER , + IMPLEMENTATIONNAME_UICONFIGURATIONMANAGER + ) + +DEFINE_INIT_SERVICE ( UIConfigurationManager, {} ) + + +// important: The order and position of the elements must match the constant +// definition of "::com::sun::star::ui::UIElementType" +static const char* UIELEMENTTYPENAMES[] = +{ + "", // Dummy value for unknown! + UIELEMENTTYPE_MENUBAR_NAME, + UIELEMENTTYPE_POPUPMENU_NAME, + UIELEMENTTYPE_TOOLBAR_NAME, + UIELEMENTTYPE_STATUSBAR_NAME, + UIELEMENTTYPE_FLOATINGWINDOW_NAME, + UIELEMENTTYPE_PROGRESSBAR_NAME +}; + +static const char RESOURCEURL_PREFIX[] = "private:resource/"; +static const sal_Int32 RESOURCEURL_PREFIX_SIZE = 17; + +static sal_Int16 RetrieveTypeFromResourceURL( const rtl::OUString& aResourceURL ) +{ + + if (( aResourceURL.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_PREFIX ))) == 0 ) && + ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE )) + { + rtl::OUString aTmpStr = aResourceURL.copy( RESOURCEURL_PREFIX_SIZE ); + sal_Int32 nIndex = aTmpStr.indexOf( '/' ); + if (( nIndex > 0 ) && ( aTmpStr.getLength() > nIndex )) + { + rtl::OUString aTypeStr( aTmpStr.copy( 0, nIndex )); + for ( int i = 0; i < UIElementType::COUNT; i++ ) + { + if ( aTypeStr.equalsAscii( UIELEMENTTYPENAMES[i] )) + return sal_Int16( i ); + } + } + } + + return UIElementType::UNKNOWN; +} + +static rtl::OUString RetrieveNameFromResourceURL( const rtl::OUString& aResourceURL ) +{ + if (( aResourceURL.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_PREFIX ))) == 0 ) && + ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE )) + { + sal_Int32 nIndex = aResourceURL.lastIndexOf( '/' ); + if (( nIndex > 0 ) && (( nIndex+1 ) < aResourceURL.getLength())) + return aResourceURL.copy( nIndex+1 ); + } + + return rtl::OUString(); +} + +void UIConfigurationManager::impl_fillSequenceWithElementTypeInfo( UIElementInfoHashMap& aUIElementInfoCollection, sal_Int16 nElementType ) +{ + // preload list of element types on demand + impl_preloadUIElementTypeList( nElementType ); + + UIElementDataHashMap& rUserElements = m_aUIElements[nElementType].aElementsHashMap; + UIElementDataHashMap::const_iterator pUserIter = rUserElements.begin(); + + while ( pUserIter != rUserElements.end() ) + { + UIElementData* pDataSettings = impl_findUIElementData( pUserIter->second.aResourceURL, nElementType ); + if ( pDataSettings && !pDataSettings->bDefault ) + { + // Retrieve user interface name from XPropertySet interface + rtl::OUString aUIName; + Reference< XPropertySet > xPropSet( pDataSettings->xSettings, UNO_QUERY ); + if ( xPropSet.is() ) + { + Any a = xPropSet->getPropertyValue( m_aPropUIName ); + a >>= aUIName; + } + + UIElementInfo aInfo( pUserIter->second.aResourceURL, aUIName ); + aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pUserIter->second.aResourceURL, aInfo )); + } + ++pUserIter; + } +} + +void UIConfigurationManager::impl_preloadUIElementTypeList( sal_Int16 nElementType ) +{ + UIElementType& rElementTypeData = m_aUIElements[nElementType]; + + if ( !rElementTypeData.bLoaded ) + { + Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage; + if ( xElementTypeStorage.is() ) + { + rtl::OUStringBuffer aBuf( RESOURCEURL_PREFIX_SIZE ); + aBuf.appendAscii( RESOURCEURL_PREFIX ); + aBuf.appendAscii( UIELEMENTTYPENAMES[ nElementType ] ); + aBuf.appendAscii( "/" ); + rtl::OUString aResURLPrefix( aBuf.makeStringAndClear() ); + + UIElementDataHashMap& rHashMap = rElementTypeData.aElementsHashMap; + Reference< XNameAccess > xNameAccess( xElementTypeStorage, UNO_QUERY ); + Sequence< rtl::OUString > aUIElementNames = xNameAccess->getElementNames(); + for ( sal_Int32 n = 0; n < aUIElementNames.getLength(); n++ ) + { + UIElementData aUIElementData; + + // Resource name must be without ".xml" + sal_Int32 nIndex = aUIElementNames[n].lastIndexOf( '.' ); + if (( nIndex > 0 ) && ( nIndex < aUIElementNames[n].getLength() )) + { + rtl::OUString aExtension( aUIElementNames[n].copy( nIndex+1 )); + rtl::OUString aUIElementName( aUIElementNames[n].copy( 0, nIndex )); + + if (( aUIElementName.getLength() > 0 ) && + ( aExtension.equalsIgnoreAsciiCaseAsciiL( "xml", 3 ))) + { + aUIElementData.aResourceURL = aResURLPrefix + aUIElementName; + aUIElementData.aName = aUIElementNames[n]; + aUIElementData.bModified = false; + aUIElementData.bDefault = false; + + // Create hash_map entries for all user interface elements inside the storage. We don't load the + // settings to speed up the process. + rHashMap.insert( UIElementDataHashMap::value_type( aUIElementData.aResourceURL, aUIElementData )); + } + } + } + } + } + + rElementTypeData.bLoaded = true; +} + +void UIConfigurationManager::impl_requestUIElementData( sal_Int16 nElementType, UIElementData& aUIElementData ) +{ + UIElementType& rElementTypeData = m_aUIElements[nElementType]; + + Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage; + if ( xElementTypeStorage.is() && aUIElementData.aName.getLength() ) + { + try + { + Reference< XStream > xStream = xElementTypeStorage->openStreamElement( aUIElementData.aName, ElementModes::READ ); + Reference< XInputStream > xInputStream = xStream->getInputStream(); + + if ( xInputStream.is() ) + { + switch ( nElementType ) + { + case ::com::sun::star::ui::UIElementType::UNKNOWN: + break; + + case ::com::sun::star::ui::UIElementType::MENUBAR: + { + try + { + MenuConfiguration aMenuCfg( m_xServiceManager ); + Reference< XIndexAccess > xContainer( aMenuCfg.CreateMenuBarConfigurationFromXML( xInputStream )); + RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xContainer ); + if ( pRootItemContainer ) + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY ); + else + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( xContainer, sal_True ) ), UNO_QUERY ); + return; + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + } + break; + + case ::com::sun::star::ui::UIElementType::POPUPMENU: + { + break; + } + + case ::com::sun::star::ui::UIElementType::TOOLBAR: + { + try + { + Reference< XIndexContainer > xIndexContainer( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY ); + ToolBoxConfiguration::LoadToolBox( m_xServiceManager, xInputStream, xIndexContainer ); + RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xIndexContainer ); + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY ); + return; + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + + break; + } + + case ::com::sun::star::ui::UIElementType::STATUSBAR: + { + try + { + Reference< XIndexContainer > xIndexContainer( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY ); + StatusBarConfiguration::LoadStatusBar( m_xServiceManager, xInputStream, xIndexContainer ); + RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xIndexContainer ); + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY ); + return; + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + + break; + } + + case ::com::sun::star::ui::UIElementType::FLOATINGWINDOW: + { + break; + } + } + } + } + catch ( ::com::sun::star::embed::InvalidStorageException& ) + { + } + catch ( ::com::sun::star::lang::IllegalArgumentException& ) + { + } + catch ( ::com::sun::star::io::IOException& ) + { + } + catch ( ::com::sun::star::embed::StorageWrappedTargetException& ) + { + } + } + + // At least we provide an empty settings container! + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer()), UNO_QUERY ); +} + +UIConfigurationManager::UIElementData* UIConfigurationManager::impl_findUIElementData( const rtl::OUString& aResourceURL, sal_Int16 nElementType, bool bLoad ) +{ + // preload list of element types on demand + impl_preloadUIElementTypeList( nElementType ); + + // try to look into our document vector/hash_map combination + UIElementDataHashMap& rUserHashMap = m_aUIElements[nElementType].aElementsHashMap; + UIElementDataHashMap::iterator pIter = rUserHashMap.find( aResourceURL ); + if ( pIter != rUserHashMap.end() ) + { + // Default data settings data means removed! + if ( pIter->second.bDefault ) + return &(pIter->second); + else + { + if ( !pIter->second.xSettings.is() && bLoad ) + impl_requestUIElementData( nElementType, pIter->second ); + return &(pIter->second); + } + } + + // Nothing has been found! + return NULL; +} + +void UIConfigurationManager::impl_storeElementTypeData( Reference< XStorage >& xStorage, UIElementType& rElementType, bool bResetModifyState ) +{ + UIElementDataHashMap& rHashMap = rElementType.aElementsHashMap; + UIElementDataHashMap::iterator pIter = rHashMap.begin(); + + while ( pIter != rHashMap.end() ) + { + UIElementData& rElement = pIter->second; + if ( rElement.bModified ) + { + if ( rElement.bDefault ) + { + xStorage->removeElement( rElement.aName ); + rElement.bModified = sal_False; // mark as not modified + } + else + { + Reference< XStream > xStream( xStorage->openStreamElement( rElement.aName, ElementModes::WRITE|ElementModes::TRUNCATE ), UNO_QUERY ); + Reference< XOutputStream > xOutputStream( xStream->getOutputStream() ); + + if ( xOutputStream.is() ) + { + switch( rElementType.nElementType ) + { + case ::com::sun::star::ui::UIElementType::MENUBAR: + { + try + { + MenuConfiguration aMenuCfg( m_xServiceManager ); + aMenuCfg.StoreMenuBarConfigurationToXML( rElement.xSettings, xOutputStream ); + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + } + break; + + case ::com::sun::star::ui::UIElementType::TOOLBAR: + { + try + { + ToolBoxConfiguration::StoreToolBox( m_xServiceManager, xOutputStream, rElement.xSettings ); + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + } + break; + + case ::com::sun::star::ui::UIElementType::STATUSBAR: + { + try + { + StatusBarConfiguration::StoreStatusBar( m_xServiceManager, xOutputStream, rElement.xSettings ); + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + } + break; + + default: + break; + } + } + + // mark as not modified if we store to our own storage + if ( bResetModifyState ) + rElement.bModified = sal_False; + } + } + + ++pIter; + } + + // commit element type storage + Reference< XTransactedObject > xTransactedObject( xStorage, UNO_QUERY ); + if ( xTransactedObject.is() ) + xTransactedObject->commit(); + + // mark UIElementType as not modified if we store to our own storage + if ( bResetModifyState ) + rElementType.bModified = sal_False; +} + +void UIConfigurationManager::impl_resetElementTypeData( + UIElementType& rDocElementType, + ConfigEventNotifyContainer& rRemoveNotifyContainer ) +{ + UIElementDataHashMap& rHashMap = rDocElementType.aElementsHashMap; + UIElementDataHashMap::iterator pIter = rHashMap.begin(); + + Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); + Reference< XInterface > xIfac( xThis, UNO_QUERY ); + + // Make copies of the event structures to be thread-safe. We have to unlock our mutex before calling + // our listeners! + while ( pIter != rHashMap.end() ) + { + UIElementData& rElement = pIter->second; + if ( !rElement.bDefault ) + { + // Remove user-defined settings from document + ConfigurationEvent aEvent; + aEvent.ResourceURL = rElement.aResourceURL; + aEvent.Accessor <<= xThis; + aEvent.Source = xIfac; + aEvent.Element <<= rElement.xSettings; + + rRemoveNotifyContainer.push_back( aEvent ); + + // Mark element as default. + rElement.bModified = false; + rElement.bDefault = true; + } + else + rElement.bModified = false; + + ++pIter; + } + + // Remove all settings from our user interface elements + rHashMap.clear(); +} + +void UIConfigurationManager::impl_reloadElementTypeData( + UIElementType& rDocElementType, + ConfigEventNotifyContainer& rRemoveNotifyContainer, + ConfigEventNotifyContainer& rReplaceNotifyContainer ) +{ + UIElementDataHashMap& rHashMap = rDocElementType.aElementsHashMap; + UIElementDataHashMap::iterator pIter = rHashMap.begin(); + Reference< XStorage > xElementStorage( rDocElementType.xStorage ); + Reference< XNameAccess > xElementNameAccess( xElementStorage, UNO_QUERY ); + + Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); + Reference< XInterface > xIfac( xThis, UNO_QUERY ); + sal_Int16 nType = rDocElementType.nElementType; + + while ( pIter != rHashMap.end() ) + { + UIElementData& rElement = pIter->second; + if ( rElement.bModified ) + { + if ( xElementNameAccess->hasByName( rElement.aName )) + { + // Replace settings with data from user layer + Reference< XIndexAccess > xOldSettings( rElement.xSettings ); + + impl_requestUIElementData( nType, rElement ); + + ConfigurationEvent aReplaceEvent; + + aReplaceEvent.ResourceURL = rElement.aResourceURL; + aReplaceEvent.Accessor <<= xThis; + aReplaceEvent.Source = xIfac; + aReplaceEvent.ReplacedElement <<= xOldSettings; + aReplaceEvent.Element <<= rElement.xSettings; + rReplaceNotifyContainer.push_back( aReplaceEvent ); + + rElement.bModified = false; + } + else + { + // Element settings are not in any storage => remove + ConfigurationEvent aRemoveEvent; + + aRemoveEvent.ResourceURL = rElement.aResourceURL; + aRemoveEvent.Accessor <<= xThis; + aRemoveEvent.Source = xIfac; + aRemoveEvent.Element <<= rElement.xSettings; + + rRemoveNotifyContainer.push_back( aRemoveEvent ); + + // Mark element as default and not modified. That means "not active" in the document anymore + rElement.bModified = false; + rElement.bDefault = true; + } + } + ++pIter; + } + + rDocElementType.bModified = sal_False; +} + +void UIConfigurationManager::impl_Initialize() +{ + // Initialize the top-level structures with the storage data + if ( m_xDocConfigStorage.is() ) + { + long nModes = m_bReadOnly ? ElementModes::READ : ElementModes::READWRITE; + + // Try to access our module sub folder + for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; + i++ ) + { + Reference< XStorage > xElementTypeStorage; + try + { + xElementTypeStorage = m_xDocConfigStorage->openStorageElement( rtl::OUString::createFromAscii( UIELEMENTTYPENAMES[i] ), 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& ) + { + } + + m_aUIElements[i].nElementType = i; + m_aUIElements[i].bModified = false; + m_aUIElements[i].xStorage = xElementTypeStorage; + m_aUIElements[i].bDefaultLayer = false; + } + } + else + { + // We have no storage, just initialize ui element types with empty storage! + for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + m_aUIElements[i].xStorage = m_xDocConfigStorage; + } +} + +UIConfigurationManager::UIConfigurationManager( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > xServiceManager ) : + ThreadHelpBase( &Application::GetSolarMutex() ) + , m_xDocConfigStorage( 0 ) + , m_bReadOnly( true ) + , m_bInitialized( false ) + , m_bModified( false ) + , m_bConfigRead( false ) + , m_bDisposed( false ) + , m_aXMLPostfix( RTL_CONSTASCII_USTRINGPARAM( ".xml" )) + , m_aPropUIName( RTL_CONSTASCII_USTRINGPARAM( "UIName" )) + , m_aPropResourceURL( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" )) + , m_xServiceManager( xServiceManager ) + , m_aListenerContainer( m_aLock.getShareableOslMutex() ) +{ + // Make sure we have a default initialized entry for every layer and user interface element type! + // The following code depends on this! + m_aUIElements.resize( ::com::sun::star::ui::UIElementType::COUNT ); +} + +UIConfigurationManager::~UIConfigurationManager() +{ +} + +// XComponent +void SAL_CALL UIConfigurationManager::dispose() throw (::com::sun::star::uno::RuntimeException) +{ + Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY ); + + css::lang::EventObject aEvent( xThis ); + m_aListenerContainer.disposeAndClear( aEvent ); + + { + ResetableGuard aGuard( m_aLock ); + try + { + if ( m_xImageManager.is() ) + m_xImageManager->dispose(); + } + catch ( Exception& ) + { + } + + m_xImageManager.clear(); + m_aUIElements.clear(); + m_xDocConfigStorage.clear(); + m_bConfigRead = false; + m_bModified = false; + m_bDisposed = true; + } +} + +void SAL_CALL UIConfigurationManager::addEventListener( const 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 Reference< XEventListener >* ) NULL ), xListener ); +} + +void SAL_CALL UIConfigurationManager::removeEventListener( const Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) +{ + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener ); +} + +// XUIConfigurationManager +void SAL_CALL UIConfigurationManager::addConfigurationListener( const 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 Reference< XUIConfigurationListener >* ) NULL ), xListener ); +} + +void SAL_CALL UIConfigurationManager::removeConfigurationListener( const Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) +{ + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XUIConfigurationListener >* ) NULL ), xListener ); +} + + +void SAL_CALL UIConfigurationManager::reset() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + if ( m_bDisposed ) + throw DisposedException(); + + if ( isReadOnly() ) + return; + + bool bResetStorage( false ); + if ( m_xDocConfigStorage.is() ) + { + try + { + // Remove all elements from our user-defined storage! + bool bCommit( false ); + for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + { + UIElementType& rElementType = m_aUIElements[i]; + Reference< XStorage > xSubStorage( rElementType.xStorage, UNO_QUERY ); + + if ( xSubStorage.is() ) + { + bool bCommitSubStorage( false ); + Reference< XNameAccess > xSubStorageNameAccess( xSubStorage, UNO_QUERY ); + Sequence< rtl::OUString > aUIElementStreamNames = xSubStorageNameAccess->getElementNames(); + for ( sal_Int32 j = 0; j < aUIElementStreamNames.getLength(); j++ ) + { + xSubStorage->removeElement( aUIElementStreamNames[j] ); + bCommitSubStorage = true; + bCommit = true; + } + + if ( bCommitSubStorage ) + { + Reference< XTransactedObject > xTransactedObject( xSubStorage, UNO_QUERY ); + if ( xTransactedObject.is() ) + xTransactedObject->commit(); + } + } + } + + // Commit changes + if ( bCommit ) + { + Reference< XTransactedObject > xTransactedObject( m_xDocConfigStorage, UNO_QUERY ); + if ( xTransactedObject.is() ) + xTransactedObject->commit(); + } + bResetStorage = true; + + // remove settings from user defined layer and notify listener about removed settings data! + // Try to access our module sub folder + ConfigEventNotifyContainer aRemoveEventNotifyContainer; + for ( sal_Int16 j = 1; j < ::com::sun::star::ui::UIElementType::COUNT; j++ ) + { + UIElementType& rDocElementType = m_aUIElements[j]; + + impl_resetElementTypeData( rDocElementType, aRemoveEventNotifyContainer ); + rDocElementType.bModified = sal_False; + } + + m_bModified = sal_False; + + // Unlock mutex before notify our listeners + aGuard.unlock(); + + // Notify our listeners + for ( sal_uInt32 k = 0; k < aRemoveEventNotifyContainer.size(); k++ ) + implts_notifyContainerListener( aRemoveEventNotifyContainer[k], NotifyOp_Remove ); + } + catch ( ::com::sun::star::lang::IllegalArgumentException& ) + { + } + catch ( ::com::sun::star::container::NoSuchElementException& ) + { + } + catch ( ::com::sun::star::embed::InvalidStorageException& ) + { + } + catch ( ::com::sun::star::embed::StorageWrappedTargetException& ) + { + } + } +} + +Sequence< Sequence< PropertyValue > > SAL_CALL UIConfigurationManager::getUIElementsInfo( sal_Int16 ElementType ) +throw ( IllegalArgumentException, RuntimeException ) +{ + if (( ElementType < 0 ) || ( ElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + + ResetableGuard aGuard( m_aLock ); + if ( m_bDisposed ) + throw DisposedException(); + + Sequence< Sequence< PropertyValue > > aElementInfoSeq; + UIElementInfoHashMap aUIElementInfoCollection; + + if ( ElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) + { + for ( sal_Int16 i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, sal_Int16( i ) ); + } + else + impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, ElementType ); + + Sequence< PropertyValue > aUIElementInfo( 2 ); + aUIElementInfo[0].Name = m_aPropResourceURL; + aUIElementInfo[1].Name = m_aPropUIName; + + aElementInfoSeq.realloc( aUIElementInfoCollection.size() ); + UIElementInfoHashMap::const_iterator pIter = aUIElementInfoCollection.begin(); + + sal_Int32 n = 0; + while ( pIter != aUIElementInfoCollection.end() ) + { + aUIElementInfo[0].Value <<= pIter->second.aResourceURL; + aUIElementInfo[1].Value <<= pIter->second.aUIName; + aElementInfoSeq[n++] = aUIElementInfo; + ++pIter; + } + + return aElementInfoSeq; +} + +Reference< XIndexContainer > SAL_CALL UIConfigurationManager::createSettings() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + // Creates an empty item container which can be filled from outside + return Reference< XIndexContainer >( static_cast< OWeakObject * >( new RootItemContainer()), UNO_QUERY ); +} + +sal_Bool SAL_CALL UIConfigurationManager::hasSettings( const ::rtl::OUString& ResourceURL ) +throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else + { + UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false ); + if ( pDataSettings && !pDataSettings->bDefault ) + return sal_True; + } + + return sal_False; +} + +Reference< XIndexAccess > SAL_CALL UIConfigurationManager::getSettings( const ::rtl::OUString& ResourceURL, sal_Bool bWriteable ) +throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType ); + if ( pDataSettings && !pDataSettings->bDefault ) + { + // Create a copy of our data if someone wants to change the data. + if ( bWriteable ) + return Reference< XIndexAccess >( static_cast< OWeakObject * >( new RootItemContainer( pDataSettings->xSettings ) ), UNO_QUERY ); + else + return pDataSettings->xSettings; + } + } + + throw NoSuchElementException(); +} + +void SAL_CALL UIConfigurationManager::replaceSettings( const ::rtl::OUString& ResourceURL, const Reference< ::com::sun::star::container::XIndexAccess >& aNewData ) +throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else if ( m_bReadOnly ) + throw IllegalAccessException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType ); + if ( pDataSettings && !pDataSettings->bDefault ) + { + // we have a settings entry in our user-defined layer - replace + Reference< XIndexAccess > xOldSettings = pDataSettings->xSettings; + + // Create a copy of the data if the container is not const + Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY ); + if ( xReplace.is() ) + pDataSettings->xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY ); + else + pDataSettings->xSettings = aNewData; + + pDataSettings->bDefault = false; + pDataSettings->bModified = true; + m_bModified = true; + + // Modify type container + UIElementType& rElementType = m_aUIElements[nElementType]; + rElementType.bModified = true; + + Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); + + // Create event to notify listener about replaced element settings + ConfigurationEvent aEvent; + Reference< XInterface > xIfac( xThis, UNO_QUERY ); + + aEvent.ResourceURL = ResourceURL; + aEvent.Accessor <<= xThis; + aEvent.Source = xIfac; + aEvent.ReplacedElement <<= xOldSettings; + aEvent.Element <<= pDataSettings->xSettings; + + aGuard.unlock(); + + implts_notifyContainerListener( aEvent, NotifyOp_Replace ); + } + else + throw NoSuchElementException(); + } +} + +void SAL_CALL UIConfigurationManager::removeSettings( const ::rtl::OUString& ResourceURL ) +throw ( NoSuchElementException, IllegalArgumentException, IllegalAccessException, RuntimeException) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else if ( m_bReadOnly ) + throw IllegalAccessException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType ); + if ( pDataSettings ) + { + // If element settings are default, we don't need to change anything! + if ( pDataSettings->bDefault ) + return; + else + { + Reference< XIndexAccess > xRemovedSettings = pDataSettings->xSettings; + pDataSettings->bDefault = true; + + // check if this is a default layer node + pDataSettings->bModified = true; // we have to remove this node from the user layer! + pDataSettings->xSettings.clear(); + m_bModified = true; // user layer must be written + + // Modify type container + UIElementType& rElementType = m_aUIElements[nElementType]; + rElementType.bModified = true; + + Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); + Reference< XInterface > xIfac( xThis, UNO_QUERY ); + + // Create event to notify listener about removed element settings + ConfigurationEvent aEvent; + + aEvent.ResourceURL = ResourceURL; + aEvent.Accessor <<= xThis; + aEvent.Source = xIfac; + aEvent.Element <<= xRemovedSettings; + + aGuard.unlock(); + + implts_notifyContainerListener( aEvent, NotifyOp_Remove ); + } + } + else + throw NoSuchElementException(); + } +} + +void SAL_CALL UIConfigurationManager::insertSettings( const ::rtl::OUString& NewResourceURL, const Reference< XIndexAccess >& aNewData ) +throw ( ElementExistException, IllegalArgumentException, IllegalAccessException, RuntimeException ) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( NewResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else if ( m_bReadOnly ) + throw IllegalAccessException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + bool bInsertData( false ); + UIElementData aUIElementData; + UIElementData* pDataSettings = impl_findUIElementData( NewResourceURL, nElementType ); + + if ( pDataSettings && !pDataSettings->bDefault ) + throw ElementExistException(); + + if ( !pDataSettings ) + { + pDataSettings = &aUIElementData; + bInsertData = true; + } + + { + pDataSettings->bDefault = false; + pDataSettings->bModified = true; + + // Create a copy of the data if the container is not const + Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY ); + if ( xReplace.is() ) + pDataSettings->xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY ); + else + pDataSettings->xSettings = aNewData; + + m_bModified = true; + + UIElementType& rElementType = m_aUIElements[nElementType]; + rElementType.bModified = true; + + if ( bInsertData ) + { + pDataSettings->aName = RetrieveNameFromResourceURL( NewResourceURL ) + m_aXMLPostfix; + pDataSettings->aResourceURL = NewResourceURL; + + UIElementDataHashMap& rElements = rElementType.aElementsHashMap; + rElements.insert( UIElementDataHashMap::value_type( NewResourceURL, *pDataSettings )); + } + + Reference< XIndexAccess > xInsertSettings( aUIElementData.xSettings ); + Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY ); + Reference< XInterface > xIfac( xThis, UNO_QUERY ); + + // Create event to notify listener about removed element settings + ConfigurationEvent aEvent; + + aEvent.ResourceURL = NewResourceURL; + aEvent.Accessor <<= xThis; + aEvent.Source = xIfac; + aEvent.Element <<= xInsertSettings; + + aGuard.unlock(); + + implts_notifyContainerListener( aEvent, NotifyOp_Insert ); + } + } +} + +Reference< XInterface > SAL_CALL UIConfigurationManager::getImageManager() throw (::com::sun::star::uno::RuntimeException) +{ + if ( m_bDisposed ) + throw DisposedException(); + + if ( !m_xImageManager.is() ) + { + m_xImageManager = Reference< XComponent >( static_cast< cppu::OWeakObject *>( new ImageManager( m_xServiceManager )), + UNO_QUERY ); + Reference< XInitialization > xInit( m_xImageManager, UNO_QUERY ); + + Sequence< Any > aPropSeq( 2 ); + PropertyValue aPropValue; + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserConfigStorage" )); + aPropValue.Value = makeAny( m_xDocConfigStorage ); + aPropSeq[0] = makeAny( aPropValue ); + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleIdentifier" )); + aPropValue.Value = makeAny( m_aModuleIdentifier ); + aPropSeq[1] = makeAny( aPropValue ); + + xInit->initialize( aPropSeq ); + } + + return Reference< XInterface >( m_xImageManager, UNO_QUERY ); +} + +Reference< XInterface > SAL_CALL UIConfigurationManager::getShortCutManager() throw (::com::sun::star::uno::RuntimeException) +{ + // SAFE -> + ResetableGuard aGuard( m_aLock ); + + if (m_xAccConfig.is()) + return m_xAccConfig; + + Reference< XMultiServiceFactory > xSMGR = m_xServiceManager; + Reference< XStorage > xDocumentRoot = m_xDocConfigStorage; + + aGuard.unlock(); + // <- SAFE + + Reference< XInterface > xAccConfig = xSMGR->createInstance(SERVICENAME_DOCUMENTACCELERATORCONFIGURATION); + Reference< XInitialization > xInit (xAccConfig, UNO_QUERY_THROW); + + PropertyValue aProp; + aProp.Name = ::rtl::OUString::createFromAscii("DocumentRoot"); + aProp.Value <<= xDocumentRoot; + + Sequence< Any > lArgs(1); + lArgs[0] <<= aProp; + + xInit->initialize(lArgs); + + // SAFE -> + aGuard.lock(); + m_xAccConfig = xAccConfig; + aGuard.unlock(); + // <- SAFE + + return xAccConfig; +} + +Reference< XInterface > SAL_CALL UIConfigurationManager::getEventsManager() throw (::com::sun::star::uno::RuntimeException) +{ + return Reference< XInterface >(); +} + +// XUIConfigurationStorage +void SAL_CALL UIConfigurationManager::setStorage( const Reference< XStorage >& Storage ) throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( m_xDocConfigStorage.is() ) + { + try + { + // Dispose old storage to be sure that it will be closed + Reference< XComponent > xComponent( m_xDocConfigStorage, UNO_QUERY ); + if ( xComponent.is() ) + xComponent->dispose(); + } + catch ( Exception& ) + { + } + } + + // We store the new storage. Be careful it could be an empty reference! + m_xDocConfigStorage = Storage; + m_bReadOnly = sal_True; + + Reference< XUIConfigurationStorage > xAccUpdate(m_xAccConfig, UNO_QUERY); + if ( xAccUpdate.is() ) + xAccUpdate->setStorage( m_xDocConfigStorage ); + + if ( m_xImageManager.is() ) + { + ImageManager* pImageManager = (ImageManager*)m_xImageManager.get(); + if ( pImageManager ) + pImageManager->setStorage( m_xDocConfigStorage ); + } + + if ( m_xDocConfigStorage.is() ) + { + Reference< XPropertySet > xPropSet( m_xDocConfigStorage, UNO_QUERY ); + if ( xPropSet.is() ) + { + try + { + long nOpenMode = 0; + Any a = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenMode" ))); + if ( a >>= nOpenMode ) + m_bReadOnly = !( nOpenMode & ElementModes::WRITE ); + } + catch ( com::sun::star::beans::UnknownPropertyException& ) + { + } + catch ( com::sun::star::lang::WrappedTargetException& ) + { + } + } + } + + impl_Initialize(); +} + +sal_Bool SAL_CALL UIConfigurationManager::hasStorage() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + return ( m_xDocConfigStorage.is() ); +} + +// XUIConfigurationPersistence +void SAL_CALL UIConfigurationManager::reload() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( m_xDocConfigStorage.is() && m_bModified && !m_bReadOnly ) + { + // Try to access our module sub folder + ConfigEventNotifyContainer aRemoveNotifyContainer; + ConfigEventNotifyContainer aReplaceNotifyContainer; + for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + { + try + { + UIElementType& rDocElementType = m_aUIElements[i]; + if ( rDocElementType.bModified ) + impl_reloadElementTypeData( rDocElementType, aRemoveNotifyContainer, aReplaceNotifyContainer ); + } + catch ( Exception& ) + { + throw IOException(); + } + } + + m_bModified = sal_False; + + // Unlock mutex before notify our listeners + aGuard.unlock(); + + // Notify our listeners + for ( sal_uInt32 j = 0; j < aRemoveNotifyContainer.size(); j++ ) + implts_notifyContainerListener( aRemoveNotifyContainer[j], NotifyOp_Remove ); + for ( sal_uInt32 k = 0; k < aReplaceNotifyContainer.size(); k++ ) + implts_notifyContainerListener( aReplaceNotifyContainer[k], NotifyOp_Replace ); + } +} + +void SAL_CALL UIConfigurationManager::store() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( m_xDocConfigStorage.is() && m_bModified && !m_bReadOnly ) + { + // Try to access our module sub folder + for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + { + try + { + UIElementType& rElementType = m_aUIElements[i]; + Reference< XStorage > xStorage( rElementType.xStorage, UNO_QUERY ); + + if ( rElementType.bModified && xStorage.is() ) + impl_storeElementTypeData( xStorage, rElementType ); + } + catch ( Exception& ) + { + throw IOException(); + } + } + + m_bModified = false; + Reference< XTransactedObject > xTransactedObject( m_xDocConfigStorage, UNO_QUERY ); + if ( xTransactedObject.is() ) + xTransactedObject->commit(); + } +} + +void SAL_CALL UIConfigurationManager::storeToStorage( const 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_xDocConfigStorage.is() && m_bModified && !m_bReadOnly ) + { + // Try to access our module sub folder + for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + { + try + { + Reference< XStorage > xElementTypeStorage( Storage->openStorageElement( + rtl::OUString::createFromAscii( UIELEMENTTYPENAMES[i] ), ElementModes::READWRITE )); + UIElementType& rElementType = m_aUIElements[i]; + + if ( rElementType.bModified && xElementTypeStorage.is() ) + impl_storeElementTypeData( xElementTypeStorage, rElementType, false ); // store data to storage, but don't reset modify flag! + } + catch ( Exception& ) + { + throw IOException(); + } + } + + Reference< XTransactedObject > xTransactedObject( Storage, UNO_QUERY ); + if ( xTransactedObject.is() ) + xTransactedObject->commit(); + } +} + +sal_Bool SAL_CALL UIConfigurationManager::isModified() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + return m_bModified; +} + +sal_Bool SAL_CALL UIConfigurationManager::isReadOnly() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + return m_bReadOnly; +} + +void UIConfigurationManager::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(); + } + } + } +} + +} // namespace framework diff --git a/framework/source/uiconfiguration/uiconfigurationmanagerimpl.cxx b/framework/source/uiconfiguration/uiconfigurationmanagerimpl.cxx new file mode 100755 index 000000000000..40c2c3f10708 --- /dev/null +++ b/framework/source/uiconfiguration/uiconfigurationmanagerimpl.cxx @@ -0,0 +1,1713 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: UIConfigurationManagerImpl.cxx,v $ + * $Revision: 1.19.208.2 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include <uiconfigurationmanagerimpl.hxx> +#include <threadhelp/resetableguard.hxx> +#include <services.h> +#include <uielement/constitemcontainer.hxx> +#include <uielement/rootitemcontainer.hxx> +#include <uielement/uielementtypenames.hxx> +#include <xml/menuconfiguration.hxx> +#include <xml/toolboxconfiguration.hxx> +#include <uiconfiguration/imagemanager.hxx> + +#ifndef __FRAMEWORK_XML_STATUSBARCONFIGURATION_HXX_ +#include <xml/statusbarconfiguration.hxx> +#endif + +//_________________________________________________________________________________________________________________ +// 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/embed/ElementModes.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/io/XStream.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#include <vcl/svapp.hxx> +#include <rtl/ustrbuf.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <boost/bind.hpp> + +//_________________________________________________________________________________________________________________ +// namespaces +//_________________________________________________________________________________________________________________ + +using rtl::OUString; +using namespace com::sun::star::uno; +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; + +namespace framework +{ + + +// important: The order and position of the elements must match the constant +// definition of "::com::sun::star::ui::UIElementType" +static const char* UIELEMENTTYPENAMES[] = +{ + "", // Dummy value for unknown! + UIELEMENTTYPE_MENUBAR_NAME, + UIELEMENTTYPE_POPUPMENU_NAME, + UIELEMENTTYPE_TOOLBAR_NAME, + UIELEMENTTYPE_STATUSBAR_NAME, + UIELEMENTTYPE_FLOATINGWINDOW_NAME, + UIELEMENTTYPE_PROGRESSBAR_NAME +}; + +static const char RESOURCEURL_PREFIX[] = "private:resource/"; +static const sal_Int32 RESOURCEURL_PREFIX_SIZE = 17; +static const char RESOURCEURL_CUSTOM_ELEMENT[] = "custom_"; + +static sal_Int16 RetrieveTypeFromResourceURL( const rtl::OUString& aResourceURL ) +{ + + if (( aResourceURL.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_PREFIX ))) == 0 ) && + ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE )) + { + rtl::OUString aTmpStr = aResourceURL.copy( RESOURCEURL_PREFIX_SIZE ); + sal_Int32 nIndex = aTmpStr.indexOf( '/' ); + if (( nIndex > 0 ) && ( aTmpStr.getLength() > nIndex )) + { + rtl::OUString aTypeStr( aTmpStr.copy( 0, nIndex )); + for ( int i = 0; i < UIElementType::COUNT; i++ ) + { + if ( aTypeStr.equalsAscii( UIELEMENTTYPENAMES[i] )) + return sal_Int16( i ); + } + } + } + + return UIElementType::UNKNOWN; +} + +static rtl::OUString RetrieveNameFromResourceURL( const rtl::OUString& aResourceURL ) +{ + if (( aResourceURL.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_PREFIX ))) == 0 ) && + ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE )) + { + sal_Int32 nIndex = aResourceURL.lastIndexOf( '/' ); + if (( nIndex > 0 ) && (( nIndex+1 ) < aResourceURL.getLength())) + return aResourceURL.copy( nIndex+1 ); + } + + return rtl::OUString(); +} + +void UIConfigurationManagerImpl::impl_fillSequenceWithElementTypeInfo( UIElementInfoHashMap& aUIElementInfoCollection, sal_Int16 nElementType ) +{ + // preload list of element types on demand + impl_preloadUIElementTypeList( LAYER_USERDEFINED, nElementType ); + if ( m_bUseDefault ) + impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType ); + + UIElementDataHashMap& rUserElements = m_aUIElements[LAYER_USERDEFINED][nElementType].aElementsHashMap; + UIElementDataHashMap::const_iterator pUserIter = rUserElements.begin(); + + rtl::OUString aCustomUrlPrefix( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_CUSTOM_ELEMENT )); + while ( pUserIter != rUserElements.end() ) + { + sal_Int32 nIndex = pUserIter->second.aResourceURL.indexOf( aCustomUrlPrefix, RESOURCEURL_PREFIX_SIZE ); + if ( nIndex > RESOURCEURL_PREFIX_SIZE ) + { + // Performance: Retrieve user interface name only for custom user interface elements. + // It's only used by them! + UIElementData* pDataSettings = impl_findUIElementData( pUserIter->second.aResourceURL, nElementType ); + if ( pDataSettings && ( m_bUseDefault || !pDataSettings->bDefault )) + { + // Retrieve user interface name from XPropertySet interface + rtl::OUString aUIName; + Reference< XPropertySet > xPropSet( pDataSettings->xSettings, UNO_QUERY ); + if ( xPropSet.is() ) + { + xPropSet->getPropertyValue( m_aPropUIName ) >>= aUIName; + } + + UIElementInfo aInfo( pUserIter->second.aResourceURL, aUIName ); + aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pUserIter->second.aResourceURL, aInfo )); + } + } + else + { + // The user interface name for standard user interface elements is stored in the WindowState.xcu file + UIElementInfo aInfo( pUserIter->second.aResourceURL, rtl::OUString() ); + aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pUserIter->second.aResourceURL, aInfo )); + } + ++pUserIter; + } + + if ( m_bUseDefault ) + { + UIElementDataHashMap& rDefaultElements = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap; + UIElementDataHashMap::const_iterator pDefIter = rDefaultElements.begin(); + + while ( pDefIter != rDefaultElements.end() ) + { + UIElementInfoHashMap::const_iterator pIterInfo = aUIElementInfoCollection.find( pDefIter->second.aResourceURL ); + if ( pIterInfo == aUIElementInfoCollection.end() ) + { + sal_Int32 nIndex = pDefIter->second.aResourceURL.indexOf( aCustomUrlPrefix, RESOURCEURL_PREFIX_SIZE ); + if ( nIndex > RESOURCEURL_PREFIX_SIZE ) + { + // Performance: Retrieve user interface name only for custom user interface elements. + // It's only used by them! + UIElementData* pDataSettings = impl_findUIElementData( pDefIter->second.aResourceURL, nElementType ); + if ( pDataSettings ) + { + // Retrieve user interface name from XPropertySet interface + rtl::OUString aUIName; + Reference< XPropertySet > xPropSet( pDataSettings->xSettings, UNO_QUERY ); + if ( xPropSet.is() ) + { + xPropSet->getPropertyValue( m_aPropUIName ) >>= aUIName; + } + + UIElementInfo aInfo( pDefIter->second.aResourceURL, aUIName ); + aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pDefIter->second.aResourceURL, aInfo )); + } + } + else + { + // The user interface name for standard user interface elements is stored in the WindowState.xcu file + UIElementInfo aInfo( pDefIter->second.aResourceURL, rtl::OUString() ); + aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pDefIter->second.aResourceURL, aInfo )); + } + } + + ++pDefIter; + } // while ( pDefIter != rDefaultElements.end() ) + } +} + +void UIConfigurationManagerImpl::impl_preloadUIElementTypeList( Layer eLayer, sal_Int16 nElementType ) +{ + UIElementType& rElementTypeData = m_aUIElements[eLayer][nElementType]; + + if ( !rElementTypeData.bLoaded ) + { + Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage; + if ( xElementTypeStorage.is() ) + { + rtl::OUStringBuffer aBuf( RESOURCEURL_PREFIX_SIZE ); + aBuf.appendAscii( RESOURCEURL_PREFIX ); + aBuf.appendAscii( UIELEMENTTYPENAMES[ nElementType ] ); + aBuf.appendAscii( "/" ); + rtl::OUString aResURLPrefix( aBuf.makeStringAndClear() ); + + UIElementDataHashMap& rHashMap = rElementTypeData.aElementsHashMap; + Reference< XNameAccess > xNameAccess( xElementTypeStorage, UNO_QUERY ); + Sequence< rtl::OUString > aUIElementNames = xNameAccess->getElementNames(); + for ( sal_Int32 n = 0; n < aUIElementNames.getLength(); n++ ) + { + UIElementData aUIElementData; + + // Resource name must be without ".xml" + sal_Int32 nIndex = aUIElementNames[n].lastIndexOf( '.' ); + if (( nIndex > 0 ) && ( nIndex < aUIElementNames[n].getLength() )) + { + rtl::OUString aExtension( aUIElementNames[n].copy( nIndex+1 )); + rtl::OUString aUIElementName( aUIElementNames[n].copy( 0, nIndex )); + + if (( aUIElementName.getLength() > 0 ) && + ( aExtension.equalsIgnoreAsciiCaseAsciiL( "xml", 3 ))) + { + aUIElementData.aResourceURL = aResURLPrefix + aUIElementName; + aUIElementData.aName = aUIElementNames[n]; + + if ( eLayer == LAYER_USERDEFINED ) + { + aUIElementData.bModified = false; + aUIElementData.bDefault = false; + aUIElementData.bDefaultNode = false; + } + + // Create hash_map entries for all user interface elements inside the storage. We don't load the + // settings to speed up the process. + rHashMap.insert( UIElementDataHashMap::value_type( aUIElementData.aResourceURL, aUIElementData )); + } + } + } + } + } + + rElementTypeData.bLoaded = true; +} + +void UIConfigurationManagerImpl::impl_requestUIElementData( sal_Int16 nElementType, Layer eLayer, UIElementData& aUIElementData ) +{ + UIElementType& rElementTypeData = m_aUIElements[eLayer][nElementType]; + + Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage; + if ( xElementTypeStorage.is() && aUIElementData.aName.getLength() ) + { + try + { + Reference< XStream > xStream = xElementTypeStorage->openStreamElement( aUIElementData.aName, ElementModes::READ ); + Reference< XInputStream > xInputStream = xStream->getInputStream(); + + if ( xInputStream.is() ) + { + switch ( nElementType ) + { + case ::com::sun::star::ui::UIElementType::UNKNOWN: + break; + + case ::com::sun::star::ui::UIElementType::MENUBAR: + { + try + { + MenuConfiguration aMenuCfg( m_xServiceManager ); + Reference< XIndexAccess > xContainer( aMenuCfg.CreateMenuBarConfigurationFromXML( xInputStream )); + RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xContainer ); + if ( pRootItemContainer ) + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY ); + else + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( xContainer, sal_True ) ), UNO_QUERY ); + return; + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + } + break; + + case ::com::sun::star::ui::UIElementType::POPUPMENU: + { + break; + } + + case ::com::sun::star::ui::UIElementType::TOOLBAR: + { + try + { + Reference< XIndexContainer > xIndexContainer( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY ); + ToolBoxConfiguration::LoadToolBox( m_xServiceManager, xInputStream, xIndexContainer ); + RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xIndexContainer ); + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY ); + return; + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + + break; + } + + case ::com::sun::star::ui::UIElementType::STATUSBAR: + { + try + { + Reference< XIndexContainer > xIndexContainer( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY ); + StatusBarConfiguration::LoadStatusBar( m_xServiceManager, xInputStream, xIndexContainer ); + RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xIndexContainer ); + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY ); + return; + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + + break; + } + + case ::com::sun::star::ui::UIElementType::FLOATINGWINDOW: + { + break; + } + } + } + } + catch ( ::com::sun::star::embed::InvalidStorageException& ) + { + } + catch ( ::com::sun::star::lang::IllegalArgumentException& ) + { + } + catch ( ::com::sun::star::io::IOException& ) + { + } + catch ( ::com::sun::star::embed::StorageWrappedTargetException& ) + { + } + } + + // At least we provide an empty settings container! + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer() ), UNO_QUERY ); +} + +UIConfigurationManagerImpl::UIElementData* UIConfigurationManagerImpl::impl_findUIElementData( const rtl::OUString& aResourceURL, sal_Int16 nElementType, bool bLoad ) +{ + // preload list of element types on demand + impl_preloadUIElementTypeList( LAYER_USERDEFINED, nElementType ); + if ( m_bUseDefault ) + impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType ); + + // first try to look into our user-defined vector/hash_map combination + UIElementDataHashMap& rUserHashMap = m_aUIElements[LAYER_USERDEFINED][nElementType].aElementsHashMap; + UIElementDataHashMap::iterator pIter = rUserHashMap.find( aResourceURL ); + if ( pIter != rUserHashMap.end() ) + { + // Default data settings data must be retrieved from the default layer! + if ( !pIter->second.bDefault ) + { + if ( !pIter->second.xSettings.is() && bLoad ) + impl_requestUIElementData( nElementType, LAYER_USERDEFINED, pIter->second ); + return &(pIter->second); + } + } + + if ( m_bUseDefault ) + { + // Not successfull, we have to look into our default vector/hash_map combination + UIElementDataHashMap& rDefaultHashMap = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap; + pIter = rDefaultHashMap.find( aResourceURL ); + if ( pIter != rDefaultHashMap.end() ) + { + if ( !pIter->second.xSettings.is() && bLoad ) + impl_requestUIElementData( nElementType, LAYER_DEFAULT, pIter->second ); + return &(pIter->second); + } // if ( pIter != rDefaultHashMap.end() ) + } + + // Nothing has been found! + return NULL; +} + +void UIConfigurationManagerImpl::impl_storeElementTypeData( Reference< XStorage > xStorage, UIElementType& rElementType, bool bResetModifyState ) +{ + UIElementDataHashMap& rHashMap = rElementType.aElementsHashMap; + UIElementDataHashMap::iterator pIter = rHashMap.begin(); + + while ( pIter != rHashMap.end() ) + { + UIElementData& rElement = pIter->second; + if ( rElement.bModified ) + { + if ( rElement.bDefault ) + { + xStorage->removeElement( rElement.aName ); + rElement.bModified = sal_False; // mark as not modified + } + else + { + Reference< XStream > xStream( xStorage->openStreamElement( rElement.aName, ElementModes::WRITE|ElementModes::TRUNCATE ), UNO_QUERY ); + Reference< XOutputStream > xOutputStream( xStream->getOutputStream() ); + + if ( xOutputStream.is() ) + { + switch( rElementType.nElementType ) + { + case ::com::sun::star::ui::UIElementType::MENUBAR: + { + try + { + MenuConfiguration aMenuCfg( m_xServiceManager ); + aMenuCfg.StoreMenuBarConfigurationToXML( rElement.xSettings, xOutputStream ); + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + } + break; + + case ::com::sun::star::ui::UIElementType::TOOLBAR: + { + try + { + ToolBoxConfiguration::StoreToolBox( m_xServiceManager, xOutputStream, rElement.xSettings ); + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + } + break; + + case ::com::sun::star::ui::UIElementType::STATUSBAR: + { + try + { + StatusBarConfiguration::StoreStatusBar( m_xServiceManager, xOutputStream, rElement.xSettings ); + } + catch ( ::com::sun::star::lang::WrappedTargetException& ) + { + } + } + break; + + default: + break; + } + } + + // mark as not modified if we store to our own storage + if ( bResetModifyState ) + rElement.bModified = sal_False; + } + } + + ++pIter; + } + + // commit element type storage + Reference< XTransactedObject > xTransactedObject( xStorage, UNO_QUERY ); + if ( xTransactedObject.is() ) + xTransactedObject->commit(); + + // mark UIElementType as not modified if we store to our own storage + if ( bResetModifyState ) + rElementType.bModified = sal_False; +} + +// This is only allowed to be called on the LAYER_USER_DEFINED! +void UIConfigurationManagerImpl::impl_resetElementTypeData( + UIElementType& rUserElementType, + UIElementType& rDefaultElementType, + ConfigEventNotifyContainer& rRemoveNotifyContainer, + ConfigEventNotifyContainer& rReplaceNotifyContainer ) +{ + UIElementDataHashMap& rHashMap = rUserElementType.aElementsHashMap; + UIElementDataHashMap::iterator pIter = rHashMap.begin(); + + Reference< XUIConfigurationManager > xThis( m_xOwner, UNO_QUERY ); + Reference< XNameAccess > xDefaultNameAccess( rDefaultElementType.xStorage, UNO_QUERY ); + sal_Int16 nType = rUserElementType.nElementType; + + // Make copies of the event structures to be thread-safe. We have to unlock our mutex before calling + // our listeners! + while ( pIter != rHashMap.end() ) + { + UIElementData& rElement = pIter->second; + if ( !rElement.bDefault ) + { + if ( m_bUseDefault && xDefaultNameAccess->hasByName( rElement.aName )) + { + // Replace settings with data from default layer + Reference< XIndexAccess > xOldSettings( rElement.xSettings ); + impl_requestUIElementData( nType, LAYER_DEFAULT, rElement ); + + ConfigurationEvent aReplaceEvent; + aReplaceEvent.ResourceURL = rElement.aResourceURL; + aReplaceEvent.Accessor <<= xThis; + aReplaceEvent.Source = m_xOwner; + aReplaceEvent.ReplacedElement <<= xOldSettings; + aReplaceEvent.Element <<= rElement.xSettings; + + rReplaceNotifyContainer.push_back( aReplaceEvent ); + + // Mark element as default and not modified. That means "not active" + // in the user layer anymore. + rElement.bModified = false; + rElement.bDefault = true; + } + else + { + // Remove user-defined settings from user layer + ConfigurationEvent aEvent; + aEvent.ResourceURL = rElement.aResourceURL; + aEvent.Accessor <<= xThis; + aEvent.Source = m_xOwner; + aEvent.Element <<= rElement.xSettings; + + rRemoveNotifyContainer.push_back( aEvent ); + + // Mark element as default and not modified. That means "not active" + // in the user layer anymore. + rElement.bModified = false; + rElement.bDefault = true; + } + } // if ( !rElement.bDefault ) + else + rElement.bModified = false; + + ++pIter; + } + + // Remove all settings from our user interface elements + rHashMap.clear(); +} + +void UIConfigurationManagerImpl::impl_reloadElementTypeData( + UIElementType& rUserElementType, + UIElementType& rDefaultElementType, + ConfigEventNotifyContainer& rRemoveNotifyContainer, + ConfigEventNotifyContainer& rReplaceNotifyContainer ) +{ + UIElementDataHashMap& rHashMap = rUserElementType.aElementsHashMap; + UIElementDataHashMap::iterator pIter = rHashMap.begin(); + Reference< XStorage > xUserStorage( rUserElementType.xStorage ); + Reference< XStorage > xDefaultStorage( rDefaultElementType.xStorage ); + Reference< XNameAccess > xUserNameAccess( rUserElementType.xStorage, UNO_QUERY ); + Reference< XNameAccess > xDefaultNameAccess( rDefaultElementType.xStorage, UNO_QUERY ); + + Reference< XUIConfigurationManager > xThis( m_xOwner, UNO_QUERY ); + sal_Int16 nType = rUserElementType.nElementType; + + while ( pIter != rHashMap.end() ) + { + UIElementData& rElement = pIter->second; + if ( rElement.bModified ) + { + if ( xUserNameAccess->hasByName( rElement.aName )) + { + // Replace settings with data from user layer + Reference< XIndexAccess > xOldSettings( rElement.xSettings ); + + impl_requestUIElementData( nType, LAYER_USERDEFINED, rElement ); + + ConfigurationEvent aReplaceEvent; + + aReplaceEvent.ResourceURL = rElement.aResourceURL; + aReplaceEvent.Accessor <<= xThis; + aReplaceEvent.Source = m_xOwner; + aReplaceEvent.ReplacedElement <<= xOldSettings; + aReplaceEvent.Element <<= rElement.xSettings; + rReplaceNotifyContainer.push_back( aReplaceEvent ); + + rElement.bModified = false; + } + else if ( m_bUseDefault && xDefaultNameAccess->hasByName( rElement.aName )) + { + // Replace settings with data from default layer + Reference< XIndexAccess > xOldSettings( rElement.xSettings ); + + impl_requestUIElementData( nType, LAYER_DEFAULT, rElement ); + + ConfigurationEvent aReplaceEvent; + + aReplaceEvent.ResourceURL = rElement.aResourceURL; + aReplaceEvent.Accessor <<= xThis; + aReplaceEvent.Source = m_xOwner; + aReplaceEvent.ReplacedElement <<= xOldSettings; + aReplaceEvent.Element <<= rElement.xSettings; + rReplaceNotifyContainer.push_back( aReplaceEvent ); + + // Mark element as default and not modified. That means "not active" + // in the user layer anymore. + rElement.bModified = false; + rElement.bDefault = true; + } + else + { + // Element settings are not in any storage => remove + ConfigurationEvent aRemoveEvent; + + aRemoveEvent.ResourceURL = rElement.aResourceURL; + aRemoveEvent.Accessor <<= xThis; + aRemoveEvent.Source = m_xOwner; + aRemoveEvent.Element <<= rElement.xSettings; + + rRemoveNotifyContainer.push_back( aRemoveEvent ); + + // Mark element as default and not modified. That means "not active" + // in the user layer anymore. + rElement.bModified = false; + rElement.bDefault = true; + } + } + ++pIter; + } + + rUserElementType.bModified = sal_False; +} + +void UIConfigurationManagerImpl::impl_Initialize() +{ + // Initialize the top-level structures with the storage data + if ( m_xUserConfigStorage.is() ) + { + // Try to access our module sub folder + for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; + i++ ) + { + Reference< XStorage > xElementTypeStorage; + try + { + if ( m_pStorageHandler[i] ) + xElementTypeStorage = m_pStorageHandler[i]->getWorkingStorageUser(); + } + 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& ) + { + } + + m_aUIElements[LAYER_USERDEFINED][i].nElementType = i; + m_aUIElements[LAYER_USERDEFINED][i].bModified = false; + m_aUIElements[LAYER_USERDEFINED][i].xStorage = xElementTypeStorage; + m_aUIElements[LAYER_USERDEFINED][i].bDefaultLayer = false; + } + } // if ( m_xUserConfigStorage.is() ) + else if ( !m_bUseDefault ) + { + // We have no storage, just initialize ui element types with empty storage! + for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + m_aUIElements[LAYER_USERDEFINED][i].xStorage.clear(); + } + + if ( m_bUseDefault && m_xUserConfigStorage.is() ) + { + Reference< XNameAccess > xNameAccess( m_xDefaultConfigStorage, UNO_QUERY_THROW ); + + // Try to access our module sub folder + for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; + i++ ) + { + Reference< XStorage > xElementTypeStorage; + try + { + xNameAccess->getByName( rtl::OUString::createFromAscii( UIELEMENTTYPENAMES[i] )) >>= xElementTypeStorage; + } + catch ( com::sun::star::container::NoSuchElementException& ) + { + } + + m_aUIElements[LAYER_DEFAULT][i].nElementType = i; + m_aUIElements[LAYER_DEFAULT][i].bModified = false; + m_aUIElements[LAYER_DEFAULT][i].xStorage = xElementTypeStorage; + m_aUIElements[LAYER_DEFAULT][i].bDefaultLayer = true; + } + } +} + +UIConfigurationManagerImpl::UIConfigurationManagerImpl( const Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager + ,const Reference< XInterface >& _xOwner + , bool _bUseDefault) : + ThreadHelpBase( &Application::GetSolarMutex() ) + , m_xOwner( _xOwner ) + , m_bUseDefault(_bUseDefault) + , m_bReadOnly( true ) + , m_bInitialized( false ) + , m_bModified( false ) + , m_bConfigRead( false ) + , m_bDisposed( false ) + , m_aXMLPostfix( RTL_CONSTASCII_USTRINGPARAM( ".xml" )) + , m_aPropUIName( RTL_CONSTASCII_USTRINGPARAM( "UIName" )) + , m_aPropResourceURL( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" )) + , m_xServiceManager( xServiceManager ) + , m_aListenerContainer( m_aLock.getShareableOslMutex() ) +{ + for ( int i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + m_pStorageHandler[i] = 0; + + // Make sure we have a default initialized entry for every layer and user interface element type! + // The following code depends on this! + m_aUIElements[LAYER_DEFAULT].resize( ::com::sun::star::ui::UIElementType::COUNT ); + m_aUIElements[LAYER_USERDEFINED].resize( ::com::sun::star::ui::UIElementType::COUNT ); +} + +UIConfigurationManagerImpl::~UIConfigurationManagerImpl() +{ + for ( int i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + delete m_pStorageHandler[i]; +} + +// XComponent +void UIConfigurationManagerImpl::dispose() throw (::com::sun::star::uno::RuntimeException) +{ + css::lang::EventObject aEvent( m_xOwner ); + m_aListenerContainer.disposeAndClear( aEvent ); + + { + ResetableGuard aGuard( m_aLock ); + try + { + if ( m_xModuleImageManager.is() ) + m_xModuleImageManager->dispose(); + } + catch ( Exception& ) + { + } + + m_xModuleImageManager.clear(); + m_aUIElements[LAYER_USERDEFINED].clear(); + m_aUIElements[LAYER_DEFAULT].clear(); + m_xDefaultConfigStorage.clear(); + m_xUserConfigStorage.clear(); + m_xUserRootCommit.clear(); + m_bConfigRead = false; + m_bModified = false; + m_bDisposed = true; + } +} + +void UIConfigurationManagerImpl::addEventListener( const 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 Reference< XEventListener >* ) NULL ), xListener ); +} + +void UIConfigurationManagerImpl::removeEventListener( const Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) +{ + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener ); +} + +// XInitialization +void UIConfigurationManagerImpl::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + if ( !m_bInitialized ) + { + ::comphelper::SequenceAsHashMap lArgs(aArguments); + m_aModuleIdentifier = lArgs.getUnpackedValueOrDefault(::rtl::OUString::createFromAscii("ModuleIdentifier"), ::rtl::OUString()); + m_aModuleShortName = lArgs.getUnpackedValueOrDefault(::rtl::OUString::createFromAscii("ModuleShortName"), ::rtl::OUString()); + + for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + { + rtl::OUString aResourceType; + if ( i == ::com::sun::star::ui::UIElementType::MENUBAR ) + aResourceType = PresetHandler::RESOURCETYPE_MENUBAR(); + else if ( i == ::com::sun::star::ui::UIElementType::TOOLBAR ) + aResourceType = PresetHandler::RESOURCETYPE_TOOLBAR(); + else if ( i == ::com::sun::star::ui::UIElementType::STATUSBAR ) + aResourceType = PresetHandler::RESOURCETYPE_STATUSBAR(); + + if ( aResourceType.getLength() > 0 ) + { + m_pStorageHandler[i] = new PresetHandler( m_xServiceManager ); + m_pStorageHandler[i]->connectToResource( PresetHandler::E_MODULES, + aResourceType, // this path wont be used later ... seee next lines! + m_aModuleShortName, + css::uno::Reference< css::embed::XStorage >()); // no document root used here! + } + } + + // initialize root storages for all resource types + m_xUserRootCommit = css::uno::Reference< css::embed::XTransactedObject >( + m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getOrCreateRootStorageUser(), css::uno::UNO_QUERY); // can be empty + m_xDefaultConfigStorage = m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getParentStorageShare( + m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getWorkingStorageShare()); + m_xUserConfigStorage = m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getParentStorageUser( + m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getWorkingStorageUser()); + + if ( m_xUserConfigStorage.is() ) + { + 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 ); + } + } + + impl_Initialize(); + + m_bInitialized = true; + } +} + +// XUIConfiguration +void UIConfigurationManagerImpl::addConfigurationListener( const 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 Reference< XUIConfigurationListener >* ) NULL ), xListener ); +} + +void UIConfigurationManagerImpl::removeConfigurationListener( const Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) +{ + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XUIConfigurationListener >* ) NULL ), xListener ); +} + + +// XUIConfigurationManager +void UIConfigurationManagerImpl::reset() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + /* SAFE AREA ----------------------------------------------------------------------------------------------- */ + if ( m_bDisposed ) + throw DisposedException(); + + bool bResetStorage( false ); + + if ( !isReadOnly() ) + { + // Remove all elements from our user-defined storage! + try + { + for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + { + UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i]; + Reference< XStorage > xSubStorage( rElementType.xStorage, UNO_QUERY ); + + if ( xSubStorage.is() ) + { + bool bCommitSubStorage( false ); + Reference< XNameAccess > xSubStorageNameAccess( xSubStorage, UNO_QUERY ); + Sequence< rtl::OUString > aUIElementStreamNames = xSubStorageNameAccess->getElementNames(); + for ( sal_Int32 j = 0; j < aUIElementStreamNames.getLength(); j++ ) + { + xSubStorage->removeElement( aUIElementStreamNames[j] ); + bCommitSubStorage = true; + } + + if ( bCommitSubStorage ) + { + Reference< XTransactedObject > xTransactedObject( xSubStorage, UNO_QUERY ); + if ( xTransactedObject.is() ) + xTransactedObject->commit(); + m_pStorageHandler[i]->commitUserChanges(); + } + } + } + + bResetStorage = true; + + // remove settings from user defined layer and notify listener about removed settings data! + ConfigEventNotifyContainer aRemoveEventNotifyContainer; + ConfigEventNotifyContainer aReplaceEventNotifyContainer; + for ( sal_Int16 j = 1; j < ::com::sun::star::ui::UIElementType::COUNT; j++ ) + { + try + { + UIElementType& rUserElementType = m_aUIElements[LAYER_USERDEFINED][j]; + UIElementType& rDefaultElementType = m_aUIElements[LAYER_DEFAULT][j]; + + impl_resetElementTypeData( rUserElementType, rDefaultElementType, aRemoveEventNotifyContainer, aReplaceEventNotifyContainer ); + rUserElementType.bModified = sal_False; + } + catch ( Exception& ) + { + throw IOException(); + } + } + + m_bModified = sal_False; + + // Unlock mutex before notify our listeners + aGuard.unlock(); + + // Notify our listeners + ::std::for_each(aRemoveEventNotifyContainer.begin(),aRemoveEventNotifyContainer.end(),::boost::bind(&UIConfigurationManagerImpl::implts_notifyContainerListener,this,_1,NotifyOp_Remove)); + ::std::for_each(aReplaceEventNotifyContainer.begin(),aReplaceEventNotifyContainer.end(),::boost::bind(&UIConfigurationManagerImpl::implts_notifyContainerListener,this,_1,NotifyOp_Replace)); + } + catch ( ::com::sun::star::lang::IllegalArgumentException& ) + { + } + catch ( ::com::sun::star::container::NoSuchElementException& ) + { + } + catch ( ::com::sun::star::embed::InvalidStorageException& ) + { + } + catch ( ::com::sun::star::embed::StorageWrappedTargetException& ) + { + } + } +} + +Sequence< Sequence< PropertyValue > > UIConfigurationManagerImpl::getUIElementsInfo( sal_Int16 ElementType ) +throw ( IllegalArgumentException, RuntimeException ) +{ + if (( ElementType < 0 ) || ( ElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + + ResetableGuard aGuard( m_aLock ); + if ( m_bDisposed ) + throw DisposedException(); + + Sequence< Sequence< PropertyValue > > aElementInfoSeq; + UIElementInfoHashMap aUIElementInfoCollection; + + if ( ElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) + { + for ( sal_Int16 i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, sal_Int16( i ) ); + } + else + impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, ElementType ); + + Sequence< PropertyValue > aUIElementInfo( 2 ); + aUIElementInfo[0].Name = m_aPropResourceURL; + aUIElementInfo[1].Name = m_aPropUIName; + + aElementInfoSeq.realloc( aUIElementInfoCollection.size() ); + UIElementInfoHashMap::const_iterator pIter = aUIElementInfoCollection.begin(); + + sal_Int32 n = 0; + while ( pIter != aUIElementInfoCollection.end() ) + { + aUIElementInfo[0].Value <<= pIter->second.aResourceURL; + aUIElementInfo[1].Value <<= pIter->second.aUIName; + aElementInfoSeq[n++] = aUIElementInfo; + ++pIter; + } + + return aElementInfoSeq; +} + +Reference< XIndexContainer > UIConfigurationManagerImpl::createSettings() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + // Creates an empty item container which can be filled from outside + return Reference< XIndexContainer >( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY ); +} + +sal_Bool UIConfigurationManagerImpl::hasSettings( const ::rtl::OUString& ResourceURL ) +throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false ); + if ( pDataSettings && ( m_bUseDefault || !pDataSettings->bDefault) ) + return sal_True; + } + + return sal_False; +} + +Reference< XIndexAccess > UIConfigurationManagerImpl::getSettings( const ::rtl::OUString& ResourceURL, sal_Bool bWriteable ) +throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType ); + if ( pDataSettings && ( m_bUseDefault || !pDataSettings->bDefault) ) + { + // Create a copy of our data if someone wants to change the data. + if ( bWriteable ) + return Reference< XIndexAccess >( static_cast< OWeakObject * >( new RootItemContainer( pDataSettings->xSettings ) ), UNO_QUERY ); + else + return pDataSettings->xSettings; + } + } + + throw NoSuchElementException(); +} + +void UIConfigurationManagerImpl::replaceSettings( const ::rtl::OUString& ResourceURL, const Reference< ::com::sun::star::container::XIndexAccess >& aNewData ) +throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else if ( m_bReadOnly ) + throw IllegalAccessException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType ); + if ( pDataSettings && ( m_bUseDefault || !pDataSettings->bDefault) ) + { + if ( !m_bUseDefault || !pDataSettings->bDefaultNode ) + { + // we have a settings entry in our user-defined layer - replace + Reference< XIndexAccess > xOldSettings = pDataSettings->xSettings; + + // Create a copy of the data if the container is not const + Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY ); + if ( xReplace.is() ) + pDataSettings->xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY ); + else + pDataSettings->xSettings = aNewData; + pDataSettings->bDefault = false; + pDataSettings->bModified = true; + m_bModified = true; + + // Modify type container + UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType]; + rElementType.bModified = true; + + Reference< XUIConfigurationManager > xThis( m_xOwner, UNO_QUERY ); + + // Create event to notify listener about replaced element settings + ConfigurationEvent aEvent; + + aEvent.ResourceURL = ResourceURL; + aEvent.Accessor <<= xThis; + aEvent.Source = m_xOwner; + aEvent.ReplacedElement <<= xOldSettings; + aEvent.Element <<= pDataSettings->xSettings; + + aGuard.unlock(); + + implts_notifyContainerListener( aEvent, NotifyOp_Replace ); + } + else + { + // we have no settings in our user-defined layer - insert + UIElementData aUIElementData; + + aUIElementData.bDefault = false; + aUIElementData.bDefaultNode = false; + aUIElementData.bModified = true; + + // Create a copy of the data if the container is not const + Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY ); + if ( xReplace.is() ) + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY ); + else + aUIElementData.xSettings = aNewData; + aUIElementData.aName = RetrieveNameFromResourceURL( ResourceURL ) + m_aXMLPostfix; + aUIElementData.aResourceURL = ResourceURL; + m_bModified = true; + + // Modify type container + UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType]; + rElementType.bModified = true; + + UIElementDataHashMap& rElements = rElementType.aElementsHashMap; + + // Check our user element settings hash map as it can already contain settings that have been set to default! + // If no node can be found, we have to insert it. + UIElementDataHashMap::iterator pIter = rElements.find( ResourceURL ); + if ( pIter != rElements.end() ) + pIter->second = aUIElementData; + else + rElements.insert( UIElementDataHashMap::value_type( ResourceURL, aUIElementData )); + + Reference< XUIConfigurationManager > xThis( m_xOwner, UNO_QUERY ); + + // Create event to notify listener about replaced element settings + ConfigurationEvent aEvent; + + aEvent.ResourceURL = ResourceURL; + aEvent.Accessor <<= xThis; + aEvent.Source = m_xOwner; + aEvent.ReplacedElement <<= pDataSettings->xSettings; + aEvent.Element <<= aUIElementData.xSettings; + + aGuard.unlock(); + + implts_notifyContainerListener( aEvent, NotifyOp_Replace ); + } + } + else + throw NoSuchElementException(); + } +} + +void UIConfigurationManagerImpl::removeSettings( const ::rtl::OUString& ResourceURL ) +throw ( NoSuchElementException, IllegalArgumentException, IllegalAccessException, RuntimeException) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else if ( m_bReadOnly ) + throw IllegalAccessException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType ); + if ( pDataSettings ) + { + // If element settings are default, we don't need to change anything! + if ( pDataSettings->bDefault ) + return; + else + { + Reference< XIndexAccess > xRemovedSettings = pDataSettings->xSettings; + pDataSettings->bDefault = true; + + // check if this is a default layer node + if ( !m_bUseDefault || !pDataSettings->bDefaultNode ) + pDataSettings->bModified = true; // we have to remove this node from the user layer! + pDataSettings->xSettings.clear(); + m_bModified = true; // user layer must be written + + // Modify type container + UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType]; + rElementType.bModified = true; + + Reference< XUIConfigurationManager > xThis( m_xOwner, UNO_QUERY ); + // Check if we have settings in the default layer which replaces the user-defined one! + UIElementData* pDefaultDataSettings = m_bUseDefault ? impl_findUIElementData( ResourceURL, nElementType ) : NULL; + if ( pDefaultDataSettings ) + { + // Create event to notify listener about replaced element settings + ConfigurationEvent aEvent; + + aEvent.ResourceURL = ResourceURL; + aEvent.Accessor <<= xThis; + aEvent.Source = m_xOwner; + aEvent.Element <<= xRemovedSettings; + aEvent.ReplacedElement <<= pDefaultDataSettings->xSettings; + + aGuard.unlock(); + + implts_notifyContainerListener( aEvent, NotifyOp_Replace ); + } + else + { + // Create event to notify listener about removed element settings + ConfigurationEvent aEvent; + + aEvent.ResourceURL = ResourceURL; + aEvent.Accessor <<= xThis; + aEvent.Source = m_xOwner; + aEvent.Element <<= xRemovedSettings; + + aGuard.unlock(); + + implts_notifyContainerListener( aEvent, NotifyOp_Remove ); + } + } + } + else + throw NoSuchElementException(); + } +} + +void UIConfigurationManagerImpl::insertSettings( const ::rtl::OUString& NewResourceURL, const Reference< XIndexAccess >& aNewData ) +throw ( ElementExistException, IllegalArgumentException, IllegalAccessException, RuntimeException ) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( NewResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else if ( m_bReadOnly ) + throw IllegalAccessException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + bool bInsertData( false ); + UIElementData aUIElementData; + UIElementData* pDataSettings = impl_findUIElementData( NewResourceURL, nElementType ); + if ( !m_bUseDefault ) + { + if ( pDataSettings && !pDataSettings->bDefault ) + throw ElementExistException(); + if ( !pDataSettings ) + { + pDataSettings = &aUIElementData; + bInsertData = true; + } + } + if ( !pDataSettings || !m_bUseDefault ) + { + aUIElementData.bDefault = false; + if ( !m_bUseDefault ) + aUIElementData.bDefaultNode = false; + aUIElementData.bModified = true; + + // Create a copy of the data if the container is not const + Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY ); + if ( xReplace.is() ) + aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY ); + else + aUIElementData.xSettings = aNewData; + + m_bModified = true; + + UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType]; + rElementType.bModified = true; + + if ( bInsertData ) + { + aUIElementData.aName = RetrieveNameFromResourceURL( NewResourceURL ) + m_aXMLPostfix; + aUIElementData.aResourceURL = NewResourceURL; + UIElementDataHashMap& rElements = rElementType.aElementsHashMap; + rElements.insert( UIElementDataHashMap::value_type( NewResourceURL, aUIElementData )); + } + + Reference< XIndexAccess > xInsertSettings( aUIElementData.xSettings ); + Reference< XUIConfigurationManager > xThis( m_xOwner, UNO_QUERY ); + + // Create event to notify listener about removed element settings + ConfigurationEvent aEvent; + + aEvent.ResourceURL = NewResourceURL; + aEvent.Accessor <<= xThis; + aEvent.Source = m_xOwner; + aEvent.Element <<= xInsertSettings; + + aGuard.unlock(); + + implts_notifyContainerListener( aEvent, NotifyOp_Insert ); + } + else + throw ElementExistException(); + } +} + +Reference< XInterface > UIConfigurationManagerImpl::getImageManager() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( !m_xModuleImageManager.is() ) + { + if ( m_bUseDefault ) + m_xModuleImageManager = Reference< XComponent >( static_cast< cppu::OWeakObject *>( new ModuleImageManager( m_xServiceManager )), + UNO_QUERY ); + else + m_xModuleImageManager = Reference< XComponent >( static_cast< cppu::OWeakObject *>( new ImageManager( m_xServiceManager )), + UNO_QUERY ); + Reference< XInitialization > xInit( m_xModuleImageManager, UNO_QUERY ); + + Sequence< Any > aPropSeq( m_bUseDefault ? 3 : 2 ); + PropertyValue aPropValue; + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserConfigStorage" )); + aPropValue.Value <<= m_xUserConfigStorage; + aPropSeq[0] <<= aPropValue; + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleIdentifier" )); + aPropValue.Value <<= m_aModuleIdentifier; + aPropSeq[1] <<= aPropValue; + if ( m_bUseDefault ) + { + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserRootCommit" )); + aPropValue.Value <<= m_xUserRootCommit; + aPropSeq[2] <<= aPropValue; + } + + xInit->initialize( aPropSeq ); + } + + return Reference< XInterface >( m_xModuleImageManager, UNO_QUERY ); + +// return Reference< XInterface >(); +} + +Reference< XInterface > UIConfigurationManagerImpl::getShortCutManager() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + if ( !m_bUseDefault && m_xAccConfig.is()) + return m_xAccConfig; + + Reference< XMultiServiceFactory > xSMGR = m_xServiceManager; + ::rtl::OUString aModule = m_aModuleIdentifier; + Reference< XStorage > xDocumentRoot = m_xUserConfigStorage; + aGuard.unlock(); + Reference< XInterface > xManager = xSMGR->createInstance(m_bUseDefault ? SERVICENAME_MODULEACCELERATORCONFIGURATION : SERVICENAME_DOCUMENTACCELERATORCONFIGURATION ); + Reference< XInitialization > xInit (xManager, UNO_QUERY_THROW); + + PropertyValue aProp; + Sequence< Any > lArgs(1); + if ( m_bUseDefault ) + { + aProp.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ModuleIdentifier")); + aProp.Value <<= aModule; + } // if ( m_bUseDefault ) + else + { + aProp.Name = ::rtl::OUString::createFromAscii("DocumentRoot"); + aProp.Value <<= xDocumentRoot; + } + lArgs[0] <<= aProp; + xInit->initialize(lArgs); + + if ( !m_bUseDefault ) + { + // SAFE -> + aGuard.lock(); + m_xAccConfig = xManager; + aGuard.unlock(); + // <- SAFE + } + + return xManager; +} + +Reference< XInterface > UIConfigurationManagerImpl::getEventsManager() throw (::com::sun::star::uno::RuntimeException) +{ + return Reference< XInterface >(); +} +// XUIConfigurationStorage +void UIConfigurationManagerImpl::setStorage( const Reference< XStorage >& Storage ) throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( m_xUserConfigStorage.is() ) + { + try + { + // Dispose old storage to be sure that it will be closed + Reference< XComponent > xComponent( m_xUserConfigStorage, UNO_QUERY ); + if ( xComponent.is() ) + xComponent->dispose(); + } + catch ( Exception& ) + { + } + } + + // We store the new storage. Be careful it could be an empty reference! + m_xUserConfigStorage = Storage; + m_bReadOnly = sal_True; + + Reference< XUIConfigurationStorage > xAccUpdate(m_xAccConfig, UNO_QUERY); + if ( xAccUpdate.is() ) + xAccUpdate->setStorage( m_xUserConfigStorage ); + + if ( m_xModuleImageManager.is() ) + { + ImageManager* pImageManager = (ImageManager*)m_xModuleImageManager.get(); + if ( pImageManager ) + pImageManager->setStorage( m_xUserConfigStorage ); + } + + if ( m_xUserConfigStorage.is() ) + { + ::rtl::OUString sEmpty; + for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + { + rtl::OUString aResourceType; + if ( i == ::com::sun::star::ui::UIElementType::MENUBAR ) + aResourceType = PresetHandler::RESOURCETYPE_MENUBAR(); + else if ( i == ::com::sun::star::ui::UIElementType::TOOLBAR ) + aResourceType = PresetHandler::RESOURCETYPE_TOOLBAR(); + else if ( i == ::com::sun::star::ui::UIElementType::STATUSBAR ) + aResourceType = PresetHandler::RESOURCETYPE_STATUSBAR(); + + //if ( aResourceType.getLength() > 0 ) + { + m_pStorageHandler[i] = new PresetHandler( m_xServiceManager ); + m_pStorageHandler[i]->connectToResource( PresetHandler::E_DOCUMENT, + rtl::OUString::createFromAscii( UIELEMENTTYPENAMES[i] ), // this path wont be used later ... seee next lines! + sEmpty, + m_xUserConfigStorage); + } + } + Reference< XPropertySet > xPropSet( m_xUserConfigStorage, UNO_QUERY ); + if ( xPropSet.is() ) + { + try + { + long nOpenMode = 0; + if ( xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenMode" ))) >>= nOpenMode ) + m_bReadOnly = !( nOpenMode & ElementModes::WRITE ); + } + catch ( com::sun::star::beans::UnknownPropertyException& ) + { + } + catch ( com::sun::star::lang::WrappedTargetException& ) + { + } + } + } + + impl_Initialize(); +} +// ----------------------------------------------------------------------------- +sal_Bool UIConfigurationManagerImpl::hasStorage() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + return ( m_xUserConfigStorage.is() ); +} + +// XUIConfigurationManagerImpl +sal_Bool UIConfigurationManagerImpl::isDefaultSettings( const ::rtl::OUString& ResourceURL ) +throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false ); + if ( pDataSettings && pDataSettings->bDefaultNode ) + return sal_True; + } + + return sal_False; +} + +Reference< XIndexAccess > UIConfigurationManagerImpl::getDefaultSettings( const ::rtl::OUString& ResourceURL ) +throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL ); + + if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) || + ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT )) + throw IllegalArgumentException(); + else + { + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + // preload list of element types on demand + impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType ); + + // Look into our default vector/hash_map combination + UIElementDataHashMap& rDefaultHashMap = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap; + UIElementDataHashMap::iterator pIter = rDefaultHashMap.find( ResourceURL ); + if ( pIter != rDefaultHashMap.end() ) + { + if ( !pIter->second.xSettings.is() ) + impl_requestUIElementData( nElementType, LAYER_DEFAULT, pIter->second ); + return pIter->second.xSettings; + } + } + + // Nothing has been found! + throw NoSuchElementException(); +} + +// XUIConfigurationPersistence +void UIConfigurationManagerImpl::reload() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly ) + { + // Try to access our module sub folder + ConfigEventNotifyContainer aRemoveNotifyContainer; + ConfigEventNotifyContainer aReplaceNotifyContainer; + for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + { + try + { + UIElementType& rUserElementType = m_aUIElements[LAYER_USERDEFINED][i]; + UIElementType& rDefaultElementType = m_aUIElements[LAYER_DEFAULT][i]; + + if ( rUserElementType.bModified ) + impl_reloadElementTypeData( rUserElementType, rDefaultElementType, aRemoveNotifyContainer, aReplaceNotifyContainer ); + } + catch ( Exception& ) + { + throw IOException(); + } + } + + m_bModified = sal_False; + + // Unlock mutex before notify our listeners + aGuard.unlock(); + + // Notify our listeners + ::std::for_each(aRemoveNotifyContainer.begin(),aRemoveNotifyContainer.end(),::boost::bind(&UIConfigurationManagerImpl::implts_notifyContainerListener,this,_1,NotifyOp_Remove)); + ::std::for_each(aReplaceNotifyContainer.begin(),aReplaceNotifyContainer.end(),::boost::bind(&UIConfigurationManagerImpl::implts_notifyContainerListener,this,_1,NotifyOp_Replace)); + } +} + +void UIConfigurationManagerImpl::store() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + if ( m_bDisposed ) + throw DisposedException(); + + if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly ) + { + // Try to access our module sub folder + for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + { + try + { + UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i]; + Reference< XStorage > xStorage( rElementType.xStorage, UNO_QUERY ); + + if ( rElementType.bModified && xStorage.is() ) + { + impl_storeElementTypeData( xStorage, rElementType ); + m_pStorageHandler[i]->commitUserChanges(); + } + } + catch ( Exception& ) + { + throw IOException(); + } + } + + m_bModified = false; + } +} + +void UIConfigurationManagerImpl::storeToStorage( const 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_xUserConfigStorage.is() && m_bModified && !m_bReadOnly ) + { + // Try to access our module sub folder + for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ ) + { + try + { + Reference< XStorage > xElementTypeStorage( Storage->openStorageElement( + rtl::OUString::createFromAscii( UIELEMENTTYPENAMES[i] ), ElementModes::READWRITE )); + UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i]; + + if ( rElementType.bModified && xElementTypeStorage.is() ) + impl_storeElementTypeData( xElementTypeStorage, rElementType, false ); // store data to storage, but don't reset modify flag! + } + catch ( Exception& ) + { + throw IOException(); + } + } + + Reference< XTransactedObject > xTransactedObject( Storage, UNO_QUERY ); + if ( xTransactedObject.is() ) + xTransactedObject->commit(); + } +} + +sal_Bool UIConfigurationManagerImpl::isModified() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + return m_bModified; +} + +sal_Bool UIConfigurationManagerImpl::isReadOnly() throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + return m_bReadOnly; +} + +void UIConfigurationManagerImpl::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(); + } + } + } +} + +} // namespace framework diff --git a/framework/source/uiconfiguration/uiconfigurationmanagerimpl.hxx b/framework/source/uiconfiguration/uiconfigurationmanagerimpl.hxx new file mode 100755 index 000000000000..3d726ba3dfa0 --- /dev/null +++ b/framework/source/uiconfiguration/uiconfigurationmanagerimpl.hxx @@ -0,0 +1,221 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: UIConfigurationManagerImpl.hxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __FRAMEWORK_UICONFIGURATION_UICONFIGMANAGERIMPL_HXX_ +#define __FRAMEWORK_UICONFIGURATION_UICONFIGMANAGERIMPL_HXX_ + + +/** Attention: stl headers must(!) be included at first. Otherwhise it can make trouble + with solaris headers ... +*/ +#include <vector> +#include <list> +#include <hash_map> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <accelerators/presethandler.hxx> +#include <threadhelp/threadhelpbase.hxx> +#include <macros/generic.hxx> +#include <macros/xinterface.hxx> +#include <macros/xtypeprovider.hxx> +#include <macros/xserviceinfo.hxx> +#include <stdtypes.h> +#include <uiconfiguration/moduleimagemanager.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/ui/XUIConfigurationPersistence.hpp> +#include <com/sun/star/ui/XUIConfiguration.hpp> +#include <com/sun/star/ui/XUIConfigurationManager.hpp> +#include <com/sun/star/ui/UIElementType.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/ui/ConfigurationEvent.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <cppuhelper/weak.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <rtl/ustring.hxx> + + +namespace framework +{ + class UIConfigurationManagerImpl : public ThreadHelpBase // Struct for right initalization of mutex member! Must be first of baseclasses. + { + public: + // XInterface, XTypeProvider, XServiceInfo + UIConfigurationManagerImpl( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager + , const com::sun::star::uno::Reference< com::sun::star::uno::XInterface >& _xOwner + , bool _bUseDefault); + ~UIConfigurationManagerImpl(); + + // XComponent + void dispose() throw (::com::sun::star::uno::RuntimeException); + void addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + void removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + + // XInitialization + void initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XUIConfiguration + void addConfigurationListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >& Listener ) throw (::com::sun::star::uno::RuntimeException); + void removeConfigurationListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >& Listener ) throw (::com::sun::star::uno::RuntimeException); + + // XUIConfigurationManager + void reset() throw (::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > > getUIElementsInfo( sal_Int16 ElementType ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > createSettings( ) throw (::com::sun::star::uno::RuntimeException); + sal_Bool hasSettings( const ::rtl::OUString& ResourceURL ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > getSettings( const ::rtl::OUString& ResourceURL, sal_Bool bWriteable ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + void replaceSettings( const ::rtl::OUString& ResourceURL, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& aNewData ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException); + void removeSettings( const ::rtl::OUString& ResourceURL ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException); + void insertSettings( const ::rtl::OUString& NewResourceURL, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& aNewData ) throw (::com::sun::star::container::ElementExistException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > getImageManager() throw (::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > getShortCutManager() throw (::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > getEventsManager() throw (::com::sun::star::uno::RuntimeException); + + // XUIConfigurationManagerImpl + sal_Bool isDefaultSettings( const ::rtl::OUString& ResourceURL ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > getDefaultSettings( const ::rtl::OUString& ResourceURL ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + // XUIConfigurationPersistence + void reload() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + void store() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + void storeToStorage( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& Storage ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + sal_Bool isModified() throw (::com::sun::star::uno::RuntimeException); + sal_Bool isReadOnly() throw (::com::sun::star::uno::RuntimeException); + + // XUIConfigurationStorage + void setStorage( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& Storage ) throw (::com::sun::star::uno::RuntimeException); + sal_Bool hasStorage() throw (::com::sun::star::uno::RuntimeException); + + enum Layer + { + LAYER_DEFAULT, + LAYER_USERDEFINED, + LAYER_COUNT + }; + + enum NotifyOp + { + NotifyOp_Remove, + NotifyOp_Insert, + NotifyOp_Replace + }; + + struct UIElementInfo + { + UIElementInfo( const rtl::OUString& rResourceURL, const rtl::OUString& rUIName ) : + aResourceURL( rResourceURL), aUIName( rUIName ) {} + rtl::OUString aResourceURL; + rtl::OUString aUIName; + }; + + struct UIElementData + { + UIElementData() : bModified( false ), bDefault( true ), bDefaultNode( true ) {}; + + rtl::OUString aResourceURL; + rtl::OUString aName; + bool bModified; // has been changed since last storing + bool bDefault; // default settings + bool bDefaultNode; // this is a default layer element data + com::sun::star::uno::Reference< com::sun::star::container::XIndexAccess > xSettings; + }; + + struct UIElementType; + friend struct UIElementType; + typedef ::std::hash_map< rtl::OUString, UIElementData, OUStringHashCode, ::std::equal_to< rtl::OUString > > UIElementDataHashMap; + + struct UIElementType + { + UIElementType() : bModified( false ), + bLoaded( false ), + bDefaultLayer( false ), + nElementType( ::com::sun::star::ui::UIElementType::UNKNOWN ) {} + + + bool bModified; + bool bLoaded; + bool bDefaultLayer; + sal_Int16 nElementType; + UIElementDataHashMap aElementsHashMap; + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > xStorage; + }; + + typedef ::std::vector< UIElementType > UIElementTypesVector; + typedef ::std::vector< ::com::sun::star::ui::ConfigurationEvent > ConfigEventNotifyContainer; + typedef ::std::hash_map< rtl::OUString, UIElementInfo, OUStringHashCode, ::std::equal_to< rtl::OUString > > UIElementInfoHashMap; + + // private methods + void impl_Initialize(); + void implts_notifyContainerListener( const ::com::sun::star::ui::ConfigurationEvent& aEvent, NotifyOp eOp ); + void impl_fillSequenceWithElementTypeInfo( UIElementInfoHashMap& aUIElementInfoCollection, sal_Int16 nElementType ); + void impl_preloadUIElementTypeList( Layer eLayer, sal_Int16 nElementType ); + UIElementData* impl_findUIElementData( const rtl::OUString& aResourceURL, sal_Int16 nElementType, bool bLoad = true ); + void impl_requestUIElementData( sal_Int16 nElementType, Layer eLayer, UIElementData& aUIElementData ); + void impl_storeElementTypeData( com::sun::star::uno::Reference< com::sun::star::embed::XStorage > xStorage, UIElementType& rElementType, bool bResetModifyState = true ); + void impl_resetElementTypeData( UIElementType& rUserElementType, UIElementType& rDefaultElementType, ConfigEventNotifyContainer& rRemoveNotifyContainer, ConfigEventNotifyContainer& rReplaceNotifyContainer ); + void impl_reloadElementTypeData( UIElementType& rUserElementType, UIElementType& rDefaultElementType, ConfigEventNotifyContainer& rRemoveNotifyContainer, ConfigEventNotifyContainer& rReplaceNotifyContainer ); + + UIElementTypesVector m_aUIElements[LAYER_COUNT]; + PresetHandler* m_pStorageHandler[::com::sun::star::ui::UIElementType::COUNT]; + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > m_xDefaultConfigStorage; + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > m_xUserConfigStorage; + com::sun::star::uno::Reference< com::sun::star::uno::XInterface > m_xOwner; + bool m_bUseDefault; + bool m_bReadOnly; + bool m_bInitialized; + bool m_bModified; + bool m_bConfigRead; + bool m_bDisposed; + rtl::OUString m_aXMLPostfix; + rtl::OUString m_aPropUIName; + rtl::OUString m_aPropResourceURL; + rtl::OUString m_aModuleIdentifier; + rtl::OUString m_aModuleShortName; + com::sun::star::uno::Reference< com::sun::star::embed::XTransactedObject > m_xUserRootCommit; + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > m_xServiceManager; + ::cppu::OMultiTypeInterfaceContainerHelper m_aListenerContainer; /// container for ALL Listener + com::sun::star::uno::Reference< com::sun::star::uno::XInterface > m_xAccConfig; + com::sun::star::uno::Reference< com::sun::star::lang::XComponent > m_xModuleImageManager; + }; +} + +#endif // __FRAMEWORK_UICONFIGURATION_UICONFIGMANAGERIMPL_HXX_ diff --git a/framework/source/uiconfiguration/windowstateconfiguration.cxx b/framework/source/uiconfiguration/windowstateconfiguration.cxx new file mode 100644 index 000000000000..ddf3cee7f848 --- /dev/null +++ b/framework/source/uiconfiguration/windowstateconfiguration.cxx @@ -0,0 +1,1493 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: windowstateconfiguration.cxx,v $ + * $Revision: 1.14 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include "uiconfiguration/windowstateconfiguration.hxx" +#include <threadhelp/resetableguard.hxx> +#include "services.h" + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XContainer.hpp> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/ui/DockingArea.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ +#include <rtl/ustrbuf.hxx> +#include <cppuhelper/weak.hxx> +#include <tools/debug.hxx> + +//_________________________________________________________________________________________________________________ +// Defines +//_________________________________________________________________________________________________________________ +// + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::util; +using namespace com::sun::star::container; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::ui; + +//_________________________________________________________________________________________________________________ +// Namespace +//_________________________________________________________________________________________________________________ +// + +static const char CONFIGURATION_ROOT_ACCESS[] = "/org.openoffice.Office.UI."; +static const char CONFIGURATION_WINDOWSTATE_ACCESS[] = "/UIElements/States"; + +static const char CONFIGURATION_PROPERTY_LOCKED[] = WINDOWSTATE_PROPERTY_LOCKED; +static const char CONFIGURATION_PROPERTY_DOCKED[] = WINDOWSTATE_PROPERTY_DOCKED; +static const char CONFIGURATION_PROPERTY_VISIBLE[] = WINDOWSTATE_PROPERTY_VISIBLE; +static const char CONFIGURATION_PROPERTY_DOCKINGAREA[] = WINDOWSTATE_PROPERTY_DOCKINGAREA; +static const char CONFIGURATION_PROPERTY_DOCKPOS[] = WINDOWSTATE_PROPERTY_DOCKPOS; +static const char CONFIGURATION_PROPERTY_DOCKSIZE[] = WINDOWSTATE_PROPERTY_DOCKSIZE; +static const char CONFIGURATION_PROPERTY_POS[] = WINDOWSTATE_PROPERTY_POS; +static const char CONFIGURATION_PROPERTY_SIZE[] = WINDOWSTATE_PROPERTY_SIZE; +static const char CONFIGURATION_PROPERTY_UINAME[] = WINDOWSTATE_PROPERTY_UINAME; +static const char CONFIGURATION_PROPERTY_INTERNALSTATE[] = WINDOWSTATE_PROPERTY_INTERNALSTATE; +static const char CONFIGURATION_PROPERTY_STYLE[] = WINDOWSTATE_PROPERTY_STYLE; +static const char CONFIGURATION_PROPERTY_CONTEXT[] = WINDOWSTATE_PROPERTY_CONTEXT; +static const char CONFIGURATION_PROPERTY_HIDEFROMMENU[] = WINDOWSTATE_PROPERTY_HIDEFROMENU; +static const char CONFIGURATION_PROPERTY_NOCLOSE[] = WINDOWSTATE_PROPERTY_NOCLOSE; +static const char CONFIGURATION_PROPERTY_SOFTCLOSE[] = WINDOWSTATE_PROPERTY_SOFTCLOSE; +static const char CONFIGURATION_PROPERTY_CONTEXTACTIVE[] = WINDOWSTATE_PROPERTY_CONTEXTACTIVE; + +// Zero based indexes, order must be the same as WindowStateMask && CONFIGURATION_PROPERTIES! +static const sal_Int16 PROPERTY_LOCKED = 0; +static const sal_Int16 PROPERTY_DOCKED = 1; +static const sal_Int16 PROPERTY_VISIBLE = 2; +static const sal_Int16 PROPERTY_CONTEXT = 3; +static const sal_Int16 PROPERTY_HIDEFROMMENU = 4; +static const sal_Int16 PROPERTY_NOCLOSE = 5; +static const sal_Int16 PROPERTY_SOFTCLOSE = 6; +static const sal_Int16 PROPERTY_CONTEXTACTIVE = 7; +static const sal_Int16 PROPERTY_DOCKINGAREA = 8; +static const sal_Int16 PROPERTY_POS = 9; +static const sal_Int16 PROPERTY_SIZE = 10; +static const sal_Int16 PROPERTY_UINAME = 11; +static const sal_Int16 PROPERTY_INTERNALSTATE = 12; +static const sal_Int16 PROPERTY_STYLE = 13; +static const sal_Int16 PROPERTY_DOCKPOS = 14; +static const sal_Int16 PROPERTY_DOCKSIZE = 15; + +// Order must be the same as WindowStateMask!! +static const char* CONFIGURATION_PROPERTIES[] = +{ + CONFIGURATION_PROPERTY_LOCKED, + CONFIGURATION_PROPERTY_DOCKED, + CONFIGURATION_PROPERTY_VISIBLE, + CONFIGURATION_PROPERTY_CONTEXT, + CONFIGURATION_PROPERTY_HIDEFROMMENU, + CONFIGURATION_PROPERTY_NOCLOSE, + CONFIGURATION_PROPERTY_SOFTCLOSE, + CONFIGURATION_PROPERTY_CONTEXTACTIVE, + CONFIGURATION_PROPERTY_DOCKINGAREA, + CONFIGURATION_PROPERTY_POS, + CONFIGURATION_PROPERTY_SIZE, + CONFIGURATION_PROPERTY_UINAME, + CONFIGURATION_PROPERTY_INTERNALSTATE, + CONFIGURATION_PROPERTY_STYLE, + CONFIGURATION_PROPERTY_DOCKPOS, + CONFIGURATION_PROPERTY_DOCKSIZE, + 0 +}; + +namespace framework +{ + +//***************************************************************************************************************** +// Configuration access class for WindowState supplier implementation +//***************************************************************************************************************** + +class ConfigurationAccess_WindowState : // interfaces + public XTypeProvider , + public XNameContainer , + public XContainerListener , + // baseclasses + // Order is neccessary for right initialization! + private ThreadHelpBase , + public ::cppu::OWeakObject +{ + public: + ConfigurationAccess_WindowState( const ::rtl::OUString& aWindowStateConfigFile, const Reference< XMultiServiceFactory >& rServiceManager ); + virtual ~ConfigurationAccess_WindowState(); + + // XInterface, XTypeProvider + FWK_DECLARE_XINTERFACE + FWK_DECLARE_XTYPEPROVIDER + + // XNameAccess + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) + throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames() + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) + throw (::com::sun::star::uno::RuntimeException); + + // XNameContainer + virtual void SAL_CALL removeByName( const ::rtl::OUString& sName ) + throw(css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException ); + + virtual void SAL_CALL insertByName( const ::rtl::OUString& sName, const css::uno::Any& aPropertySet ) + throw(css::lang::IllegalArgumentException, css::container::ElementExistException, css::lang::WrappedTargetException, css::uno::RuntimeException ); + + // XNameReplace + virtual void SAL_CALL replaceByName( const ::rtl::OUString& sName, const css::uno::Any& aPropertySet ) + throw(css::lang::IllegalArgumentException, css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException ); + + // XElementAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType() + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL hasElements() + throw (::com::sun::star::uno::RuntimeException); + + // container.XContainerListener + virtual void SAL_CALL elementInserted( const ContainerEvent& aEvent ) throw(RuntimeException); + virtual void SAL_CALL elementRemoved ( const ContainerEvent& aEvent ) throw(RuntimeException); + virtual void SAL_CALL elementReplaced( const ContainerEvent& aEvent ) throw(RuntimeException); + + // lang.XEventListener + virtual void SAL_CALL disposing( const EventObject& aEvent ) throw(RuntimeException); + + protected: + enum WindowStateMask + { + WINDOWSTATE_MASK_LOCKED = 1, + WINDOWSTATE_MASK_DOCKED = 2, + WINDOWSTATE_MASK_VISIBLE = 4, + WINDOWSTATE_MASK_CONTEXT = 8, + WINDOWSTATE_MASK_HIDEFROMMENU = 16, + WINDOWSTATE_MASK_NOCLOSE = 32, + WINDOWSTATE_MASK_SOFTCLOSE = 64, + WINDOWSTATE_MASK_CONTEXTACTIVE = 128, + WINDOWSTATE_MASK_DOCKINGAREA = 256, + WINDOWSTATE_MASK_POS = 512, + WINDOWSTATE_MASK_SIZE = 1024, + WINDOWSTATE_MASK_UINAME = 2048, + WINDOWSTATE_MASK_INTERNALSTATE = 4096, + WINDOWSTATE_MASK_STYLE = 8192, + WINDOWSTATE_MASK_DOCKPOS = 16384, + WINDOWSTATE_MASK_DOCKSIZE = 32768 + }; + + // Cache structure. Valid values are described by tje eMask member. All other values should not be + // provided to outside code! + struct WindowStateInfo + { + WindowStateInfo() : aDockingArea( ::com::sun::star::ui::DockingArea_DOCKINGAREA_TOP ), + aDockPos( 0, 0 ), + aPos( 0, 0 ), + aSize( 0, 0 ), + nInternalState( 0 ), + nStyle( 0 ), + nMask( 0 ) {} + + bool bLocked : 1, + bDocked : 1, + bVisible : 1, + bContext : 1, + bHideFromMenu : 1, + bNoClose : 1, + bSoftClose : 1, + bContextActive : 1; + ::com::sun::star::ui::DockingArea aDockingArea; + com::sun::star::awt::Point aDockPos; + com::sun::star::awt::Size aDockSize; + com::sun::star::awt::Point aPos; + com::sun::star::awt::Size aSize; + rtl::OUString aUIName; + sal_uInt32 nInternalState; + sal_uInt16 nStyle; + sal_uInt32 nMask; // see WindowStateMask + }; + + void impl_putPropertiesFromStruct( const WindowStateInfo& rWinStateInfo, Reference< XPropertySet >& xPropSet ); + Any impl_insertCacheAndReturnSequence( const rtl::OUString& rResourceURL, Reference< XNameAccess >& rNameAccess ); + WindowStateInfo& impl_insertCacheAndReturnWinState( const rtl::OUString& rResourceURL, Reference< XNameAccess >& rNameAccess ); + Any impl_getSequenceFromStruct( const WindowStateInfo& rWinStateInfo ); + void impl_fillStructFromSequence( WindowStateInfo& rWinStateInfo, const Sequence< PropertyValue >& rSeq ); + Any impl_getWindowStateFromResourceURL( const rtl::OUString& rResourceURL ); + sal_Bool impl_initializeConfigAccess(); + + private: + typedef ::std::hash_map< ::rtl::OUString, + WindowStateInfo, + OUStringHashCode, + ::std::equal_to< ::rtl::OUString > > ResourceURLToInfoCache; + + rtl::OUString m_aConfigWindowAccess; + Reference< XMultiServiceFactory > m_xServiceManager; + Reference< XMultiServiceFactory > m_xConfigProvider; + Reference< XNameAccess > m_xConfigAccess; + ResourceURLToInfoCache m_aResourceURLToInfoCache; + sal_Bool m_bConfigAccessInitialized : 1, + m_bModified : 1; + std::vector< ::rtl::OUString > m_aPropArray; +}; + +//***************************************************************************************************************** +// XInterface, XTypeProvider +//***************************************************************************************************************** +DEFINE_XINTERFACE_7 ( ConfigurationAccess_WindowState , + OWeakObject , + DIRECT_INTERFACE ( css::container::XNameContainer ), + DIRECT_INTERFACE ( css::container::XContainerListener ), + DIRECT_INTERFACE ( css::lang::XTypeProvider ), + DERIVED_INTERFACE( css::container::XElementAccess, css::container::XNameAccess ), + DERIVED_INTERFACE( css::container::XNameAccess, css::container::XNameReplace ), + DERIVED_INTERFACE( css::container::XNameReplace, css::container::XNameContainer ), + DERIVED_INTERFACE( css::lang::XEventListener, XContainerListener ) + ) + +DEFINE_XTYPEPROVIDER_7 ( ConfigurationAccess_WindowState , + css::container::XNameContainer , + css::container::XNameReplace , + css::container::XNameAccess , + css::container::XElementAccess , + css::container::XContainerListener , + css::lang::XEventListener , + css::lang::XTypeProvider + ) + +ConfigurationAccess_WindowState::ConfigurationAccess_WindowState( const rtl::OUString& aModuleName, const Reference< XMultiServiceFactory >& rServiceManager ) : + ThreadHelpBase(), + m_aConfigWindowAccess( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_ROOT_ACCESS )), + m_xServiceManager( rServiceManager ), + m_bConfigAccessInitialized( sal_False ), + m_bModified( sal_False ) +{ + // Create configuration hierachical access name + m_aConfigWindowAccess += aModuleName; + m_aConfigWindowAccess += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_WINDOWSTATE_ACCESS )); + m_xConfigProvider = Reference< XMultiServiceFactory >( rServiceManager->createInstance( SERVICENAME_CFGPROVIDER ), UNO_QUERY ); + + // Initialize access array with property names. + sal_Int32 n = 0; + while ( CONFIGURATION_PROPERTIES[n] ) + { + m_aPropArray.push_back( ::rtl::OUString::createFromAscii( CONFIGURATION_PROPERTIES[n] )); + ++n; + } +} + +ConfigurationAccess_WindowState::~ConfigurationAccess_WindowState() +{ + // SAFE + ResetableGuard aLock( m_aLock ); + Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY ); + if ( xContainer.is() ) + xContainer->removeContainerListener( this ); +} + +// XNameAccess +Any SAL_CALL ConfigurationAccess_WindowState::getByName( const ::rtl::OUString& rResourceURL ) +throw ( NoSuchElementException, WrappedTargetException, RuntimeException) +{ + // SAFE + ResetableGuard aLock( m_aLock ); + + ResourceURLToInfoCache::const_iterator pIter = m_aResourceURLToInfoCache.find( rResourceURL ); + if ( pIter != m_aResourceURLToInfoCache.end() ) + return impl_getSequenceFromStruct( pIter->second ); + else + { + Any a( impl_getWindowStateFromResourceURL( rResourceURL ) ); + if ( a == Any() ) + throw NoSuchElementException(); + else + return a; + } +} + +Sequence< ::rtl::OUString > SAL_CALL ConfigurationAccess_WindowState::getElementNames() +throw ( RuntimeException ) +{ + // SAFE + ResetableGuard aLock( m_aLock ); + + if ( !m_bConfigAccessInitialized ) + { + impl_initializeConfigAccess(); + m_bConfigAccessInitialized = sal_True; + } + + if ( m_xConfigAccess.is() ) + return m_xConfigAccess->getElementNames(); + else + return Sequence< ::rtl::OUString > (); +} + +sal_Bool SAL_CALL ConfigurationAccess_WindowState::hasByName( const ::rtl::OUString& rResourceURL ) +throw (::com::sun::star::uno::RuntimeException) +{ + try + { + getByName( rResourceURL ); + } + catch ( NoSuchElementException& ) + { + return sal_False; + } + + return sal_True; +} + +// XElementAccess +Type SAL_CALL ConfigurationAccess_WindowState::getElementType() +throw ( RuntimeException ) +{ + return( ::getCppuType( (const Sequence< PropertyValue >*)NULL ) ); +} + +sal_Bool SAL_CALL ConfigurationAccess_WindowState::hasElements() +throw ( RuntimeException ) +{ + // SAFE + ResetableGuard aLock( m_aLock ); + + if ( !m_bConfigAccessInitialized ) + { + impl_initializeConfigAccess(); + m_bConfigAccessInitialized = sal_True; + } + + if ( m_xConfigAccess.is() ) + return m_xConfigAccess->hasElements(); + else + return sal_False; +} + +// XNameContainer +void SAL_CALL ConfigurationAccess_WindowState::removeByName( const ::rtl::OUString& rResourceURL ) +throw( NoSuchElementException, WrappedTargetException, RuntimeException ) +{ + // SAFE + ResetableGuard aLock( m_aLock ); + + ResourceURLToInfoCache::iterator pIter = m_aResourceURLToInfoCache.find( rResourceURL ); + if ( pIter != m_aResourceURLToInfoCache.end() ) + m_aResourceURLToInfoCache.erase( pIter ); + + if ( !m_bConfigAccessInitialized ) + { + impl_initializeConfigAccess(); + m_bConfigAccessInitialized = sal_True; + } + + try + { + // Remove must be write-through => remove element from configuration + Reference< XNameContainer > xNameContainer( m_xConfigAccess, UNO_QUERY ); + if ( xNameContainer.is() ) + { + aLock.unlock(); + + xNameContainer->removeByName( rResourceURL ); + Reference< XChangesBatch > xFlush( m_xConfigAccess, UNO_QUERY ); + if ( xFlush.is() ) + xFlush->commitChanges(); + } + } + catch ( com::sun::star::lang::WrappedTargetException& ) + { + } +} + +void SAL_CALL ConfigurationAccess_WindowState::insertByName( const ::rtl::OUString& rResourceURL, const css::uno::Any& aPropertySet ) +throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException ) +{ + // SAFE + ResetableGuard aLock( m_aLock ); + + Sequence< PropertyValue > aPropSet; + if ( aPropertySet >>= aPropSet ) + { + ResourceURLToInfoCache::const_iterator pIter = m_aResourceURLToInfoCache.find( rResourceURL ); + if ( pIter != m_aResourceURLToInfoCache.end() ) + throw ElementExistException(); + else + { + if ( !m_bConfigAccessInitialized ) + { + impl_initializeConfigAccess(); + m_bConfigAccessInitialized = sal_True; + } + + // Try to ask our configuration access + if ( m_xConfigAccess.is() ) + { + if ( m_xConfigAccess->hasByName( rResourceURL ) ) + throw ElementExistException(); + else + { + WindowStateInfo aWinStateInfo; + impl_fillStructFromSequence( aWinStateInfo, aPropSet ); + m_aResourceURLToInfoCache.insert( ResourceURLToInfoCache::value_type( rResourceURL, aWinStateInfo )); + + // insert must be write-through => insert element into configuration + Reference< XNameContainer > xNameContainer( m_xConfigAccess, UNO_QUERY ); + if ( xNameContainer.is() ) + { + Reference< XSingleServiceFactory > xFactory( m_xConfigAccess, UNO_QUERY ); + aLock.unlock(); + + try + { + Reference< XPropertySet > xPropSet( xFactory->createInstance(), UNO_QUERY ); + if ( xPropSet.is() ) + { + Any a; + impl_putPropertiesFromStruct( aWinStateInfo, xPropSet ); + a <<= xPropSet; + xNameContainer->insertByName( rResourceURL, a ); + Reference< XChangesBatch > xFlush( xFactory, UNO_QUERY ); + if ( xFlush.is() ) + xFlush->commitChanges(); + } + } + catch ( Exception& ) + { + } + } + } + } + } + } + else + throw IllegalArgumentException(); +} + +// XNameReplace +void SAL_CALL ConfigurationAccess_WindowState::replaceByName( const ::rtl::OUString& rResourceURL, const css::uno::Any& aPropertySet ) +throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException ) +{ + // SAFE + ResetableGuard aLock( m_aLock ); + + Sequence< PropertyValue > aPropSet; + if ( aPropertySet >>= aPropSet ) + { + ResourceURLToInfoCache::iterator pIter = m_aResourceURLToInfoCache.find( rResourceURL ); + if ( pIter != m_aResourceURLToInfoCache.end() ) + { + WindowStateInfo& rWinStateInfo = pIter->second; + impl_fillStructFromSequence( rWinStateInfo, aPropSet ); + m_bModified = sal_True; + } + else + { + if ( !m_bConfigAccessInitialized ) + { + impl_initializeConfigAccess(); + m_bConfigAccessInitialized = sal_True; + } + + // Try to ask our configuration access + Reference< XNameAccess > xNameAccess; + Any a( m_xConfigAccess->getByName( rResourceURL )); + + if ( a >>= xNameAccess ) + { + WindowStateInfo& rWinStateInfo( impl_insertCacheAndReturnWinState( rResourceURL, xNameAccess )); + impl_fillStructFromSequence( rWinStateInfo, aPropSet ); + m_bModified = sal_True; + pIter = m_aResourceURLToInfoCache.find( rResourceURL ); + } + else + throw NoSuchElementException(); + } + + if ( m_bModified && pIter != m_aResourceURLToInfoCache.end() ) + { + Reference< XNameContainer > xNameContainer( m_xConfigAccess, UNO_QUERY ); + if ( xNameContainer.is() ) + { + WindowStateInfo aWinStateInfo( pIter->second ); + ::rtl::OUString aResourceURL( pIter->first ); + m_bModified = sal_False; + aLock.unlock(); + + try + { + Reference< XPropertySet > xPropSet; + if ( xNameContainer->getByName( aResourceURL ) >>= xPropSet ) + { + impl_putPropertiesFromStruct( aWinStateInfo, xPropSet ); + + Reference< XChangesBatch > xFlush( m_xConfigAccess, UNO_QUERY ); + if ( xFlush.is() ) + xFlush->commitChanges(); + } + } + catch ( Exception& ) + { + } + } + } + } + else + throw IllegalArgumentException(); +} + +// container.XContainerListener +void SAL_CALL ConfigurationAccess_WindowState::elementInserted( const ContainerEvent& ) throw(RuntimeException) +{ + // do nothing - next time someone wants to retrieve this node we will find it in the configuration +} + +void SAL_CALL ConfigurationAccess_WindowState::elementRemoved ( const ContainerEvent& ) throw(RuntimeException) +{ + // +} + +void SAL_CALL ConfigurationAccess_WindowState::elementReplaced( const ContainerEvent& ) throw(RuntimeException) +{ + // +} + +// lang.XEventListener +void SAL_CALL ConfigurationAccess_WindowState::disposing( const EventObject& aEvent ) throw(RuntimeException) +{ + // SAFE + // remove our reference to the config access + ResetableGuard aLock( m_aLock ); + + Reference< XInterface > xIfac1( aEvent.Source, UNO_QUERY ); + Reference< XInterface > xIfac2( m_xConfigAccess, UNO_QUERY ); + if ( xIfac1 == xIfac2 ) + m_xConfigAccess.clear(); +} + +// private helper methods +Any ConfigurationAccess_WindowState::impl_getSequenceFromStruct( const WindowStateInfo& rWinStateInfo ) +{ + sal_Int32 i( 0 ); + sal_Int32 nCount( m_aPropArray.size() ); + Sequence< PropertyValue > aPropSeq; + + for ( i = 0; i < nCount; i++ ) + { + if ( rWinStateInfo.nMask & ( 1 << i )) + { + // put value into the return sequence + sal_Int32 nIndex( aPropSeq.getLength()); + aPropSeq.realloc( nIndex+1 ); + aPropSeq[nIndex].Name = m_aPropArray[i]; + + switch ( i ) + { + case PROPERTY_LOCKED: + aPropSeq[nIndex].Value = makeAny( rWinStateInfo.bLocked ); break; + case PROPERTY_DOCKED: + aPropSeq[nIndex].Value = makeAny( rWinStateInfo.bDocked ); break; + case PROPERTY_VISIBLE: + aPropSeq[nIndex].Value = makeAny( rWinStateInfo.bVisible ); break; + case PROPERTY_CONTEXT: + aPropSeq[nIndex].Value = makeAny( rWinStateInfo.bContext ); break; + case PROPERTY_HIDEFROMMENU: + aPropSeq[nIndex].Value = makeAny( rWinStateInfo.bHideFromMenu ); break; + case PROPERTY_NOCLOSE: + aPropSeq[nIndex].Value = makeAny( rWinStateInfo.bNoClose ); break; + case PROPERTY_SOFTCLOSE: + aPropSeq[nIndex].Value = makeAny( rWinStateInfo.bSoftClose ); break; + case PROPERTY_CONTEXTACTIVE: + aPropSeq[nIndex].Value = makeAny( rWinStateInfo.bContextActive ); break; + case PROPERTY_DOCKINGAREA: + aPropSeq[nIndex].Value = makeAny( rWinStateInfo.aDockingArea ); break; + case PROPERTY_POS: + aPropSeq[nIndex].Value = makeAny( rWinStateInfo.aPos ); break; + case PROPERTY_SIZE: + aPropSeq[nIndex].Value = makeAny( rWinStateInfo.aSize ); break; + case PROPERTY_UINAME: + aPropSeq[nIndex].Value = makeAny( rWinStateInfo.aUIName ); break; + case PROPERTY_INTERNALSTATE: + aPropSeq[nIndex].Value = makeAny( sal_Int32( rWinStateInfo.nInternalState )); break; + case PROPERTY_STYLE: + aPropSeq[nIndex].Value = makeAny( sal_Int16( rWinStateInfo.nStyle )); break; + case PROPERTY_DOCKPOS: + aPropSeq[nIndex].Value = makeAny( rWinStateInfo.aDockPos ); break; + case PROPERTY_DOCKSIZE: + aPropSeq[nIndex].Value = makeAny( rWinStateInfo.aDockSize ); break; + default: + DBG_ASSERT( sal_False, "Wrong value for ConfigurationAccess_WindowState. Who has forgotten to add this new property!" ); + } + } + } + + return makeAny( aPropSeq ); +} + +Any ConfigurationAccess_WindowState::impl_insertCacheAndReturnSequence( const rtl::OUString& rResourceURL, Reference< XNameAccess >& xNameAccess ) +{ + sal_Int32 nMask( 0 ); + sal_Int32 nCount( m_aPropArray.size() ); + sal_Int32 i( 0 ); + sal_Int32 nIndex( 0 ); + Sequence< PropertyValue > aPropSeq; + WindowStateInfo aWindowStateInfo; + + for ( i = 0; i < nCount; i++ ) + { + try + { + bool bAddToSeq( false ); + Any a( xNameAccess->getByName( m_aPropArray[i] ) ); + switch ( i ) + { + case PROPERTY_LOCKED: + case PROPERTY_DOCKED: + case PROPERTY_VISIBLE: + case PROPERTY_CONTEXT: + case PROPERTY_HIDEFROMMENU: + case PROPERTY_NOCLOSE: + case PROPERTY_SOFTCLOSE: + case PROPERTY_CONTEXTACTIVE: + { + sal_Bool bValue = sal_Bool(); + if ( a >>= bValue ) + { + sal_Int32 nValue( 1 << i ); + nMask |= nValue; + bAddToSeq = true; + switch ( i ) + { + case PROPERTY_LOCKED: + aWindowStateInfo.bLocked = bValue; break; + case PROPERTY_DOCKED: + aWindowStateInfo.bDocked = bValue; break; + case PROPERTY_VISIBLE: + aWindowStateInfo.bVisible = bValue; break; + case PROPERTY_CONTEXT: + aWindowStateInfo.bContext = bValue; break; + case PROPERTY_HIDEFROMMENU: + aWindowStateInfo.bHideFromMenu = bValue; break; + case PROPERTY_NOCLOSE: + aWindowStateInfo.bNoClose = bValue; break; + case PROPERTY_SOFTCLOSE: + aWindowStateInfo.bSoftClose = bValue; break; + case PROPERTY_CONTEXTACTIVE: + aWindowStateInfo.bContextActive = bValue; break; + } + } + } + break; + + case PROPERTY_DOCKINGAREA: + { + sal_Int32 nDockingArea = 0; + if ( a >>= nDockingArea ) + { + if (( nDockingArea >= 0 ) && + ( nDockingArea <= sal_Int32( DockingArea_DOCKINGAREA_RIGHT ))) + { + aWindowStateInfo.aDockingArea = (DockingArea)nDockingArea; + nMask |= WINDOWSTATE_MASK_DOCKINGAREA; + a = makeAny( aWindowStateInfo.aDockingArea ); + bAddToSeq = true; + } + } + } + break; + + case PROPERTY_POS: + case PROPERTY_DOCKPOS: + { + ::rtl::OUString aString; + if ( a >>= aString ) + { + sal_Int32 nToken( 0 ); + ::rtl::OUString aXStr = aString.getToken( 0, ',', nToken ); + if ( nToken > 0 ) + { + com::sun::star::awt::Point aPos; + aPos.X = aXStr.toInt32(); + aPos.Y = aString.getToken( 0, ',', nToken ).toInt32(); + + if ( i == PROPERTY_POS ) + { + aWindowStateInfo.aPos = aPos; + nMask |= WINDOWSTATE_MASK_POS; + } + else + { + aWindowStateInfo.aDockPos = aPos; + nMask |= WINDOWSTATE_MASK_DOCKPOS; + } + + a <<= aPos; + bAddToSeq = true; + } + } + } + break; + + case PROPERTY_SIZE: + case PROPERTY_DOCKSIZE: + { + ::rtl::OUString aString; + if ( a >>= aString ) + { + sal_Int32 nToken( 0 ); + ::rtl::OUString aStr = aString.getToken( 0, ',', nToken ); + if ( nToken > 0 ) + { + com::sun::star::awt::Size aSize; + aSize.Width = aStr.toInt32(); + aSize.Height = aString.getToken( 0, ',', nToken ).toInt32(); + if ( i == PROPERTY_SIZE ) + { + aWindowStateInfo.aSize = aSize; + nMask |= WINDOWSTATE_MASK_SIZE; + } + else + { + aWindowStateInfo.aDockSize = aSize; + nMask |= WINDOWSTATE_MASK_DOCKSIZE; + } + + a <<= aSize; + bAddToSeq = true; + } + } + } + break; + + case PROPERTY_UINAME: + { + ::rtl::OUString aValue; + if ( a >>= aValue ) + { + nMask |= WINDOWSTATE_MASK_UINAME; + aWindowStateInfo.aUIName = aValue; + bAddToSeq = true; + } + } + break; + + case PROPERTY_INTERNALSTATE: + { + sal_uInt32 nValue = 0; + if ( a >>= nValue ) + { + nMask |= WINDOWSTATE_MASK_INTERNALSTATE; + aWindowStateInfo.nInternalState = nValue; + bAddToSeq = true; + } + } + break; + + case PROPERTY_STYLE: + { + sal_Int32 nValue = 0; + if ( a >>= nValue ) + { + nMask |= WINDOWSTATE_MASK_STYLE; + aWindowStateInfo.nStyle = sal_uInt16( nValue ); + bAddToSeq = true; + } + } + break; + + default: + DBG_ASSERT( sal_False, "Wrong value for ConfigurationAccess_WindowState. Who has forgotten to add this new property!" ); + } + + if ( bAddToSeq ) + { + // put value into the return sequence + nIndex = aPropSeq.getLength(); + aPropSeq.realloc( nIndex+1 ); + aPropSeq[nIndex].Name = m_aPropArray[i]; + aPropSeq[nIndex].Value = a; + } + } + catch( com::sun::star::container::NoSuchElementException& ) + { + } + catch ( com::sun::star::lang::WrappedTargetException& ) + { + } + } + + aWindowStateInfo.nMask = nMask; + m_aResourceURLToInfoCache.insert( ResourceURLToInfoCache::value_type( rResourceURL, aWindowStateInfo )); + return makeAny( aPropSeq ); +} + +ConfigurationAccess_WindowState::WindowStateInfo& ConfigurationAccess_WindowState::impl_insertCacheAndReturnWinState( const rtl::OUString& rResourceURL, Reference< XNameAccess >& rNameAccess ) +{ + sal_Int32 nMask( 0 ); + sal_Int32 nCount( m_aPropArray.size() ); + sal_Int32 i( 0 ); + Sequence< PropertyValue > aPropSeq; + WindowStateInfo aWindowStateInfo; + + for ( i = 0; i < nCount; i++ ) + { + try + { + Any a( rNameAccess->getByName( m_aPropArray[i] ) ); + switch ( i ) + { + case PROPERTY_LOCKED: + case PROPERTY_DOCKED: + case PROPERTY_VISIBLE: + case PROPERTY_CONTEXT: + case PROPERTY_HIDEFROMMENU: + case PROPERTY_NOCLOSE: + case PROPERTY_SOFTCLOSE: + case PROPERTY_CONTEXTACTIVE: + { + sal_Bool bValue = sal_Bool(); + if ( a >>= bValue ) + { + sal_Int32 nValue( 1 << i ); + nMask |= nValue; + switch ( i ) + { + case PROPERTY_LOCKED: + aWindowStateInfo.bLocked = bValue; break; + case PROPERTY_DOCKED: + aWindowStateInfo.bDocked = bValue; break; + case PROPERTY_VISIBLE: + aWindowStateInfo.bVisible = bValue; break; + case PROPERTY_CONTEXT: + aWindowStateInfo.bContext = bValue; break; + case PROPERTY_HIDEFROMMENU: + aWindowStateInfo.bHideFromMenu = bValue; break; + case PROPERTY_NOCLOSE: + aWindowStateInfo.bNoClose = bValue; break; + case PROPERTY_SOFTCLOSE: + aWindowStateInfo.bNoClose = bValue; break; + case PROPERTY_CONTEXTACTIVE: + aWindowStateInfo.bContextActive = bValue; break; + default: + DBG_ASSERT( sal_False, "Unknown boolean property in WindowState found!" ); + } + } + } + break; + + case PROPERTY_DOCKINGAREA: + { + sal_Int32 nDockingArea = 0; + if ( a >>= nDockingArea ) + { + if (( nDockingArea >= 0 ) && + ( nDockingArea <= sal_Int32( DockingArea_DOCKINGAREA_RIGHT ))) + { + aWindowStateInfo.aDockingArea = (DockingArea)nDockingArea; + nMask |= WINDOWSTATE_MASK_DOCKINGAREA; + } + } + } + break; + + case PROPERTY_POS: + case PROPERTY_DOCKPOS: + { + ::rtl::OUString aString; + if ( a >>= aString ) + { + sal_Int32 nToken( 0 ); + ::rtl::OUString aXStr = aString.getToken( 0, ',', nToken ); + if ( nToken > 0 ) + { + com::sun::star::awt::Point aPos; + aPos.X = aXStr.toInt32(); + aPos.Y = aString.getToken( 0, ',', nToken ).toInt32(); + + if ( i == PROPERTY_POS ) + { + aWindowStateInfo.aPos = aPos; + nMask |= WINDOWSTATE_MASK_POS; + } + else + { + aWindowStateInfo.aDockPos = aPos; + nMask |= WINDOWSTATE_MASK_DOCKPOS; + } + } + } + } + break; + + case PROPERTY_SIZE: + case PROPERTY_DOCKSIZE: + { + ::rtl::OUString aString; + if ( a >>= aString ) + { + sal_Int32 nToken( 0 ); + ::rtl::OUString aStr = aString.getToken( 0, ',', nToken ); + if ( nToken > 0 ) + { + com::sun::star::awt::Size aSize; + aSize.Width = aStr.toInt32(); + aSize.Height = aString.getToken( 0, ',', nToken ).toInt32(); + if ( i == PROPERTY_SIZE ) + { + aWindowStateInfo.aSize = aSize; + nMask |= WINDOWSTATE_MASK_SIZE; + } + else + { + aWindowStateInfo.aDockSize = aSize; + nMask |= WINDOWSTATE_MASK_DOCKSIZE; + } + } + } + } + break; + + case PROPERTY_UINAME: + { + ::rtl::OUString aValue; + if ( a >>= aValue ) + { + nMask |= WINDOWSTATE_MASK_UINAME; + aWindowStateInfo.aUIName = aValue; + } + } + break; + + case PROPERTY_INTERNALSTATE: + { + sal_Int32 nValue = 0; + if ( a >>= nValue ) + { + nMask |= WINDOWSTATE_MASK_INTERNALSTATE; + aWindowStateInfo.nInternalState = sal_uInt32( nValue ); + } + } + break; + + case PROPERTY_STYLE: + { + sal_Int32 nValue = 0; + if ( a >>= nValue ) + { + nMask |= WINDOWSTATE_MASK_STYLE; + aWindowStateInfo.nStyle = sal_uInt16( nValue ); + } + } + + default: + DBG_ASSERT( sal_False, "Wrong value for ConfigurationAccess_WindowState. Who has forgotten to add this new property!" ); + } + } + catch( com::sun::star::container::NoSuchElementException& ) + { + } + catch ( com::sun::star::lang::WrappedTargetException& ) + { + } + } + + aWindowStateInfo.nMask = nMask; + ResourceURLToInfoCache::iterator pIter = (m_aResourceURLToInfoCache.insert( ResourceURLToInfoCache::value_type( rResourceURL, aWindowStateInfo ))).first; + return pIter->second; +} + +Any ConfigurationAccess_WindowState::impl_getWindowStateFromResourceURL( const rtl::OUString& rResourceURL ) +{ + if ( !m_bConfigAccessInitialized ) + { + impl_initializeConfigAccess(); + m_bConfigAccessInitialized = sal_True; + } + + try + { + // Try to ask our configuration access + if ( m_xConfigAccess.is() ) + { + Reference< XNameAccess > xNameAccess; + Any a( m_xConfigAccess->getByName( rResourceURL )); + + if ( a >>= xNameAccess ) + return impl_insertCacheAndReturnSequence( rResourceURL, xNameAccess ); + } + } + catch( com::sun::star::container::NoSuchElementException& ) + { + } + catch ( com::sun::star::lang::WrappedTargetException& ) + { + } + + return Any(); +} + +void ConfigurationAccess_WindowState::impl_fillStructFromSequence( WindowStateInfo& rWinStateInfo, const Sequence< PropertyValue >& rSeq ) +{ + sal_Int32 nCompareCount( m_aPropArray.size() ); + sal_Int32 nCount( rSeq.getLength() ); + sal_Int32 i( 0 ); + + for ( i = 0; i < nCount; i++ ) + { + for ( sal_Int32 j = 0; j < nCompareCount; j++ ) + { + if ( rSeq[i].Name.equals( m_aPropArray[j] )) + { + switch ( j ) + { + case PROPERTY_LOCKED: + case PROPERTY_DOCKED: + case PROPERTY_VISIBLE: + case PROPERTY_CONTEXT: + case PROPERTY_HIDEFROMMENU: + case PROPERTY_NOCLOSE: + case PROPERTY_SOFTCLOSE: + case PROPERTY_CONTEXTACTIVE: + { + sal_Bool bValue = sal_Bool(); + if ( rSeq[i].Value >>= bValue ) + { + sal_Int32 nValue( 1 << j ); + rWinStateInfo.nMask |= nValue; + switch ( j ) + { + case PROPERTY_LOCKED: + rWinStateInfo.bLocked = bValue; + break; + case PROPERTY_DOCKED: + rWinStateInfo.bDocked = bValue; + break; + case PROPERTY_VISIBLE: + rWinStateInfo.bVisible = bValue; + break; + case PROPERTY_CONTEXT: + rWinStateInfo.bContext = bValue; + break; + case PROPERTY_HIDEFROMMENU: + rWinStateInfo.bHideFromMenu = bValue; + break; + case PROPERTY_NOCLOSE: + rWinStateInfo.bNoClose = bValue; + break; + case PROPERTY_SOFTCLOSE: + rWinStateInfo.bSoftClose = bValue; + break; + case PROPERTY_CONTEXTACTIVE: + rWinStateInfo.bContextActive = bValue; + break; + default: + DBG_ASSERT( sal_False, "Unknown boolean property in WindowState found!" ); + } + } + } + break; + + case PROPERTY_DOCKINGAREA: + { + ::com::sun::star::ui::DockingArea eDockingArea; + if ( rSeq[i].Value >>= eDockingArea ) + { + rWinStateInfo.aDockingArea = eDockingArea; + rWinStateInfo.nMask |= WINDOWSTATE_MASK_DOCKINGAREA; + } + } + break; + + case PROPERTY_POS: + case PROPERTY_DOCKPOS: + { + com::sun::star::awt::Point aPoint; + if ( rSeq[i].Value >>= aPoint ) + { + if ( j == PROPERTY_POS ) + { + rWinStateInfo.aPos = aPoint; + rWinStateInfo.nMask |= WINDOWSTATE_MASK_POS; + } + else + { + rWinStateInfo.aDockPos = aPoint; + rWinStateInfo.nMask |= WINDOWSTATE_MASK_DOCKPOS; + } + } + } + break; + + case PROPERTY_SIZE: + case PROPERTY_DOCKSIZE: + { + com::sun::star::awt::Size aSize; + if ( rSeq[i].Value >>= aSize ) + { + if ( j == PROPERTY_SIZE ) + { + rWinStateInfo.aSize = aSize; + rWinStateInfo.nMask |= WINDOWSTATE_MASK_SIZE; + } + else + { + rWinStateInfo.aDockSize = aSize; + rWinStateInfo.nMask |= WINDOWSTATE_MASK_DOCKSIZE; + } + } + } + break; + + case PROPERTY_UINAME: + { + ::rtl::OUString aValue; + if ( rSeq[i].Value >>= aValue ) + { + rWinStateInfo.aUIName = aValue; + rWinStateInfo.nMask |= WINDOWSTATE_MASK_UINAME; + } + } + break; + + case PROPERTY_INTERNALSTATE: + { + sal_Int32 nValue = 0; + if ( rSeq[i].Value >>= nValue ) + { + rWinStateInfo.nInternalState = sal_uInt32( nValue ); + rWinStateInfo.nMask |= WINDOWSTATE_MASK_INTERNALSTATE; + } + } + break; + + case PROPERTY_STYLE: + { + sal_Int32 nValue = 0; + if ( rSeq[i].Value >>= nValue ) + { + rWinStateInfo.nStyle = sal_uInt16( nValue ); + rWinStateInfo.nMask |= WINDOWSTATE_MASK_STYLE; + } + } + break; + + default: + DBG_ASSERT( sal_False, "Wrong value for ConfigurationAccess_WindowState. Who has forgotten to add this new property!" ); + } + + break; + } + } + } +} + +void ConfigurationAccess_WindowState::impl_putPropertiesFromStruct( const WindowStateInfo& rWinStateInfo, Reference< XPropertySet >& xPropSet ) +{ + sal_Int32 i( 0 ); + sal_Int32 nCount( m_aPropArray.size() ); + Sequence< PropertyValue > aPropSeq; + ::rtl::OUString aDelim( ::rtl::OUString::createFromAscii( "," )); + + for ( i = 0; i < nCount; i++ ) + { + if ( rWinStateInfo.nMask & ( 1 << i )) + { + try + { + // put values into the property set + switch ( i ) + { + case PROPERTY_LOCKED: + xPropSet->setPropertyValue( m_aPropArray[i], makeAny( sal_Bool( rWinStateInfo.bLocked )) ); break; + case PROPERTY_DOCKED: + xPropSet->setPropertyValue( m_aPropArray[i], makeAny( sal_Bool( rWinStateInfo.bDocked )) ); break; + case PROPERTY_VISIBLE: + xPropSet->setPropertyValue( m_aPropArray[i], makeAny( sal_Bool( rWinStateInfo.bVisible )) ); break; + case PROPERTY_CONTEXT: + xPropSet->setPropertyValue( m_aPropArray[i], makeAny( sal_Bool( rWinStateInfo.bContext )) ); break; + case PROPERTY_HIDEFROMMENU: + xPropSet->setPropertyValue( m_aPropArray[i], makeAny( sal_Bool( rWinStateInfo.bHideFromMenu )) ); break; + case PROPERTY_NOCLOSE: + xPropSet->setPropertyValue( m_aPropArray[i], makeAny( sal_Bool( rWinStateInfo.bNoClose )) ); break; + case PROPERTY_SOFTCLOSE: + xPropSet->setPropertyValue( m_aPropArray[i], makeAny( sal_Bool( rWinStateInfo.bSoftClose )) ); break; + case PROPERTY_CONTEXTACTIVE: + xPropSet->setPropertyValue( m_aPropArray[i], makeAny( sal_Bool( rWinStateInfo.bContextActive )) ); break; + case PROPERTY_DOCKINGAREA: + xPropSet->setPropertyValue( m_aPropArray[i], makeAny( sal_Int16( rWinStateInfo.aDockingArea ) ) ); break; + case PROPERTY_POS: + case PROPERTY_DOCKPOS: + { + ::rtl::OUString aPosStr; + if ( i == PROPERTY_POS ) + aPosStr = ::rtl::OUString::valueOf( rWinStateInfo.aPos.X ); + else + aPosStr = ::rtl::OUString::valueOf( rWinStateInfo.aDockPos.X ); + aPosStr += aDelim; + if ( i == PROPERTY_POS ) + aPosStr += ::rtl::OUString::valueOf( rWinStateInfo.aPos.Y ); + else + aPosStr += ::rtl::OUString::valueOf( rWinStateInfo.aDockPos.Y ); + xPropSet->setPropertyValue( m_aPropArray[i], makeAny( aPosStr ) ); + break; + } + case PROPERTY_SIZE: + case PROPERTY_DOCKSIZE: + { + ::rtl::OUString aSizeStr; + if ( i == PROPERTY_SIZE ) + aSizeStr = ( ::rtl::OUString::valueOf( rWinStateInfo.aSize.Width )); + else + aSizeStr = ( ::rtl::OUString::valueOf( rWinStateInfo.aDockSize.Width )); + aSizeStr += aDelim; + if ( i == PROPERTY_SIZE ) + aSizeStr += ::rtl::OUString::valueOf( rWinStateInfo.aSize.Height ); + else + aSizeStr += ::rtl::OUString::valueOf( rWinStateInfo.aDockSize.Height ); + xPropSet->setPropertyValue( m_aPropArray[i], makeAny( aSizeStr ) ); + break; + } + case PROPERTY_UINAME: + xPropSet->setPropertyValue( m_aPropArray[i], makeAny( rWinStateInfo.aUIName ) ); break; + case PROPERTY_INTERNALSTATE: + xPropSet->setPropertyValue( m_aPropArray[i], makeAny( sal_Int32( rWinStateInfo.nInternalState )) ); break; + case PROPERTY_STYLE: + xPropSet->setPropertyValue( m_aPropArray[i], makeAny( sal_Int32( rWinStateInfo.nStyle )) ); break; + default: + DBG_ASSERT( sal_False, "Wrong value for ConfigurationAccess_WindowState. Who has forgotten to add this new property!" ); + } + } + catch( Exception& ) + { + } + } + } +} + +sal_Bool ConfigurationAccess_WindowState::impl_initializeConfigAccess() +{ + Sequence< Any > aArgs( 2 ); + PropertyValue aPropValue; + + try + { + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" )); + aPropValue.Value <<= m_aConfigWindowAccess; + aArgs[0] <<= aPropValue; + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "lazywrite" )); + aPropValue.Value <<= sal_True; + aArgs[1] <<= aPropValue; + + m_xConfigAccess = Reference< XNameAccess >( m_xConfigProvider->createInstanceWithArguments( + SERVICENAME_CFGUPDATEACCESS, aArgs ), + UNO_QUERY ); + if ( m_xConfigAccess.is() ) + { + // Add as container listener + Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY ); + if ( xContainer.is() ) + xContainer->addContainerListener( this ); + } + + return sal_True; + } + catch ( WrappedTargetException& ) + { + } + catch ( Exception& ) + { + } + + return sal_False; +} + + +//***************************************************************************************************************** +// XInterface, XTypeProvider, XServiceInfo +//***************************************************************************************************************** +DEFINE_XINTERFACE_4 ( WindowStateConfiguration , + OWeakObject , + DIRECT_INTERFACE( css::lang::XTypeProvider ), + DIRECT_INTERFACE( css::lang::XServiceInfo ), + DIRECT_INTERFACE( css::container::XNameAccess ), + DERIVED_INTERFACE( css::container::XElementAccess, css::container::XNameAccess ) + ) + +DEFINE_XTYPEPROVIDER_4 ( WindowStateConfiguration , + css::lang::XTypeProvider , + css::lang::XServiceInfo , + css::container::XNameAccess , + css::container::XElementAccess + ) + +DEFINE_XSERVICEINFO_ONEINSTANCESERVICE ( WindowStateConfiguration , + ::cppu::OWeakObject , + SERVICENAME_WINDOWSTATECONFIGURATION , + IMPLEMENTATIONNAME_WINDOWSTATECONFIGURATION + ) + +DEFINE_INIT_SERVICE ( WindowStateConfiguration, {} ) + +WindowStateConfiguration::WindowStateConfiguration( const Reference< XMultiServiceFactory >& xServiceManager ) : + ThreadHelpBase(), + m_xServiceManager( xServiceManager ) +{ + m_xModuleManager = Reference< XModuleManager >( m_xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ), + UNO_QUERY ); + Reference< XNameAccess > xEmptyNameAccess; + Reference< XNameAccess > xNameAccess( m_xModuleManager, UNO_QUERY_THROW ); + Sequence< rtl::OUString > aElementNames = xNameAccess->getElementNames(); + Sequence< PropertyValue > aSeq; + ::rtl::OUString aModuleIdentifier; + + for ( sal_Int32 i = 0; i < aElementNames.getLength(); i++ ) + { + aModuleIdentifier = aElementNames[i]; + if ( xNameAccess->getByName( aModuleIdentifier ) >>= aSeq ) + { + ::rtl::OUString aWindowStateFileStr; + for ( sal_Int32 y = 0; y < aSeq.getLength(); y++ ) + { + if ( aSeq[y].Name.equalsAscii("ooSetupFactoryWindowStateConfigRef") ) + { + aSeq[y].Value >>= aWindowStateFileStr; + break; + } + } + + if ( aWindowStateFileStr.getLength() > 0 ) + { + // Create first mapping ModuleIdentifier ==> Window state configuration file + m_aModuleToFileHashMap.insert( ModuleToWindowStateFileMap::value_type( aModuleIdentifier, aWindowStateFileStr )); + + // Create second mapping Command File ==> Window state configuration instance + ModuleToWindowStateConfigHashMap::iterator pIter = m_aModuleToWindowStateHashMap.find( aWindowStateFileStr ); + if ( pIter == m_aModuleToWindowStateHashMap.end() ) + m_aModuleToWindowStateHashMap.insert( ModuleToWindowStateConfigHashMap::value_type( aWindowStateFileStr, xEmptyNameAccess )); + } + } + } +} + +WindowStateConfiguration::~WindowStateConfiguration() +{ + ResetableGuard aLock( m_aLock ); + m_aModuleToFileHashMap.clear(); + m_aModuleToWindowStateHashMap.clear(); +} + +Any SAL_CALL WindowStateConfiguration::getByName( const ::rtl::OUString& aModuleIdentifier ) +throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + ModuleToWindowStateFileMap::const_iterator pIter = m_aModuleToFileHashMap.find( aModuleIdentifier ); + if ( pIter != m_aModuleToFileHashMap.end() ) + { + Any a; + ::rtl::OUString aWindowStateConfigFile( pIter->second ); + + ModuleToWindowStateConfigHashMap::iterator pModuleIter = m_aModuleToWindowStateHashMap.find( aWindowStateConfigFile ); + if ( pModuleIter != m_aModuleToWindowStateHashMap.end() ) + { + if ( pModuleIter->second.is() ) + a = makeAny( pModuleIter->second ); + else + { + Reference< XNameAccess > xResourceURLWindowState; + ConfigurationAccess_WindowState* pModuleWindowState = new ConfigurationAccess_WindowState( aWindowStateConfigFile, m_xServiceManager ); + xResourceURLWindowState = Reference< XNameAccess >( static_cast< cppu::OWeakObject* >( pModuleWindowState ),UNO_QUERY ); + pModuleIter->second = xResourceURLWindowState; + a <<= xResourceURLWindowState; + } + + return a; + } + } + + throw NoSuchElementException(); +} + +Sequence< ::rtl::OUString > SAL_CALL WindowStateConfiguration::getElementNames() +throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + Sequence< rtl::OUString > aSeq( m_aModuleToFileHashMap.size() ); + + sal_Int32 n = 0; + ModuleToWindowStateFileMap::const_iterator pIter = m_aModuleToFileHashMap.begin(); + while ( pIter != m_aModuleToFileHashMap.end() ) + { + aSeq[n] = pIter->first; + ++pIter; + } + + return aSeq; +} + +sal_Bool SAL_CALL WindowStateConfiguration::hasByName( const ::rtl::OUString& aName ) +throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + + ModuleToWindowStateFileMap::const_iterator pIter = m_aModuleToFileHashMap.find( aName ); + return ( pIter != m_aModuleToFileHashMap.end() ); +} + +// XElementAccess +Type SAL_CALL WindowStateConfiguration::getElementType() +throw (::com::sun::star::uno::RuntimeException) +{ + return( ::getCppuType( (const Reference< XNameAccess >*)NULL ) ); +} + +sal_Bool SAL_CALL WindowStateConfiguration::hasElements() +throw (::com::sun::star::uno::RuntimeException) +{ + // We always have at least one module. So it is valid to return true! + return sal_True; +} + +} // namespace framework + |