diff options
author | Mikhail Voytenko <mav@openoffice.org> | 2011-01-06 14:57:12 +0100 |
---|---|---|
committer | Mikhail Voytenko <mav@openoffice.org> | 2011-01-06 14:57:12 +0100 |
commit | 8ff51afa0dcd4e5e644e923131ee72435c80b57b (patch) | |
tree | d63f6b6e298485b5f29f60c7af25baca46f59375 /framework/source/fwe | |
parent | fa1f3c352c6126b24ab5af87ea4ebea742c546c2 (diff) | |
parent | 794c821e4d48c34aa376cdc7b6ab2cb029d9574d (diff) |
removetooltypes01: rebase to DEV300_m96
Diffstat (limited to 'framework/source/fwe')
35 files changed, 13190 insertions, 0 deletions
diff --git a/framework/source/fwe/classes/actiontriggercontainer.cxx b/framework/source/fwe/classes/actiontriggercontainer.cxx new file mode 100644 index 000000000000..ea549fd3fda8 --- /dev/null +++ b/framework/source/fwe/classes/actiontriggercontainer.cxx @@ -0,0 +1,203 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <classes/actiontriggercontainer.hxx> +#include <cppuhelper/typeprovider.hxx> + +#include <classes/actiontriggerpropertyset.hxx> +#include <classes/actiontriggerseparatorpropertyset.hxx> + +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; + +namespace framework +{ + +ActionTriggerContainer::ActionTriggerContainer( const Reference< XMultiServiceFactory >& rServiceManager ) : + PropertySetContainer( rServiceManager ) +{ +} + + +ActionTriggerContainer::~ActionTriggerContainer() +{ +} + +// XInterface +Any SAL_CALL ActionTriggerContainer::queryInterface( const Type& aType ) +throw ( RuntimeException ) +{ + Any a = ::cppu::queryInterface( + aType , + SAL_STATIC_CAST( XMultiServiceFactory*, this ), + SAL_STATIC_CAST( XServiceInfo* , this )); + + if( a.hasValue() ) + { + return a; + } + + return PropertySetContainer::queryInterface( aType ); +} + +void ActionTriggerContainer::acquire() throw() +{ + PropertySetContainer::acquire(); +} + +void ActionTriggerContainer::release() throw() +{ + PropertySetContainer::release(); +} + + +// XMultiServiceFactory +Reference< XInterface > SAL_CALL ActionTriggerContainer::createInstance( const ::rtl::OUString& aServiceSpecifier ) +throw ( ::com::sun::star::uno::Exception, RuntimeException) +{ + if ( aServiceSpecifier.equalsAscii( SERVICENAME_ACTIONTRIGGER )) + return (OWeakObject *)( new ActionTriggerPropertySet( m_xServiceManager )); + else if ( aServiceSpecifier.equalsAscii( SERVICENAME_ACTIONTRIGGERCONTAINER )) + return (OWeakObject *)( new ActionTriggerContainer( m_xServiceManager )); + else if ( aServiceSpecifier.equalsAscii( SERVICENAME_ACTIONTRIGGERSEPARATOR )) + return (OWeakObject *)( new ActionTriggerSeparatorPropertySet( m_xServiceManager )); + else + throw com::sun::star::uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unknown service specifier!" )), (OWeakObject *)this ); +} + + +Reference< XInterface > SAL_CALL ActionTriggerContainer::createInstanceWithArguments( const ::rtl::OUString& ServiceSpecifier, const Sequence< Any >& /*Arguments*/ ) +throw ( Exception, RuntimeException) +{ + return createInstance( ServiceSpecifier ); +} + + +Sequence< ::rtl::OUString > SAL_CALL ActionTriggerContainer::getAvailableServiceNames() +throw ( RuntimeException ) +{ + Sequence< ::rtl::OUString > aSeq( 3 ); + + aSeq[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGER )); + aSeq[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGERCONTAINER )); + aSeq[2] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGERSEPARATOR )); + + return aSeq; +} + +// XServiceInfo +::rtl::OUString SAL_CALL ActionTriggerContainer::getImplementationName() +throw ( RuntimeException ) +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATIONNAME_ACTIONTRIGGERCONTAINER )); +} + +sal_Bool SAL_CALL ActionTriggerContainer::supportsService( const ::rtl::OUString& ServiceName ) +throw ( RuntimeException ) +{ + if ( ServiceName.equalsAscii( SERVICENAME_ACTIONTRIGGERCONTAINER )) + return sal_True; + + return sal_False; +} + +Sequence< ::rtl::OUString > SAL_CALL ActionTriggerContainer::getSupportedServiceNames() +throw ( RuntimeException ) +{ + Sequence< ::rtl::OUString > seqServiceNames( 1 ); + + seqServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGERCONTAINER )); + return seqServiceNames; +} + +// XTypeProvider +Sequence< Type > SAL_CALL ActionTriggerContainer::getTypes() throw ( RuntimeException ) +{ + // Optimize this method ! + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pTypeCollection is NULL - for the second call pTypeCollection is different from NULL! + static ::cppu::OTypeCollection* pTypeCollection = NULL ; + + if ( pTypeCollection == NULL ) + { + // Ready for multithreading; get global mutex for first call of this method only! see before + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; + + // Control these pointer again ... it can be, that another instance will be faster then these! + if ( pTypeCollection == NULL ) + { + // Create a static typecollection ... + static ::cppu::OTypeCollection aTypeCollection( + ::getCppuType(( const Reference< XMultiServiceFactory >*)NULL ) , + ::getCppuType(( const Reference< XIndexContainer >*)NULL ) , + ::getCppuType(( const Reference< XIndexAccess >*)NULL ) , + ::getCppuType(( const Reference< XIndexReplace >*)NULL ) , + ::getCppuType(( const Reference< XServiceInfo >*)NULL ) , + ::getCppuType(( const Reference< XTypeProvider >*)NULL ) ) ; + + // ... and set his address to static pointer! + pTypeCollection = &aTypeCollection ; + } + } + + return pTypeCollection->getTypes() ; +} + +Sequence< sal_Int8 > SAL_CALL ActionTriggerContainer::getImplementationId() throw ( RuntimeException ) +{ + // Create one Id for all instances of this class. + // Use ethernet address to do this! (sal_True) + + // Optimize this method + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pID is NULL - for the second call pID is different from NULL! + static ::cppu::OImplementationId* pID = NULL ; + + if ( pID == NULL ) + { + // Ready for multithreading; get global mutex for first call of this method only! see before + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; + + // Control these pointer again ... it can be, that another instance will be faster then these! + if ( pID == NULL ) + { + // Create a new static ID ... + static ::cppu::OImplementationId aID( sal_False ) ; + // ... and set his address to static pointer! + pID = &aID ; + } + } + + return pID->getImplementationId() ; +} + +} + diff --git a/framework/source/fwe/classes/actiontriggerpropertyset.cxx b/framework/source/fwe/classes/actiontriggerpropertyset.cxx new file mode 100644 index 000000000000..9b881448202f --- /dev/null +++ b/framework/source/fwe/classes/actiontriggerpropertyset.cxx @@ -0,0 +1,480 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <classes/actiontriggerpropertyset.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <cppuhelper/proptypehlp.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <vcl/svapp.hxx> + + +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::awt; + +//struct SAL_DLLPUBLIC_IMPORT ::cppu::OBroadcastHelperVar< OMultiTypeInterfaceContainerHelper, OMultiTypeInterfaceContainerHelper::keyType >; + +// Handles for properties +// (PLEASE SORT THIS FIELD, IF YOU ADD NEW PROPERTIES!) +// We use an enum to define these handles, to use all numbers from 0 to nn and +// if you add someone, you don't must control this! +// But don't forget to change values of follow defines, if you do something with this enum! +enum EPROPERTIES +{ + HANDLE_COMMANDURL, + HANDLE_HELPURL, + HANDLE_IMAGE, + HANDLE_SUBCONTAINER, + HANDLE_TEXT, + PROPERTYCOUNT +}; + +namespace framework +{ + +ActionTriggerPropertySet::ActionTriggerPropertySet( const Reference< XMultiServiceFactory >& /*xServiceManager*/ ) + : ThreadHelpBase ( &Application::GetSolarMutex() ) + , OBroadcastHelper ( m_aLock.getShareableOslMutex() ) + , OPropertySetHelper ( *SAL_STATIC_CAST( OBroadcastHelper *, this )) + , OWeakObject () + , m_xBitmap ( 0 ) + , m_xActionTriggerContainer( 0 ) +{ +} + +ActionTriggerPropertySet::~ActionTriggerPropertySet() +{ +} + +// XInterface +Any SAL_CALL ActionTriggerPropertySet::queryInterface( const Type& aType ) +throw ( RuntimeException ) +{ + Any a = ::cppu::queryInterface( + aType , + SAL_STATIC_CAST( XServiceInfo*, this )); + + if( a.hasValue() ) + return a; + else + { + a = OPropertySetHelper::queryInterface( aType ); + + if( a.hasValue() ) + return a; + } + + return OWeakObject::queryInterface( aType ); +} + +void SAL_CALL ActionTriggerPropertySet::acquire() throw () +{ + OWeakObject::acquire(); +} + +void SAL_CALL ActionTriggerPropertySet::release() throw () +{ + OWeakObject::release(); +} + + +// XServiceInfo +::rtl::OUString SAL_CALL ActionTriggerPropertySet::getImplementationName() +throw ( RuntimeException ) +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATIONNAME_ACTIONTRIGGER )); +} + +sal_Bool SAL_CALL ActionTriggerPropertySet::supportsService( const ::rtl::OUString& ServiceName ) +throw ( RuntimeException ) +{ + if ( ServiceName.equalsAscii( SERVICENAME_ACTIONTRIGGER )) + return sal_True; + + return sal_False; +} + +Sequence< ::rtl::OUString > SAL_CALL ActionTriggerPropertySet::getSupportedServiceNames() +throw ( RuntimeException ) +{ + Sequence< ::rtl::OUString > seqServiceNames( 1 ); + seqServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGER )); + return seqServiceNames; +} + +// XTypeProvider +Sequence< Type > SAL_CALL ActionTriggerPropertySet::getTypes() throw ( RuntimeException ) +{ + // Optimize this method ! + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pTypeCollection is NULL - for the second call pTypeCollection is different from NULL! + static ::cppu::OTypeCollection* pTypeCollection = NULL ; + + if ( pTypeCollection == NULL ) + { + // Ready for multithreading; get global mutex for first call of this method only! see before + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; + + // Control these pointer again ... it can be, that another instance will be faster then these! + if ( pTypeCollection == NULL ) + { + // Create a static typecollection ... + static ::cppu::OTypeCollection aTypeCollection( + ::getCppuType(( const Reference< XPropertySet >*)NULL ) , + ::getCppuType(( const Reference< XFastPropertySet >*)NULL ) , + ::getCppuType(( const Reference< XMultiPropertySet >*)NULL ) , + ::getCppuType(( const Reference< XServiceInfo >*)NULL ) , + ::getCppuType(( const Reference< XTypeProvider >*)NULL ) ) ; + + // ... and set his address to static pointer! + pTypeCollection = &aTypeCollection ; + } + } + + return pTypeCollection->getTypes() ; +} + +Sequence< sal_Int8 > SAL_CALL ActionTriggerPropertySet::getImplementationId() throw ( RuntimeException ) +{ + // Create one Id for all instances of this class. + // Use ethernet address to do this! (sal_True) + + // Optimize this method + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pID is NULL - for the second call pID is different from NULL! + static ::cppu::OImplementationId* pID = NULL ; + + if ( pID == NULL ) + { + // Ready for multithreading; get global mutex for first call of this method only! see before + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; + + // Control these pointer again ... it can be, that another instance will be faster then these! + if ( pID == NULL ) + { + // Create a new static ID ... + static ::cppu::OImplementationId aID( sal_False ) ; + // ... and set his address to static pointer! + pID = &aID ; + } + } + + return pID->getImplementationId() ; +} + +//--------------------------------------------------------------------------------------------------------- +// OPropertySetHelper implementation +//--------------------------------------------------------------------------------------------------------- + +sal_Bool SAL_CALL ActionTriggerPropertySet::convertFastPropertyValue( + Any& aConvertedValue, + Any& aOldValue, + sal_Int32 nHandle, + const Any& aValue ) +throw( IllegalArgumentException ) +{ + // Check, if value of property will changed in method "setFastPropertyValue_NoBroadcast()". + // Return sal_True, if changed - else return sal_False. + // Attention: Method "impl_tryToChangeProperty()" can throw the IllegalArgumentException !!! + // Initialize return value with sal_False !!! + // (Handle can be invalid) + sal_Bool bReturn = sal_False; + + switch( nHandle ) + { + case HANDLE_COMMANDURL: + bReturn = impl_tryToChangeProperty( m_aCommandURL, aValue, aOldValue, aConvertedValue ); + break; + + case HANDLE_HELPURL: + bReturn = impl_tryToChangeProperty( m_aHelpURL, aValue, aOldValue, aConvertedValue ) ; + break; + + case HANDLE_IMAGE: + bReturn = impl_tryToChangeProperty( m_xBitmap, aValue, aOldValue, aConvertedValue ) ; + break; + + case HANDLE_SUBCONTAINER: + bReturn = impl_tryToChangeProperty( m_xActionTriggerContainer, aValue, aOldValue, aConvertedValue ); + break; + + case HANDLE_TEXT: + bReturn = impl_tryToChangeProperty( m_aText, aValue, aOldValue, aConvertedValue ) ; + break; + } + + // Return state of operation. + return bReturn; +} + + +void SAL_CALL ActionTriggerPropertySet::setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, const Any& aValue ) +throw( Exception ) +{ + ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() ); + + // Search for right handle ... and try to set property value. + switch( nHandle ) + { + case HANDLE_COMMANDURL: + aValue >>= m_aCommandURL; + break; + + case HANDLE_HELPURL: + aValue >>= m_aHelpURL; + break; + + case HANDLE_IMAGE: + aValue >>= m_xBitmap; + break; + + case HANDLE_SUBCONTAINER: + aValue >>= m_xActionTriggerContainer; + break; + + case HANDLE_TEXT: + aValue >>= m_aText; + break; + } +} + +void SAL_CALL ActionTriggerPropertySet::getFastPropertyValue( + Any& aValue, sal_Int32 nHandle ) const +{ + ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() ); + + // Search for right handle ... and try to get property value. + switch( nHandle ) + { + case HANDLE_COMMANDURL: + aValue <<= m_aCommandURL; + break; + + case HANDLE_HELPURL: + aValue <<= m_aHelpURL; + break; + + case HANDLE_IMAGE: + aValue <<= m_xBitmap; + break; + + case HANDLE_SUBCONTAINER: + aValue <<= m_xActionTriggerContainer; + break; + + case HANDLE_TEXT: + aValue <<= m_aText; + break; + } +} + +::cppu::IPropertyArrayHelper& SAL_CALL ActionTriggerPropertySet::getInfoHelper() +{ + // Optimize this method ! + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pInfoHelper is NULL - for the second call pInfoHelper is different from NULL! + static OPropertyArrayHelper* pInfoHelper = NULL; + + if( pInfoHelper == NULL ) + { + // Ready for multithreading + ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() ); + // Control this pointer again, another instance can be faster then these! + if( pInfoHelper == NULL ) + { + // Define static member to give structure of properties to baseclass "OPropertySetHelper". + // "impl_getStaticPropertyDescriptor" is a non exported and static funtion, who will define a static propertytable. + // "sal_True" say: Table is sorted by name. + static OPropertyArrayHelper aInfoHelper( impl_getStaticPropertyDescriptor(), sal_True ); + pInfoHelper = &aInfoHelper; + } + } + + return (*pInfoHelper); +} + +Reference< XPropertySetInfo > SAL_CALL ActionTriggerPropertySet::getPropertySetInfo() +throw ( RuntimeException ) +{ + // Optimize this method ! + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pInfo is NULL - for the second call pInfo is different from NULL! + static Reference< XPropertySetInfo >* pInfo = NULL ; + + if( pInfo == NULL ) + { + // Ready for multithreading + ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() ); + // Control this pointer again, another instance can be faster then these! + if( pInfo == NULL ) + { + // Create structure of propertysetinfo for baseclass "OPropertySetHelper". + // (Use method "getInfoHelper()".) + static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); + pInfo = &xInfo; + } + } + + return (*pInfo); +} + +const Sequence< Property > ActionTriggerPropertySet::impl_getStaticPropertyDescriptor() +{ + static const Property pActionTriggerPropertys[] = + { + Property( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )), HANDLE_COMMANDURL , ::getCppuType((::rtl::OUString*)0) , PropertyAttribute::TRANSIENT ), + Property( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HelpURL" )), HANDLE_HELPURL , ::getCppuType((::rtl::OUString*)0) , PropertyAttribute::TRANSIENT ), + Property( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Image" )), HANDLE_IMAGE , ::getCppuType((Reference<XBitmap>*)0) , PropertyAttribute::TRANSIENT ), + Property( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SubContainer" )), HANDLE_SUBCONTAINER , ::getCppuType((::rtl::OUString*)0) , PropertyAttribute::TRANSIENT ), + Property( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" )), HANDLE_TEXT , ::getCppuType((Reference<XInterface>*)0) , PropertyAttribute::TRANSIENT ) + }; + + // Use it to initialize sequence! + static const Sequence< Property > seqActionTriggerPropertyDescriptor( pActionTriggerPropertys, PROPERTYCOUNT ); + + // Return static "PropertyDescriptor" + return seqActionTriggerPropertyDescriptor ; +} + + +//****************************************************************************************************************************** +// private method +//****************************************************************************************************************************** +sal_Bool ActionTriggerPropertySet::impl_tryToChangeProperty( + const ::rtl::OUString& sCurrentValue , + const Any& aNewValue , + Any& aOldValue , + Any& aConvertedValue ) +throw( IllegalArgumentException ) +{ + // Set default return value if method failed. + sal_Bool bReturn = sal_False; + // Get new value from any. + // IllegalArgumentException() can be thrown! + ::rtl::OUString sValue ; + convertPropertyValue( sValue, aNewValue ); + + // If value change ... + if( sValue != sCurrentValue ) + { + // ... set information of change. + aOldValue <<= sCurrentValue ; + aConvertedValue <<= sValue ; + // Return OK - "value will be change ..." + bReturn = sal_True; + } + else + { + // ... clear information of return parameter! + aOldValue.clear () ; + aConvertedValue.clear () ; + // Return NOTHING - "value will not be change ..." + bReturn = sal_False; + } + + return bReturn; +} + + +sal_Bool ActionTriggerPropertySet::impl_tryToChangeProperty( + const Reference< XBitmap > aCurrentValue , + const Any& aNewValue , + Any& aOldValue , + Any& aConvertedValue ) +throw( IllegalArgumentException ) +{ + // Set default return value if method failed. + sal_Bool bReturn = sal_False; + // Get new value from any. + // IllegalArgumentException() can be thrown! + Reference< XBitmap > aValue ; + convertPropertyValue( aValue, aNewValue ); + + // If value change ... + if( aValue != aCurrentValue ) + { + // ... set information of change. + aOldValue <<= aCurrentValue ; + aConvertedValue <<= aValue ; + // Return OK - "value will be change ..." + bReturn = sal_True; + } + else + { + // ... clear information of return parameter! + aOldValue.clear () ; + aConvertedValue.clear () ; + // Return NOTHING - "value will not be change ..." + bReturn = sal_False; + } + + return bReturn; +} + +sal_Bool ActionTriggerPropertySet::impl_tryToChangeProperty( + const Reference< XInterface > aCurrentValue , + const Any& aNewValue , + Any& aOldValue , + Any& aConvertedValue ) +throw( IllegalArgumentException ) +{ + // Set default return value if method failed. + sal_Bool bReturn = sal_False; + // Get new value from any. + // IllegalArgumentException() can be thrown! + Reference< XInterface > aValue ; + convertPropertyValue( aValue, aNewValue ); + + // If value change ... + if( aValue != aCurrentValue ) + { + // ... set information of change. + aOldValue <<= aCurrentValue ; + aConvertedValue <<= aValue ; + // Return OK - "value will be change ..." + bReturn = sal_True; + } + else + { + // ... clear information of return parameter! + aOldValue.clear () ; + aConvertedValue.clear () ; + // Return NOTHING - "value will not be change ..." + bReturn = sal_False; + } + + return bReturn; +} + +} + diff --git a/framework/source/fwe/classes/actiontriggerseparatorpropertyset.cxx b/framework/source/fwe/classes/actiontriggerseparatorpropertyset.cxx new file mode 100644 index 000000000000..ce6aaef12dac --- /dev/null +++ b/framework/source/fwe/classes/actiontriggerseparatorpropertyset.cxx @@ -0,0 +1,349 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <classes/actiontriggerseparatorpropertyset.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <cppuhelper/proptypehlp.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <vcl/svapp.hxx> + + +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::awt; + +// Handles for properties +// (PLEASE SORT THIS FIELD, IF YOU ADD NEW PROPERTIES!) +// We use an enum to define these handles, to use all numbers from 0 to nn and +// if you add someone, you don't must control this! +// But don't forget to change values of follow defines, if you do something with this enum! +enum EPROPERTIES +{ + HANDLE_TYPE, + PROPERTYCOUNT +}; + +namespace framework +{ + +ActionTriggerSeparatorPropertySet::ActionTriggerSeparatorPropertySet( const Reference< XMultiServiceFactory >& /*ServiceManager*/ ) + : ThreadHelpBase ( &Application::GetSolarMutex() ) + , OBroadcastHelper ( m_aLock.getShareableOslMutex() ) + , OPropertySetHelper ( *SAL_STATIC_CAST( OBroadcastHelper *, this ) ) + , OWeakObject ( ) + , m_nSeparatorType( 0 ) +{ +} + +ActionTriggerSeparatorPropertySet::~ActionTriggerSeparatorPropertySet() +{ +} + +// XInterface +Any SAL_CALL ActionTriggerSeparatorPropertySet::queryInterface( const Type& aType ) +throw ( RuntimeException ) +{ + Any a = ::cppu::queryInterface( + aType , + SAL_STATIC_CAST( XServiceInfo*, this )); + + if( a.hasValue() ) + return a; + else + { + a = OPropertySetHelper::queryInterface( aType ); + + if( a.hasValue() ) + return a; + } + + return OWeakObject::queryInterface( aType ); +} + +void ActionTriggerSeparatorPropertySet::acquire() throw() +{ + OWeakObject::acquire(); +} + +void ActionTriggerSeparatorPropertySet::release() throw() +{ + OWeakObject::release(); +} + +// XServiceInfo +::rtl::OUString SAL_CALL ActionTriggerSeparatorPropertySet::getImplementationName() +throw ( RuntimeException ) +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATIONNAME_ACTIONTRIGGERSEPARATOR )); +} + +sal_Bool SAL_CALL ActionTriggerSeparatorPropertySet::supportsService( const ::rtl::OUString& ServiceName ) +throw ( RuntimeException ) +{ + if ( ServiceName.equalsAscii( SERVICENAME_ACTIONTRIGGERSEPARATOR )) + return sal_True; + + return sal_False; +} + +Sequence< ::rtl::OUString > SAL_CALL ActionTriggerSeparatorPropertySet::getSupportedServiceNames() +throw ( RuntimeException ) +{ + Sequence< ::rtl::OUString > seqServiceNames( 1 ); + seqServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGERSEPARATOR )); + return seqServiceNames; +} + +// XTypeProvider +Sequence< Type > SAL_CALL ActionTriggerSeparatorPropertySet::getTypes() throw ( RuntimeException ) +{ + // Optimize this method ! + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pTypeCollection is NULL - for the second call pTypeCollection is different from NULL! + static ::cppu::OTypeCollection* pTypeCollection = NULL ; + + if ( pTypeCollection == NULL ) + { + // Ready for multithreading; get global mutex for first call of this method only! see before + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; + + // Control these pointer again ... it can be, that another instance will be faster then these! + if ( pTypeCollection == NULL ) + { + // Create a static typecollection ... + static ::cppu::OTypeCollection aTypeCollection( + ::getCppuType(( const Reference< XPropertySet >*)NULL ) , + ::getCppuType(( const Reference< XFastPropertySet >*)NULL ) , + ::getCppuType(( const Reference< XMultiPropertySet >*)NULL ) , + ::getCppuType(( const Reference< XServiceInfo >*)NULL ) , + ::getCppuType(( const Reference< XTypeProvider >*)NULL ) ) ; + + // ... and set his address to static pointer! + pTypeCollection = &aTypeCollection ; + } + } + + return pTypeCollection->getTypes() ; +} + +Sequence< sal_Int8 > SAL_CALL ActionTriggerSeparatorPropertySet::getImplementationId() throw ( RuntimeException ) +{ + // Create one Id for all instances of this class. + // Use ethernet address to do this! (sal_True) + + // Optimize this method + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pID is NULL - for the second call pID is different from NULL! + static ::cppu::OImplementationId* pID = NULL ; + + if ( pID == NULL ) + { + // Ready for multithreading; get global mutex for first call of this method only! see before + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; + + // Control these pointer again ... it can be, that another instance will be faster then these! + if ( pID == NULL ) + { + // Create a new static ID ... + static ::cppu::OImplementationId aID( sal_False ) ; + // ... and set his address to static pointer! + pID = &aID ; + } + } + + return pID->getImplementationId() ; +} + +//--------------------------------------------------------------------------------------------------------- +// OPropertySetHelper implementation +//--------------------------------------------------------------------------------------------------------- + +sal_Bool SAL_CALL ActionTriggerSeparatorPropertySet::convertFastPropertyValue( + Any& aConvertedValue, + Any& aOldValue, + sal_Int32 nHandle, + const Any& aValue ) +throw( IllegalArgumentException ) +{ + // Check, if value of property will changed in method "setFastPropertyValue_NoBroadcast()". + // Return sal_True, if changed - else return sal_False. + // Attention: Method "impl_tryToChangeProperty()" can throw the IllegalArgumentException !!! + // Initialize return value with sal_False !!! + // (Handle can be invalid) + sal_Bool bReturn = sal_False; + + switch( nHandle ) + { + case HANDLE_TYPE: + bReturn = impl_tryToChangeProperty( m_nSeparatorType, aValue, aOldValue, aConvertedValue ); + break; + } + + // Return state of operation. + return bReturn; +} + + +void SAL_CALL ActionTriggerSeparatorPropertySet::setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, const Any& aValue ) +throw( Exception ) +{ + ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() ); + + // Search for right handle ... and try to set property value. + switch( nHandle ) + { + case HANDLE_TYPE: + aValue >>= m_nSeparatorType; + break; + } +} + +void SAL_CALL ActionTriggerSeparatorPropertySet::getFastPropertyValue( + Any& aValue, sal_Int32 nHandle ) const +{ + ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() ); + + // Search for right handle ... and try to get property value. + switch( nHandle ) + { + case HANDLE_TYPE: + aValue <<= m_nSeparatorType; + break; + } +} + +::cppu::IPropertyArrayHelper& SAL_CALL ActionTriggerSeparatorPropertySet::getInfoHelper() +{ + // Optimize this method ! + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pInfoHelper is NULL - for the second call pInfoHelper is different from NULL! + static OPropertyArrayHelper* pInfoHelper = NULL; + + if( pInfoHelper == NULL ) + { + // Ready for multithreading + ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() ); + // Control this pointer again, another instance can be faster then these! + if( pInfoHelper == NULL ) + { + // Define static member to give structure of properties to baseclass "OPropertySetHelper". + // "impl_getStaticPropertyDescriptor" is a non exported and static funtion, who will define a static propertytable. + // "sal_True" say: Table is sorted by name. + static OPropertyArrayHelper aInfoHelper( impl_getStaticPropertyDescriptor(), sal_True ); + pInfoHelper = &aInfoHelper; + } + } + + return (*pInfoHelper); +} + +Reference< XPropertySetInfo > SAL_CALL ActionTriggerSeparatorPropertySet::getPropertySetInfo() +throw ( RuntimeException ) +{ + // Optimize this method ! + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pInfo is NULL - for the second call pInfo is different from NULL! + static Reference< XPropertySetInfo >* pInfo = NULL ; + + if( pInfo == NULL ) + { + // Ready for multithreading + ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() ); + // Control this pointer again, another instance can be faster then these! + if( pInfo == NULL ) + { + // Create structure of propertysetinfo for baseclass "OPropertySetHelper". + // (Use method "getInfoHelper()".) + static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); + pInfo = &xInfo; + } + } + + return (*pInfo); +} + +const Sequence< Property > ActionTriggerSeparatorPropertySet::impl_getStaticPropertyDescriptor() +{ + static const Property pActionTriggerPropertys[] = + { + Property( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SeparatorType" )), HANDLE_TYPE, ::getCppuType((sal_Int16*)0), PropertyAttribute::TRANSIENT ) + }; + + // Use it to initialize sequence! + static const Sequence< Property > seqActionTriggerPropertyDescriptor( pActionTriggerPropertys, PROPERTYCOUNT ); + + // Return static "PropertyDescriptor" + return seqActionTriggerPropertyDescriptor ; +} + + +//****************************************************************************************************************************** +// private method +//****************************************************************************************************************************** +sal_Bool ActionTriggerSeparatorPropertySet::impl_tryToChangeProperty( + sal_Int16 aCurrentValue , + const Any& aNewValue , + Any& aOldValue , + Any& aConvertedValue ) +throw( IllegalArgumentException ) +{ + // Set default return value if method failed. + sal_Bool bReturn = sal_False; + // Get new value from any. + // IllegalArgumentException() can be thrown! + sal_Int16 aValue = 0; + convertPropertyValue( aValue, aNewValue ); + + // If value change ... + if( aValue != aCurrentValue ) + { + // ... set information of change. + aOldValue <<= aCurrentValue ; + aConvertedValue <<= aValue ; + // Return OK - "value will be change ..." + bReturn = sal_True; + } + else + { + // ... clear information of return parameter! + aOldValue.clear () ; + aConvertedValue.clear () ; + // Return NOTHING - "value will not be change ..." + bReturn = sal_False; + } + + return bReturn; +} + +} + diff --git a/framework/source/fwe/classes/addonmenu.cxx b/framework/source/fwe/classes/addonmenu.cxx new file mode 100644 index 000000000000..811a4bdfc383 --- /dev/null +++ b/framework/source/fwe/classes/addonmenu.cxx @@ -0,0 +1,456 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "framework/addonmenu.hxx" +#include "framework/addonsoptions.hxx" +#include <general.h> +#include <macros/debug/assertion.hxx> +#include <framework/imageproducer.hxx> +#include <framework/menuconfiguration.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/util/URL.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ +#include <tools/config.hxx> +#include <vcl/svapp.hxx> +#include <svtools/menuoptions.hxx> +#include <svl/solar.hrc> +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::beans; + +// Please look at sfx2/inc/sfxsids.hrc the values are defined there. Due to build dependencies +// we cannot include the header file. +const sal_uInt16 SID_HELPMENU = (SID_SFX_START + 410); +const sal_uInt16 SID_ONLINE_REGISTRATION = (SID_SFX_START + 1537); + +namespace framework +{ + +AddonMenu::AddonMenu( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame ) : + m_xFrame( rFrame ) +{ +} + +AddonMenu::~AddonMenu() +{ + for ( sal_uInt16 i = 0; i < GetItemCount(); i++ ) + { + if ( GetItemType( i ) != MENUITEM_SEPARATOR ) + { + // delete user attributes created with new! + sal_uInt16 nId = GetItemId( i ); + MenuConfiguration::Attributes* pUserAttributes = (MenuConfiguration::Attributes*)GetUserValue( nId ); + delete pUserAttributes; + delete GetPopupMenu( nId ); + } + } +} + +// ------------------------------------------------------------------------ + +// ------------------------------------------------------------------------ +// Check if command URL string has the unique prefix to identify addon popup menus +sal_Bool AddonPopupMenu::IsCommandURLPrefix( const ::rtl::OUString& aCmdURL ) +{ + const char aPrefixCharBuf[] = ADDONSPOPUPMENU_URL_PREFIX_STR; + + return aCmdURL.matchAsciiL( aPrefixCharBuf, sizeof( aPrefixCharBuf )-1, 0 ); +} + +AddonPopupMenu::AddonPopupMenu( const com::sun::star::uno::Reference< com::sun::star::frame::XFrame >& rFrame ) : + AddonMenu( rFrame ) +{ +} + +AddonPopupMenu::~AddonPopupMenu() +{ +} + +// ------------------------------------------------------------------------ + +static Reference< XModel > GetModelFromFrame( const Reference< XFrame >& rFrame ) +{ + // Query for the model to get check the context information + Reference< XModel > xModel; + if ( rFrame.is() ) + { + Reference< XController > xController( rFrame->getController(), UNO_QUERY ); + if ( xController.is() ) + xModel = xController->getModel(); + } + + return xModel; +} + +// ------------------------------------------------------------------------ + +sal_Bool AddonMenuManager::HasAddonMenuElements() +{ + return AddonsOptions().HasAddonsMenu(); +} + +sal_Bool AddonMenuManager::HasAddonHelpMenuElements() +{ + return AddonsOptions().HasAddonsHelpMenu(); +} + +// Factory method to create different Add-On menu types +PopupMenu* AddonMenuManager::CreatePopupMenuType( MenuType eMenuType, const Reference< XFrame >& rFrame ) +{ + if ( eMenuType == ADDON_MENU ) + return new AddonMenu( rFrame ); + else if ( eMenuType == ADDON_POPUPMENU ) + return new AddonPopupMenu( rFrame ); + else + return NULL; +} + +// Create the Add-Ons menu +AddonMenu* AddonMenuManager::CreateAddonMenu( const Reference< XFrame >& rFrame ) +{ + AddonsOptions aOptions; + AddonMenu* pAddonMenu = NULL; + sal_uInt16 nUniqueMenuId = ADDONMENU_ITEMID_START; + + const Sequence< Sequence< PropertyValue > >& rAddonMenuEntries = aOptions.GetAddonsMenu(); + if ( rAddonMenuEntries.getLength() > 0 ) + { + pAddonMenu = (AddonMenu *)AddonMenuManager::CreatePopupMenuType( ADDON_MENU, rFrame ); + Reference< XModel > xModel = GetModelFromFrame( rFrame ); + AddonMenuManager::BuildMenu( pAddonMenu, ADDON_MENU, MENU_APPEND, nUniqueMenuId, rAddonMenuEntries, rFrame, xModel ); + + // Don't return an empty Add-On menu + if ( pAddonMenu->GetItemCount() == 0 ) + { + delete pAddonMenu; + pAddonMenu = NULL; + } + } + + return pAddonMenu; +} + +// Returns the next insert position from nPos. +sal_uInt16 AddonMenuManager::GetNextPos( sal_uInt16 nPos ) +{ + return ( nPos == MENU_APPEND ) ? MENU_APPEND : ( nPos+1 ); +} + + +static sal_uInt16 FindMenuId( Menu* pMenu, const String aCommand ) +{ + sal_uInt16 nPos = 0; + String aCmd; + for ( nPos = 0; nPos < pMenu->GetItemCount(); nPos++ ) + { + sal_uInt16 nId = pMenu->GetItemId( nPos ); + aCmd = pMenu->GetItemCommand( nId ); + if ( aCmd == aCommand ) + return nId; + } + + return USHRT_MAX; +} + + +// Merge the Add-Ons help menu items into the given menu bar at a defined pos +void AddonMenuManager::MergeAddonHelpMenu( const Reference< XFrame >& rFrame, MenuBar* pMergeMenuBar ) +{ + if ( pMergeMenuBar ) + { + PopupMenu* pHelpMenu = pMergeMenuBar->GetPopupMenu( SID_HELPMENU ); + if ( !pHelpMenu ) + { + sal_uInt16 nId = FindMenuId( pMergeMenuBar, String::CreateFromAscii( ".uno:HelpMenu" )); + if ( nId != USHRT_MAX ) + pHelpMenu = pMergeMenuBar->GetPopupMenu( nId ); + } + + if ( pHelpMenu ) + { + static const char REFERENCECOMMAND_AFTER[] = ".uno:OnlineRegistrationDlg"; + static const char REFERENCECOMMAND_BEFORE[] = ".uno:About"; + + // Add-Ons help menu items should be inserted after the "registration" menu item + bool bAddAfter = true; + sal_uInt16 nItemCount = pHelpMenu->GetItemCount(); + sal_uInt16 nRegPos = pHelpMenu->GetItemPos( SID_ONLINE_REGISTRATION ); + sal_uInt16 nInsPos = nRegPos; + sal_uInt16 nInsSepAfterPos = MENU_APPEND; + sal_uInt16 nUniqueMenuId = ADDONMENU_ITEMID_START; + AddonsOptions aOptions; + + if ( nRegPos == USHRT_MAX ) + { + // try to detect the online registration dialog menu item with the command URL + sal_uInt16 nId = FindMenuId( pHelpMenu, String::CreateFromAscii( REFERENCECOMMAND_AFTER )); + nRegPos = pHelpMenu->GetItemPos( nId ); + nInsPos = nRegPos; + } + + if ( nRegPos == USHRT_MAX ) + { + // second try: + // try to detect the about menu item with the command URL + sal_uInt16 nId = FindMenuId( pHelpMenu, String::CreateFromAscii( REFERENCECOMMAND_BEFORE )); + nRegPos = pHelpMenu->GetItemPos( nId ); + nInsPos = nRegPos; + bAddAfter = false; + } + + Sequence< Sequence< PropertyValue > > aAddonSubMenu; + const Sequence< Sequence< PropertyValue > >& rAddonHelpMenuEntries = aOptions.GetAddonsHelpMenu(); + + nInsPos = bAddAfter ? AddonMenuManager::GetNextPos( nInsPos ) : nInsPos; + if ( nInsPos < nItemCount && pHelpMenu->GetItemType( nInsPos ) != MENUITEM_SEPARATOR ) + nInsSepAfterPos = nInsPos; + + Reference< XModel > xModel = GetModelFromFrame( rFrame ); + AddonMenuManager::BuildMenu( pHelpMenu, ADDON_MENU, nInsPos, nUniqueMenuId, rAddonHelpMenuEntries, rFrame, xModel ); + + if ( pHelpMenu->GetItemCount() > nItemCount ) + { + if ( nInsSepAfterPos < MENU_APPEND ) + { + nInsSepAfterPos += ( pHelpMenu->GetItemCount() - nItemCount ); + if ( pHelpMenu->GetItemType( nInsSepAfterPos ) != MENUITEM_SEPARATOR ) + pHelpMenu->InsertSeparator( nInsSepAfterPos ); + } + if ( nRegPos < MENU_APPEND ) + pHelpMenu->InsertSeparator( nRegPos+1 ); + else + pHelpMenu->InsertSeparator( nItemCount ); + } + } + } +} + +// Merge the addon popup menus into the given menu bar at the provided pos. +void AddonMenuManager::MergeAddonPopupMenus( const Reference< XFrame >& rFrame, + const Reference< XModel >& rModel, + sal_uInt16 nMergeAtPos, + MenuBar* pMergeMenuBar ) +{ + if ( pMergeMenuBar ) + { + AddonsOptions aAddonsOptions; + sal_uInt16 nInsertPos = nMergeAtPos; + + ::rtl::OUString aTitle; + ::rtl::OUString aURL; + ::rtl::OUString aTarget; + ::rtl::OUString aImageId; + ::rtl::OUString aContext; + Sequence< Sequence< PropertyValue > > aAddonSubMenu; + sal_uInt16 nUniqueMenuId = ADDONMENU_ITEMID_START; + + const Sequence< Sequence< PropertyValue > >& rAddonMenuEntries = aAddonsOptions.GetAddonsMenuBarPart(); + for ( sal_Int32 i = 0; i < rAddonMenuEntries.getLength(); i++ ) + { + AddonMenuManager::GetMenuEntry( rAddonMenuEntries[i], + aTitle, + aURL, + aTarget, + aImageId, + aContext, + aAddonSubMenu ); + if ( aTitle.getLength() > 0 && + aURL.getLength() > 0 && + aAddonSubMenu.getLength() > 0 && + AddonMenuManager::IsCorrectContext( rModel, aContext )) + { + sal_uInt16 nId = nUniqueMenuId++; + AddonPopupMenu* pAddonPopupMenu = (AddonPopupMenu *)AddonMenuManager::CreatePopupMenuType( ADDON_POPUPMENU, rFrame ); + + AddonMenuManager::BuildMenu( pAddonPopupMenu, ADDON_MENU, MENU_APPEND, nUniqueMenuId, aAddonSubMenu, rFrame, rModel ); + + if ( pAddonPopupMenu->GetItemCount() > 0 ) + { + pAddonPopupMenu->SetCommandURL( aURL ); + pMergeMenuBar->InsertItem( nId, aTitle, 0, nInsertPos++ ); + pMergeMenuBar->SetPopupMenu( nId, pAddonPopupMenu ); + + // Store the command URL into the VCL menu bar for later identification + pMergeMenuBar->SetItemCommand( nId, aURL ); + } + else + delete pAddonPopupMenu; + } + } + } +} + +// Insert the menu and sub menu entries into pCurrentMenu with the aAddonMenuDefinition provided +void AddonMenuManager::BuildMenu( PopupMenu* pCurrentMenu, + MenuType nSubMenuType, + sal_uInt16 nInsPos, + sal_uInt16& nUniqueMenuId, + Sequence< Sequence< PropertyValue > > aAddonMenuDefinition, + const Reference< XFrame >& rFrame, + const Reference< XModel >& rModel ) +{ + Sequence< Sequence< PropertyValue > > aAddonSubMenu; + sal_Bool bInsertSeparator = sal_False; + sal_uInt32 i = 0; + sal_uInt32 nElements = 0; + sal_uInt32 nCount = aAddonMenuDefinition.getLength(); + AddonsOptions aAddonsOptions; + + ::rtl::OUString aTitle; + ::rtl::OUString aURL; + ::rtl::OUString aTarget; + ::rtl::OUString aImageId; + ::rtl::OUString aContext; + + for ( i = 0; i < nCount; ++i ) + { + GetMenuEntry( aAddonMenuDefinition[i], aTitle, aURL, aTarget, aImageId, aContext, aAddonSubMenu ); + + if ( !IsCorrectContext( rModel, aContext ) || ( !aTitle.getLength() && !aURL.getLength() )) + continue; + + if ( aURL == ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:separator" ))) + bInsertSeparator = sal_True; + else + { + PopupMenu* pSubMenu = NULL; + if ( aAddonSubMenu.getLength() > 0 ) + { + pSubMenu = AddonMenuManager::CreatePopupMenuType( nSubMenuType, rFrame ); + AddonMenuManager::BuildMenu( pSubMenu, nSubMenuType, MENU_APPEND, nUniqueMenuId, aAddonSubMenu, rFrame, rModel ); + + // Don't create a menu item for an empty sub menu + if ( pSubMenu->GetItemCount() == 0 ) + { + delete pSubMenu; + pSubMenu = NULL; + continue; + } + } + + if ( bInsertSeparator && nElements > 0 ) + { + // Insert a separator only when we insert a new element afterwards and we + // have already one before us + nElements = 0; + bInsertSeparator = sal_False; + pCurrentMenu->InsertSeparator( nInsPos ); + nInsPos = AddonMenuManager::GetNextPos( nInsPos ); + } + + sal_uInt16 nId = nUniqueMenuId++; + pCurrentMenu->InsertItem( nId, aTitle, 0, nInsPos ); + nInsPos = AddonMenuManager::GetNextPos( nInsPos ); + + ++nElements; + + // Store values from configuration to the New and Wizard menu entries to enable + // sfx2 based code to support high contrast mode correctly! + pCurrentMenu->SetUserValue( nId, sal_uIntPtr( new MenuConfiguration::Attributes( aTarget, aImageId )) ); + pCurrentMenu->SetItemCommand( nId, aURL ); + + if ( pSubMenu ) + pCurrentMenu->SetPopupMenu( nId, pSubMenu ); + } + } +} + +// Retrieve the menu entry property values from a sequence +void AddonMenuManager::GetMenuEntry( const Sequence< PropertyValue >& rAddonMenuEntry, + ::rtl::OUString& rTitle, + ::rtl::OUString& rURL, + ::rtl::OUString& rTarget, + ::rtl::OUString& rImageId, + ::rtl::OUString& rContext, + Sequence< Sequence< PropertyValue > >& rAddonSubMenu ) +{ + // Reset submenu parameter + rAddonSubMenu = Sequence< Sequence< PropertyValue > >(); + + for ( int i = 0; i < rAddonMenuEntry.getLength(); i++ ) + { + ::rtl::OUString aMenuEntryPropName = rAddonMenuEntry[i].Name; + if ( aMenuEntryPropName == ADDONSMENUITEM_PROPERTYNAME_URL ) + rAddonMenuEntry[i].Value >>= rURL; + else if ( aMenuEntryPropName == ADDONSMENUITEM_PROPERTYNAME_TITLE ) + rAddonMenuEntry[i].Value >>= rTitle; + else if ( aMenuEntryPropName == ADDONSMENUITEM_PROPERTYNAME_TARGET ) + rAddonMenuEntry[i].Value >>= rTarget; + else if ( aMenuEntryPropName == ADDONSMENUITEM_PROPERTYNAME_IMAGEIDENTIFIER ) + rAddonMenuEntry[i].Value >>= rImageId; + else if ( aMenuEntryPropName == ADDONSMENUITEM_PROPERTYNAME_SUBMENU ) + rAddonMenuEntry[i].Value >>= rAddonSubMenu; + else if ( aMenuEntryPropName == ADDONSMENUITEM_PROPERTYNAME_CONTEXT ) + rAddonMenuEntry[i].Value >>= rContext; + } +} + +// Check if the context string matches the provided xModel context +sal_Bool AddonMenuManager::IsCorrectContext( const Reference< XModel >& rModel, const ::rtl::OUString& aContext ) +{ + if ( rModel.is() ) + { + Reference< com::sun::star::lang::XServiceInfo > xServiceInfo( rModel, UNO_QUERY ); + if ( xServiceInfo.is() ) + { + sal_Int32 nIndex = 0; + do + { + ::rtl::OUString aToken = aContext.getToken( 0, ',', nIndex ); + + if ( xServiceInfo->supportsService( aToken )) + return sal_True; + } + while ( nIndex >= 0 ); + } + } + + return ( aContext.getLength() == 0 ); +} + +} + diff --git a/framework/source/fwe/classes/addonsoptions.cxx b/framework/source/fwe/classes/addonsoptions.cxx new file mode 100644 index 000000000000..1d947c651a67 --- /dev/null +++ b/framework/source/fwe/classes/addonsoptions.cxx @@ -0,0 +1,1858 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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" + +//_________________________________________________________________________________________________________________ +// includes +//_________________________________________________________________________________________________________________ +#include <framework/addonsoptions.hxx> +#include <unotools/configmgr.hxx> +#include <unotools/configitem.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <tools/debug.hxx> +#include <tools/stream.hxx> +#include <tools/color.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include "com/sun/star/util/XMacroExpander.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/beans/XPropertySet.hpp" +#include <rtl/ustrbuf.hxx> +#include <rtl/uri.hxx> +#include <comphelper/processfactory.hxx> +#include <vcl/graph.hxx> +#include <svtools/filter.hxx> + +#include <hash_map> +#include <algorithm> +#include <vector> + +//_________________________________________________________________________________________________________________ +// namespaces +//_________________________________________________________________________________________________________________ + +using namespace ::std ; +using namespace ::utl ; +using namespace ::osl ; +using namespace ::com::sun::star::uno ; +using namespace ::com::sun::star::beans ; +using namespace ::com::sun::star::lang ; + +//_________________________________________________________________________________________________________________ +// const +//_________________________________________________________________________________________________________________ + +#define ROOTNODE_ADDONMENU ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Addons" )) +#define PATHDELIMITER ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/" )) +#define TOOLBARITEMS ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ToolBarItems" )) +#define SEPARATOR_URL_STR "private:separator" +#define SEPARATOR_URL_LEN 17 +#define SEPARATOR_URL ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SEPARATOR_URL_STR )) + +#define PROPERTYNAME_URL ADDONSMENUITEM_PROPERTYNAME_URL +#define PROPERTYNAME_TITLE ADDONSMENUITEM_PROPERTYNAME_TITLE +#define PROPERTYNAME_TARGET ADDONSMENUITEM_PROPERTYNAME_TARGET +#define PROPERTYNAME_IMAGEIDENTIFIER ADDONSMENUITEM_PROPERTYNAME_IMAGEIDENTIFIER +#define PROPERTYNAME_CONTEXT ADDONSMENUITEM_PROPERTYNAME_CONTEXT +#define PROPERTYNAME_SUBMENU ADDONSMENUITEM_PROPERTYNAME_SUBMENU +#define PROPERTYNAME_CONTROLTYPE ADDONSMENUITEM_PROPERTYNAME_CONTROLTYPE +#define PROPERTYNAME_WIDTH ADDONSMENUITEM_PROPERTYNAME_WIDTH + +#define PROPERTYNAME_IMAGESMALL ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageSmall" )) +#define PROPERTYNAME_IMAGEBIG ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageBig" )) +#define PROPERTYNAME_IMAGESMALLHC ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageSmallHC" )) +#define PROPERTYNAME_IMAGEBIGHC ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageBigHC" )) +#define PROPERTYNAME_IMAGESMALL_URL ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageSmallURL" )) +#define PROPERTYNAME_IMAGEBIG_URL ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageBigURL" )) +#define PROPERTYNAME_IMAGESMALLHC_URL ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageSmallHCURL" )) +#define PROPERTYNAME_IMAGEBIGHC_URL ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageBigHCURL" )) + +#define IMAGES_NODENAME ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("UserDefinedImages" )) +#define PRIVATE_IMAGE_URL ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:image/" )) + +#define PROPERTYNAME_MERGEMENU_MERGEPOINT ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergePoint" )) +#define PROPERTYNAME_MERGEMENU_MERGECOMMAND ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeCommand" )) +#define PROPERTYNAME_MERGEMENU_MERGECOMMANDPARAMETER ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeCommandParameter" )) +#define PROPERTYNAME_MERGEMENU_MERGEFALLBACK ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeFallback" )) +#define PROPERTYNAME_MERGEMENU_MERGECONTEXT ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeContext" )) +#define PROPERTYNAME_MERGEMENU_MENUITEMS ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MenuItems" )) +#define MERGEMENU_MERGEPOINT_SEPARATOR '\\' + +#define PROPERTYNAME_MERGETOOLBAR_TOOLBAR ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeToolBar" )) +#define PROPERTYNAME_MERGETOOLBAR_MERGEPOINT ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergePoint" )) +#define PROPERTYNAME_MERGETOOLBAR_MERGECOMMAND ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeCommand" )) +#define PROPERTYNAME_MERGETOOLBAR_MERGECOMMANDPARAMETER ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeCommandParameter" )) +#define PROPERTYNAME_MERGETOOLBAR_MERGEFALLBACK ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeFallback" )) +#define PROPERTYNAME_MERGETOOLBAR_MERGECONTEXT ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeContext" )) +#define PROPERTYNAME_MERGETOOLBAR_TOOLBARITEMS ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ToolBarItems" )) + +// The following order is mandatory. Please add properties at the end! +#define INDEX_URL 0 +#define INDEX_TITLE 1 +#define INDEX_IMAGEIDENTIFIER 2 +#define INDEX_TARGET 3 +#define INDEX_CONTEXT 4 +#define INDEX_SUBMENU 5 +#define INDEX_CONTROLTYPE 6 +#define INDEX_WIDTH 7 +#define PROPERTYCOUNT_INDEX 8 + +// The following order is mandatory. Please add properties at the end! +#define PROPERTYCOUNT_MENUITEM 6 +#define OFFSET_MENUITEM_URL 0 +#define OFFSET_MENUITEM_TITLE 1 +#define OFFSET_MENUITEM_IMAGEIDENTIFIER 2 +#define OFFSET_MENUITEM_TARGET 3 +#define OFFSET_MENUITEM_CONTEXT 4 +#define OFFSET_MENUITEM_SUBMENU 5 + +// The following order is mandatory. Please add properties at the end! +#define PROPERTYCOUNT_POPUPMENU 4 +#define OFFSET_POPUPMENU_TITLE 0 +#define OFFSET_POPUPMENU_CONTEXT 1 +#define OFFSET_POPUPMENU_SUBMENU 2 +#define OFFSET_POPUPMENU_URL 3 // Used for property set + +// The following order is mandatory. Please add properties at the end! +#define PROPERTYCOUNT_TOOLBARITEM 7 +#define OFFSET_TOOLBARITEM_URL 0 +#define OFFSET_TOOLBARITEM_TITLE 1 +#define OFFSET_TOOLBARITEM_IMAGEIDENTIFIER 2 +#define OFFSET_TOOLBARITEM_TARGET 3 +#define OFFSET_TOOLBARITEM_CONTEXT 4 +#define OFFSET_TOOLBARITEM_CONTROLTYPE 5 +#define OFFSET_TOOLBARITEM_WIDTH 6 + +// The following order is mandatory. Please add properties at the end! +#define PROPERTYCOUNT_IMAGES 8 +#define PROPERTYCOUNT_EMBEDDED_IMAGES 4 +#define OFFSET_IMAGES_SMALL 0 +#define OFFSET_IMAGES_BIG 1 +#define OFFSET_IMAGES_SMALLHC 2 +#define OFFSET_IMAGES_BIGHC 3 +#define OFFSET_IMAGES_SMALL_URL 4 +#define OFFSET_IMAGES_BIG_URL 5 +#define OFFSET_IMAGES_SMALLHC_URL 6 +#define OFFSET_IMAGES_BIGHC_URL 7 + +#define PROPERTYCOUNT_MERGE_MENUBAR 6 +#define OFFSET_MERGEMENU_MERGEPOINT 0 +#define OFFSET_MERGEMENU_MERGECOMMAND 1 +#define OFFSET_MERGEMENU_MERGECOMMANDPARAMETER 2 +#define OFFSET_MERGEMENU_MERGEFALLBACK 3 +#define OFFSET_MERGEMENU_MERGECONTEXT 4 +#define OFFSET_MERGEMENU_MENUITEMS 5 + +#define PROPERTYCOUNT_MERGE_TOOLBAR 7 +#define OFFSET_MERGETOOLBAR_TOOLBAR 0 +#define OFFSET_MERGETOOLBAR_MERGEPOINT 1 +#define OFFSET_MERGETOOLBAR_MERGECOMMAND 2 +#define OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER 3 +#define OFFSET_MERGETOOLBAR_MERGEFALLBACK 4 +#define OFFSET_MERGETOOLBAR_MERGECONTEXT 5 +#define OFFSET_MERGETOOLBAR_TOOLBARITEMS 6 + +#define EXPAND_PROTOCOL "vnd.sun.star.expand:" + +const Size aImageSizeSmall( 16, 16 ); +const Size aImageSizeBig( 26, 26 ); + +//_________________________________________________________________________________________________________________ +// private declarations! +//_________________________________________________________________________________________________________________ + +/*-**************************************************************************************************************** + @descr struct to hold information about one menu entry. +****************************************************************************************************************-*/ + +namespace framework +{ + +class AddonsOptions_Impl : public ConfigItem +{ + //------------------------------------------------------------------------------------------------------------- + // public methods + //------------------------------------------------------------------------------------------------------------- + + public: + //--------------------------------------------------------------------------------------------------------- + // constructor / destructor + //--------------------------------------------------------------------------------------------------------- + + AddonsOptions_Impl(); + ~AddonsOptions_Impl(); + + //--------------------------------------------------------------------------------------------------------- + // overloaded methods of baseclass + //--------------------------------------------------------------------------------------------------------- + + /*-****************************************************************************************************//** + @short called for notify of configmanager + @descr These method is called from the ConfigManager before application ends or from the + PropertyChangeListener if the sub tree broadcasts changes. You must update your + internal values. + + @seealso baseclass ConfigItem + + @param "lPropertyNames" is the list of properties which should be updated. + @return - + + @onerror - + *//*-*****************************************************************************************************/ + + virtual void Notify( const Sequence< ::rtl::OUString >& lPropertyNames ); + + /*-****************************************************************************************************//** + @short write changes to configuration + @descr These method writes the changed values into the sub tree + and should always called in our destructor to guarantee consistency of config data. + + @seealso baseclass ConfigItem + + @param - + @return - + + @onerror - + *//*-*****************************************************************************************************/ + + virtual void Commit(); + + //--------------------------------------------------------------------------------------------------------- + // public interface + //--------------------------------------------------------------------------------------------------------- + + /*-****************************************************************************************************//** + @short base implementation of public interface for "SvtDynamicMenuOptions"! + @descr These class is used as static member of "SvtDynamicMenuOptions" ... + => The code exist only for one time and isn't duplicated for every instance! + + @seealso - + + @param - + @return - + + @onerror - + *//*-*****************************************************************************************************/ + + sal_Bool HasAddonsMenu () const ; + sal_Bool HasAddonsHelpMenu () const ; + sal_Int32 GetAddonsToolBarCount() const ; + const Sequence< Sequence< PropertyValue > >& GetAddonsMenu () const ; + const Sequence< Sequence< PropertyValue > >& GetAddonsMenuBarPart () const ; + const Sequence< Sequence< PropertyValue > >& GetAddonsToolBarPart ( sal_uInt32 nIndex ) const ; + const ::rtl::OUString GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const; + const Sequence< Sequence< PropertyValue > >& GetAddonsHelpMenu () const ; + Image GetImageFromURL( const rtl::OUString& aURL, sal_Bool bBig, sal_Bool bHiContrast, sal_Bool bNoScale ) const; + const MergeMenuInstructionContainer& GetMergeMenuInstructions() const; + bool GetMergeToolbarInstructions( const ::rtl::OUString& rToolbarName, MergeToolbarInstructionContainer& rToolbarInstructions ) const; + + void ReadConfigurationData(); + + //------------------------------------------------------------------------------------------------------------- + // private methods + //------------------------------------------------------------------------------------------------------------- + + private: + struct OUStringHashCode + { + size_t operator()( const ::rtl::OUString& sString ) const + { + return sString.hashCode(); + } + }; + + struct ImageEntry + { + Image aImageSmall; + Image aImageBig; + Image aImageSmallHC; + Image aImageBigHC; + + Image aImageSmallNoScale; + Image aImageBigNoScale; + Image aImageSmallHCNoScale; + Image aImageBigHCNoScale; + }; + + typedef std::hash_map< ::rtl::OUString, ImageEntry, OUStringHashCode, ::std::equal_to< ::rtl::OUString > > ImageManager; + typedef std::hash_map< ::rtl::OUString, sal_uInt32, OUStringHashCode, ::std::equal_to< ::rtl::OUString > > StringToIndexMap; + typedef std::vector< Sequence< Sequence< PropertyValue > > > AddonToolBars; + typedef ::std::hash_map< ::rtl::OUString, MergeToolbarInstructionContainer, OUStringHashCode, ::std::equal_to< ::rtl::OUString > > ToolbarMergingInstructions; + + enum ImageSize + { + IMGSIZE_SMALL, + IMGSIZE_BIG + }; + + /*-****************************************************************************************************//** + @short return list of key names of our configuration management which represent oue module tree + @descr These methods return the current list of key names! We need it to get needed values from our + configuration management! + + @seealso - + + @param "nCount" , returns count of menu entries for "new" + @return A list of configuration key names is returned. + + @onerror - + *//*-*****************************************************************************************************/ + + sal_Bool ReadAddonMenuSet( Sequence< Sequence< PropertyValue > >& aAddonMenuSeq ); + sal_Bool ReadOfficeMenuBarSet( Sequence< Sequence< PropertyValue > >& aAddonOfficeMenuBarSeq ); + sal_Bool ReadOfficeToolBarSet( AddonToolBars& rAddonOfficeToolBars, std::vector< rtl::OUString >& rAddonOfficeToolBarResNames ); + sal_Bool ReadToolBarItemSet( const rtl::OUString rToolBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& aAddonOfficeToolBarSeq ); + sal_Bool ReadOfficeHelpSet( Sequence< Sequence< PropertyValue > >& aAddonOfficeHelpMenuSeq ); + sal_Bool ReadImages( ImageManager& aImageManager ); + sal_Bool ReadMenuMergeInstructions( MergeMenuInstructionContainer& rContainer ); + sal_Bool ReadToolbarMergeInstructions( ToolbarMergingInstructions& rToolbarMergeMap ); + + sal_Bool ReadMergeMenuData( const ::rtl::OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeMenu ); + sal_Bool ReadMergeToolbarData( const ::rtl::OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeToolbarItems ); + sal_Bool ReadMenuItem( const ::rtl::OUString& aMenuItemNodeName, Sequence< PropertyValue >& aMenuItem, sal_Bool bIgnoreSubMenu = sal_False ); + sal_Bool ReadPopupMenu( const ::rtl::OUString& aPopupMenuNodeName, Sequence< PropertyValue >& aPopupMenu ); + sal_Bool AppendPopupMenu( Sequence< PropertyValue >& aTargetPopupMenu, const Sequence< PropertyValue >& rSourcePopupMenu ); + sal_Bool ReadToolBarItem( const ::rtl::OUString& aToolBarItemNodeName, Sequence< PropertyValue >& aToolBarItem ); + sal_Bool ReadImagesItem( const ::rtl::OUString& aImagesItemNodeName, Sequence< PropertyValue >& aImagesItem ); + ImageEntry* ReadImageData( const ::rtl::OUString& aImagesNodeName ); + void ReadAndAssociateImages( const ::rtl::OUString& aURL, const ::rtl::OUString& aImageId ); + void ReadImageFromURL( ImageSize nImageSize, const ::rtl::OUString& aURL, Image& aImage, Image& aNoScaleImage ); + sal_Bool HasAssociatedImages( const ::rtl::OUString& aURL ); + void SubstituteVariables( ::rtl::OUString& aURL ); + + sal_Bool ReadSubMenuEntries( const Sequence< ::rtl::OUString >& aSubMenuNodeNames, Sequence< Sequence< PropertyValue > >& rSubMenu ); + void InsertToolBarSeparator( Sequence< Sequence< PropertyValue > >& rAddonOfficeToolBarSeq ); + ::rtl::OUString GeneratePrefixURL(); + + Sequence< ::rtl::OUString > GetPropertyNamesMergeMenuInstruction( const ::rtl::OUString& aPropertyRootName ) const; + Sequence< ::rtl::OUString > GetPropertyNamesMenuItem( const ::rtl::OUString& aPropertyRootNode ) const; + Sequence< ::rtl::OUString > GetPropertyNamesPopupMenu( const ::rtl::OUString& aPropertyRootNode ) const; + Sequence< ::rtl::OUString > GetPropertyNamesToolBarItem( const ::rtl::OUString& aPropertyRootNode ) const; + Sequence< ::rtl::OUString > GetPropertyNamesImages( const ::rtl::OUString& aPropertyRootNode ) const; + sal_Bool CreateImageFromSequence( Image& rImage, sal_Bool bBig, Sequence< sal_Int8 >& rBitmapDataSeq ) const; + + //------------------------------------------------------------------------------------------------------------- + // private member + //------------------------------------------------------------------------------------------------------------- + + private: + ImageEntry* ReadOptionalImageData( const ::rtl::OUString& aMenuNodeName ); + + sal_Int32 m_nRootAddonPopupMenuId; + ::rtl::OUString m_aPropNames[PROPERTYCOUNT_INDEX]; + ::rtl::OUString m_aPropImagesNames[PROPERTYCOUNT_IMAGES]; + ::rtl::OUString m_aPropMergeMenuNames[PROPERTYCOUNT_MERGE_MENUBAR]; + ::rtl::OUString m_aPropMergeToolbarNames[PROPERTYCOUNT_MERGE_TOOLBAR]; + ::rtl::OUString m_aEmpty; + ::rtl::OUString m_aPathDelimiter; + ::rtl::OUString m_aSeparator; + ::rtl::OUString m_aRootAddonPopupMenuURLPrexfix; + ::rtl::OUString m_aPrivateImageURL; + Sequence< Sequence< PropertyValue > > m_aCachedMenuProperties; + Sequence< Sequence< PropertyValue > > m_aCachedMenuBarPartProperties; + AddonToolBars m_aCachedToolBarPartProperties; + std::vector< rtl::OUString > m_aCachedToolBarPartResourceNames; + Sequence< Sequence< PropertyValue > > m_aCachedHelpMenuProperties; + Reference< com::sun::star::util::XMacroExpander > m_xMacroExpander; + ImageManager m_aImageManager; + Sequence< Sequence< PropertyValue > > m_aEmptyAddonToolBar; + MergeMenuInstructionContainer m_aCachedMergeMenuInsContainer; + ToolbarMergingInstructions m_aCachedToolbarMergingInstructions; +}; + +//_________________________________________________________________________________________________________________ +// definitions +//_________________________________________________________________________________________________________________ + +//***************************************************************************************************************** +// constructor +//***************************************************************************************************************** +AddonsOptions_Impl::AddonsOptions_Impl() + // Init baseclasses first + : ConfigItem( ROOTNODE_ADDONMENU ), + m_nRootAddonPopupMenuId( 0 ), + m_aPathDelimiter( PATHDELIMITER ), + m_aSeparator( SEPARATOR_URL ), + m_aRootAddonPopupMenuURLPrexfix( ADDONSPOPUPMENU_URL_PREFIX ), + m_aPrivateImageURL( PRIVATE_IMAGE_URL ) +{ + // initialize array with fixed property names + m_aPropNames[ INDEX_URL ] = PROPERTYNAME_URL; + m_aPropNames[ INDEX_TITLE ] = PROPERTYNAME_TITLE; + m_aPropNames[ INDEX_TARGET ] = PROPERTYNAME_TARGET; + m_aPropNames[ INDEX_IMAGEIDENTIFIER ] = PROPERTYNAME_IMAGEIDENTIFIER; + m_aPropNames[ INDEX_CONTEXT ] = PROPERTYNAME_CONTEXT; + m_aPropNames[ INDEX_SUBMENU ] = PROPERTYNAME_SUBMENU; // Submenu set! + m_aPropNames[ INDEX_CONTROLTYPE ] = PROPERTYNAME_CONTROLTYPE; + m_aPropNames[ INDEX_WIDTH ] = PROPERTYNAME_WIDTH; + + // initialize array with fixed images property names + m_aPropImagesNames[ OFFSET_IMAGES_SMALL ] = PROPERTYNAME_IMAGESMALL; + m_aPropImagesNames[ OFFSET_IMAGES_BIG ] = PROPERTYNAME_IMAGEBIG; + m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC ] = PROPERTYNAME_IMAGESMALLHC; + m_aPropImagesNames[ OFFSET_IMAGES_BIGHC ] = PROPERTYNAME_IMAGEBIGHC; + m_aPropImagesNames[ OFFSET_IMAGES_SMALL_URL ] = PROPERTYNAME_IMAGESMALL_URL; + m_aPropImagesNames[ OFFSET_IMAGES_BIG_URL ] = PROPERTYNAME_IMAGEBIG_URL; + m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC_URL ] = PROPERTYNAME_IMAGESMALLHC_URL; + m_aPropImagesNames[ OFFSET_IMAGES_BIGHC_URL ] = PROPERTYNAME_IMAGEBIGHC_URL; + + // initialize array with fixed merge menu property names + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT ] = PROPERTYNAME_MERGEMENU_MERGEPOINT; + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND ] = PROPERTYNAME_MERGEMENU_MERGECOMMAND; + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] = PROPERTYNAME_MERGEMENU_MERGECOMMANDPARAMETER; + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ] = PROPERTYNAME_MERGEMENU_MERGEFALLBACK; + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT ] = PROPERTYNAME_MERGEMENU_MERGECONTEXT; + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS ] = PROPERTYNAME_MERGEMENU_MENUITEMS; + + m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBAR ] = PROPERTYNAME_MERGETOOLBAR_TOOLBAR; + m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEPOINT ] = PROPERTYNAME_MERGETOOLBAR_MERGEPOINT; + m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMAND ] = PROPERTYNAME_MERGETOOLBAR_MERGECOMMAND; + m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER ] = PROPERTYNAME_MERGETOOLBAR_MERGECOMMANDPARAMETER; + m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEFALLBACK ] = PROPERTYNAME_MERGETOOLBAR_MERGEFALLBACK; + m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECONTEXT ] = PROPERTYNAME_MERGETOOLBAR_MERGECONTEXT; + m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBARITEMS ] = PROPERTYNAME_MERGETOOLBAR_TOOLBARITEMS; + + Reference< XComponentContext > xContext; + Reference< com::sun::star::beans::XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY ); + xProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext; + if ( xContext.is() ) + { + m_xMacroExpander = Reference< com::sun::star::util::XMacroExpander >( xContext->getValueByName( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.util.theMacroExpander"))), + UNO_QUERY ); + } + + ReadConfigurationData(); + + // Enable notification mechanism of ouer baseclass. + // We need it to get information about changes outside these class on ouer used configuration keys! + Sequence< rtl::OUString > aNotifySeq( 1 ); + aNotifySeq[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AddonUI" )); + EnableNotification( aNotifySeq ); +} + +//***************************************************************************************************************** +// destructor +//***************************************************************************************************************** +AddonsOptions_Impl::~AddonsOptions_Impl() +{ + // We must save our current values .. if user forget it! + if( IsModified() == sal_True ) + { + Commit(); + } +} + +void AddonsOptions_Impl::ReadConfigurationData() +{ + // reset members to be read again from configuration + m_aCachedMenuProperties = Sequence< Sequence< PropertyValue > >(); + m_aCachedMenuBarPartProperties = Sequence< Sequence< PropertyValue > >(); + m_aCachedToolBarPartProperties = AddonToolBars(); + m_aCachedHelpMenuProperties = Sequence< Sequence< PropertyValue > >(); + m_aCachedToolBarPartResourceNames.clear(); + m_aImageManager = ImageManager(); + + ReadAddonMenuSet( m_aCachedMenuProperties ); + ReadOfficeMenuBarSet( m_aCachedMenuBarPartProperties ); + ReadOfficeToolBarSet( m_aCachedToolBarPartProperties, m_aCachedToolBarPartResourceNames ); + ReadOfficeHelpSet( m_aCachedHelpMenuProperties ); + ReadImages( m_aImageManager ); + + m_aCachedMergeMenuInsContainer.clear(); + m_aCachedToolbarMergingInstructions.clear(); + + ReadMenuMergeInstructions( m_aCachedMergeMenuInsContainer ); + ReadToolbarMergeInstructions( m_aCachedToolbarMergingInstructions ); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +void AddonsOptions_Impl::Notify( const Sequence< ::rtl::OUString >& /*lPropertyNames*/ ) +{ + Application::PostUserEvent( STATIC_LINK( 0, AddonsOptions, Notify ) ); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +void AddonsOptions_Impl::Commit() +{ + DBG_ERROR( "AddonsOptions_Impl::Commit()\nNot implemented yet!\n" ); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::HasAddonsMenu() const +{ + return ( m_aCachedMenuProperties.getLength() > 0 ); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::HasAddonsHelpMenu () const +{ + return ( m_aCachedHelpMenuProperties.getLength() > 0 ); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +sal_Int32 AddonsOptions_Impl::GetAddonsToolBarCount() const +{ + return m_aCachedToolBarPartProperties.size(); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsMenu() const +{ + return m_aCachedMenuProperties; +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsMenuBarPart() const +{ + return m_aCachedMenuBarPartProperties; +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsToolBarPart( sal_uInt32 nIndex ) const +{ + if ( /*nIndex >= 0 &&*/ nIndex < m_aCachedToolBarPartProperties.size() ) + return m_aCachedToolBarPartProperties[nIndex]; + else + return m_aEmptyAddonToolBar; +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +const ::rtl::OUString AddonsOptions_Impl::GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const +{ + if ( nIndex < m_aCachedToolBarPartResourceNames.size() ) + return m_aCachedToolBarPartResourceNames[nIndex]; + else + return rtl::OUString(); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsHelpMenu () const +{ + return m_aCachedHelpMenuProperties; +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +const MergeMenuInstructionContainer& AddonsOptions_Impl::GetMergeMenuInstructions() const +{ + return m_aCachedMergeMenuInsContainer; +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +bool AddonsOptions_Impl::GetMergeToolbarInstructions( + const ::rtl::OUString& rToolbarName, + MergeToolbarInstructionContainer& rToolbarInstructions ) const +{ + ToolbarMergingInstructions::const_iterator pIter = m_aCachedToolbarMergingInstructions.find( rToolbarName ); + if ( pIter != m_aCachedToolbarMergingInstructions.end() ) + { + rToolbarInstructions = pIter->second; + return true; + } + else + return false; +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +Image AddonsOptions_Impl::GetImageFromURL( const rtl::OUString& aURL, sal_Bool bBig, sal_Bool bHiContrast, sal_Bool bNoScale ) const +{ + Image aImage; + + ImageManager::const_iterator pIter = m_aImageManager.find( aURL ); + if ( pIter != m_aImageManager.end() ) + { + if ( !bHiContrast ) + { + if ( bNoScale ) + aImage = ( bBig ? pIter->second.aImageBigNoScale : pIter->second.aImageSmallNoScale ); + if ( !aImage ) + aImage = ( bBig ? pIter->second.aImageBig : pIter->second.aImageSmall ); + } + else + { + if ( bNoScale ) + aImage = ( bBig ? pIter->second.aImageBigHCNoScale : pIter->second.aImageSmallHCNoScale ); + if ( !aImage ) + aImage = ( bBig ? pIter->second.aImageBigHC : pIter->second.aImageSmallHC ); + } + } + + return aImage; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::ReadAddonMenuSet( Sequence< Sequence< PropertyValue > >& rAddonMenuSeq ) +{ + // Read the AddonMenu set and fill property sequences + ::rtl::OUString aAddonMenuNodeName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/AddonMenu" )); + Sequence< ::rtl::OUString > aAddonMenuNodeSeq = GetNodeNames( aAddonMenuNodeName ); + ::rtl::OUString aAddonMenuItemNode( aAddonMenuNodeName + m_aPathDelimiter ); + + sal_uInt32 nCount = aAddonMenuNodeSeq.getLength(); + sal_uInt32 nIndex = 0; + Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM ); + + // Init the property value sequence + aMenuItem[ OFFSET_MENUITEM_URL ].Name = m_aPropNames[ INDEX_URL ]; + aMenuItem[ OFFSET_MENUITEM_TITLE ].Name = m_aPropNames[ INDEX_TITLE ]; + aMenuItem[ OFFSET_MENUITEM_TARGET ].Name = m_aPropNames[ INDEX_TARGET ]; + aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER]; + aMenuItem[ OFFSET_MENUITEM_CONTEXT ].Name = m_aPropNames[ INDEX_CONTEXT ]; + aMenuItem[ OFFSET_MENUITEM_SUBMENU ].Name = m_aPropNames[ INDEX_SUBMENU ]; // Submenu set! + + for ( sal_uInt32 n = 0; n < nCount; n++ ) + { + ::rtl::OUString aRootMenuItemNode( aAddonMenuItemNode + aAddonMenuNodeSeq[n] ); + + // Read the MenuItem + if ( ReadMenuItem( aRootMenuItemNode, aMenuItem ) ) + { + // Successfully read a menu item, append to our list + sal_uInt32 nMenuItemCount = rAddonMenuSeq.getLength() + 1; + rAddonMenuSeq.realloc( nMenuItemCount ); + rAddonMenuSeq[nIndex++] = aMenuItem; + } + } + + return ( rAddonMenuSeq.getLength() > 0 ); +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::ReadOfficeHelpSet( Sequence< Sequence< PropertyValue > >& rAddonOfficeHelpMenuSeq ) +{ + // Read the AddonMenu set and fill property sequences + ::rtl::OUString aAddonHelpMenuNodeName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/OfficeHelp" )); + Sequence< ::rtl::OUString > aAddonHelpMenuNodeSeq = GetNodeNames( aAddonHelpMenuNodeName ); + ::rtl::OUString aAddonHelpMenuItemNode( aAddonHelpMenuNodeName + m_aPathDelimiter ); + + sal_uInt32 nCount = aAddonHelpMenuNodeSeq.getLength(); + sal_uInt32 nIndex = 0; + Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM ); + + // Init the property value sequence + aMenuItem[ OFFSET_MENUITEM_URL ].Name = m_aPropNames[ INDEX_URL ]; + aMenuItem[ OFFSET_MENUITEM_TITLE ].Name = m_aPropNames[ INDEX_TITLE ]; + aMenuItem[ OFFSET_MENUITEM_TARGET ].Name = m_aPropNames[ INDEX_TARGET ]; + aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER]; + aMenuItem[ OFFSET_MENUITEM_CONTEXT ].Name = m_aPropNames[ INDEX_CONTEXT ]; + aMenuItem[ OFFSET_MENUITEM_SUBMENU ].Name = m_aPropNames[ INDEX_SUBMENU ]; // Submenu set! + + for ( sal_uInt32 n = 0; n < nCount; n++ ) + { + ::rtl::OUString aRootMenuItemNode( aAddonHelpMenuItemNode + aAddonHelpMenuNodeSeq[n] ); + + // Read the MenuItem + if ( ReadMenuItem( aRootMenuItemNode, aMenuItem, sal_True ) ) + { + // Successfully read a menu item, append to our list + sal_uInt32 nMenuItemCount = rAddonOfficeHelpMenuSeq.getLength() + 1; + rAddonOfficeHelpMenuSeq.realloc( nMenuItemCount ); + rAddonOfficeHelpMenuSeq[nIndex++] = aMenuItem; + } + } + + return ( rAddonOfficeHelpMenuSeq.getLength() > 0 ); +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::ReadOfficeMenuBarSet( Sequence< Sequence< PropertyValue > >& rAddonOfficeMenuBarSeq ) +{ + // Read the OfficeMenuBar set and fill property sequences + ::rtl::OUString aAddonMenuBarNodeName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/OfficeMenuBar" )); + Sequence< ::rtl::OUString > aAddonMenuBarNodeSeq = GetNodeNames( aAddonMenuBarNodeName ); + ::rtl::OUString aAddonMenuBarNode( aAddonMenuBarNodeName + m_aPathDelimiter ); + + sal_uInt32 nCount = aAddonMenuBarNodeSeq.getLength(); + sal_uInt32 nIndex = 0; + Sequence< PropertyValue > aPopupMenu( PROPERTYCOUNT_POPUPMENU ); + + // Init the property value sequence + aPopupMenu[ OFFSET_POPUPMENU_TITLE ].Name = m_aPropNames[ INDEX_TITLE ]; + aPopupMenu[ OFFSET_POPUPMENU_CONTEXT ].Name = m_aPropNames[ INDEX_CONTEXT]; + aPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Name = m_aPropNames[ INDEX_SUBMENU]; + aPopupMenu[ OFFSET_POPUPMENU_URL ].Name = m_aPropNames[ INDEX_URL ]; + + StringToIndexMap aTitleToIndexMap; + + for ( sal_uInt32 n = 0; n < nCount; n++ ) + { + ::rtl::OUString aPopupMenuNode( aAddonMenuBarNode + aAddonMenuBarNodeSeq[n] ); + + // Read the MenuItem + if ( ReadPopupMenu( aPopupMenuNode, aPopupMenu ) ) + { + // Successfully read a popup menu, append to our list + ::rtl::OUString aPopupTitle; + if ( aPopupMenu[OFFSET_POPUPMENU_TITLE].Value >>= aPopupTitle ) + { + StringToIndexMap::const_iterator pIter = aTitleToIndexMap.find( aPopupTitle ); + if ( pIter != aTitleToIndexMap.end() ) + { + // title already there => concat both popup menus + Sequence< PropertyValue >& rOldPopupMenu = rAddonOfficeMenuBarSeq[pIter->second]; + AppendPopupMenu( rOldPopupMenu, aPopupMenu ); + } + else + { + // not found + sal_uInt32 nMenuItemCount = rAddonOfficeMenuBarSeq.getLength() + 1; + rAddonOfficeMenuBarSeq.realloc( nMenuItemCount ); + rAddonOfficeMenuBarSeq[nIndex] = aPopupMenu; + aTitleToIndexMap.insert( StringToIndexMap::value_type( aPopupTitle, nIndex )); + ++nIndex; + } + } + } + } + + return ( rAddonOfficeMenuBarSeq.getLength() > 0 ); +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::ReadOfficeToolBarSet( AddonToolBars& rAddonOfficeToolBars, std::vector< rtl::OUString >& rAddonOfficeToolBarResNames ) +{ + // Read the OfficeToolBar set and fill property sequences + ::rtl::OUString aAddonToolBarNodeName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/OfficeToolBar" )); + Sequence< ::rtl::OUString > aAddonToolBarNodeSeq = GetNodeNames( aAddonToolBarNodeName ); + ::rtl::OUString aAddonToolBarNode( aAddonToolBarNodeName + m_aPathDelimiter ); + + sal_uInt32 nCount = aAddonToolBarNodeSeq.getLength(); + + for ( sal_uInt32 n = 0; n < nCount; n++ ) + { + ::rtl::OUString aToolBarItemNode( aAddonToolBarNode + aAddonToolBarNodeSeq[n] ); + rAddonOfficeToolBarResNames.push_back( aAddonToolBarNodeSeq[n] ); + rAddonOfficeToolBars.push_back( m_aEmptyAddonToolBar ); + ReadToolBarItemSet( aToolBarItemNode, rAddonOfficeToolBars[n] ); + } + + return ( !rAddonOfficeToolBars.empty() ); +} + + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::ReadToolBarItemSet( const rtl::OUString rToolBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& rAddonOfficeToolBarSeq ) +{ + sal_Bool bInsertSeparator = sal_False; + sal_uInt32 nToolBarItemCount = rAddonOfficeToolBarSeq.getLength(); + ::rtl::OUString aAddonToolBarItemSetNode( rToolBarItemSetNodeName + m_aPathDelimiter ); + Sequence< ::rtl::OUString > aAddonToolBarItemSetNodeSeq = GetNodeNames( rToolBarItemSetNodeName ); + Sequence< PropertyValue > aToolBarItem( PROPERTYCOUNT_TOOLBARITEM ); + + // Init the property value sequence + aToolBarItem[ OFFSET_TOOLBARITEM_URL ].Name = m_aPropNames[ INDEX_URL ]; + aToolBarItem[ OFFSET_TOOLBARITEM_TITLE ].Name = m_aPropNames[ INDEX_TITLE ]; + aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER]; + aToolBarItem[ OFFSET_TOOLBARITEM_TARGET ].Name = m_aPropNames[ INDEX_TARGET ]; + aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT ].Name = m_aPropNames[ INDEX_CONTEXT ]; + aToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE ].Name = m_aPropNames[ INDEX_CONTROLTYPE ]; + aToolBarItem[ OFFSET_TOOLBARITEM_WIDTH ].Name = m_aPropNames[ INDEX_WIDTH ]; + + sal_uInt32 nCount = aAddonToolBarItemSetNodeSeq.getLength(); + for ( sal_uInt32 n = 0; n < nCount; n++ ) + { + ::rtl::OUString aToolBarItemNode( aAddonToolBarItemSetNode + aAddonToolBarItemSetNodeSeq[n] ); + + // Read the ToolBarItem + if ( ReadToolBarItem( aToolBarItemNode, aToolBarItem ) ) + { + if ( bInsertSeparator ) + { + bInsertSeparator = sal_False; + InsertToolBarSeparator( rAddonOfficeToolBarSeq ); + } + + // Successfully read a toolbar item, append to our list + sal_uInt32 nAddonCount = rAddonOfficeToolBarSeq.getLength(); + rAddonOfficeToolBarSeq.realloc( nAddonCount+1 ); + rAddonOfficeToolBarSeq[nAddonCount] = aToolBarItem; + } + } + + return ( (sal_uInt32)rAddonOfficeToolBarSeq.getLength() > nToolBarItemCount ); +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +void AddonsOptions_Impl::InsertToolBarSeparator( Sequence< Sequence< PropertyValue > >& rAddonOfficeToolBarSeq ) +{ + Sequence< PropertyValue > aToolBarItem( PROPERTYCOUNT_TOOLBARITEM ); + + aToolBarItem[ OFFSET_TOOLBARITEM_URL ].Name = m_aPropNames[ INDEX_URL ]; + aToolBarItem[ OFFSET_TOOLBARITEM_TITLE ].Name = m_aPropNames[ INDEX_TITLE ]; + aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER]; + aToolBarItem[ OFFSET_TOOLBARITEM_TARGET ].Name = m_aPropNames[ INDEX_TARGET ]; + aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT ].Name = m_aPropNames[ INDEX_CONTEXT ]; + + aToolBarItem[ OFFSET_TOOLBARITEM_URL ].Value <<= SEPARATOR_URL; + aToolBarItem[ OFFSET_TOOLBARITEM_TITLE ].Value <<= m_aEmpty; + aToolBarItem[ OFFSET_TOOLBARITEM_TARGET ].Value <<= m_aEmpty; + aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ].Value <<= m_aEmpty; + aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT ].Value <<= m_aEmpty; + + sal_uInt32 nToolBarItemCount = rAddonOfficeToolBarSeq.getLength(); + rAddonOfficeToolBarSeq.realloc( nToolBarItemCount+1 ); + rAddonOfficeToolBarSeq[nToolBarItemCount] = aToolBarItem; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::ReadImages( ImageManager& aImageManager ) +{ + // Read the user-defined Images set and fill image manager + ::rtl::OUString aAddonImagesNodeName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/Images" )); + Sequence< ::rtl::OUString > aAddonImagesNodeSeq = GetNodeNames( aAddonImagesNodeName ); + ::rtl::OUString aAddonImagesNode( aAddonImagesNodeName + m_aPathDelimiter ); + + sal_uInt32 nCount = aAddonImagesNodeSeq.getLength(); + + // Init the property value sequence + Sequence< ::rtl::OUString > aAddonImageItemNodePropNames( 1 ); + ::rtl::OUString aURL; + + for ( sal_uInt32 n = 0; n < nCount; n++ ) + { + ::rtl::OUString aImagesItemNode( aAddonImagesNode + aAddonImagesNodeSeq[n] ); + + // Create sequence for data access + ::rtl::OUStringBuffer aBuffer( aImagesItemNode ); + aBuffer.append( m_aPathDelimiter ); + aBuffer.append( m_aPropNames[ OFFSET_MENUITEM_URL ] ); + aAddonImageItemNodePropNames[0] = aBuffer.makeStringAndClear(); + + Sequence< Any > aAddonImageItemNodeValues = GetProperties( aAddonImageItemNodePropNames ); + + // An user-defined image entry must have an URL. As "ImageIdentifier" has a higher priority + // we also check if we already have an images association. + if (( aAddonImageItemNodeValues[0] >>= aURL ) && + aURL.getLength() > 0 && + !HasAssociatedImages( aURL )) + { + ::rtl::OUStringBuffer aBuf( aImagesItemNode ); + aBuf.append( m_aPathDelimiter ); + aBuf.append( IMAGES_NODENAME ); + aBuf.append( m_aPathDelimiter ); + ::rtl::OUString aImagesUserDefinedItemNode = aBuf.makeStringAndClear(); + + // Read a user-defined images data + ImageEntry* pImageEntry = ReadImageData( aImagesUserDefinedItemNode ); + if ( pImageEntry ) + { + // Successfully read a user-defined images item, put it into our image manager + aImageManager.insert( ImageManager::value_type( aURL, *pImageEntry )); + delete pImageEntry; // We have the ownership of the pointer + } + } + } + + return sal_True; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** + +::rtl::OUString AddonsOptions_Impl::GeneratePrefixURL() +{ + // Create an unique prefixed Add-On popup menu URL so it can be identified later as a runtime popup menu. + // They use a different image manager, so they must be identified by the sfx2/framework code. + ::rtl::OUString aPopupMenuURL; + ::rtl::OUStringBuffer aBuf( m_aRootAddonPopupMenuURLPrexfix.getLength() + 3 ); + aBuf.append( m_aRootAddonPopupMenuURLPrexfix ); + aBuf.append( ::rtl::OUString::valueOf( ++m_nRootAddonPopupMenuId )); + aPopupMenuURL = aBuf.makeStringAndClear(); + return aPopupMenuURL; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** + +sal_Bool AddonsOptions_Impl::ReadMenuMergeInstructions( MergeMenuInstructionContainer& aContainer ) +{ + const ::rtl::OUString aMenuMergeRootName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/OfficeMenuBarMerging/" )); + + Sequence< ::rtl::OUString > aAddonMergeNodesSeq = GetNodeNames( aMenuMergeRootName ); + ::rtl::OUString aAddonMergeNode( aMenuMergeRootName ); + + sal_uInt32 nCount = aAddonMergeNodesSeq.getLength(); + + // Init the property value sequence + Sequence< ::rtl::OUString > aNodePropNames( 5 ); + ::rtl::OUString aURL; + + for ( sal_uInt32 i = 0; i < nCount; i++ ) + { + ::rtl::OUString aMergeAddonInstructions( aAddonMergeNode + aAddonMergeNodesSeq[i] ); + + Sequence< ::rtl::OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions ); + sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength(); + + for ( sal_uInt32 j = 0; j < nCountAddons; j++ ) + { + ::rtl::OUStringBuffer aMergeAddonInstructionBase( aMergeAddonInstructions ); + aMergeAddonInstructionBase.append( m_aPathDelimiter ); + aMergeAddonInstructionBase.append( aAddonInstMergeNodesSeq[j] ); + aMergeAddonInstructionBase.append( m_aPathDelimiter ); + + // Create sequence for data access + ::rtl::OUStringBuffer aBuffer( aMergeAddonInstructionBase ); + aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT ] ); + aNodePropNames[0] = aBuffer.makeStringAndClear(); + + aBuffer = aMergeAddonInstructionBase; + aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND ] ); + aNodePropNames[1] = aBuffer.makeStringAndClear(); + + aBuffer = aMergeAddonInstructionBase; + aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] ); + aNodePropNames[2] = aBuffer.makeStringAndClear(); + + aBuffer = aMergeAddonInstructionBase; + aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ] ); + aNodePropNames[3] = aBuffer.makeStringAndClear(); + + aBuffer = aMergeAddonInstructionBase; + aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT ] ); + aNodePropNames[4] = aBuffer.makeStringAndClear(); + + Sequence< Any > aNodePropValues = GetProperties( aNodePropNames ); + + MergeMenuInstruction aMergeMenuInstruction; + aNodePropValues[0] >>= aMergeMenuInstruction.aMergePoint; + aNodePropValues[1] >>= aMergeMenuInstruction.aMergeCommand; + aNodePropValues[2] >>= aMergeMenuInstruction.aMergeCommandParameter; + aNodePropValues[3] >>= aMergeMenuInstruction.aMergeFallback; + aNodePropValues[4] >>= aMergeMenuInstruction.aMergeContext; + + ::rtl::OUString aMergeMenuBase = aMergeAddonInstructionBase.makeStringAndClear(); + ReadMergeMenuData( aMergeMenuBase, aMergeMenuInstruction.aMergeMenu ); + + aContainer.push_back( aMergeMenuInstruction ); + } + } + + return sal_True; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::ReadMergeMenuData( const ::rtl::OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeMenu ) +{ + ::rtl::OUString aMergeMenuBaseNode( aMergeAddonInstructionBase+m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS ] ); + + Sequence< ::rtl::OUString > aSubMenuNodeNames = GetNodeNames( aMergeMenuBaseNode ); + aMergeMenuBaseNode += m_aPathDelimiter; + + // extend the node names to have full path strings + for ( sal_uInt32 i = 0; i < (sal_uInt32)aSubMenuNodeNames.getLength(); i++ ) + aSubMenuNodeNames[i] = ::rtl::OUString( aMergeMenuBaseNode + aSubMenuNodeNames[i] ); + + return ReadSubMenuEntries( aSubMenuNodeNames, rMergeMenu ); +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::ReadToolbarMergeInstructions( ToolbarMergingInstructions& rCachedToolbarMergingInstructions ) +{ + const ::rtl::OUString aToolbarMergeRootName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/OfficeToolbarMerging/" )); + + Sequence< ::rtl::OUString > aAddonMergeNodesSeq = GetNodeNames( aToolbarMergeRootName ); + ::rtl::OUString aAddonMergeNode( aToolbarMergeRootName ); + + sal_uInt32 nCount = aAddonMergeNodesSeq.getLength(); + + // Init the property value sequence + Sequence< ::rtl::OUString > aNodePropNames( 6 ); + ::rtl::OUString aURL; + + for ( sal_uInt32 i = 0; i < nCount; i++ ) + { + ::rtl::OUString aMergeAddonInstructions( aAddonMergeNode + aAddonMergeNodesSeq[i] ); + + Sequence< ::rtl::OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions ); + sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength(); + + for ( sal_uInt32 j = 0; j < nCountAddons; j++ ) + { + ::rtl::OUStringBuffer aMergeAddonInstructionBase( aMergeAddonInstructions ); + aMergeAddonInstructionBase.append( m_aPathDelimiter ); + aMergeAddonInstructionBase.append( aAddonInstMergeNodesSeq[j] ); + aMergeAddonInstructionBase.append( m_aPathDelimiter ); + + // Create sequence for data access + ::rtl::OUStringBuffer aBuffer( aMergeAddonInstructionBase ); + aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBAR ] ); + aNodePropNames[0] = aBuffer.makeStringAndClear(); + + aBuffer = aMergeAddonInstructionBase; + aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEPOINT ] ); + aNodePropNames[1] = aBuffer.makeStringAndClear(); + + aBuffer = aMergeAddonInstructionBase; + aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMAND ] ); + aNodePropNames[2] = aBuffer.makeStringAndClear(); + + aBuffer = aMergeAddonInstructionBase; + aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER ] ); + aNodePropNames[3] = aBuffer.makeStringAndClear(); + + aBuffer = aMergeAddonInstructionBase; + aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEFALLBACK ] ); + aNodePropNames[4] = aBuffer.makeStringAndClear(); + + aBuffer = aMergeAddonInstructionBase; + aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECONTEXT ] ); + aNodePropNames[5] = aBuffer.makeStringAndClear(); + + Sequence< Any > aNodePropValues = GetProperties( aNodePropNames ); + + MergeToolbarInstruction aMergeToolbarInstruction; + aNodePropValues[0] >>= aMergeToolbarInstruction.aMergeToolbar; + aNodePropValues[1] >>= aMergeToolbarInstruction.aMergePoint; + aNodePropValues[2] >>= aMergeToolbarInstruction.aMergeCommand; + aNodePropValues[3] >>= aMergeToolbarInstruction.aMergeCommandParameter; + aNodePropValues[4] >>= aMergeToolbarInstruction.aMergeFallback; + aNodePropValues[5] >>= aMergeToolbarInstruction.aMergeContext; + + ReadMergeToolbarData( aMergeAddonInstructionBase.makeStringAndClear(), + aMergeToolbarInstruction.aMergeToolbarItems ); + + MergeToolbarInstructionContainer& rVector = rCachedToolbarMergingInstructions[ aMergeToolbarInstruction.aMergeToolbar ]; + rVector.push_back( aMergeToolbarInstruction ); + } + } + + return sal_True; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::ReadMergeToolbarData( const ::rtl::OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeToolbarItems ) +{ + ::rtl::OUStringBuffer aBuffer( aMergeAddonInstructionBase ); + aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBARITEMS ] ); + + ::rtl::OUString aMergeToolbarBaseNode = aBuffer.makeStringAndClear(); + + return ReadToolBarItemSet( aMergeToolbarBaseNode, rMergeToolbarItems ); +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::ReadMenuItem( const ::rtl::OUString& aMenuNodeName, Sequence< PropertyValue >& aMenuItem, sal_Bool bIgnoreSubMenu ) +{ + sal_Bool bResult = sal_False; + ::rtl::OUString aStrValue; + ::rtl::OUString aAddonMenuItemTreeNode( aMenuNodeName + m_aPathDelimiter ); + Sequence< Any > aMenuItemNodePropValues; + + aMenuItemNodePropValues = GetProperties( GetPropertyNamesMenuItem( aAddonMenuItemTreeNode ) ); + if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_TITLE ] >>= aStrValue ) && aStrValue.getLength() > 0 ) + { + aMenuItem[ OFFSET_MENUITEM_TITLE ].Value <<= aStrValue; + + ::rtl::OUString aRootSubMenuName( aAddonMenuItemTreeNode + m_aPropNames[ INDEX_SUBMENU ] ); + Sequence< ::rtl::OUString > aRootSubMenuNodeNames = GetNodeNames( aRootSubMenuName ); + if ( aRootSubMenuNodeNames.getLength() > 0 && !bIgnoreSubMenu ) + { + // Set a unique prefixed Add-On popup menu URL so it can be identified later + ::rtl::OUString aPopupMenuURL = GeneratePrefixURL(); + ::rtl::OUString aPopupMenuImageId; + + aMenuItemNodePropValues[ OFFSET_MENUITEM_IMAGEIDENTIFIER ] >>= aPopupMenuImageId; + ReadAndAssociateImages( aPopupMenuURL, aPopupMenuImageId ); + + // A popup menu must have a title and can have a URL and ImageIdentifier + // Set the other property values to empty + aMenuItem[ OFFSET_MENUITEM_URL ].Value <<= aPopupMenuURL; + aMenuItem[ OFFSET_MENUITEM_TARGET ].Value <<= m_aEmpty; + aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Value <<= aPopupMenuImageId; + aMenuItem[ OFFSET_MENUITEM_CONTEXT ].Value <<= aMenuItemNodePropValues[ OFFSET_MENUITEM_CONTEXT ]; + + // Continue to read the sub menu nodes + Sequence< Sequence< PropertyValue > > aSubMenuSeq; + ::rtl::OUString aSubMenuRootNodeName( aRootSubMenuName + m_aPathDelimiter ); + for ( sal_uInt32 n = 0; n < (sal_uInt32)aRootSubMenuNodeNames.getLength(); n++ ) + aRootSubMenuNodeNames[n] = ::rtl::OUString( aSubMenuRootNodeName + aRootSubMenuNodeNames[n] ); + ReadSubMenuEntries( aRootSubMenuNodeNames, aSubMenuSeq ); + aMenuItem[ OFFSET_MENUITEM_SUBMENU ].Value <<= aSubMenuSeq; + bResult = sal_True; + } + else if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_URL ] >>= aStrValue ) && aStrValue.getLength() > 0 ) + { + // A simple menu item => read the other properties; + ::rtl::OUString aMenuImageId; + + aMenuItemNodePropValues[ OFFSET_MENUITEM_IMAGEIDENTIFIER ] >>= aMenuImageId; + ReadAndAssociateImages( aStrValue, aMenuImageId ); + + aMenuItem[ OFFSET_MENUITEM_URL ].Value <<= aStrValue; + aMenuItem[ OFFSET_MENUITEM_TARGET ].Value <<= aMenuItemNodePropValues[ OFFSET_MENUITEM_TARGET ]; + aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Value <<= aMenuImageId; + aMenuItem[ OFFSET_MENUITEM_CONTEXT ].Value <<= aMenuItemNodePropValues[ OFFSET_MENUITEM_CONTEXT ]; + aMenuItem[ OFFSET_MENUITEM_SUBMENU ].Value <<= Sequence< Sequence< PropertyValue > >(); // Submenu set! + + bResult = sal_True; + } + } + else if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_URL ] >>= aStrValue ) && + aStrValue.equalsAsciiL( SEPARATOR_URL_STR, SEPARATOR_URL_LEN )) + { + // Separator + aMenuItem[ OFFSET_MENUITEM_URL ].Value <<= aStrValue; + aMenuItem[ OFFSET_MENUITEM_TARGET ].Value <<= m_aEmpty; + aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Value <<= m_aEmpty; + aMenuItem[ OFFSET_MENUITEM_CONTEXT ].Value <<= m_aEmpty; + aMenuItem[ OFFSET_MENUITEM_SUBMENU ].Value <<= Sequence< Sequence< PropertyValue > >(); // Submenu set! + bResult = sal_True; + } + + return bResult; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::ReadPopupMenu( const ::rtl::OUString& aPopupMenuNodeName, Sequence< PropertyValue >& aPopupMenu ) +{ + sal_Bool bResult = sal_False; + ::rtl::OUString aStrValue; + ::rtl::OUString aAddonPopupMenuTreeNode( aPopupMenuNodeName + m_aPathDelimiter ); + Sequence< Any > aPopupMenuNodePropValues; + + aPopupMenuNodePropValues = GetProperties( GetPropertyNamesPopupMenu( aAddonPopupMenuTreeNode ) ); + if (( aPopupMenuNodePropValues[ OFFSET_POPUPMENU_TITLE ] >>= aStrValue ) && + aStrValue.getLength() > 0 ) + { + aPopupMenu[ OFFSET_POPUPMENU_TITLE ].Value <<= aStrValue; + + ::rtl::OUString aRootSubMenuName( aAddonPopupMenuTreeNode + m_aPropNames[ INDEX_SUBMENU ] ); + Sequence< ::rtl::OUString > aRootSubMenuNodeNames = GetNodeNames( aRootSubMenuName ); + if ( aRootSubMenuNodeNames.getLength() > 0 ) + { + // A top-level popup menu needs a title + // Set a unique prefixed Add-On popup menu URL so it can be identified later + ::rtl::OUString aPopupMenuURL = GeneratePrefixURL(); + + aPopupMenu[ OFFSET_POPUPMENU_URL ].Value <<= aPopupMenuURL; + aPopupMenu[ OFFSET_POPUPMENU_CONTEXT ].Value <<= aPopupMenuNodePropValues[ OFFSET_POPUPMENU_CONTEXT ]; + + // Continue to read the sub menu nodes + Sequence< Sequence< PropertyValue > > aSubMenuSeq; + ::rtl::OUString aSubMenuRootNodeName( aRootSubMenuName + m_aPathDelimiter ); + for ( sal_uInt32 n = 0; n < (sal_uInt32)aRootSubMenuNodeNames.getLength(); n++ ) + aRootSubMenuNodeNames[n] = ::rtl::OUString( aSubMenuRootNodeName + aRootSubMenuNodeNames[n] ); + ReadSubMenuEntries( aRootSubMenuNodeNames, aSubMenuSeq ); + aPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value <<= aSubMenuSeq; + bResult = sal_True; + } + } + + return bResult; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::AppendPopupMenu( Sequence< PropertyValue >& rTargetPopupMenu, const Sequence< PropertyValue >& rSourcePopupMenu ) +{ + Sequence< Sequence< PropertyValue > > aTargetSubMenuSeq; + Sequence< Sequence< PropertyValue > > aSourceSubMenuSeq; + + if (( rTargetPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value >>= aTargetSubMenuSeq ) && + ( rSourcePopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value >>= aSourceSubMenuSeq )) + { + sal_uInt32 nIndex = aTargetSubMenuSeq.getLength(); + aTargetSubMenuSeq.realloc( nIndex + aSourceSubMenuSeq.getLength() ); + for ( sal_uInt32 i = 0; i < sal_uInt32( aSourceSubMenuSeq.getLength() ); i++ ) + aTargetSubMenuSeq[nIndex++] = aSourceSubMenuSeq[i]; + rTargetPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value <<= aTargetSubMenuSeq; + } + + return sal_True; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::ReadToolBarItem( const ::rtl::OUString& aToolBarItemNodeName, Sequence< PropertyValue >& aToolBarItem ) +{ + sal_Bool bResult = sal_False; + ::rtl::OUString aTitle; + ::rtl::OUString aURL; + ::rtl::OUString aAddonToolBarItemTreeNode( aToolBarItemNodeName + m_aPathDelimiter ); + Sequence< Any > aToolBarItemNodePropValues; + + aToolBarItemNodePropValues = GetProperties( GetPropertyNamesToolBarItem( aAddonToolBarItemTreeNode ) ); + + // A toolbar item must have a command URL + if (( aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_URL ] >>= aURL ) && aURL.getLength() > 0 ) + { + if ( aURL.equals( SEPARATOR_URL )) + { + // A speparator toolbar item only needs a URL + aToolBarItem[ OFFSET_TOOLBARITEM_URL ].Value <<= aURL; + aToolBarItem[ OFFSET_TOOLBARITEM_TITLE ].Value <<= m_aEmpty; + aToolBarItem[ OFFSET_TOOLBARITEM_TARGET ].Value <<= m_aEmpty; + aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ].Value <<= m_aEmpty; + aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT ].Value <<= m_aEmpty; + aToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE ].Value <<= m_aEmpty; + aToolBarItem[ OFFSET_TOOLBARITEM_WIDTH ].Value <<= sal_Int32( 0 ); + + bResult = sal_True; + } + else if (( aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_TITLE ] >>= aTitle ) && aTitle.getLength() > 0 ) + { + // A normal toolbar item must also have title => read the other properties; + ::rtl::OUString aImageId; + + // Try to map a user-defined image URL to our internal private image URL + aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ] >>= aImageId; + ReadAndAssociateImages( aURL, aImageId ); + + aToolBarItem[ OFFSET_TOOLBARITEM_URL ].Value <<= aURL; + aToolBarItem[ OFFSET_TOOLBARITEM_TITLE ].Value <<= aTitle; + aToolBarItem[ OFFSET_TOOLBARITEM_TARGET ].Value <<= aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_TARGET ]; + aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ].Value <<= aImageId; + aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT ].Value <<= aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_CONTEXT ]; + aToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE ].Value <<= aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_CONTROLTYPE ]; + + // Configuration uses hyper for long. Therefore transform into sal_Int32 + sal_Int64 nValue( 0 ); + aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_WIDTH ] >>= nValue; + aToolBarItem[ OFFSET_TOOLBARITEM_WIDTH ].Value <<= sal_Int32( nValue ); + + bResult = sal_True; + } + } + + return bResult; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::ReadSubMenuEntries( const Sequence< ::rtl::OUString >& aSubMenuNodeNames, Sequence< Sequence< PropertyValue > >& rSubMenuSeq ) +{ + Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM ); + + // Init the property value sequence + aMenuItem[ OFFSET_MENUITEM_URL ].Name = PROPERTYNAME_URL; + aMenuItem[ OFFSET_MENUITEM_TITLE ].Name = PROPERTYNAME_TITLE; + aMenuItem[ OFFSET_MENUITEM_TARGET ].Name = PROPERTYNAME_TARGET; + aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Name = PROPERTYNAME_IMAGEIDENTIFIER; + aMenuItem[ OFFSET_MENUITEM_CONTEXT ].Name = PROPERTYNAME_CONTEXT; + aMenuItem[ OFFSET_MENUITEM_SUBMENU ].Name = PROPERTYNAME_SUBMENU; // Submenu set! + + sal_uInt32 nIndex = 0; + sal_uInt32 nCount = aSubMenuNodeNames.getLength(); + for ( sal_uInt32 n = 0; n < nCount; n++ ) + { + if ( ReadMenuItem( aSubMenuNodeNames[n], aMenuItem )) + { + sal_uInt32 nSubMenuCount = rSubMenuSeq.getLength() + 1; + rSubMenuSeq.realloc( nSubMenuCount ); + rSubMenuSeq[nIndex++] = aMenuItem; + } + } + + return sal_True; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::HasAssociatedImages( const ::rtl::OUString& aURL ) +{ + ImageManager::const_iterator pIter = m_aImageManager.find( aURL ); + return ( pIter != m_aImageManager.end() ); +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +void AddonsOptions_Impl::SubstituteVariables( ::rtl::OUString& aURL ) +{ + if (( aURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( EXPAND_PROTOCOL )) == 0 ) && + m_xMacroExpander.is() ) + { + // cut protocol + ::rtl::OUString macro( aURL.copy( sizeof ( EXPAND_PROTOCOL ) -1 ) ); + // decode uric class chars + macro = ::rtl::Uri::decode( + macro, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + // expand macro string + aURL = m_xMacroExpander->expandMacros( macro ); + } +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +void AddonsOptions_Impl::ReadImageFromURL( ImageSize nImageSize, const ::rtl::OUString& aImageURL, Image& aImage, Image& aImageNoScale ) +{ + SvStream* pStream = UcbStreamHelper::CreateStream( aImageURL, STREAM_STD_READ ); + if ( pStream && ( pStream->GetErrorCode() == 0 )) + { + // Use graphic class to also support more graphic formats (bmp,png,...) + Graphic aGraphic; + + GraphicFilter* pGF = GraphicFilter::GetGraphicFilter(); + pGF->ImportGraphic( aGraphic, String(), *pStream, GRFILTER_FORMAT_DONTKNOW ); + + BitmapEx aBitmapEx = aGraphic.GetBitmapEx(); + + const Size aSize = ( nImageSize == IMGSIZE_SMALL ) ? aImageSizeSmall : aImageSizeBig; // Sizes used for menu/toolbox images + + Size aBmpSize = aBitmapEx.GetSizePixel(); + if ( aBmpSize.Width() > 0 && aBmpSize.Height() > 0 ) + { + // Support non-transparent bitmaps to be downward compatible with OOo 1.1.x addons + if( !aBitmapEx.IsTransparent() ) + aBitmapEx = BitmapEx( aBitmapEx.GetBitmap(), COL_LIGHTMAGENTA ); + + // A non-scaled bitmap can have a flexible width, but must have a defined height! + Size aNoScaleSize( aBmpSize.Width(), aSize.Height() ); + if ( aBmpSize != aNoScaleSize ) + { + BitmapEx aNoScaleBmp( aBitmapEx ); + aNoScaleBmp.Scale( aNoScaleSize, BMP_SCALE_INTERPOLATE ); + } + else + aImageNoScale = Image( aBitmapEx ); + + if ( aBmpSize != aSize ) + aBitmapEx.Scale( aSize, BMP_SCALE_INTERPOLATE ); + + aImage = Image( aBitmapEx ); + } + } + + delete pStream; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +void AddonsOptions_Impl::ReadAndAssociateImages( const ::rtl::OUString& aURL, const ::rtl::OUString& aImageId ) +{ + const int MAX_NUM_IMAGES = 4; + const char* aExtArray[MAX_NUM_IMAGES] = { "_16", "_26", "_16h", "_26h" }; + const char* pBmpExt = ".bmp"; + + if ( aImageId.getLength() == 0 ) + return; + + bool bImageFound = true; + ImageEntry aImageEntry; + ::rtl::OUString aImageURL( aImageId ); + + SubstituteVariables( aImageURL ); + + // Loop to create the four possible image names and try to read the bitmap files + for ( int i = 0; i < MAX_NUM_IMAGES; i++ ) + { + ::rtl::OUStringBuffer aFileURL( aImageURL ); + aFileURL.appendAscii( aExtArray[i] ); + aFileURL.appendAscii( pBmpExt ); + + Image aImage; + Image aImageNoScale; + ReadImageFromURL( ((i==0)||(i==2)) ? IMGSIZE_SMALL : IMGSIZE_BIG, aFileURL.makeStringAndClear(), aImage, aImageNoScale ); + if ( !!aImage ) + { + bImageFound = true; + switch ( i ) + { + case 0: + aImageEntry.aImageSmall = aImage; + aImageEntry.aImageSmallNoScale = aImageNoScale; + break; + case 1: + aImageEntry.aImageBig = aImage; + aImageEntry.aImageBigNoScale = aImageNoScale; + break; + case 2: + aImageEntry.aImageSmallHC = aImage; + aImageEntry.aImageSmallHCNoScale = aImageNoScale; + break; + case 3: + aImageEntry.aImageBigHC = aImage; + aImageEntry.aImageBigHCNoScale = aImageNoScale; + break; + } + } + } + + if ( bImageFound ) + m_aImageManager.insert( ImageManager::value_type( aURL, aImageEntry )); +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +AddonsOptions_Impl::ImageEntry* AddonsOptions_Impl::ReadImageData( const ::rtl::OUString& aImagesNodeName ) +{ + Sequence< ::rtl::OUString > aImageDataNodeNames = GetPropertyNamesImages( aImagesNodeName ); + Sequence< Any > aPropertyData; + Sequence< sal_Int8 > aImageDataSeq; + ::rtl::OUString aImageURL; + + ImageEntry* pEntry = NULL; + + // It is possible to use both forms (embedded image data and URLs to external bitmap files) at the + // same time. Embedded image data has a higher priority. + aPropertyData = GetProperties( aImageDataNodeNames ); + for ( int i = 0; i < PROPERTYCOUNT_IMAGES; i++ ) + { + if ( i < PROPERTYCOUNT_EMBEDDED_IMAGES ) + { + // Extract image data from the embedded hex binary sequence + Image aImage; + if (( aPropertyData[i] >>= aImageDataSeq ) && + aImageDataSeq.getLength() > 0 && + ( CreateImageFromSequence( aImage, + (( i == OFFSET_IMAGES_BIG ) || + ( i == OFFSET_IMAGES_BIGHC )), + aImageDataSeq )) ) + { + if ( !pEntry ) + pEntry = new ImageEntry; + + if ( i == OFFSET_IMAGES_SMALL ) + pEntry->aImageSmall = aImage; + else if ( i == OFFSET_IMAGES_BIG ) + pEntry->aImageBig = aImage; + else if ( i == OFFSET_IMAGES_SMALLHC ) + pEntry->aImageSmallHC = aImage; + else + pEntry->aImageBigHC = aImage; + } + } + else + { + // Retrieve image data from a external bitmap file. Make sure that embedded image data + // has a higher priority. + aPropertyData[i] >>= aImageURL; + + if ( aImageURL.getLength() > 0 ) + { + Image aImage; + Image aImageNoScale; + + SubstituteVariables( aImageURL ); + ReadImageFromURL( ((i==OFFSET_IMAGES_SMALL_URL)||(i==OFFSET_IMAGES_SMALLHC_URL)) ? IMGSIZE_SMALL : IMGSIZE_BIG, + aImageURL, aImage, aImageNoScale ); + if ( !!aImage ) + { + if ( !pEntry ) + pEntry = new ImageEntry; + + if ( i == OFFSET_IMAGES_SMALL_URL && !pEntry->aImageSmall ) + { + pEntry->aImageSmall = aImage; + pEntry->aImageSmallNoScale = aImageNoScale; + } + else if ( i == OFFSET_IMAGES_BIG_URL && !pEntry->aImageBig ) + { + pEntry->aImageBig = aImage; + pEntry->aImageBigNoScale = aImageNoScale; + } + else if ( i == OFFSET_IMAGES_SMALLHC_URL && !pEntry->aImageSmallHC ) + { + pEntry->aImageSmallHC = aImage; + pEntry->aImageSmallHCNoScale = aImageNoScale; + } + else if ( !pEntry->aImageBigHC ) + { + pEntry->aImageBigHC = aImage; + pEntry->aImageBigHCNoScale = aImageNoScale; + } + } + } + } + } + + return pEntry; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +sal_Bool AddonsOptions_Impl::CreateImageFromSequence( Image& rImage, sal_Bool bBig, Sequence< sal_Int8 >& rBitmapDataSeq ) const +{ + sal_Bool bResult = sal_False; + Size aSize = bBig ? aImageSizeBig : aImageSizeSmall; // Sizes used for menu/toolbox images + + if ( rBitmapDataSeq.getLength() > 0 ) + { + SvMemoryStream aMemStream( rBitmapDataSeq.getArray(), rBitmapDataSeq.getLength(), STREAM_STD_READ ); + BitmapEx aBitmapEx; + + aMemStream >> aBitmapEx; + + // Scale bitmap to fit the correct size for the menu/toolbar. Use best quality + if ( aBitmapEx.GetSizePixel() != aSize ) + aBitmapEx.Scale( aSize, BMP_SCALE_INTERPOLATE ); + + if( !aBitmapEx.IsTransparent() ) + { + // Support non-transparent bitmaps to be downward compatible with OOo 1.1.x addons + aBitmapEx = BitmapEx( aBitmapEx.GetBitmap(), COL_LIGHTMAGENTA ); + } + + rImage = Image( aBitmapEx ); + bResult = sal_True; + } + + return bResult; +} + +//***************************************************************************************************************** +// private methods +//***************************************************************************************************************** +Sequence< ::rtl::OUString > AddonsOptions_Impl::GetPropertyNamesMergeMenuInstruction( const ::rtl::OUString& aPropertyRootNode ) const +{ + Sequence< ::rtl::OUString > lResult( PROPERTYCOUNT_MERGE_MENUBAR ); + + // Create property names dependent from the root node name + lResult[ OFFSET_MERGEMENU_MERGEPOINT ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT ] ); + lResult[ OFFSET_MERGEMENU_MERGECOMMAND ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND ] ); + lResult[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] ); + lResult[ OFFSET_MERGEMENU_MERGEFALLBACK ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ] ); + lResult[ OFFSET_MERGEMENU_MERGECONTEXT ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT ] ); + lResult[ OFFSET_MERGEMENU_MENUITEMS ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS ] ); + + return lResult; +} + +Sequence< ::rtl::OUString > AddonsOptions_Impl::GetPropertyNamesMenuItem( const ::rtl::OUString& aPropertyRootNode ) const +{ + Sequence< ::rtl::OUString > lResult( PROPERTYCOUNT_MENUITEM ); + + // Create property names dependent from the root node name + lResult[OFFSET_MENUITEM_URL] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_URL ] ); + lResult[OFFSET_MENUITEM_TITLE] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_TITLE ] ); + lResult[OFFSET_MENUITEM_IMAGEIDENTIFIER] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER ] ); + lResult[OFFSET_MENUITEM_TARGET] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_TARGET ] ); + lResult[OFFSET_MENUITEM_CONTEXT] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ] ); + lResult[OFFSET_MENUITEM_SUBMENU] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_SUBMENU ] ); + + return lResult; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +Sequence< ::rtl::OUString > AddonsOptions_Impl::GetPropertyNamesPopupMenu( const ::rtl::OUString& aPropertyRootNode ) const +{ + // The URL is automatically set and not read from the configuration. + Sequence< ::rtl::OUString > lResult( PROPERTYCOUNT_POPUPMENU-1 ); + + // Create property names dependent from the root node name + lResult[OFFSET_POPUPMENU_TITLE] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_TITLE ] ); + lResult[OFFSET_POPUPMENU_CONTEXT] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ] ); + lResult[OFFSET_POPUPMENU_SUBMENU] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_SUBMENU ] ); + + return lResult; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +Sequence< ::rtl::OUString > AddonsOptions_Impl::GetPropertyNamesToolBarItem( const ::rtl::OUString& aPropertyRootNode ) const +{ + Sequence< ::rtl::OUString > lResult( PROPERTYCOUNT_TOOLBARITEM ); + + // Create property names dependent from the root node name + lResult[0] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_URL ] ); + lResult[1] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_TITLE ] ); + lResult[2] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER] ); + lResult[3] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_TARGET ] ); + lResult[4] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ] ); + lResult[5] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_CONTROLTYPE ] ); + lResult[6] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_WIDTH ] ); + + return lResult; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +Sequence< ::rtl::OUString > AddonsOptions_Impl::GetPropertyNamesImages( const ::rtl::OUString& aPropertyRootNode ) const +{ + Sequence< ::rtl::OUString > lResult( PROPERTYCOUNT_IMAGES ); + + // Create property names dependent from the root node name + lResult[0] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALL ] ); + lResult[1] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIG ] ); + lResult[2] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC ] ); + lResult[3] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIGHC ] ); + lResult[4] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALL_URL ] ); + lResult[5] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIG_URL ] ); + lResult[6] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC_URL] ); + lResult[7] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIGHC_URL ] ); + + return lResult; +} + +//***************************************************************************************************************** +// initialize static member +// DON'T DO IT IN YOUR HEADER! +// see definition for further informations +//***************************************************************************************************************** +AddonsOptions_Impl* AddonsOptions::m_pDataContainer = NULL ; +sal_Int32 AddonsOptions::m_nRefCount = 0 ; + +//***************************************************************************************************************** +// constructor +//***************************************************************************************************************** +AddonsOptions::AddonsOptions() +{ + // Global access, must be guarded (multithreading!). + MutexGuard aGuard( GetOwnStaticMutex() ); + // Increase ouer refcount ... + ++m_nRefCount; + // ... and initialize ouer data container only if it not already exist! + if( m_pDataContainer == NULL ) + { + m_pDataContainer = new AddonsOptions_Impl; + } +} + +//***************************************************************************************************************** +// destructor +//***************************************************************************************************************** +AddonsOptions::~AddonsOptions() +{ + // Global access, must be guarded (multithreading!) + MutexGuard aGuard( GetOwnStaticMutex() ); + // Decrease ouer refcount. + --m_nRefCount; + // If last instance was deleted ... + // we must destroy ouer static data container! + if( m_nRefCount <= 0 ) + { + delete m_pDataContainer; + m_pDataContainer = NULL; + } +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +sal_Bool AddonsOptions::HasAddonsMenu() const +{ + MutexGuard aGuard( GetOwnStaticMutex() ); + return m_pDataContainer->HasAddonsMenu(); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** + +sal_Bool AddonsOptions::HasAddonsHelpMenu() const +{ + MutexGuard aGuard( GetOwnStaticMutex() ); + return m_pDataContainer->HasAddonsHelpMenu(); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** + +sal_Int32 AddonsOptions::GetAddonsToolBarCount() const +{ + MutexGuard aGuard( GetOwnStaticMutex() ); + return m_pDataContainer->GetAddonsToolBarCount(); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsMenu() const +{ + MutexGuard aGuard( GetOwnStaticMutex() ); + return m_pDataContainer->GetAddonsMenu(); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsMenuBarPart() const +{ + MutexGuard aGuard( GetOwnStaticMutex() ); + return m_pDataContainer->GetAddonsMenuBarPart(); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsToolBarPart( sal_uInt32 nIndex ) const +{ + MutexGuard aGuard( GetOwnStaticMutex() ); + return m_pDataContainer->GetAddonsToolBarPart( nIndex ); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +const ::rtl::OUString AddonsOptions::GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const +{ + MutexGuard aGuard( GetOwnStaticMutex() ); + return m_pDataContainer->GetAddonsToolbarResourceName( nIndex ); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsHelpMenu() const +{ + MutexGuard aGuard( GetOwnStaticMutex() ); + return m_pDataContainer->GetAddonsHelpMenu(); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +const MergeMenuInstructionContainer& AddonsOptions::GetMergeMenuInstructions() const +{ + MutexGuard aGuard( GetOwnStaticMutex() ); + return m_pDataContainer->GetMergeMenuInstructions(); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +bool AddonsOptions::GetMergeToolbarInstructions( + const ::rtl::OUString& rToolbarName, + MergeToolbarInstructionContainer& rToolbarInstructions ) const +{ + MutexGuard aGuard( GetOwnStaticMutex() ); + return m_pDataContainer->GetMergeToolbarInstructions( + rToolbarName, rToolbarInstructions ); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +Image AddonsOptions::GetImageFromURL( const rtl::OUString& aURL, sal_Bool bBig, sal_Bool bHiContrast, sal_Bool bNoScale ) const +{ + MutexGuard aGuard( GetOwnStaticMutex() ); + return m_pDataContainer->GetImageFromURL( aURL, bBig, bHiContrast, bNoScale ); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +Image AddonsOptions::GetImageFromURL( const rtl::OUString& aURL, sal_Bool bBig, sal_Bool bHiContrast ) const +{ + return GetImageFromURL( aURL, bBig, bHiContrast, sal_False ); +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +Mutex& AddonsOptions::GetOwnStaticMutex() +{ + // Initialize static mutex only for one time! + static Mutex* pMutex = NULL; + // If these method first called (Mutex not already exist!) ... + if( pMutex == NULL ) + { + // ... we must create a new one. Protect follow code with the global mutex - + // It must be - we create a static variable! + MutexGuard aGuard( Mutex::getGlobalMutex() ); + // We must check our pointer again - because it can be that another instance of ouer class will be fastr then these! + if( pMutex == NULL ) + { + // Create the new mutex and set it for return on static variable. + static Mutex aMutex; + pMutex = &aMutex; + } + } + // Return new created or already existing mutex object. + return *pMutex; +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +IMPL_STATIC_LINK_NOINSTANCE( AddonsOptions, Notify, void*, EMPTYARG ) +{ + MutexGuard aGuard( GetOwnStaticMutex() ); + m_pDataContainer->ReadConfigurationData(); + return 0; +} + +} + diff --git a/framework/source/fwe/classes/bmkmenu.cxx b/framework/source/fwe/classes/bmkmenu.cxx new file mode 100644 index 000000000000..ac588be9a881 --- /dev/null +++ b/framework/source/fwe/classes/bmkmenu.cxx @@ -0,0 +1,254 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <limits.h> + +#include "framework/bmkmenu.hxx" +#include <general.h> +#include <macros/debug/assertion.hxx> +#include <framework/imageproducer.hxx> +#include <framework/menuconfiguration.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/util/URL.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#ifndef _UNOTOOLS_PROCESSFACTORY_HXX +#include <comphelper/processfactory.hxx> +#endif +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/util/DateTime.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ +#include <tools/config.hxx> +#include <vcl/svapp.hxx> +#include <unotools/dynamicmenuoptions.hxx> +#include <svtools/menuoptions.hxx> +#include <rtl/logfile.hxx> + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +using namespace ::comphelper; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::beans; + +namespace framework +{ + +void GetMenuEntry( + Sequence< PropertyValue >& aDynamicMenuEntry, + ::rtl::OUString& rTitle, + ::rtl::OUString& rURL, + ::rtl::OUString& rFrame, + ::rtl::OUString& rImageId ); + +class BmkMenu_Impl +{ + private: + static sal_uInt16 m_nMID; + + public: + BmkMenu* m_pRoot; + sal_Bool m_bInitialized; + + BmkMenu_Impl( BmkMenu* pRoot ); + BmkMenu_Impl(); + ~BmkMenu_Impl(); + + static sal_uInt16 GetMID(); +}; + +sal_uInt16 BmkMenu_Impl::m_nMID = BMKMENU_ITEMID_START; + +BmkMenu_Impl::BmkMenu_Impl( BmkMenu* pRoot ) : + m_pRoot(pRoot), + m_bInitialized(sal_False) +{ +} + +BmkMenu_Impl::BmkMenu_Impl() : + m_pRoot(0), + m_bInitialized(sal_False) +{ +} + +BmkMenu_Impl::~BmkMenu_Impl() +{ +} + +sal_uInt16 BmkMenu_Impl::GetMID() +{ + m_nMID++; + if( !m_nMID ) + m_nMID = BMKMENU_ITEMID_START; + return m_nMID; +} + +// ------------------------------------------------------------------------ + +BmkMenu::BmkMenu( com::sun::star::uno::Reference< XFrame >& xFrame, BmkMenu::BmkMenuType nType, BmkMenu* pRoot ) + :AddonMenu(xFrame) + ,m_nType( nType ) +{ + _pImp = new BmkMenu_Impl( pRoot ); + Initialize(); +} + +BmkMenu::BmkMenu( Reference< XFrame >& xFrame, BmkMenu::BmkMenuType nType ) + :AddonMenu(xFrame) + ,m_nType( nType ) +{ + _pImp = new BmkMenu_Impl(); + Initialize(); +} + +BmkMenu::~BmkMenu() +{ + delete _pImp; +} + +void BmkMenu::Initialize() +{ + RTL_LOGFILE_CONTEXT( aLog, "framework (cd100003) ::BmkMenu::Initialize" ); + + if( _pImp->m_bInitialized ) + return; + + _pImp->m_bInitialized = sal_True; + + Sequence< Sequence< PropertyValue > > aDynamicMenuEntries; + + if ( m_nType == BmkMenu::BMK_NEWMENU ) + aDynamicMenuEntries = SvtDynamicMenuOptions().GetMenu( E_NEWMENU ); + else if ( m_nType == BmkMenu::BMK_WIZARDMENU ) + aDynamicMenuEntries = SvtDynamicMenuOptions().GetMenu( E_WIZARDMENU ); + + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + sal_Bool bShowMenuImages = rSettings.GetUseImagesInMenus(); + + ::rtl::OUString aTitle; + ::rtl::OUString aURL; + ::rtl::OUString aTargetFrame; + ::rtl::OUString aImageId; + + sal_Bool bIsHiContrastMode = rSettings.GetHighContrastMode(); + + sal_uInt32 i, nCount = aDynamicMenuEntries.getLength(); + for ( i = 0; i < nCount; ++i ) + { + GetMenuEntry( aDynamicMenuEntries[i], aTitle, aURL, aTargetFrame, aImageId ); + + if ( !aTitle.getLength() && !aURL.getLength() ) + continue; + + if ( aURL == ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:separator" ))) + InsertSeparator(); + else + { + sal_Bool bImageSet = sal_False; + sal_uInt16 nId = CreateMenuId(); + + if ( bShowMenuImages ) + { + if ( aImageId.getLength() > 0 ) + { + Image aImage = GetImageFromURL( m_xFrame, aImageId, sal_False, bIsHiContrastMode ); + if ( !!aImage ) + { + bImageSet = sal_True; + InsertItem( nId, aTitle, aImage ); + } + } + + if ( !bImageSet ) + { + Image aImage = GetImageFromURL( m_xFrame, aURL, sal_False, bIsHiContrastMode ); + if ( !aImage ) + InsertItem( nId, aTitle ); + else + InsertItem( nId, aTitle, aImage ); + } + } + else + InsertItem( nId, aTitle ); + + // Store values from configuration to the New and Wizard menu entries to enable + // sfx2 based code to support high contrast mode correctly! + MenuConfiguration::Attributes* pUserAttributes = new MenuConfiguration::Attributes( aTargetFrame, aImageId ); + SetUserValue( nId, (sal_uIntPtr)pUserAttributes ); + + SetItemCommand( nId, aURL ); + } + } +} + +sal_uInt16 BmkMenu::CreateMenuId() +{ + return BmkMenu_Impl::GetMID(); +} + +void GetMenuEntry +( + Sequence< PropertyValue >& aDynamicMenuEntry, + ::rtl::OUString& rTitle, + ::rtl::OUString& rURL, + ::rtl::OUString& rFrame, + ::rtl::OUString& rImageId +) +{ + for ( int i = 0; i < aDynamicMenuEntry.getLength(); i++ ) + { + if ( aDynamicMenuEntry[i].Name == DYNAMICMENU_PROPERTYNAME_URL ) + aDynamicMenuEntry[i].Value >>= rURL; + else if ( aDynamicMenuEntry[i].Name == DYNAMICMENU_PROPERTYNAME_TITLE ) + aDynamicMenuEntry[i].Value >>= rTitle; + else if ( aDynamicMenuEntry[i].Name == DYNAMICMENU_PROPERTYNAME_IMAGEIDENTIFIER ) + aDynamicMenuEntry[i].Value >>= rImageId; + else if ( aDynamicMenuEntry[i].Name == DYNAMICMENU_PROPERTYNAME_TARGETNAME ) + aDynamicMenuEntry[i].Value >>= rFrame; + } +} + +} + diff --git a/framework/source/fwe/classes/framelistanalyzer.cxx b/framework/source/fwe/classes/framelistanalyzer.cxx new file mode 100644 index 000000000000..1a33ebf91d7e --- /dev/null +++ b/framework/source/fwe/classes/framelistanalyzer.cxx @@ -0,0 +1,302 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "framework/framelistanalyzer.hxx" + +//_______________________________________________ +// my own includes +#include <threadhelp/writeguard.hxx> +#include <threadhelp/readguard.hxx> +#include <targets.h> +#include <properties.h> +#include <services.h> + +//_______________________________________________ +// interface includes +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> + +//_______________________________________________ +// includes of other projects +#include <unotools/processfactory.hxx> +#include <vcl/svapp.hxx> + +//_______________________________________________ +// namespace + +namespace framework{ + +//_______________________________________________ +// non exported const + +//_______________________________________________ +// non exported definitions + +//_______________________________________________ +// declarations + +//_______________________________________________ + +/** + */ + +FrameListAnalyzer::FrameListAnalyzer( const css::uno::Reference< css::frame::XFramesSupplier >& xSupplier , + const css::uno::Reference< css::frame::XFrame >& xReferenceFrame , + sal_uInt32 eDetectMode ) + : m_xSupplier (xSupplier ) + , m_xReferenceFrame(xReferenceFrame) + , m_eDetectMode (eDetectMode ) +{ + impl_analyze(); +} + +//_______________________________________________ + +/** + */ + +FrameListAnalyzer::~FrameListAnalyzer() +{ +} + +//_______________________________________________ + +/** returns an analyzed list of all currently opened (top!) frames inside the desktop tree. + + We try to get a snapshot of all opened frames, which are part of the desktop frame container. + Of course we can't access frames, which stands outside of this tree. + But it's neccessary to collect top frames here only. Otherwhise we interpret closing of last + frame wrong. Further we analyze this list and split into different parts. + E.g. for "CloseDoc" we must know, which frames of the given list referr to the same model. + These frames must be closed then. But all other frames must be untouched. + In case the request was "CloseWin" these splitted lists can be used too, to decide if the last window + or document was closed. Then we have to initialize the backing window ... + Last but not least we must know something about our special help frame. It must be handled + seperatly. And last but not least - the backing component frame must be detected too. +*/ + +void FrameListAnalyzer::impl_analyze() +{ + // reset all members to get a consistent state + m_bReferenceIsHidden = sal_False; + m_bReferenceIsHelp = sal_False; + m_bReferenceIsBacking = sal_False; + m_xHelp = css::uno::Reference< css::frame::XFrame >(); + m_xBackingComponent = css::uno::Reference< css::frame::XFrame >(); + + // try to get the task container by using the given supplier + css::uno::Reference< css::container::XIndexAccess > xFrameContainer(m_xSupplier->getFrames(), css::uno::UNO_QUERY); + + // All return list get an initial size to include all possible frames. + // They will be packed at the end of this method ... using the actual step positions then. + sal_Int32 nVisibleStep = 0; + sal_Int32 nHiddenStep = 0; + sal_Int32 nModelStep = 0; + sal_Int32 nCount = xFrameContainer->getCount(); + + m_lOtherVisibleFrames.realloc(nCount); + m_lOtherHiddenFrames.realloc(nCount); + m_lModelFrames.realloc(nCount); + + // ask for the model of the given reference frame. + // It must be compared with the model of every frame of the container + // to sort it into the list of frames with the same model. + // Supress this step, if right detect mode isn't set. + css::uno::Reference< css::frame::XModel > xReferenceModel; + if ((m_eDetectMode & E_MODEL) == E_MODEL ) + { + css::uno::Reference< css::frame::XController > xReferenceController; + if (m_xReferenceFrame.is()) + xReferenceController = m_xReferenceFrame->getController(); + if (xReferenceController.is()) + xReferenceModel = xReferenceController->getModel(); + } + + // check, if the reference frame is in hidden mode. + // But look, if this analyze step is realy needed. + css::uno::Reference< css::beans::XPropertySet > xSet(m_xReferenceFrame, css::uno::UNO_QUERY); + if ( + ((m_eDetectMode & E_HIDDEN) == E_HIDDEN) && + (xSet.is() ) + ) + { + xSet->getPropertyValue(FRAME_PROPNAME_ISHIDDEN) >>= m_bReferenceIsHidden; + } + + // check, if the reference frame includes the backing component. + // But look, if this analyze step is realy needed. + if ((m_eDetectMode & E_BACKINGCOMPONENT) == E_BACKINGCOMPONENT) + { + try + { + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::utl::getProcessServiceFactory(); + css::uno::Reference< css::frame::XModuleManager > xModuleMgr(xSMGR->createInstance(SERVICENAME_MODULEMANAGER), css::uno::UNO_QUERY_THROW); + ::rtl::OUString sModule = xModuleMgr->identify(m_xReferenceFrame); + m_bReferenceIsBacking = (sModule.equals(SERVICENAME_STARTMODULE)); + } + catch(const css::uno::Exception&) + {} + } + + // check, if the reference frame includes the help module. + // But look, if this analyze step is realy needed. + if ( + ((m_eDetectMode & E_HELP) == E_HELP ) && + (m_xReferenceFrame.is() ) && + (m_xReferenceFrame->getName() == SPECIALTARGET_HELPTASK) + ) + { + m_bReferenceIsHelp = sal_True; + } + + try + { + // Step over all frames of the desktop frame container and analyze it. + for (sal_Int32 i=0; i<nCount; ++i) + { + // Ignore invalid items ... and of course the reference frame. + // It will be a member of the given frame list too - but it was already + // analyzed before! + css::uno::Reference< css::frame::XFrame > xFrame; + if ( + !(xFrameContainer->getByIndex(i) >>= xFrame) || + !(xFrame.is() ) || + (xFrame==m_xReferenceFrame ) + ) + continue; + + #ifdef ENABLE_WARNINGS + if ( + ((m_eDetectMode & E_ZOMBIE) == E_ZOMBIE) && + ( + (!xFrame->getContainerWindow().is()) || + (!xFrame->getComponentWindow().is()) + ) + ) + { + LOG_WARNING("FrameListAnalyzer::impl_analyze()", "ZOMBIE!") + } + #endif + + // ------------------------------------------------- + // a) Is it the special help task? + // Return it seperated from any return list. + if ( + ((m_eDetectMode & E_HELP) == E_HELP ) && + (xFrame->getName()==SPECIALTARGET_HELPTASK) + ) + { + m_xHelp = xFrame; + continue; + } + + // ------------------------------------------------- + // b) Or is includes this task the special backing component? + // Return it seperated from any return list. + // But check if the reference task itself is the backing frame. + // Our user mst know it to decide right. + if ((m_eDetectMode & E_BACKINGCOMPONENT) == E_BACKINGCOMPONENT) + { + try + { + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::utl::getProcessServiceFactory(); + css::uno::Reference< css::frame::XModuleManager > xModuleMgr(xSMGR->createInstance(SERVICENAME_MODULEMANAGER), css::uno::UNO_QUERY); + ::rtl::OUString sModule = xModuleMgr->identify(xFrame); + if (sModule.equals(SERVICENAME_STARTMODULE)) + { + m_xBackingComponent = xFrame; + continue; + } + } + catch(const css::uno::Exception&) + {} + } + + // ------------------------------------------------- + // c) Or is it the a task, which uses the specified model? + // Add it to the list of "model frames". + if ((m_eDetectMode & E_MODEL) == E_MODEL) + { + css::uno::Reference< css::frame::XController > xController = xFrame->getController(); + css::uno::Reference< css::frame::XModel > xModel ; + if (xController.is()) + xModel = xController->getModel(); + if (xModel==xReferenceModel) + { + m_lModelFrames[nModelStep] = xFrame; + ++nModelStep; + continue; + } + } + + // ------------------------------------------------- + // d) Or is it the a task, which use another or no model at all? + // Add it to the list of "other frames". But look for it's + // visible state ... if it's allowed to do so. + // ------------------------------------------------- + sal_Bool bHidden = sal_False; + if ((m_eDetectMode & E_HIDDEN) == E_HIDDEN ) + { + xSet = css::uno::Reference< css::beans::XPropertySet >(xFrame, css::uno::UNO_QUERY); + if (xSet.is()) + { + xSet->getPropertyValue(FRAME_PROPNAME_ISHIDDEN) >>= bHidden; + } + } + + if (bHidden) + { + m_lOtherHiddenFrames[nHiddenStep] = xFrame; + ++nHiddenStep; + } + else + { + m_lOtherVisibleFrames[nVisibleStep] = xFrame; + ++nVisibleStep; + } + } + } + catch(css::lang::IndexOutOfBoundsException) + { + // stop copying if index seams to be wrong. + // This interface can't realy guarantee its count for multithreaded + // environments. So it can occure! + } + + // Pack both lists by using the actual step positions. + // All empty or ignorable items should exist at the end of these lists + // behind the position pointers. So they will be removed by a reallocation. + m_lOtherVisibleFrames.realloc(nVisibleStep); + m_lOtherHiddenFrames.realloc(nHiddenStep); + m_lModelFrames.realloc(nModelStep); +} + +} // namespace framework diff --git a/framework/source/fwe/classes/fwkresid.cxx b/framework/source/fwe/classes/fwkresid.cxx new file mode 100644 index 000000000000..47e6ddb49fea --- /dev/null +++ b/framework/source/fwe/classes/fwkresid.cxx @@ -0,0 +1,65 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "classes/fwkresid.hxx" +#include <tools/string.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> + +#include <rtl/strbuf.hxx> + +namespace framework +{ + +ResMgr* FwkResId::GetResManager() +{ + static ResMgr* pResMgr = NULL; + + if ( !pResMgr ) + { + rtl::OStringBuffer aBuf( 32 ); + aBuf.append( "fwe" ); + + vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + pResMgr = ResMgr::CreateResMgr( aBuf.getStr() ); + } + + return pResMgr; +} + +// ----------------------------------------------------------------------- + +FwkResId::FwkResId( sal_uInt16 nId ) : + ResId( nId, *FwkResId::GetResManager() ) +{ +} + +} + diff --git a/framework/source/fwe/classes/imagewrapper.cxx b/framework/source/fwe/classes/imagewrapper.cxx new file mode 100644 index 000000000000..82a7f684413c --- /dev/null +++ b/framework/source/fwe/classes/imagewrapper.cxx @@ -0,0 +1,120 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <classes/imagewrapper.hxx> +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> +#include <vcl/bitmap.hxx> +#include <vcl/bitmapex.hxx> +#include <tools/stream.hxx> +#include <cppuhelper/typeprovider.hxx> + +using namespace com::sun::star::lang; +using namespace com::sun::star::uno; + +namespace framework +{ + +static Sequence< sal_Int8 > impl_getStaticIdentifier() +{ + static sal_uInt8 pGUID[16] = { 0x46, 0xAD, 0x69, 0xFB, 0xA7, 0xBE, 0x44, 0x83, 0xB2, 0xA7, 0xB3, 0xEC, 0x59, 0x4A, 0xB7, 0x00 }; + static ::com::sun::star::uno::Sequence< sal_Int8 > seqID((sal_Int8*)pGUID,16) ; + return seqID ; +} + + +ImageWrapper::ImageWrapper( const Image& aImage ) : ThreadHelpBase( &Application::GetSolarMutex() ) + , m_aImage( aImage ) +{ +} + + +ImageWrapper::~ImageWrapper() +{ +} + + +Sequence< sal_Int8 > ImageWrapper::GetUnoTunnelId() +{ + return impl_getStaticIdentifier(); +} + +// XBitmap +com::sun::star::awt::Size SAL_CALL ImageWrapper::getSize() throw ( RuntimeException ) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + BitmapEx aBitmapEx( m_aImage.GetBitmapEx() ); + Size aBitmapSize( aBitmapEx.GetSizePixel() ); + + return com::sun::star::awt::Size( aBitmapSize.Width(), aBitmapSize.Height() ); +} + +Sequence< sal_Int8 > SAL_CALL ImageWrapper::getDIB() throw ( RuntimeException ) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + SvMemoryStream aMem; + aMem << m_aImage.GetBitmapEx().GetBitmap(); + return Sequence< sal_Int8 >( (sal_Int8*) aMem.GetData(), aMem.Tell() ); +} + +Sequence< sal_Int8 > SAL_CALL ImageWrapper::getMaskDIB() throw ( RuntimeException ) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + BitmapEx aBmpEx( m_aImage.GetBitmapEx() ); + + if ( aBmpEx.IsAlpha() ) + { + SvMemoryStream aMem; + aMem << aBmpEx.GetAlpha().GetBitmap(); + return Sequence< sal_Int8 >( (sal_Int8*) aMem.GetData(), aMem.Tell() ); + } + else if ( aBmpEx.IsTransparent() ) + { + SvMemoryStream aMem; + aMem << aBmpEx.GetMask(); + return Sequence< sal_Int8 >( (sal_Int8*) aMem.GetData(), aMem.Tell() ); + } + + return Sequence< sal_Int8 >(); +} + +// XUnoTunnel +sal_Int64 SAL_CALL ImageWrapper::getSomething( const Sequence< sal_Int8 >& aIdentifier ) throw ( RuntimeException ) +{ + if ( aIdentifier == impl_getStaticIdentifier() ) + return reinterpret_cast< sal_Int64 >( this ); + else + return 0; +} + +} + diff --git a/framework/source/fwe/classes/menuextensionsupplier.cxx b/framework/source/fwe/classes/menuextensionsupplier.cxx new file mode 100644 index 000000000000..3849a34d5425 --- /dev/null +++ b/framework/source/fwe/classes/menuextensionsupplier.cxx @@ -0,0 +1,64 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <framework/menuextensionsupplier.hxx> +#include <osl/mutex.hxx> + +static pfunc_setMenuExtensionSupplier pMenuExtensionSupplierFunc = NULL; + +namespace framework +{ + +pfunc_setMenuExtensionSupplier SAL_CALL SetMenuExtensionSupplier( pfunc_setMenuExtensionSupplier pMenuExtensionSupplierFuncArg ) +{ + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + + pfunc_setMenuExtensionSupplier pOldMenuExtensionSupplierFunc = pMenuExtensionSupplierFunc; + pMenuExtensionSupplierFunc = pMenuExtensionSupplierFuncArg; + return pOldMenuExtensionSupplierFunc; +} + +MenuExtensionItem SAL_CALL GetMenuExtension() +{ + MenuExtensionItem aItem; + + pfunc_setMenuExtensionSupplier pLocalMenuExtensionSupplierFunc( 0 ); + + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + pLocalMenuExtensionSupplierFunc = pMenuExtensionSupplierFunc; + } + + if ( pLocalMenuExtensionSupplierFunc ) + return (*pLocalMenuExtensionSupplierFunc)(); + else + return aItem; +} + +} diff --git a/framework/source/fwe/classes/rootactiontriggercontainer.cxx b/framework/source/fwe/classes/rootactiontriggercontainer.cxx new file mode 100644 index 000000000000..cdcc9aea5e1f --- /dev/null +++ b/framework/source/fwe/classes/rootactiontriggercontainer.cxx @@ -0,0 +1,379 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <classes/rootactiontriggercontainer.hxx> +#include <classes/actiontriggercontainer.hxx> +#include <classes/actiontriggerpropertyset.hxx> +#include <classes/actiontriggerseparatorpropertyset.hxx> +#include <framework/actiontriggerhelper.hxx> +#include <threadhelp/resetableguard.hxx> +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> +#include <cppuhelper/typeprovider.hxx> + + +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; +using namespace com::sun::star::beans; + + +namespace framework +{ + +static Sequence< sal_Int8 > impl_getStaticIdentifier() +{ + static sal_uInt8 pGUID[16] = { 0x17, 0x0F, 0xA2, 0xC9, 0xCA, 0x50, 0x4A, 0xD3, 0xA6, 0x3B, 0x39, 0x99, 0xC5, 0x96, 0x43, 0x27 }; + static ::com::sun::star::uno::Sequence< sal_Int8 > seqID((sal_Int8*)pGUID,16) ; + return seqID ; +} + + +RootActionTriggerContainer::RootActionTriggerContainer( const Menu* pMenu, const ::rtl::OUString* pMenuIdentifier, const Reference< XMultiServiceFactory >& rServiceManager ) : + PropertySetContainer( rServiceManager ) + , m_bContainerCreated( sal_False ) + , m_bContainerChanged( sal_False ) + , m_bInContainerCreation( sal_False ) + , m_pMenu( pMenu ) + , m_pMenuIdentifier( pMenuIdentifier ) +{ +} + +RootActionTriggerContainer::~RootActionTriggerContainer() +{ +} + +Sequence< sal_Int8 > RootActionTriggerContainer::GetUnoTunnelId() const +{ + return impl_getStaticIdentifier(); +} + +const Menu* RootActionTriggerContainer::GetMenu() +{ + if ( !m_bContainerChanged ) + return m_pMenu; + else + { + ResetableGuard aGuard( m_aLock ); + + Menu* pNewMenu = new PopupMenu; + + ActionTriggerHelper::CreateMenuFromActionTriggerContainer( pNewMenu, this ); + m_pMenu = pNewMenu; + m_bContainerChanged = sal_False; + + return m_pMenu; + } +} + + +// XInterface +Any SAL_CALL RootActionTriggerContainer::queryInterface( const Type& aType ) +throw ( RuntimeException ) +{ + Any a = ::cppu::queryInterface( + aType , + SAL_STATIC_CAST( XMultiServiceFactory* , this ), + SAL_STATIC_CAST( XServiceInfo* , this ), + SAL_STATIC_CAST( XUnoTunnel* , this ), + SAL_STATIC_CAST( XTypeProvider* , this ), + SAL_STATIC_CAST( XNamed* , this )); + + if( a.hasValue() ) + { + return a; + } + + return PropertySetContainer::queryInterface( aType ); +} + +void SAL_CALL RootActionTriggerContainer::acquire() throw () +{ + PropertySetContainer::acquire(); +} + +void SAL_CALL RootActionTriggerContainer::release() throw () +{ + PropertySetContainer::release(); +} + +// XMultiServiceFactory +Reference< XInterface > SAL_CALL RootActionTriggerContainer::createInstance( const ::rtl::OUString& aServiceSpecifier ) +throw ( Exception, RuntimeException ) +{ + if ( aServiceSpecifier.equalsAscii( SERVICENAME_ACTIONTRIGGER )) + return (OWeakObject *)( new ActionTriggerPropertySet( m_xServiceManager )); + else if ( aServiceSpecifier.equalsAscii( SERVICENAME_ACTIONTRIGGERCONTAINER )) + return (OWeakObject *)( new ActionTriggerContainer( m_xServiceManager )); + else if ( aServiceSpecifier.equalsAscii( SERVICENAME_ACTIONTRIGGERSEPARATOR )) + return (OWeakObject *)( new ActionTriggerSeparatorPropertySet( m_xServiceManager )); + else + throw com::sun::star::uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unknown service specifier!" )), (OWeakObject *)this ); +} + +Reference< XInterface > SAL_CALL RootActionTriggerContainer::createInstanceWithArguments( const ::rtl::OUString& ServiceSpecifier, const Sequence< Any >& /*Arguments*/ ) +throw ( Exception, RuntimeException ) +{ + return createInstance( ServiceSpecifier ); +} + +Sequence< ::rtl::OUString > SAL_CALL RootActionTriggerContainer::getAvailableServiceNames() +throw ( RuntimeException ) +{ + Sequence< ::rtl::OUString > aSeq( 3 ); + + aSeq[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGER )); + aSeq[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGERCONTAINER )); + aSeq[2] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGERSEPARATOR )); + + return aSeq; +} + + +// XIndexContainer +void SAL_CALL RootActionTriggerContainer::insertByIndex( sal_Int32 Index, const Any& Element ) +throw ( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + if ( !m_bContainerCreated ) + FillContainer(); + + if ( !m_bInContainerCreation ) + m_bContainerChanged = sal_True; + PropertySetContainer::insertByIndex( Index, Element ); +} + +void SAL_CALL RootActionTriggerContainer::removeByIndex( sal_Int32 Index ) +throw ( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + if ( !m_bContainerCreated ) + FillContainer(); + + if ( !m_bInContainerCreation ) + m_bContainerChanged = sal_True; + PropertySetContainer::removeByIndex( Index ); +} + + +// XIndexReplace +void SAL_CALL RootActionTriggerContainer::replaceByIndex( sal_Int32 Index, const Any& Element ) +throw ( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + if ( !m_bContainerCreated ) + FillContainer(); + + if ( !m_bInContainerCreation ) + m_bContainerChanged = sal_True; + PropertySetContainer::replaceByIndex( Index, Element ); +} + + +// XIndexAccess +sal_Int32 SAL_CALL RootActionTriggerContainer::getCount() +throw ( RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + if ( !m_bContainerCreated ) + { + if ( m_pMenu ) + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + return m_pMenu->GetItemCount(); + } + else + return 0; + } + else + { + return PropertySetContainer::getCount(); + } +} + +Any SAL_CALL RootActionTriggerContainer::getByIndex( sal_Int32 Index ) +throw ( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + if ( !m_bContainerCreated ) + FillContainer(); + + return PropertySetContainer::getByIndex( Index ); +} + + +// XElementAccess +Type SAL_CALL RootActionTriggerContainer::getElementType() + throw (::com::sun::star::uno::RuntimeException) +{ + return ::getCppuType(( Reference< XPropertySet >*)0); +} + +sal_Bool SAL_CALL RootActionTriggerContainer::hasElements() +throw (::com::sun::star::uno::RuntimeException) +{ + if ( m_pMenu ) + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + return ( m_pMenu->GetItemCount() > 0 ); + } + + return sal_False; +} + + +// XServiceInfo +::rtl::OUString SAL_CALL RootActionTriggerContainer::getImplementationName() +throw ( RuntimeException ) +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATIONNAME_ROOTACTIONTRIGGERCONTAINER )); +} + +sal_Bool SAL_CALL RootActionTriggerContainer::supportsService( const ::rtl::OUString& ServiceName ) +throw ( RuntimeException ) +{ + if ( ServiceName.equalsAscii( SERVICENAME_ACTIONTRIGGERCONTAINER )) + return sal_True; + + return sal_False; +} + +Sequence< ::rtl::OUString > SAL_CALL RootActionTriggerContainer::getSupportedServiceNames() +throw ( RuntimeException ) +{ + Sequence< ::rtl::OUString > seqServiceNames( 1 ); + + seqServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGERCONTAINER )); + return seqServiceNames; +} + +// XUnoTunnel +sal_Int64 SAL_CALL RootActionTriggerContainer::getSomething( const Sequence< sal_Int8 >& aIdentifier ) throw ( RuntimeException ) +{ + if ( aIdentifier == impl_getStaticIdentifier() ) + return reinterpret_cast< sal_Int64 >( this ); + else + return 0; +} + +// XTypeProvider +Sequence< Type > SAL_CALL RootActionTriggerContainer::getTypes() throw ( RuntimeException ) +{ + // Optimize this method ! + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pTypeCollection is NULL - for the second call pTypeCollection is different from NULL! + static ::cppu::OTypeCollection* pTypeCollection = NULL ; + + if ( pTypeCollection == NULL ) + { + // Ready for multithreading; get global mutex for first call of this method only! see before + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; + + // Control these pointer again ... it can be, that another instance will be faster then these! + if ( pTypeCollection == NULL ) + { + // Create a static typecollection ... + static ::cppu::OTypeCollection aTypeCollection( + ::getCppuType(( const Reference< XMultiServiceFactory >*)NULL ) , + ::getCppuType(( const Reference< XIndexContainer >*)NULL ) , + ::getCppuType(( const Reference< XIndexAccess >*)NULL ) , + ::getCppuType(( const Reference< XIndexReplace >*)NULL ) , + ::getCppuType(( const Reference< XServiceInfo >*)NULL ) , + ::getCppuType(( const Reference< XTypeProvider >*)NULL ) , + ::getCppuType(( const Reference< XUnoTunnel >*)NULL ) , + ::getCppuType(( const Reference< XNamed >*)NULL )) ; + + // ... and set his address to static pointer! + pTypeCollection = &aTypeCollection ; + } + } + + return pTypeCollection->getTypes() ; +} + +Sequence< sal_Int8 > SAL_CALL RootActionTriggerContainer::getImplementationId() throw ( RuntimeException ) +{ + // Create one Id for all instances of this class. + // Use ethernet address to do this! (sal_True) + + // Optimize this method + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pID is NULL - for the second call pID is different from NULL! + static ::cppu::OImplementationId* pID = NULL ; + + if ( pID == NULL ) + { + // Ready for multithreading; get global mutex for first call of this method only! see before + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; + + // Control these pointer again ... it can be, that another instance will be faster then these! + if ( pID == NULL ) + { + // Create a new static ID ... + static ::cppu::OImplementationId aID( sal_False ) ; + // ... and set his address to static pointer! + pID = &aID ; + } + } + + return pID->getImplementationId() ; +} + +// private implementation helper +void RootActionTriggerContainer::FillContainer() +{ + m_bContainerCreated = sal_True; + m_bInContainerCreation = sal_True; + Reference<XIndexContainer> xXIndexContainer( (OWeakObject *)this, UNO_QUERY ); + ActionTriggerHelper::FillActionTriggerContainerFromMenu( + xXIndexContainer, + m_pMenu ); + m_bInContainerCreation = sal_False; +} +::rtl::OUString RootActionTriggerContainer::getName() throw ( RuntimeException ) +{ + ::rtl::OUString sRet; + if( m_pMenuIdentifier ) + sRet = *m_pMenuIdentifier; + return sRet; +} + +void RootActionTriggerContainer::setName( const ::rtl::OUString& ) throw ( RuntimeException) +{ + throw RuntimeException(); +} +} + diff --git a/framework/source/fwe/classes/sfxhelperfunctions.cxx b/framework/source/fwe/classes/sfxhelperfunctions.cxx new file mode 100644 index 000000000000..ba3db729817d --- /dev/null +++ b/framework/source/fwe/classes/sfxhelperfunctions.cxx @@ -0,0 +1,179 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <framework/sfxhelperfunctions.hxx> + +#include <tools/diagnose_ex.h> + +static pfunc_setToolBoxControllerCreator pToolBoxControllerCreator = NULL; +static pfunc_setStatusBarControllerCreator pStatusBarControllerCreator = NULL; +static pfunc_getRefreshToolbars pRefreshToolbars = NULL; +static pfunc_createDockingWindow pCreateDockingWindow = NULL; +static pfunc_isDockingWindowVisible pIsDockingWindowVisible = NULL; +static pfunc_activateToolPanel pActivateToolPanel = NULL; + + + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::frame; + +namespace framework +{ + +pfunc_setToolBoxControllerCreator SAL_CALL SetToolBoxControllerCreator( pfunc_setToolBoxControllerCreator pSetToolBoxControllerCreator ) +{ + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + pfunc_setToolBoxControllerCreator pOldSetToolBoxControllerCreator = pToolBoxControllerCreator; + pToolBoxControllerCreator = pSetToolBoxControllerCreator; + return pOldSetToolBoxControllerCreator; +} + +svt::ToolboxController* SAL_CALL CreateToolBoxController( const Reference< XFrame >& rFrame, ToolBox* pToolbox, unsigned short nID, const ::rtl::OUString& aCommandURL ) +{ + pfunc_setToolBoxControllerCreator pFactory = NULL; + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + pFactory = pToolBoxControllerCreator; + } + + if ( pFactory ) + return (*pFactory)( rFrame, pToolbox, nID, aCommandURL ); + else + return NULL; +} + +pfunc_setStatusBarControllerCreator SAL_CALL SetStatusBarControllerCreator( pfunc_setStatusBarControllerCreator pSetStatusBarControllerCreator ) +{ + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + pfunc_setStatusBarControllerCreator pOldSetStatusBarControllerCreator = pSetStatusBarControllerCreator; + pStatusBarControllerCreator = pSetStatusBarControllerCreator; + return pOldSetStatusBarControllerCreator; +} + +svt::StatusbarController* SAL_CALL CreateStatusBarController( const Reference< XFrame >& rFrame, StatusBar* pStatusBar, unsigned short nID, const ::rtl::OUString& aCommandURL ) +{ + pfunc_setStatusBarControllerCreator pFactory = NULL; + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + pFactory = pStatusBarControllerCreator; + } + + if ( pFactory ) + return (*pFactory)( rFrame, pStatusBar, nID, aCommandURL ); + else + return NULL; +} + +pfunc_getRefreshToolbars SAL_CALL SetRefreshToolbars( pfunc_getRefreshToolbars pNewRefreshToolbarsFunc ) +{ + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + pfunc_getRefreshToolbars pOldFunc = pRefreshToolbars; + pRefreshToolbars = pNewRefreshToolbarsFunc; + + return pOldFunc; +} + +void SAL_CALL RefreshToolbars( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame ) +{ + pfunc_getRefreshToolbars pCallback = NULL; + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + pCallback = pRefreshToolbars; + } + + if ( pCallback ) + (*pCallback)( rFrame ); +} + +pfunc_createDockingWindow SAL_CALL SetDockingWindowCreator( pfunc_createDockingWindow pNewCreateDockingWindow ) +{ + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + pfunc_createDockingWindow pOldFunc = pCreateDockingWindow; + pCreateDockingWindow = pNewCreateDockingWindow; + + return pOldFunc; +} + +void SAL_CALL CreateDockingWindow( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame, const ::rtl::OUString& rResourceURL ) +{ + pfunc_createDockingWindow pFactory = NULL; + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + pFactory = pCreateDockingWindow; + } + + if ( pFactory ) + (*pFactory)( rFrame, rResourceURL ); +} + +pfunc_isDockingWindowVisible SAL_CALL SetIsDockingWindowVisible( pfunc_isDockingWindowVisible pNewIsDockingWindowVisible) +{ + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + pfunc_isDockingWindowVisible pOldFunc = pIsDockingWindowVisible; + pIsDockingWindowVisible = pNewIsDockingWindowVisible; + + return pOldFunc; +} + +bool SAL_CALL IsDockingWindowVisible( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame, const ::rtl::OUString& rResourceURL ) +{ + pfunc_isDockingWindowVisible pCall = NULL; + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + pCall = pIsDockingWindowVisible; + } + + if ( pIsDockingWindowVisible ) + return (*pIsDockingWindowVisible)( rFrame, rResourceURL ); + else + return false; +} + +pfunc_activateToolPanel SAL_CALL SetActivateToolPanel( pfunc_activateToolPanel i_pActivator ) +{ + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + pfunc_activateToolPanel pOldFunc = pActivateToolPanel; + pActivateToolPanel = i_pActivator; + return pOldFunc; +} + +void SAL_CALL ActivateToolPanel( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& i_rFrame, const ::rtl::OUString& i_rPanelURL ) +{ + pfunc_activateToolPanel pActivator = NULL; + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + pActivator = pActivateToolPanel; + } + + ENSURE_OR_RETURN_VOID( pActivator, "framework::ActivateToolPanel: no activator function!" ); + (*pActivator)( i_rFrame, i_rPanelURL ); +} + +} diff --git a/framework/source/fwe/dispatch/interaction.cxx b/framework/source/fwe/dispatch/interaction.cxx new file mode 100644 index 000000000000..9b3d4f4c69d8 --- /dev/null +++ b/framework/source/fwe/dispatch/interaction.cxx @@ -0,0 +1,366 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <comphelper/interaction.hxx> +#include <framework/interaction.hxx> +#include <general.h> + +using namespace ::com::sun::star; + +namespace framework{ + +/*-************************************************************************************************************//** + @short declaration of special continuation for filter selection + @descr Sometimes filter detection during loading document failed. Then we need a possibility + to ask user for his decision. These continuation transport selected filter by user to + code user of interaction. + + @attention This implementation could be used one times only. We don't support a resetable continuation yet! + Why? Normaly interaction should show a filter selection dialog and ask user for his decision. + He can select any filter - then instances of these class will be called by handler ... or user + close dialog without any selection. Then another continuation should be slected by handler to + abort continuations ... Retrying isn't very usefull here ... I think. + + @implements XInteractionFilterSelect + + @base ImplInheritanceHelper1 + ContinuationBase + + @devstatus ready to use + @threadsafe no (used on once position only!) +*//*-*************************************************************************************************************/ +class ContinuationFilterSelect : public comphelper::OInteraction< ::com::sun::star::document::XInteractionFilterSelect > +{ + // c++ interface + public: + ContinuationFilterSelect(); + + // uno interface + public: + virtual void SAL_CALL setFilter( const ::rtl::OUString& sFilter ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL getFilter( ) throw( ::com::sun::star::uno::RuntimeException ); + + // member + private: + ::rtl::OUString m_sFilter; + +}; // class ContinuationFilterSelect + + +//--------------------------------------------------------------------------------------------------------- +// initialize continuation with right start values +//--------------------------------------------------------------------------------------------------------- +ContinuationFilterSelect::ContinuationFilterSelect() + : m_sFilter( ::rtl::OUString() ) +{ +} + +//--------------------------------------------------------------------------------------------------------- +// handler should use it after selection to set user specified filter for transport +//--------------------------------------------------------------------------------------------------------- +void SAL_CALL ContinuationFilterSelect::setFilter( const ::rtl::OUString& sFilter ) throw( css::uno::RuntimeException ) +{ + m_sFilter = sFilter; +} + +//--------------------------------------------------------------------------------------------------------- +// read access to transported filter +//--------------------------------------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ContinuationFilterSelect::getFilter() throw( css::uno::RuntimeException ) +{ + return m_sFilter; +} + +class RequestFilterSelect_Impl : public ::cppu::WeakImplHelper1< ::com::sun::star::task::XInteractionRequest > +{ +public: + RequestFilterSelect_Impl( const ::rtl::OUString& sURL ); + sal_Bool isAbort () const; + ::rtl::OUString getFilter() const; + +public: + virtual ::com::sun::star::uno::Any SAL_CALL getRequest() throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionContinuation > > SAL_CALL getContinuations() throw( ::com::sun::star::uno::RuntimeException ); + +private: + ::com::sun::star::uno::Any m_aRequest ; + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionContinuation > > m_lContinuations; + comphelper::OInteractionAbort* m_pAbort; + ContinuationFilterSelect* m_pFilter; +}; + +//--------------------------------------------------------------------------------------------------------- +// initialize instance with all neccessary informations +// We use it without any further checks on our member then ...! +//--------------------------------------------------------------------------------------------------------- +RequestFilterSelect_Impl::RequestFilterSelect_Impl( const ::rtl::OUString& sURL ) +{ + ::rtl::OUString temp; + css::uno::Reference< css::uno::XInterface > temp2; + css::document::NoSuchFilterRequest aFilterRequest( temp , + temp2 , + sURL ); + m_aRequest <<= aFilterRequest; + + m_pAbort = new comphelper::OInteractionAbort; + m_pFilter = new ContinuationFilterSelect; + + m_lContinuations.realloc( 2 ); + m_lContinuations[0] = css::uno::Reference< css::task::XInteractionContinuation >( m_pAbort ); + m_lContinuations[1] = css::uno::Reference< css::task::XInteractionContinuation >( m_pFilter ); +} + +//--------------------------------------------------------------------------------------------------------- +// return abort state of interaction +// If it is true, return value of method "getFilter()" will be unspecified then! +//--------------------------------------------------------------------------------------------------------- +sal_Bool RequestFilterSelect_Impl::isAbort() const +{ + return m_pAbort->wasSelected(); +} + +//--------------------------------------------------------------------------------------------------------- +// return user selected filter +// Return value valid for non aborted interaction only. Please check "isAbort()" before you call these ony! +//--------------------------------------------------------------------------------------------------------- +::rtl::OUString RequestFilterSelect_Impl::getFilter() const +{ + return m_pFilter->getFilter(); +} + +//--------------------------------------------------------------------------------------------------------- +// handler call it to get type of request +// Is hard coded to "please select filter" here. see ctor for further informations. +//--------------------------------------------------------------------------------------------------------- +css::uno::Any SAL_CALL RequestFilterSelect_Impl::getRequest() throw( css::uno::RuntimeException ) +{ + return m_aRequest; +} + +//--------------------------------------------------------------------------------------------------------- +// handler call it to get possible continuations +// We support "abort/select_filter" only here. +// After interaction we support read access on these continuations on our c++ interface to +// return user decision. +//--------------------------------------------------------------------------------------------------------- +css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > SAL_CALL RequestFilterSelect_Impl::getContinuations() throw( css::uno::RuntimeException ) +{ + return m_lContinuations; +} + + +RequestFilterSelect::RequestFilterSelect( const ::rtl::OUString& sURL ) +{ + pImp = new RequestFilterSelect_Impl( sURL ); + pImp->acquire(); +} + +RequestFilterSelect::~RequestFilterSelect() +{ + pImp->release(); +} + + +//--------------------------------------------------------------------------------------------------------- +// return abort state of interaction +// If it is true, return value of method "getFilter()" will be unspecified then! +//--------------------------------------------------------------------------------------------------------- +sal_Bool RequestFilterSelect::isAbort() const +{ + return pImp->isAbort(); +} + +//--------------------------------------------------------------------------------------------------------- +// return user selected filter +// Return value valid for non aborted interaction only. Please check "isAbort()" before you call these ony! +//--------------------------------------------------------------------------------------------------------- +::rtl::OUString RequestFilterSelect::getFilter() const +{ + return pImp->getFilter(); +} + +uno::Reference < task::XInteractionRequest > RequestFilterSelect::GetRequest() +{ + return uno::Reference < task::XInteractionRequest > (pImp); +} + +/* +class RequestAmbigousFilter_Impl : public ::cppu::WeakImplHelper1< ::com::sun::star::task::XInteractionRequest > +{ +public: + RequestAmbigousFilter_Impl( const ::rtl::OUString& sURL , + const ::rtl::OUString& sSelectedFilter , + const ::rtl::OUString& sDetectedFilter ); + sal_Bool isAbort () const; + ::rtl::OUString getFilter() const; + + virtual ::com::sun::star::uno::Any SAL_CALL getRequest () throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionContinuation > > SAL_CALL getContinuations() throw( ::com::sun::star::uno::RuntimeException ); + + ::com::sun::star::uno::Any m_aRequest ; + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionContinuation > > m_lContinuations; + ContinuationAbort* m_pAbort ; + ContinuationFilterSelect* m_pFilter ; +}; + +RequestAmbigousFilter::RequestAmbigousFilter( const ::rtl::OUString& sURL, const ::rtl::OUString& sSelectedFilter, + const ::rtl::OUString& sDetectedFilter ) +{ + pImp = new RequestAmbigousFilter_Impl( sURL, sSelectedFilter, sDetectedFilter ); + pImp->acquire(); +} + +RequestAmbigousFilter::~RequestAmbigousFilter() +{ + pImp->release(); +} + +sal_Bool RequestAmbigousFilter::isAbort() const +{ + return pImp->isAbort(); +} + +//--------------------------------------------------------------------------------------------------------- +// return user selected filter +// Return value valid for non aborted interaction only. Please check "isAbort()" before you call these ony! +//--------------------------------------------------------------------------------------------------------- +::rtl::OUString RequestAmbigousFilter::getFilter() const +{ + return pImp->getFilter(); +} + +uno::Reference < task::XInteractionRequest > RequestAmbigousFilter::GetRequest() +{ + return uno::Reference < task::XInteractionRequest > (pImp); +} + +//--------------------------------------------------------------------------------------------------------- +// initialize instance with all neccessary informations +// We use it without any further checks on our member then ...! +//--------------------------------------------------------------------------------------------------------- +RequestAmbigousFilter_Impl::RequestAmbigousFilter_Impl( const ::rtl::OUString& sURL , + const ::rtl::OUString& sSelectedFilter , + const ::rtl::OUString& sDetectedFilter ) +{ + ::rtl::OUString temp; + css::uno::Reference< css::uno::XInterface > temp2; + css::document::AmbigousFilterRequest aFilterRequest( temp , + temp2 , + sURL , + sSelectedFilter , + sDetectedFilter ); + m_aRequest <<= aFilterRequest; + + m_pAbort = new ContinuationAbort ; + m_pFilter = new ContinuationFilterSelect; + + m_lContinuations.realloc( 2 ); + m_lContinuations[0] = css::uno::Reference< css::task::XInteractionContinuation >( m_pAbort ); + m_lContinuations[1] = css::uno::Reference< css::task::XInteractionContinuation >( m_pFilter ); +} + +//--------------------------------------------------------------------------------------------------------- +// return abort state of interaction +// If it is true, return value of method "getFilter()" will be unspecified then! +//--------------------------------------------------------------------------------------------------------- +sal_Bool RequestAmbigousFilter_Impl::isAbort() const +{ + return m_pAbort->isSelected(); +} + +//--------------------------------------------------------------------------------------------------------- +// return user selected filter +// Return value valid for non aborted interaction only. Please check "isAbort()" before you call these ony! +//--------------------------------------------------------------------------------------------------------- +::rtl::OUString RequestAmbigousFilter_Impl::getFilter() const +{ + return m_pFilter->getFilter(); +} + +//--------------------------------------------------------------------------------------------------------- +// handler call it to get type of request +// Is hard coded to "please select filter" here. see ctor for further informations. +//--------------------------------------------------------------------------------------------------------- +css::uno::Any SAL_CALL RequestAmbigousFilter_Impl::getRequest() throw( css::uno::RuntimeException ) +{ + return m_aRequest; +} + +//--------------------------------------------------------------------------------------------------------- +// handler call it to get possible continuations +// We support "abort/select_filter" only here. +// After interaction we support read access on these continuations on our c++ interface to +// return user decision. +//--------------------------------------------------------------------------------------------------------- +css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > SAL_CALL RequestAmbigousFilter_Impl::getContinuations() throw( css::uno::RuntimeException ) +{ + return m_lContinuations; +} +*/ + +class InteractionRequest_Impl : public ::cppu::WeakImplHelper1< ::com::sun::star::task::XInteractionRequest > +{ + uno::Any m_aRequest; + uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionContinuation > > m_lContinuations; + +public: + InteractionRequest_Impl( const ::com::sun::star::uno::Any& aRequest, + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionContinuation > > lContinuations ) + { + m_aRequest = aRequest; + m_lContinuations = lContinuations; + } + + virtual uno::Any SAL_CALL getRequest() throw( uno::RuntimeException ); + virtual uno::Sequence< uno::Reference< task::XInteractionContinuation > > SAL_CALL getContinuations() + throw( uno::RuntimeException ); +}; + +uno::Any SAL_CALL InteractionRequest_Impl::getRequest() throw( uno::RuntimeException ) +{ + return m_aRequest; +} + +uno::Sequence< uno::Reference< task::XInteractionContinuation > > SAL_CALL InteractionRequest_Impl::getContinuations() + throw( uno::RuntimeException ) +{ + return m_lContinuations; +} + +uno::Reference < task::XInteractionRequest > InteractionRequest::CreateRequest( + const uno::Any& aRequest, const uno::Sequence< uno::Reference< task::XInteractionContinuation > > lContinuations ) +{ + return new InteractionRequest_Impl( aRequest, lContinuations ); +} + +} // namespace framework diff --git a/framework/source/fwe/helper/acceleratorinfo.cxx b/framework/source/fwe/helper/acceleratorinfo.cxx new file mode 100644 index 000000000000..5774bc35a253 --- /dev/null +++ b/framework/source/fwe/helper/acceleratorinfo.cxx @@ -0,0 +1,71 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <framework/acceleratorinfo.hxx> + +namespace framework +{ + +static pfunc_getCommandURLFromKeyCode _pGetCommandURLFromKeyCode = NULL; +static pfunc_getKeyCodeFromCommandURL _pGetKeyCodeFromCommandURL = NULL; + +pfunc_getCommandURLFromKeyCode SAL_CALL SetCommandURLFromKeyCode( pfunc_getCommandURLFromKeyCode pNewFunc ) +{ + pfunc_getCommandURLFromKeyCode pOldFunc = _pGetCommandURLFromKeyCode; + _pGetCommandURLFromKeyCode = pNewFunc; + + return pOldFunc; +} + +::rtl::OUString SAL_CALL GetCommandURLFromKeyCode( const KeyCode& aKeyCode ) +{ + if ( _pGetCommandURLFromKeyCode ) + return _pGetCommandURLFromKeyCode( aKeyCode ); + else + return rtl::OUString(); +} + +pfunc_getKeyCodeFromCommandURL SAL_CALL SetKeyCodeFromCommandURL( pfunc_getKeyCodeFromCommandURL pNewFunc ) +{ + pfunc_getKeyCodeFromCommandURL pOldFunc = _pGetKeyCodeFromCommandURL; + _pGetKeyCodeFromCommandURL = pNewFunc; + + return pOldFunc; +} + +KeyCode SAL_CALL GetKeyCodeFromCommandURL( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame, const rtl::OUString& aCommandURL ) +{ + if ( _pGetKeyCodeFromCommandURL ) + return _pGetKeyCodeFromCommandURL( rFrame, aCommandURL ); + else + return KeyCode(); +} + +} diff --git a/framework/source/fwe/helper/actiontriggerhelper.cxx b/framework/source/fwe/helper/actiontriggerhelper.cxx new file mode 100644 index 000000000000..7c008687ec7d --- /dev/null +++ b/framework/source/fwe/helper/actiontriggerhelper.cxx @@ -0,0 +1,408 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <framework/actiontriggerhelper.hxx> +#include <classes/actiontriggerseparatorpropertyset.hxx> +#include <classes/rootactiontriggercontainer.hxx> +#include <classes/imagewrapper.hxx> +#include <framework/addonsoptions.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/XBitmap.hpp> +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> +#include <tools/stream.hxx> +#include <cppuhelper/weak.hxx> +#include <comphelper/processfactory.hxx> + + +const sal_uInt16 START_ITEMID = 1000; + +using namespace rtl; +using namespace vos; +using namespace com::sun::star::awt; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; + +namespace framework +{ + +// ---------------------------------------------------------------------------- +// implementation helper ( menu => ActionTrigger ) +// ---------------------------------------------------------------------------- + +sal_Bool IsSeparator( Reference< XPropertySet > xPropertySet ) +{ + Reference< XServiceInfo > xServiceInfo( xPropertySet, UNO_QUERY ); + try + { + return xServiceInfo->supportsService( OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGERSEPARATOR )) ); + } + catch ( Exception& ) + { + } + + return sal_False; +} + +void GetMenuItemAttributes( Reference< XPropertySet > xActionTriggerPropertySet, + OUString& aMenuLabel, + OUString& aCommandURL, + OUString& aHelpURL, + Reference< XBitmap >& xBitmap, + Reference< XIndexContainer >& xSubContainer ) +{ + Any a; + + try + { + // mandatory properties + a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" )) ); + a >>= aMenuLabel; + a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )) ); + a >>= aCommandURL; + a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Image" )) ); + a >>= xBitmap; + a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "SubContainer" )) ); + a >>= xSubContainer; + } + catch ( Exception& ) + { + } + + // optional properties + try + { + a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "HelpURL" )) ); + a >>= aHelpURL; + } + catch ( Exception& ) + { + } +} + +void InsertSubMenuItems( Menu* pSubMenu, sal_uInt16& nItemId, Reference< XIndexContainer > xActionTriggerContainer ) +{ + Reference< XIndexAccess > xIndexAccess( xActionTriggerContainer, UNO_QUERY ); + if ( xIndexAccess.is() ) + { + AddonsOptions aAddonOptions; + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + sal_Bool bHiContrast = rSettings.GetHighContrastMode(); + + OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" )); + + for ( sal_Int32 i = 0; i < xIndexAccess->getCount(); i++ ) + { + try + { + Reference< XPropertySet > xPropSet; + if (( xIndexAccess->getByIndex( i ) >>= xPropSet ) && ( xPropSet.is() )) + { + if ( IsSeparator( xPropSet )) + { + // Separator + OGuard aGuard( Application::GetSolarMutex() ); + pSubMenu->InsertSeparator(); + } + else + { + // Menu item + OUString aLabel; + OUString aCommandURL; + OUString aHelpURL; + Reference< XBitmap > xBitmap; + Reference< XIndexContainer > xSubContainer; + sal_Bool bSpecialItemId = sal_False; + + sal_uInt16 nNewItemId = nItemId++; + GetMenuItemAttributes( xPropSet, aLabel, aCommandURL, aHelpURL, xBitmap, xSubContainer ); + + OGuard aGuard( Application::GetSolarMutex() ); + { + // insert new menu item + sal_Int32 nIndex = aCommandURL.indexOf( aSlotURL ); + if ( nIndex >= 0 ) + { + // Special code for our menu implementation: some menu items don't have a + // command url but uses the item id as a unqiue identifier. These entries + // got a special url during conversion from menu=>actiontriggercontainer. + // Now we have to extract this special url and set the correct item id!!! + bSpecialItemId = sal_True; + nNewItemId = (sal_uInt16)aCommandURL.copy( nIndex+aSlotURL.getLength() ).toInt32(); + pSubMenu->InsertItem( nNewItemId, aLabel ); + } + else + { + pSubMenu->InsertItem( nNewItemId, aLabel ); + pSubMenu->SetItemCommand( nNewItemId, aCommandURL ); + } + + // handle bitmap + if ( xBitmap.is() ) + { + sal_Bool bImageSet = sal_False; + + Reference< XUnoTunnel > xUnoTunnel( xBitmap, UNO_QUERY ); + if ( xUnoTunnel.is() ) + { + // Try to get implementation pointer through XUnoTunnel + sal_Int64 nPointer = xUnoTunnel->getSomething( ImageWrapper::GetUnoTunnelId() ); + if ( nPointer ) + { + // This is our own optimized implementation of menu images! + ImageWrapper* pImageWrapper = reinterpret_cast< ImageWrapper * >( nPointer ); + Image aMenuImage = pImageWrapper->GetImage(); + + if ( !!aMenuImage ) + pSubMenu->SetItemImage( nNewItemId, aMenuImage ); + + bImageSet = sal_True; + } + } + + if ( !bImageSet ) + { + // This is an unknown implementation of a XBitmap interface. We have to + // use a more time consuming way to build an Image! + Image aImage; + Bitmap aBitmap; + + Sequence< sal_Int8 > aDIBSeq; + { + aDIBSeq = xBitmap->getDIB(); + SvMemoryStream aMem( (void *)aDIBSeq.getConstArray(), aDIBSeq.getLength(), STREAM_READ ); + aMem >> aBitmap; + } + + aDIBSeq = xBitmap->getMaskDIB(); + if ( aDIBSeq.getLength() > 0 ) + { + Bitmap aMaskBitmap; + SvMemoryStream aMem( (void *)aDIBSeq.getConstArray(), aDIBSeq.getLength(), STREAM_READ ); + aMem >> aMaskBitmap; + aImage = Image( aBitmap, aMaskBitmap ); + } + else + aImage = Image( aBitmap ); + + if ( !!aImage ) + pSubMenu->SetItemImage( nNewItemId, aImage ); + } + } + else + { + // Support add-on images for context menu interceptors + Image aImage = aAddonOptions.GetImageFromURL( aCommandURL, sal_False, bHiContrast, sal_True ); + if ( !!aImage ) + pSubMenu->SetItemImage( nNewItemId, aImage ); + } + + if ( xSubContainer.is() ) + { + PopupMenu* pNewSubMenu = new PopupMenu; + + // Sub menu (recursive call CreateSubMenu ) + InsertSubMenuItems( pNewSubMenu, nItemId, xSubContainer ); + pSubMenu->SetPopupMenu( nNewItemId, pNewSubMenu ); + } + } + } + } + } + catch ( IndexOutOfBoundsException ) + { + return; + } + catch ( WrappedTargetException ) + { + return; + } + catch ( RuntimeException ) + { + return; + } + } + } +} + + +// ---------------------------------------------------------------------------- +// implementation helper ( ActionTrigger => menu ) +// ---------------------------------------------------------------------------- + +Reference< XPropertySet > CreateActionTrigger( sal_uInt16 nItemId, const Menu* pMenu, const Reference< XIndexContainer >& rActionTriggerContainer ) throw ( RuntimeException ) +{ + Reference< XPropertySet > xPropSet; + + Reference< XMultiServiceFactory > xMultiServiceFactory( rActionTriggerContainer, UNO_QUERY ); + if ( xMultiServiceFactory.is() ) + { + xPropSet = Reference< XPropertySet >( xMultiServiceFactory->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.ActionTrigger" )) ), + UNO_QUERY ); + + Any a; + + try + { + // Retrieve the menu attributes and set them in our PropertySet + OUString aLabel = pMenu->GetItemText( nItemId ); + a <<= aLabel; + xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" )), a ); + + OUString aCommandURL = pMenu->GetItemCommand( nItemId ); + + if ( aCommandURL.getLength() == 0 ) + { + aCommandURL = OUString( RTL_CONSTASCII_USTRINGPARAM( "slot:" )); + aCommandURL += OUString::valueOf( (sal_Int32)nItemId ); + } + + a <<= aCommandURL; + xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )), a ); + + Image aImage = pMenu->GetItemImage( nItemId ); + if ( !!aImage ) + { + // We use our own optimized XBitmap implementation + Reference< XBitmap > xBitmap( static_cast< cppu::OWeakObject* >( new ImageWrapper( aImage )), UNO_QUERY ); + a <<= xBitmap; + xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Image" )), a ); + } + } + catch ( Exception& ) + { + } + } + + return xPropSet; +} + +Reference< XPropertySet > CreateActionTriggerSeparator( const Reference< XIndexContainer >& rActionTriggerContainer ) throw ( RuntimeException ) +{ + Reference< XMultiServiceFactory > xMultiServiceFactory( rActionTriggerContainer, UNO_QUERY ); + if ( xMultiServiceFactory.is() ) + { + return Reference< XPropertySet >( xMultiServiceFactory->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.ActionTriggerSeparator" )) ), + UNO_QUERY ); + } + + return Reference< XPropertySet >(); +} + +Reference< XIndexContainer > CreateActionTriggerContainer( const Reference< XIndexContainer >& rActionTriggerContainer ) throw ( RuntimeException ) +{ + Reference< XMultiServiceFactory > xMultiServiceFactory( rActionTriggerContainer, UNO_QUERY ); + if ( xMultiServiceFactory.is() ) + { + return Reference< XIndexContainer >( xMultiServiceFactory->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.ActionTriggerContainer" )) ), + UNO_QUERY ); + } + + return Reference< XIndexContainer >(); +} + +void FillActionTriggerContainerWithMenu( const Menu* pMenu, Reference< XIndexContainer >& rActionTriggerContainer ) +{ + OGuard aGuard( Application::GetSolarMutex() ); + + for ( sal_uInt16 nPos = 0; nPos < pMenu->GetItemCount(); nPos++ ) + { + sal_uInt16 nItemId = pMenu->GetItemId( nPos ); + MenuItemType nType = pMenu->GetItemType( nPos ); + + try + { + Any a; + Reference< XPropertySet > xPropSet; + + if ( nType == MENUITEM_SEPARATOR ) + { + xPropSet = CreateActionTriggerSeparator( rActionTriggerContainer ); + + a <<= xPropSet; + rActionTriggerContainer->insertByIndex( nPos, a ); + } + else + { + xPropSet = CreateActionTrigger( nItemId, pMenu, rActionTriggerContainer ); + + a <<= xPropSet; + rActionTriggerContainer->insertByIndex( nPos, a ); + + PopupMenu* pPopupMenu = pMenu->GetPopupMenu( nItemId ); + if ( pPopupMenu ) + { + // recursive call to build next sub menu + Reference< XIndexContainer > xSubContainer = CreateActionTriggerContainer( rActionTriggerContainer ); + + a <<= xSubContainer; + xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "SubContainer" )), a ); + FillActionTriggerContainerWithMenu( pPopupMenu, xSubContainer ); + } + } + } + catch ( Exception& ) + { + } + } +} + +void ActionTriggerHelper::CreateMenuFromActionTriggerContainer( + Menu* pNewMenu, + const Reference< XIndexContainer >& rActionTriggerContainer ) +{ + sal_uInt16 nItemId = START_ITEMID; + + if ( rActionTriggerContainer.is() ) + InsertSubMenuItems( pNewMenu, nItemId, rActionTriggerContainer ); +} + +void ActionTriggerHelper::FillActionTriggerContainerFromMenu( + Reference< XIndexContainer >& xActionTriggerContainer, + const Menu* pMenu ) +{ + FillActionTriggerContainerWithMenu( pMenu, xActionTriggerContainer ); +} + +Reference< XIndexContainer > ActionTriggerHelper::CreateActionTriggerContainerFromMenu( + // #110897# + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory, + const Menu* pMenu, + const ::rtl::OUString* pMenuIdentifier ) +{ + return new RootActionTriggerContainer( pMenu, pMenuIdentifier, xServiceFactory ); +} + +} diff --git a/framework/source/fwe/helper/configimporter.cxx b/framework/source/fwe/helper/configimporter.cxx new file mode 100644 index 000000000000..0b7571416c9d --- /dev/null +++ b/framework/source/fwe/helper/configimporter.cxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <framework/configimporter.hxx> +#include <framework/toolboxconfiguration.hxx> +#include <com/sun/star/embed/ElementModes.hpp> + +#include <rtl/ustrbuf.hxx> + +using namespace ::com::sun::star; + +namespace framework +{ + +sal_Bool UIConfigurationImporterOOo1x::ImportCustomToolbars( + const uno::Reference< ui::XUIConfigurationManager >& rContainerFactory, + uno::Sequence< uno::Reference< container::XIndexContainer > >& rSeqContainer, + const uno::Reference< lang::XMultiServiceFactory >& rServiceManager, + const uno::Reference< embed::XStorage >& rToolbarStorage ) +{ + const char USERDEFTOOLBOX[] = "userdeftoolbox0.xml"; + uno::Reference< lang::XMultiServiceFactory > rSrvMgr( rServiceManager ); + + sal_Bool bResult ( sal_False ); + if ( rToolbarStorage.is() && rContainerFactory.is() ) + { + try + { + for ( sal_uInt16 i = 1; i <= 4; i++ ) + { + rtl::OUStringBuffer aCustomTbxName( 20 ); + aCustomTbxName.appendAscii( USERDEFTOOLBOX ); + aCustomTbxName.setCharAt( 14, aCustomTbxName.charAt( 14 ) + i ); + + rtl::OUString aTbxStreamName( aCustomTbxName.makeStringAndClear() ); + uno::Reference< io::XStream > xStream = rToolbarStorage->openStreamElement( aTbxStreamName, embed::ElementModes::READ ); + if ( xStream.is() ) + { + uno::Reference< io::XInputStream > xInputStream = xStream->getInputStream(); + if ( xInputStream.is() ) + { + uno::Reference< container::XIndexContainer > xContainer = rContainerFactory->createSettings(); + if ( ToolBoxConfiguration::LoadToolBox( rSrvMgr, xInputStream, xContainer )) + { + sal_uInt32 nIndex = rSeqContainer.getLength(); + rSeqContainer.realloc( nIndex+1 ); + rSeqContainer[nIndex] = xContainer; + bResult = sal_True; + } + } + } + } + } + catch ( uno::RuntimeException& ) + { + throw; + } + catch ( uno::Exception& ) + { + } + } + + return bResult; +} + +} // namespace framework diff --git a/framework/source/fwe/helper/imageproducer.cxx b/framework/source/fwe/helper/imageproducer.cxx new file mode 100644 index 000000000000..ab13b2caef6c --- /dev/null +++ b/framework/source/fwe/helper/imageproducer.cxx @@ -0,0 +1,56 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <framework/imageproducer.hxx> + +namespace framework +{ + +static pfunc_getImage _pGetImageFunc = NULL; + +pfunc_getImage SAL_CALL SetImageProducer( pfunc_getImage pNewGetImageFunc ) +{ + pfunc_getImage pOldFunc = _pGetImageFunc; + _pGetImageFunc = pNewGetImageFunc; + + return pOldFunc; +} + + +Image SAL_CALL GetImageFromURL( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame, const ::rtl::OUString& aURL, sal_Bool bBig, sal_Bool bHiContrast ) +{ + if ( _pGetImageFunc ) + return _pGetImageFunc( rFrame, aURL, bBig, bHiContrast ); + else + return Image(); +} + +} + diff --git a/framework/source/fwe/helper/propertysetcontainer.cxx b/framework/source/fwe/helper/propertysetcontainer.cxx new file mode 100644 index 000000000000..0fe750f92fd9 --- /dev/null +++ b/framework/source/fwe/helper/propertysetcontainer.cxx @@ -0,0 +1,196 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <helper/propertysetcontainer.hxx> +#include <threadhelp/resetableguard.hxx> + +#include <vcl/svapp.hxx> + +#define WRONG_TYPE_EXCEPTION "Only XPropertSet allowed!" + +using namespace rtl; +using namespace vos; +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::container; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; + +namespace framework +{ + +PropertySetContainer::PropertySetContainer( const Reference< XMultiServiceFactory >& ) + : ThreadHelpBase( &Application::GetSolarMutex() ) + , OWeakObject() + +{ +} + + +PropertySetContainer::~PropertySetContainer() +{ +} + + +// XInterface +void SAL_CALL PropertySetContainer::acquire() throw () +{ + OWeakObject::acquire(); +} + +void SAL_CALL PropertySetContainer::release() throw () +{ + OWeakObject::release(); +} + +Any SAL_CALL PropertySetContainer::queryInterface( const Type& rType ) +throw ( RuntimeException ) +{ + Any a = ::cppu::queryInterface( + rType , + SAL_STATIC_CAST( XIndexContainer*, this ), + SAL_STATIC_CAST( XIndexReplace*, this ), + SAL_STATIC_CAST( XIndexAccess*, this ), + SAL_STATIC_CAST( XElementAccess*, this ) ); + + if( a.hasValue() ) + { + return a; + } + + return OWeakObject::queryInterface( rType ); +} + +// XIndexContainer +void SAL_CALL PropertySetContainer::insertByIndex( sal_Int32 Index, const ::com::sun::star::uno::Any& Element ) + throw ( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + sal_Int32 nSize = m_aPropertySetVector.size(); + + if ( nSize >= Index ) + { + Reference< XPropertySet > aPropertySetElement; + + if ( Element >>= aPropertySetElement ) + { + if ( nSize == Index ) + m_aPropertySetVector.push_back( aPropertySetElement ); + else + { + PropertySetVector::iterator aIter = m_aPropertySetVector.begin(); + aIter += Index; + m_aPropertySetVector.insert( aIter, aPropertySetElement ); + } + } + else + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM( WRONG_TYPE_EXCEPTION )), + (OWeakObject *)this, 2 ); + } + } + else + throw IndexOutOfBoundsException( OUString(), (OWeakObject *)this ); +} + +void SAL_CALL PropertySetContainer::removeByIndex( sal_Int32 Index ) + throw ( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + if ( (sal_Int32)m_aPropertySetVector.size() > Index ) + { + PropertySetVector::iterator aIter = m_aPropertySetVector.begin(); + aIter += Index; + m_aPropertySetVector.erase( aIter ); + } + else + throw IndexOutOfBoundsException( OUString(), (OWeakObject *)this ); +} + +// XIndexReplace +void SAL_CALL PropertySetContainer::replaceByIndex( sal_Int32 Index, const ::com::sun::star::uno::Any& Element ) + throw ( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException) +{ + if ( (sal_Int32)m_aPropertySetVector.size() > Index ) + { + Reference< XPropertySet > aPropertySetElement; + + if ( Element >>= aPropertySetElement ) + { + m_aPropertySetVector[ Index ] = aPropertySetElement; + } + else + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM( WRONG_TYPE_EXCEPTION )), + (OWeakObject *)this, 2 ); + } + } + else + throw IndexOutOfBoundsException( OUString(), (OWeakObject *)this ); +} + +// XIndexAccess +sal_Int32 SAL_CALL PropertySetContainer::getCount() + throw ( RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + return m_aPropertySetVector.size(); +} + +Any SAL_CALL PropertySetContainer::getByIndex( sal_Int32 Index ) + throw ( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + if ( (sal_Int32)m_aPropertySetVector.size() > Index ) + { + Any a; + + a <<= m_aPropertySetVector[ Index ]; + return a; + } + else + throw IndexOutOfBoundsException( OUString(), (OWeakObject *)this ); +} + +// XElementAccess +sal_Bool SAL_CALL PropertySetContainer::hasElements() + throw (::com::sun::star::uno::RuntimeException) +{ + ResetableGuard aGuard( m_aLock ); + + return !( m_aPropertySetVector.empty() ); +} + +} diff --git a/framework/source/fwe/helper/titlehelper.cxx b/framework/source/fwe/helper/titlehelper.cxx new file mode 100644 index 000000000000..d9191da2be2e --- /dev/null +++ b/framework/source/fwe/helper/titlehelper.cxx @@ -0,0 +1,760 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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" + +//_______________________________________________ +// includes + +#include <framework/titlehelper.hxx> +#include <services.h> +#include <properties.h> + +#include <com/sun/star/frame/UntitledNumbersConst.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/document/XEventBroadcaster.hpp> +#include <com/sun/star/beans/XMaterialHolder.hpp> + +#include <unotools/configmgr.hxx> +#include <unotools/bootstrap.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/mutex.hxx> +#include <tools/urlobj.hxx> + +//_______________________________________________ +// namespace + +namespace framework{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +static const ::rtl::OUString ERRMSG_INVALID_COMPONENT_PARAM = ::rtl::OUString::createFromAscii("NULL as component reference not allowed."); +static const ::rtl::OUString ERRMSG_INVALID_NUMBER_PARAM = ::rtl::OUString::createFromAscii("Special valkud INVALID_NUMBER not allowed as input parameter."); + +//----------------------------------------------- +TitleHelper::TitleHelper(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) + : ::cppu::BaseMutex () + , m_xSMGR (xSMGR) + , m_xOwner () + , m_xUntitledNumbers() + , m_xSubTitle () + , m_bExternalTitle (sal_False) + , m_sTitle () + , m_nLeasedNumber (css::frame::UntitledNumbersConst::INVALID_NUMBER) + , m_aListener (m_aMutex) +{ +} + +//----------------------------------------------- +TitleHelper::~TitleHelper() +{ +} + +//----------------------------------------------- +void TitleHelper::setOwner(const css::uno::Reference< css::uno::XInterface >& xOwner) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + m_xOwner = xOwner; + + aLock.clear (); + // <- SYNCHRONIZED + + css::uno::Reference< css::frame::XModel > xModel(xOwner, css::uno::UNO_QUERY); + if (xModel.is ()) + { + impl_startListeningForModel (xModel); + return; + } + + css::uno::Reference< css::frame::XController > xController(xOwner, css::uno::UNO_QUERY); + if (xController.is ()) + { + impl_startListeningForController (xController); + return; + } + + css::uno::Reference< css::frame::XFrame > xFrame(xOwner, css::uno::UNO_QUERY); + if (xFrame.is ()) + { + impl_startListeningForFrame (xFrame); + return; + } +} + +//----------------------------------------------- +::rtl::OUString SAL_CALL TitleHelper::getTitle() + throw (css::uno::RuntimeException) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + // An external title will win always and disable all internal logic about + // creating/using a title value. + // Even an empty string will be accepted as valid title ! + if (m_bExternalTitle) + return m_sTitle; + + // Title seams to be up-to-date. Return it directly. + if (m_sTitle.getLength() > 0) + return m_sTitle; + + // Title seams to be unused till now ... do bootstraping + impl_updateTitle (); + + return m_sTitle; + + // <- SYNCHRONIZED +} + +//----------------------------------------------- +void TitleHelper::connectWithUntitledNumbers (const css::uno::Reference< css::frame::XUntitledNumbers >& xNumbers) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + m_xUntitledNumbers = xNumbers; + + // <- SYNCHRONIZED +} + +//----------------------------------------------- +void SAL_CALL TitleHelper::setTitle(const ::rtl::OUString& sTitle) + throw (css::uno::RuntimeException) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + m_bExternalTitle = sal_True; + m_sTitle = sTitle; + + aLock.clear (); + // <- SYNCHRONIZED + + impl_sendTitleChangedEvent (); +} + +//----------------------------------------------- +void SAL_CALL TitleHelper::addTitleChangeListener(const css::uno::Reference< css::frame::XTitleChangeListener >& xListener) + throw (css::uno::RuntimeException) +{ + // container is threadsafe by himself + m_aListener.addInterface( ::getCppuType( (const css::uno::Reference< css::frame::XTitleChangeListener >*)NULL ), xListener ); +} + +//----------------------------------------------- +void SAL_CALL TitleHelper::removeTitleChangeListener(const css::uno::Reference< css::frame::XTitleChangeListener >& xListener) + throw (css::uno::RuntimeException) +{ + // container is threadsafe by himself + m_aListener.removeInterface( ::getCppuType( (const css::uno::Reference< css::frame::XTitleChangeListener >*)NULL ), xListener ); +} + +//----------------------------------------------- +void SAL_CALL TitleHelper::titleChanged(const css::frame::TitleChangedEvent& aEvent) + throw (css::uno::RuntimeException) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + css::uno::Reference< css::frame::XTitle > xSubTitle(m_xSubTitle.get (), css::uno::UNO_QUERY); + + aLock.clear (); + // <- SYNCHRONIZED + + if (aEvent.Source != xSubTitle) + return; + + impl_updateTitle (); +} + +//----------------------------------------------- +void SAL_CALL TitleHelper::notifyEvent(const css::document::EventObject& aEvent) + throw (css::uno::RuntimeException) +{ + if ( ! aEvent.EventName.equalsIgnoreAsciiCaseAscii ("OnSaveAsDone") + && ! aEvent.EventName.equalsIgnoreAsciiCaseAscii ("OnTitleChanged")) + return; + + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + css::uno::Reference< css::frame::XModel > xOwner(m_xOwner.get (), css::uno::UNO_QUERY); + + aLock.clear (); + // <- SYNCHRONIZED + + if ( + aEvent.Source != xOwner || + (aEvent.EventName.equalsIgnoreAsciiCaseAscii ("OnTitleChanged") && !xOwner.is()) + ) + { + return; + } + + impl_updateTitle (); +} + +//----------------------------------------------- +void SAL_CALL TitleHelper::frameAction(const css::frame::FrameActionEvent& aEvent) + throw(css::uno::RuntimeException) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + css::uno::Reference< css::frame::XFrame > xOwner(m_xOwner.get (), css::uno::UNO_QUERY); + + aLock.clear (); + // <- SYNCHRONIZED + + if (aEvent.Source != xOwner) + return; + + // we are interested on events only, which must trigger a title bar update + // because component was changed. + if ( + (aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED ) || + (aEvent.Action == css::frame::FrameAction_COMPONENT_REATTACHED) || + (aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING ) + ) + { + impl_updateListeningForFrame (xOwner); + impl_updateTitle (); + } +} + +//----------------------------------------------- +void SAL_CALL TitleHelper::disposing(const css::lang::EventObject& aEvent) + throw (css::uno::RuntimeException) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + css::uno::Reference< css::uno::XInterface > xOwner (m_xOwner.get() , css::uno::UNO_QUERY); + css::uno::Reference< css::frame::XUntitledNumbers > xNumbers (m_xUntitledNumbers.get(), css::uno::UNO_QUERY); + ::sal_Int32 nLeasedNumber = m_nLeasedNumber; + aLock.clear (); + // <- SYNCHRONIZED + + if ( ! xOwner.is ()) + return; + + if (xOwner != aEvent.Source) + return; + + if ( + (xNumbers.is () ) && + (nLeasedNumber != css::frame::UntitledNumbersConst::INVALID_NUMBER) + ) + xNumbers->releaseNumber (nLeasedNumber); + + // SYNCHRONIZED -> + aLock.reset (); + + m_sTitle = ::rtl::OUString (); + m_nLeasedNumber = css::frame::UntitledNumbersConst::INVALID_NUMBER; + + aLock.clear (); + // <- SYNCHRONIZED + + impl_sendTitleChangedEvent (); +} + +//----------------------------------------------- +void TitleHelper::impl_sendTitleChangedEvent () +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + css::frame::TitleChangedEvent aEvent(m_xOwner.get (), m_sTitle); + + aLock.clear (); + // <- SYNCHRONIZED + + ::cppu::OInterfaceContainerHelper* pContainer = m_aListener.getContainer( ::getCppuType( ( const css::uno::Reference< css::frame::XTitleChangeListener >*) NULL ) ); + if ( ! pContainer) + return; + + ::cppu::OInterfaceIteratorHelper pIt( *pContainer ); + while ( pIt.hasMoreElements() ) + { + try + { + ((css::frame::XTitleChangeListener*)pIt.next())->titleChanged( aEvent ); + } + catch(const css::uno::Exception&) + { + pIt.remove(); + } + } +} + +//----------------------------------------------- +void TitleHelper::impl_updateTitle () +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + css::uno::Reference< css::frame::XModel > xModel (m_xOwner.get(), css::uno::UNO_QUERY); + css::uno::Reference< css::frame::XController > xController(m_xOwner.get(), css::uno::UNO_QUERY); + css::uno::Reference< css::frame::XFrame > xFrame (m_xOwner.get(), css::uno::UNO_QUERY); + + aLock.clear (); + // <- SYNCHRONIZED + + if (xModel.is ()) + { + impl_updateTitleForModel (xModel); + return; + } + + if (xController.is ()) + { + impl_updateTitleForController (xController); + return; + } + + if (xFrame.is ()) + { + impl_updateTitleForFrame (xFrame); + return; + } +} + +//----------------------------------------------- +void TitleHelper::impl_updateTitleForModel (const css::uno::Reference< css::frame::XModel >& xModel) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + // external title wont be updated internaly ! + // It has to be set from outside new. + if (m_bExternalTitle) + return; + + css::uno::Reference< css::uno::XInterface > xOwner (m_xOwner.get() , css::uno::UNO_QUERY); + css::uno::Reference< css::frame::XUntitledNumbers > xNumbers (m_xUntitledNumbers.get(), css::uno::UNO_QUERY); + ::sal_Int32 nLeasedNumber = m_nLeasedNumber; + + aLock.clear (); + // <- SYNCHRONIZED + + if ( + ( ! xOwner.is ()) || + ( ! xNumbers.is ()) || + ( ! xModel.is ()) + ) + return; + + ::rtl::OUString sTitle; + ::rtl::OUString sURL ; + + css::uno::Reference< css::frame::XStorable > xURLProvider(xModel , css::uno::UNO_QUERY); + if (xURLProvider.is()) + sURL = xURLProvider->getLocation (); + + if (sURL.getLength () > 0) + { + sTitle = impl_convertURL2Title(sURL); + if (nLeasedNumber != css::frame::UntitledNumbersConst::INVALID_NUMBER) + xNumbers->releaseNumber (nLeasedNumber); + nLeasedNumber = css::frame::UntitledNumbersConst::INVALID_NUMBER; + } + else + { + if (nLeasedNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER) + nLeasedNumber = xNumbers->leaseNumber (xOwner); + + ::rtl::OUStringBuffer sNewTitle(256); + sNewTitle.append (xNumbers->getUntitledPrefix ()); + if (nLeasedNumber != css::frame::UntitledNumbersConst::INVALID_NUMBER) + sNewTitle.append ((::sal_Int32)nLeasedNumber); + else + sNewTitle.appendAscii ("?"); + + sTitle = sNewTitle.makeStringAndClear (); + } + + // SYNCHRONIZED -> + aLock.reset (); + + // WORKAROUND: the notification is currently sent always, + // can be changed after shared mode is supported per UNO API + sal_Bool bChanged = sal_True; // (! m_sTitle.equals(sTitle)); + + m_sTitle = sTitle; + m_nLeasedNumber = nLeasedNumber; + + aLock.clear (); + // <- SYNCHRONIZED + + if (bChanged) + impl_sendTitleChangedEvent (); +} + +//----------------------------------------------- +void TitleHelper::impl_updateTitleForController (const css::uno::Reference< css::frame::XController >& xController) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + // external title wont be updated internaly ! + // It has to be set from outside new. + if (m_bExternalTitle) + return; + + css::uno::Reference< css::uno::XInterface > xOwner (m_xOwner.get() , css::uno::UNO_QUERY); + css::uno::Reference< css::frame::XUntitledNumbers > xNumbers (m_xUntitledNumbers.get(), css::uno::UNO_QUERY); + ::sal_Int32 nLeasedNumber = m_nLeasedNumber; + + aLock.clear (); + // <- SYNCHRONIZED + + if ( + ( ! xOwner.is ()) || + ( ! xNumbers.is ()) || + ( ! xController.is ()) + ) + return; + + ::rtl::OUStringBuffer sTitle(256); + + if (nLeasedNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER) + nLeasedNumber = xNumbers->leaseNumber (xOwner); + + css::uno::Reference< css::frame::XTitle > xModelTitle(xController->getModel (), css::uno::UNO_QUERY); + if (!xModelTitle.is ()) + xModelTitle.set(xController, css::uno::UNO_QUERY); + if (xModelTitle.is ()) + { + sTitle.append (xModelTitle->getTitle ()); + if ( nLeasedNumber > 1 ) + { + sTitle.appendAscii (" : "); + sTitle.append ((::sal_Int32)nLeasedNumber); + } + } + else + { + sTitle.append (xNumbers->getUntitledPrefix ()); + if ( nLeasedNumber > 1 ) + { + sTitle.append ((::sal_Int32)nLeasedNumber ); + } + } + + // SYNCHRONIZED -> + aLock.reset (); + + ::rtl::OUString sNewTitle = sTitle.makeStringAndClear (); + sal_Bool bChanged = (! m_sTitle.equals(sNewTitle)); + m_sTitle = sNewTitle; + m_nLeasedNumber = nLeasedNumber; + + aLock.clear (); + // <- SYNCHRONIZED + + if (bChanged) + impl_sendTitleChangedEvent (); +} + +//----------------------------------------------- +void TitleHelper::impl_updateTitleForFrame (const css::uno::Reference< css::frame::XFrame >& xFrame) +{ + if ( ! xFrame.is ()) + return; + + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + // external title wont be updated internaly ! + // It has to be set from outside new. + if (m_bExternalTitle) + return; + + aLock.clear (); + // <- SYNCHRONIZED + + css::uno::Reference< css::uno::XInterface > xComponent; + xComponent = xFrame->getController (); + if ( ! xComponent.is ()) + xComponent = xFrame->getComponentWindow (); + + ::rtl::OUStringBuffer sTitle (256); + + impl_appendComponentTitle (sTitle, xComponent); + impl_appendProductName (sTitle); + impl_appendModuleName (sTitle); + impl_appendProductExtension (sTitle); + //impl_appendEvalVersion (sTitle); + impl_appendDebugVersion (sTitle); + + // SYNCHRONIZED -> + aLock.reset (); + + ::rtl::OUString sNewTitle = sTitle.makeStringAndClear (); + sal_Bool bChanged = (! m_sTitle.equals(sNewTitle)); + m_sTitle = sNewTitle; + + aLock.clear (); + // <- SYNCHRONIZED + + if (bChanged) + impl_sendTitleChangedEvent (); +} + +//***************************************************************************************************************** +void TitleHelper::impl_appendComponentTitle ( ::rtl::OUStringBuffer& sTitle , + const css::uno::Reference< css::uno::XInterface >& xComponent) +{ + css::uno::Reference< css::frame::XTitle > xTitle(xComponent, css::uno::UNO_QUERY); + + // Note: Title has to be used (even if it's empty) if the right interface is supported. + if (xTitle.is ()) + sTitle.append (xTitle->getTitle ()); +} + +//***************************************************************************************************************** +void TitleHelper::impl_appendProductName (::rtl::OUStringBuffer& sTitle) +{ + ::rtl::OUString sProductName; + ::utl::ConfigManager::GetDirectConfigProperty(::utl::ConfigManager::PRODUCTNAME) >>= sProductName; + + if (sProductName.getLength ()) + { + if (sTitle.getLength() > 0) + sTitle.appendAscii (" - "); + + sTitle.append (sProductName); + } +} + +//***************************************************************************************************************** +void TitleHelper::impl_appendProductExtension (::rtl::OUStringBuffer& sTitle) +{ + ::rtl::OUString sProductExtension; + ::utl::ConfigManager::GetDirectConfigProperty(::utl::ConfigManager::PRODUCTEXTENSION) >>= sProductExtension; + + if (sProductExtension.getLength ()) + { + sTitle.appendAscii (" "); + sTitle.append (sProductExtension); + } +} + +//***************************************************************************************************************** +void TitleHelper::impl_appendModuleName (::rtl::OUStringBuffer& sTitle) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + css::uno::Reference< css::uno::XInterface > xOwner = m_xOwner.get(); + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; + + aLock.clear (); + // <- SYNCHRONIZED + + try + { + css::uno::Reference< css::frame::XModuleManager > xModuleManager( + xSMGR->createInstance(SERVICENAME_MODULEMANAGER), + css::uno::UNO_QUERY_THROW); + + css::uno::Reference< css::container::XNameAccess > xConfig( + xModuleManager, + css::uno::UNO_QUERY_THROW); + + const ::rtl::OUString sID = xModuleManager->identify(xOwner); + ::comphelper::SequenceAsHashMap lProps = xConfig->getByName (sID); + const ::rtl::OUString sUIName = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_UINAME, ::rtl::OUString()); + + // An UIname property is an optional value ! + // So please add it to the title in case it does realy exists only. + if (sUIName.getLength() > 0) + { + sTitle.appendAscii (" " ); + sTitle.append (sUIName); + } + } + catch(const css::uno::Exception&) + {} +} + +//***************************************************************************************************************** +#ifdef DBG_UTIL +void TitleHelper::impl_appendDebugVersion (::rtl::OUStringBuffer& sTitle) +{ + ::rtl::OUString sDefault ; + ::rtl::OUString sVersion = ::utl::Bootstrap::getBuildIdData( sDefault ); + + sTitle.appendAscii (" [" ); + sTitle.append (sVersion); + sTitle.appendAscii ("]" ); +} +#else +void TitleHelper::impl_appendDebugVersion (::rtl::OUStringBuffer&) +{ +} +#endif + +//***************************************************************************************************************** +void TitleHelper::impl_appendEvalVersion (::rtl::OUStringBuffer& /*sTitle*/) +{ + // SYNCHRONIZED -> + // ::osl::ResettableMutexGuard aLock(m_aMutex); + // css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR ; + //aLock.clear (); + //// <- SYNCHRONIZED + + //css::uno::Reference< css::beans::XMaterialHolder > xHolder( + // xSMGR->createInstance(SERVICENAME_TABREG), + // css::uno::UNO_QUERY); + + // if ( ! xHolder.is()) + // return; + + // ::comphelper::SequenceAsHashMap aMaterial(xHolder->getMaterial()); + //const ::rtl::OUString sEvalTitle = aMaterial.getUnpackedValueOrDefault(TABREG_PROPNAME_TITLE, ::rtl::OUString()); + + //if (sEvalTitle.getLength()) + //{ + // sTitle.appendAscii (" " ); + // sTitle.append (sEvalTitle); + //} +} + +//----------------------------------------------- +void TitleHelper::impl_startListeningForModel (const css::uno::Reference< css::frame::XModel >& xModel) +{ + css::uno::Reference< css::document::XEventBroadcaster > xBroadcaster(xModel, css::uno::UNO_QUERY); + if ( ! xBroadcaster.is ()) + return; + + xBroadcaster->addEventListener (static_cast< css::document::XEventListener* >(this)); +} + +//----------------------------------------------- +void TitleHelper::impl_startListeningForController (const css::uno::Reference< css::frame::XController >& xController) +{ + css::uno::Reference< css::frame::XTitle > xSubTitle(xController->getModel (), css::uno::UNO_QUERY); + impl_setSubTitle (xSubTitle); +} + +//----------------------------------------------- +void TitleHelper::impl_startListeningForFrame (const css::uno::Reference< css::frame::XFrame >& xFrame) +{ + xFrame->addFrameActionListener(this ); + impl_updateListeningForFrame (xFrame); +} + +//----------------------------------------------- +void TitleHelper::impl_updateListeningForFrame (const css::uno::Reference< css::frame::XFrame >& xFrame) +{ + css::uno::Reference< css::frame::XTitle > xSubTitle(xFrame->getController (), css::uno::UNO_QUERY); + impl_setSubTitle (xSubTitle); +} + +//----------------------------------------------- +void TitleHelper::impl_setSubTitle (const css::uno::Reference< css::frame::XTitle >& xSubTitle) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + // ignore duplicate calls. Makes outside using of this helper more easy :-) + css::uno::Reference< css::frame::XTitle > xOldSubTitle(m_xSubTitle.get(), css::uno::UNO_QUERY); + if (xOldSubTitle == xSubTitle) + return; + + m_xSubTitle = xSubTitle; + + aLock.clear (); + // <- SYNCHRONIZED + + css::uno::Reference< css::frame::XTitleChangeBroadcaster > xOldBroadcaster(xOldSubTitle , css::uno::UNO_QUERY ); + css::uno::Reference< css::frame::XTitleChangeBroadcaster > xNewBroadcaster(xSubTitle , css::uno::UNO_QUERY ); + css::uno::Reference< css::frame::XTitleChangeListener > xThis (static_cast< css::frame::XTitleChangeListener* >(this), css::uno::UNO_QUERY_THROW); + + if (xOldBroadcaster.is()) + xOldBroadcaster->removeTitleChangeListener (xThis); + + if (xNewBroadcaster.is()) + xNewBroadcaster->addTitleChangeListener (xThis); +} + +//----------------------------------------------- +::rtl::OUString TitleHelper::impl_getSubTitle () +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + css::uno::Reference< css::frame::XTitle > xSubTitle(m_xSubTitle.get (), css::uno::UNO_QUERY); + + aLock.clear (); + // <- SYNCHRONIZED + + if (xSubTitle.is ()) + return xSubTitle->getTitle (); + + return ::rtl::OUString (); +} + +//----------------------------------------------- +::rtl::OUString TitleHelper::impl_convertURL2Title(const ::rtl::OUString& sURL) +{ + INetURLObject aURL (sURL); + ::rtl::OUString sTitle; + + if (aURL.GetProtocol() == INET_PROT_FILE) + { + if (aURL.HasMark()) + aURL = INetURLObject(aURL.GetURLNoMark()); + + sTitle = aURL.getName(INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::DECODE_WITH_CHARSET); + } + else + { + if (aURL.hasExtension(INetURLObject::LAST_SEGMENT)) + sTitle = aURL.getName(INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::DECODE_WITH_CHARSET); + + if ( ! sTitle.getLength() ) + sTitle = aURL.GetHostPort(INetURLObject::DECODE_WITH_CHARSET); + + if ( ! sTitle.getLength() ) + sTitle = aURL.GetURLNoPass(INetURLObject::DECODE_WITH_CHARSET); + } + + return sTitle; +} + +} // namespace framework diff --git a/framework/source/fwe/helper/uiconfigelementwrapperbase.cxx b/framework/source/fwe/helper/uiconfigelementwrapperbase.cxx new file mode 100644 index 000000000000..7c1a8c905588 --- /dev/null +++ b/framework/source/fwe/helper/uiconfigelementwrapperbase.cxx @@ -0,0 +1,571 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <helper/uiconfigelementwrapperbase.hxx> +#include <general.h> +#include <properties.h> +#include <threadhelp/resetableguard.hxx> +#include <uielement/constitemcontainer.hxx> +#include <uielement/rootitemcontainer.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/ui/XUIConfiguration.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ +#include <vcl/svapp.hxx> +#include <rtl/logfile.hxx> + +const int UIELEMENT_PROPHANDLE_CONFIGSOURCE = 1; +const int UIELEMENT_PROPHANDLE_FRAME = 2; +const int UIELEMENT_PROPHANDLE_PERSISTENT = 3; +const int UIELEMENT_PROPHANDLE_RESOURCEURL = 4; +const int UIELEMENT_PROPHANDLE_TYPE = 5; +const int UIELEMENT_PROPHANDLE_XMENUBAR = 6; +const int UIELEMENT_PROPHANDLE_CONFIGLISTENER = 7; +const int UIELEMENT_PROPHANDLE_NOCLOSE = 8; +const int UIELEMENT_PROPCOUNT = 8; +const rtl::OUString UIELEMENT_PROPNAME_CONFIGLISTENER( RTL_CONSTASCII_USTRINGPARAM( "ConfigListener" )); +const rtl::OUString UIELEMENT_PROPNAME_CONFIGSOURCE( RTL_CONSTASCII_USTRINGPARAM( "ConfigurationSource" )); +const rtl::OUString UIELEMENT_PROPNAME_FRAME( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); +const rtl::OUString UIELEMENT_PROPNAME_PERSISTENT( RTL_CONSTASCII_USTRINGPARAM( "Persistent" )); +const rtl::OUString UIELEMENT_PROPNAME_RESOURCEURL( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" )); +const rtl::OUString UIELEMENT_PROPNAME_TYPE( RTL_CONSTASCII_USTRINGPARAM( "Type" )); +const rtl::OUString UIELEMENT_PROPNAME_XMENUBAR( RTL_CONSTASCII_USTRINGPARAM( "XMenuBar" )); +const rtl::OUString UIELEMENT_PROPNAME_NOCLOSE( RTL_CONSTASCII_USTRINGPARAM( "NoClose" )); + +using namespace rtl; +using namespace com::sun::star::beans; +using namespace com::sun::star::uno; +using namespace com::sun::star::frame; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; +using namespace ::com::sun::star::ui; + +namespace framework +{ + +//***************************************************************************************************************** +// XInterface, XTypeProvider +//***************************************************************************************************************** +DEFINE_XINTERFACE_10 ( UIConfigElementWrapperBase , + OWeakObject , + DIRECT_INTERFACE( ::com::sun::star::lang::XTypeProvider ), + DIRECT_INTERFACE( ::com::sun::star::ui::XUIElement ), + DIRECT_INTERFACE( ::com::sun::star::ui::XUIElementSettings ), + DIRECT_INTERFACE( ::com::sun::star::beans::XMultiPropertySet ), + DIRECT_INTERFACE( ::com::sun::star::beans::XFastPropertySet ), + DIRECT_INTERFACE( ::com::sun::star::beans::XPropertySet ), + DIRECT_INTERFACE( ::com::sun::star::lang::XInitialization ), + DIRECT_INTERFACE( ::com::sun::star::lang::XComponent ), + DIRECT_INTERFACE( ::com::sun::star::util::XUpdatable ), + DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationListener ) + ) + +DEFINE_XTYPEPROVIDER_10 ( UIConfigElementWrapperBase , + ::com::sun::star::lang::XTypeProvider , + ::com::sun::star::ui::XUIElement , + ::com::sun::star::ui::XUIElementSettings , + ::com::sun::star::beans::XMultiPropertySet , + ::com::sun::star::beans::XFastPropertySet , + ::com::sun::star::beans::XPropertySet , + ::com::sun::star::lang::XInitialization , + ::com::sun::star::lang::XComponent , + ::com::sun::star::util::XUpdatable , + ::com::sun::star::ui::XUIConfigurationListener + ) + +UIConfigElementWrapperBase::UIConfigElementWrapperBase( sal_Int16 nType,const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xServiceFactory ) + : ThreadHelpBase ( &Application::GetSolarMutex() ) + , ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType >( m_aLock.getShareableOslMutex() ) + , ::cppu::OPropertySetHelper ( *(static_cast< ::cppu::OBroadcastHelper* >(this)) ) + , ::cppu::OWeakObject ( ) + , m_nType ( nType ) + , m_bPersistent ( sal_True ) + , m_bInitialized ( sal_False ) + , m_bConfigListener ( sal_False ) + , m_bConfigListening ( sal_False ) + , m_bDisposed ( sal_False ) + , m_bNoClose ( sal_False ) + , m_xServiceFactory ( _xServiceFactory ) + , m_aListenerContainer ( m_aLock.getShareableOslMutex() ) +{ +} + +UIConfigElementWrapperBase::~UIConfigElementWrapperBase() +{ +} + +// XComponent +void SAL_CALL UIConfigElementWrapperBase::dispose() throw (::com::sun::star::uno::RuntimeException) +{ + // must be implemented by derived class + ResetableGuard aLock( m_aLock ); + m_bDisposed = sal_True; +} + +void SAL_CALL UIConfigElementWrapperBase::addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) +{ + m_aListenerContainer.addInterface( ::getCppuType( ( const css::uno::Reference< css::lang::XEventListener >* ) NULL ), xListener ); +} + +void SAL_CALL UIConfigElementWrapperBase::removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw (::com::sun::star::uno::RuntimeException) +{ + m_aListenerContainer.removeInterface( ::getCppuType( ( const css::uno::Reference< css::lang::XEventListener >* ) NULL ), aListener ); +} + +// XEventListener +void SAL_CALL UIConfigElementWrapperBase::disposing( const EventObject& ) +throw( RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + m_xConfigSource.clear(); +} + +void SAL_CALL UIConfigElementWrapperBase::initialize( const Sequence< Any >& aArguments ) +throw ( Exception, RuntimeException ) +{ + 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.equals( UIELEMENT_PROPNAME_CONFIGSOURCE )) + setFastPropertyValue_NoBroadcast( UIELEMENT_PROPHANDLE_CONFIGSOURCE, aPropValue.Value ); + else if ( aPropValue.Name.equals( UIELEMENT_PROPNAME_FRAME )) + setFastPropertyValue_NoBroadcast( UIELEMENT_PROPHANDLE_FRAME, aPropValue.Value ); + else if ( aPropValue.Name.equals( UIELEMENT_PROPNAME_PERSISTENT )) + setFastPropertyValue_NoBroadcast( UIELEMENT_PROPHANDLE_PERSISTENT, aPropValue.Value ); + else if ( aPropValue.Name.equals( UIELEMENT_PROPNAME_RESOURCEURL )) + setFastPropertyValue_NoBroadcast( UIELEMENT_PROPHANDLE_RESOURCEURL, aPropValue.Value ); + else if ( aPropValue.Name.equals( UIELEMENT_PROPNAME_TYPE )) + setFastPropertyValue_NoBroadcast( UIELEMENT_PROPHANDLE_TYPE, aPropValue.Value ); + else if ( aPropValue.Name.equals( UIELEMENT_PROPNAME_CONFIGLISTENER )) + setFastPropertyValue_NoBroadcast( UIELEMENT_PROPHANDLE_CONFIGLISTENER, aPropValue.Value ); + else if ( aPropValue.Name.equals( UIELEMENT_PROPNAME_NOCLOSE )) + setFastPropertyValue_NoBroadcast( UIELEMENT_PROPHANDLE_NOCLOSE, aPropValue.Value ); + } + } + + m_bInitialized = sal_True; + } +} + +// XUpdatable +void SAL_CALL UIConfigElementWrapperBase::update() throw (::com::sun::star::uno::RuntimeException) +{ + // can be implemented by derived class +} + +void SAL_CALL UIConfigElementWrapperBase::elementInserted( const ::com::sun::star::ui::ConfigurationEvent& ) throw (::com::sun::star::uno::RuntimeException) +{ + // can be implemented by derived class +} + +void SAL_CALL UIConfigElementWrapperBase::elementRemoved( const ::com::sun::star::ui::ConfigurationEvent& ) throw (::com::sun::star::uno::RuntimeException) +{ + // can be implemented by derived class +} + +void SAL_CALL UIConfigElementWrapperBase::elementReplaced( const ::com::sun::star::ui::ConfigurationEvent& ) throw (::com::sun::star::uno::RuntimeException) +{ + // can be implemented by derived class +} + +// XPropertySet helper +sal_Bool SAL_CALL UIConfigElementWrapperBase::convertFastPropertyValue( Any& aConvertedValue , + Any& aOldValue , + sal_Int32 nHandle , + const Any& aValue ) throw( com::sun::star::lang::IllegalArgumentException ) +{ + // Initialize state with sal_False !!! + // (Handle can be invalid) + sal_Bool bReturn = sal_False; + + switch( nHandle ) + { + case UIELEMENT_PROPHANDLE_CONFIGLISTENER: + bReturn = PropHelper::willPropertyBeChanged( + com::sun::star::uno::makeAny(m_bConfigListener), + aValue, + aOldValue, + aConvertedValue); + break; + + case UIELEMENT_PROPHANDLE_CONFIGSOURCE: + bReturn = PropHelper::willPropertyBeChanged( + com::sun::star::uno::makeAny(m_xConfigSource), + aValue, + aOldValue, + aConvertedValue); + break; + + case UIELEMENT_PROPHANDLE_FRAME: + { + Reference< XFrame > xFrame( m_xWeakFrame ); + bReturn = PropHelper::willPropertyBeChanged( + com::sun::star::uno::makeAny(xFrame), + aValue, + aOldValue, + aConvertedValue); + } + break; + + case UIELEMENT_PROPHANDLE_PERSISTENT: + bReturn = PropHelper::willPropertyBeChanged( + com::sun::star::uno::makeAny(m_bPersistent), + aValue, + aOldValue, + aConvertedValue); + break; + + case UIELEMENT_PROPHANDLE_RESOURCEURL: + bReturn = PropHelper::willPropertyBeChanged( + com::sun::star::uno::makeAny(m_aResourceURL), + aValue, + aOldValue, + aConvertedValue); + break; + + case UIELEMENT_PROPHANDLE_TYPE : + bReturn = PropHelper::willPropertyBeChanged( + com::sun::star::uno::makeAny(m_nType), + aValue, + aOldValue, + aConvertedValue); + break; + + case UIELEMENT_PROPHANDLE_XMENUBAR : + bReturn = PropHelper::willPropertyBeChanged( + com::sun::star::uno::makeAny(m_xMenuBar), + aValue, + aOldValue, + aConvertedValue); + break; + + case UIELEMENT_PROPHANDLE_NOCLOSE: + bReturn = PropHelper::willPropertyBeChanged( + com::sun::star::uno::makeAny(m_bNoClose), + aValue, + aOldValue, + aConvertedValue); + break; + } + + // Return state of operation. + return bReturn ; +} + +void SAL_CALL UIConfigElementWrapperBase::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle , + const com::sun::star::uno::Any& aValue ) throw( com::sun::star::uno::Exception ) +{ + switch( nHandle ) + { + case UIELEMENT_PROPHANDLE_CONFIGLISTENER: + { + bool bBool( m_bConfigListener ); + aValue >>= bBool; + if ( m_bConfigListener != bBool ) + { + if ( m_bConfigListening ) + { + if ( m_xConfigSource.is() && !bBool ) + { + try + { + Reference< XUIConfiguration > xUIConfig( m_xConfigSource, UNO_QUERY ); + if ( xUIConfig.is() ) + { + xUIConfig->removeConfigurationListener( Reference< XUIConfigurationListener >( static_cast< OWeakObject* >( this ), UNO_QUERY )); + m_bConfigListening = sal_False; + } + } + catch ( Exception& ) + { + } + } + } + else + { + if ( m_xConfigSource.is() && bBool ) + { + try + { + Reference< XUIConfiguration > xUIConfig( m_xConfigSource, UNO_QUERY ); + if ( xUIConfig.is() ) + { + xUIConfig->addConfigurationListener( Reference< XUIConfigurationListener >( static_cast< OWeakObject* >( this ), UNO_QUERY )); + m_bConfigListening = sal_True; + } + } + catch ( Exception& ) + { + } + } + } + + m_bConfigListener = bBool; + } + } + break; + case UIELEMENT_PROPHANDLE_CONFIGSOURCE: + aValue >>= m_xConfigSource; + break; + case UIELEMENT_PROPHANDLE_FRAME: + { + Reference< XFrame > xFrame; + + aValue >>= xFrame; + m_xWeakFrame = xFrame; + break; + } + case UIELEMENT_PROPHANDLE_PERSISTENT: + { + sal_Bool bBool( m_bPersistent ); + aValue >>= bBool; + m_bPersistent = bBool; + break; + } + case UIELEMENT_PROPHANDLE_RESOURCEURL: + aValue >>= m_aResourceURL; + break; + case UIELEMENT_PROPHANDLE_TYPE: + aValue >>= m_nType; + break; + case UIELEMENT_PROPHANDLE_XMENUBAR: + aValue >>= m_xMenuBar; + break; + case UIELEMENT_PROPHANDLE_NOCLOSE: + { + sal_Bool bBool( m_bNoClose ); + aValue >>= bBool; + m_bNoClose = bBool; + break; + } + } +} + +void SAL_CALL UIConfigElementWrapperBase::getFastPropertyValue( com::sun::star::uno::Any& aValue , + sal_Int32 nHandle ) const +{ + switch( nHandle ) + { + case UIELEMENT_PROPHANDLE_CONFIGLISTENER: + aValue <<= m_bConfigListener; + break; + case UIELEMENT_PROPHANDLE_CONFIGSOURCE: + aValue <<= m_xConfigSource; + break; + case UIELEMENT_PROPHANDLE_FRAME: + { + Reference< XFrame > xFrame( m_xWeakFrame ); + aValue <<= xFrame; + break; + } + case UIELEMENT_PROPHANDLE_PERSISTENT: + aValue <<= m_bPersistent; + break; + case UIELEMENT_PROPHANDLE_RESOURCEURL: + aValue <<= m_aResourceURL; + break; + case UIELEMENT_PROPHANDLE_TYPE: + aValue <<= m_nType; + break; + case UIELEMENT_PROPHANDLE_XMENUBAR: + aValue <<= m_xMenuBar; + break; + case UIELEMENT_PROPHANDLE_NOCLOSE: + aValue <<= m_bNoClose; + break; + } +} + +::cppu::IPropertyArrayHelper& SAL_CALL UIConfigElementWrapperBase::getInfoHelper() +{ + // Optimize this method ! + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pInfoHelper is NULL - for the second call pInfoHelper is different from NULL! + static ::cppu::OPropertyArrayHelper* pInfoHelper = NULL; + + if( pInfoHelper == NULL ) + { + // Ready for multithreading + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; + + // Control this pointer again, another instance can be faster then these! + if( pInfoHelper == NULL ) + { + // Define static member to give structure of properties to baseclass "OPropertySetHelper". + // "impl_getStaticPropertyDescriptor" is a non exported and static funtion, who will define a static propertytable. + // "sal_True" say: Table is sorted by name. + static ::cppu::OPropertyArrayHelper aInfoHelper( impl_getStaticPropertyDescriptor(), sal_True ); + pInfoHelper = &aInfoHelper; + } + } + + return(*pInfoHelper); +} + +com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > SAL_CALL UIConfigElementWrapperBase::getPropertySetInfo() throw (::com::sun::star::uno::RuntimeException) +{ + // Optimize this method ! + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pInfo is NULL - for the second call pInfo is different from NULL! + static com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo >* pInfo = NULL; + + if( pInfo == NULL ) + { + // Ready for multithreading + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; + // Control this pointer again, another instance can be faster then these! + if( pInfo == NULL ) + { + // Create structure of propertysetinfo for baseclass "OPropertySetHelper". + // (Use method "getInfoHelper()".) + static com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); + pInfo = &xInfo; + } + } + + return (*pInfo); +} + +const com::sun::star::uno::Sequence< com::sun::star::beans::Property > UIConfigElementWrapperBase::impl_getStaticPropertyDescriptor() +{ + // Create a new static property array to initialize sequence! + // Table of all predefined properties of this class. Its used from OPropertySetHelper-class! + // Don't forget to change the defines (see begin of this file), if you add, change or delete a property in this list!!! + // It's necessary for methods of OPropertySetHelper. + // ATTENTION: + // YOU MUST SORT FOLLOW TABLE BY NAME ALPHABETICAL !!! + + static const com::sun::star::beans::Property pProperties[] = + { + com::sun::star::beans::Property( UIELEMENT_PROPNAME_CONFIGLISTENER, UIELEMENT_PROPHANDLE_CONFIGLISTENER , ::getCppuType((const sal_Bool*)NULL), com::sun::star::beans::PropertyAttribute::TRANSIENT ), + com::sun::star::beans::Property( UIELEMENT_PROPNAME_CONFIGSOURCE , UIELEMENT_PROPHANDLE_CONFIGSOURCE , ::getCppuType((const Reference< ::com::sun::star::ui::XUIConfigurationManager >*)NULL), com::sun::star::beans::PropertyAttribute::TRANSIENT ), + com::sun::star::beans::Property( UIELEMENT_PROPNAME_FRAME , UIELEMENT_PROPHANDLE_FRAME , ::getCppuType((const Reference< com::sun::star::frame::XFrame >*)NULL), com::sun::star::beans::PropertyAttribute::TRANSIENT | com::sun::star::beans::PropertyAttribute::READONLY ), + com::sun::star::beans::Property( UIELEMENT_PROPNAME_NOCLOSE , UIELEMENT_PROPHANDLE_NOCLOSE , ::getCppuType((const sal_Bool*)NULL), com::sun::star::beans::PropertyAttribute::TRANSIENT ), + com::sun::star::beans::Property( UIELEMENT_PROPNAME_PERSISTENT , UIELEMENT_PROPHANDLE_PERSISTENT , ::getCppuType((const sal_Bool*)NULL), com::sun::star::beans::PropertyAttribute::TRANSIENT ), + com::sun::star::beans::Property( UIELEMENT_PROPNAME_RESOURCEURL , UIELEMENT_PROPHANDLE_RESOURCEURL , ::getCppuType((const ::rtl::OUString*)NULL), com::sun::star::beans::PropertyAttribute::TRANSIENT | com::sun::star::beans::PropertyAttribute::READONLY ), + com::sun::star::beans::Property( UIELEMENT_PROPNAME_TYPE , UIELEMENT_PROPHANDLE_TYPE , ::getCppuType((const ::rtl::OUString*)NULL), com::sun::star::beans::PropertyAttribute::TRANSIENT | com::sun::star::beans::PropertyAttribute::READONLY ), + com::sun::star::beans::Property( UIELEMENT_PROPNAME_XMENUBAR , UIELEMENT_PROPHANDLE_XMENUBAR , ::getCppuType((const Reference< com::sun::star::awt::XMenuBar >*)NULL), com::sun::star::beans::PropertyAttribute::TRANSIENT | com::sun::star::beans::PropertyAttribute::READONLY ) + }; + // Use it to initialize sequence! + static const com::sun::star::uno::Sequence< com::sun::star::beans::Property > lPropertyDescriptor( pProperties, UIELEMENT_PROPCOUNT ); + // Return static "PropertyDescriptor" + return lPropertyDescriptor; +} +void SAL_CALL UIConfigElementWrapperBase::setSettings( const Reference< XIndexAccess >& xSettings ) throw ( RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + //if ( m_bDisposed ) + // throw DisposedException(); + + if ( xSettings.is() ) + { + // Create a copy of the data if the container is not const + Reference< XIndexReplace > xReplace( xSettings, UNO_QUERY ); + if ( xReplace.is() ) + m_xConfigData = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( xSettings ) ), UNO_QUERY ); + else + m_xConfigData = xSettings; + + if ( m_xConfigSource.is() && m_bPersistent ) + { + ::rtl::OUString aResourceURL( m_aResourceURL ); + Reference< XUIConfigurationManager > xUICfgMgr( m_xConfigSource ); + + aLock.unlock(); + + try + { + xUICfgMgr->replaceSettings( aResourceURL, m_xConfigData ); + } + catch( NoSuchElementException& ) + { + } + } + else if ( !m_bPersistent ) + { + // Transient menubar => Fill menubar with new data + impl_fillNewData(); + } + } +} +void UIConfigElementWrapperBase::impl_fillNewData() +{ +} +Reference< XIndexAccess > SAL_CALL UIConfigElementWrapperBase::getSettings( sal_Bool bWriteable ) throw ( RuntimeException ) +{ + ResetableGuard aLock( m_aLock ); + + //if ( m_bDisposed ) + // throw DisposedException(); + + if ( bWriteable ) + return Reference< XIndexAccess >( static_cast< OWeakObject * >( new RootItemContainer( m_xConfigData ) ), UNO_QUERY ); + + return m_xConfigData; +} + +Reference< XFrame > SAL_CALL UIConfigElementWrapperBase::getFrame() throw (RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + Reference< XFrame > xFrame( m_xWeakFrame ); + return xFrame; +} + +::rtl::OUString SAL_CALL UIConfigElementWrapperBase::getResourceURL() throw (RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + return m_aResourceURL; +} + +::sal_Int16 SAL_CALL UIConfigElementWrapperBase::getType() throw (RuntimeException) +{ + ResetableGuard aLock( m_aLock ); + return m_nType; +} + +} diff --git a/framework/source/fwe/helper/uielementwrapperbase.cxx b/framework/source/fwe/helper/uielementwrapperbase.cxx new file mode 100644 index 000000000000..ef5d01eb85b8 --- /dev/null +++ b/framework/source/fwe/helper/uielementwrapperbase.cxx @@ -0,0 +1,282 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <helper/uielementwrapperbase.hxx> +#include <general.h> +#include <properties.h> +#include <threadhelp/resetableguard.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ +#include <vcl/svapp.hxx> +#include <rtl/logfile.hxx> + +const int UIELEMENT_PROPHANDLE_RESOURCEURL = 1; +const int UIELEMENT_PROPHANDLE_TYPE = 2; +const int UIELEMENT_PROPHANDLE_FRAME = 3; +const int UIELEMENT_PROPCOUNT = 3; +const rtl::OUString UIELEMENT_PROPNAME_RESOURCEURL( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" )); +const rtl::OUString UIELEMENT_PROPNAME_TYPE( RTL_CONSTASCII_USTRINGPARAM( "Type" )); +const rtl::OUString UIELEMENT_PROPNAME_FRAME( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); + +using namespace rtl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; + +namespace framework +{ + +//***************************************************************************************************************** +// XInterface, XTypeProvider +//***************************************************************************************************************** +DEFINE_XINTERFACE_8 ( UIElementWrapperBase , + OWeakObject , + DIRECT_INTERFACE( ::com::sun::star::lang::XTypeProvider ), + DIRECT_INTERFACE( ::com::sun::star::ui::XUIElement ), + DIRECT_INTERFACE( ::com::sun::star::beans::XMultiPropertySet ), + DIRECT_INTERFACE( ::com::sun::star::beans::XFastPropertySet ), + DIRECT_INTERFACE( ::com::sun::star::beans::XPropertySet ), + DIRECT_INTERFACE( ::com::sun::star::lang::XInitialization ), + DIRECT_INTERFACE( ::com::sun::star::util::XUpdatable ), + DIRECT_INTERFACE( ::com::sun::star::lang::XComponent ) + ) + +DEFINE_XTYPEPROVIDER_8 ( UIElementWrapperBase , + ::com::sun::star::lang::XTypeProvider , + ::com::sun::star::ui::XUIElement , + ::com::sun::star::beans::XMultiPropertySet , + ::com::sun::star::beans::XFastPropertySet , + ::com::sun::star::beans::XPropertySet , + ::com::sun::star::lang::XInitialization , + ::com::sun::star::util::XUpdatable , + ::com::sun::star::lang::XComponent + ) + +UIElementWrapperBase::UIElementWrapperBase( sal_Int16 nType ) + : ThreadHelpBase ( &Application::GetSolarMutex() ) + , ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType >( m_aLock.getShareableOslMutex() ) + , ::cppu::OPropertySetHelper ( *(static_cast< ::cppu::OBroadcastHelper* >(this)) ) + , ::cppu::OWeakObject ( ) + , m_aListenerContainer ( m_aLock.getShareableOslMutex() ) + , m_nType ( nType ) + , m_bInitialized ( sal_False ) + , m_bDisposed ( sal_False ) +{ +} + +UIElementWrapperBase::~UIElementWrapperBase() +{ +} + +void SAL_CALL UIElementWrapperBase::dispose() throw (::com::sun::star::uno::RuntimeException) +{ + // must be implemented by derived class + ResetableGuard aLock( m_aLock ); + m_bDisposed = sal_True; +} + +void SAL_CALL UIElementWrapperBase::addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) +{ + m_aListenerContainer.addInterface( ::getCppuType( ( const css::uno::Reference< css::lang::XEventListener >* ) NULL ), xListener ); +} + +void SAL_CALL UIElementWrapperBase::removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException) +{ + m_aListenerContainer.removeInterface( ::getCppuType( ( const css::uno::Reference< css::lang::XEventListener >* ) NULL ), xListener ); +} + +void SAL_CALL UIElementWrapperBase::initialize( const Sequence< Any >& aArguments ) +throw ( Exception, RuntimeException ) +{ + 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( "ResourceURL" )) + aPropValue.Value >>= m_aResourceURL; + else if ( aPropValue.Name.equalsAscii( "Frame" )) + { + Reference< XFrame > xFrame; + aPropValue.Value >>= xFrame; + m_xWeakFrame = xFrame; + } + } + } + + m_bInitialized = sal_True; + } +} + +// XUIElement +::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > SAL_CALL UIElementWrapperBase::getFrame() throw (::com::sun::star::uno::RuntimeException) +{ + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame( m_xWeakFrame ); + return xFrame; +} + +::rtl::OUString SAL_CALL UIElementWrapperBase::getResourceURL() throw (::com::sun::star::uno::RuntimeException) +{ + return m_aResourceURL; +} + +::sal_Int16 SAL_CALL UIElementWrapperBase::getType() throw (::com::sun::star::uno::RuntimeException) +{ + return m_nType; +} + +// XUpdatable +void SAL_CALL UIElementWrapperBase::update() throw (::com::sun::star::uno::RuntimeException) +{ + // can be implemented by derived class +} + +// XPropertySet helper +sal_Bool SAL_CALL UIElementWrapperBase::convertFastPropertyValue( Any& /*aConvertedValue*/ , + Any& /*aOldValue*/ , + sal_Int32 /*nHandle*/ , + const Any& /*aValue*/ ) throw( com::sun::star::lang::IllegalArgumentException ) +{ + // Initialize state with sal_False !!! + // (Handle can be invalid) + return sal_False ; +} + +void SAL_CALL UIElementWrapperBase::setFastPropertyValue_NoBroadcast( sal_Int32 /*nHandle*/ , + const com::sun::star::uno::Any& /*aValue*/ ) throw( com::sun::star::uno::Exception ) +{ +} + +void SAL_CALL UIElementWrapperBase::getFastPropertyValue( com::sun::star::uno::Any& aValue , + sal_Int32 nHandle ) const +{ + switch( nHandle ) + { + case UIELEMENT_PROPHANDLE_RESOURCEURL: + aValue <<= m_aResourceURL; + break; + case UIELEMENT_PROPHANDLE_TYPE: + aValue <<= m_nType; + break; + case UIELEMENT_PROPHANDLE_FRAME: + Reference< XFrame > xFrame( m_xWeakFrame ); + aValue <<= xFrame; + break; + } +} + +::cppu::IPropertyArrayHelper& SAL_CALL UIElementWrapperBase::getInfoHelper() +{ + // Optimize this method ! + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pInfoHelper is NULL - for the second call pInfoHelper is different from NULL! + static ::cppu::OPropertyArrayHelper* pInfoHelper = NULL; + + if( pInfoHelper == NULL ) + { + // Ready for multithreading + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; + + // Control this pointer again, another instance can be faster then these! + if( pInfoHelper == NULL ) + { + // Define static member to give structure of properties to baseclass "OPropertySetHelper". + // "impl_getStaticPropertyDescriptor" is a non exported and static funtion, who will define a static propertytable. + // "sal_True" say: Table is sorted by name. + static ::cppu::OPropertyArrayHelper aInfoHelper( impl_getStaticPropertyDescriptor(), sal_True ); + pInfoHelper = &aInfoHelper; + } + } + + return(*pInfoHelper); +} + +com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > SAL_CALL UIElementWrapperBase::getPropertySetInfo() throw (::com::sun::star::uno::RuntimeException) +{ + // Optimize this method ! + // We initialize a static variable only one time. And we don't must use a mutex at every call! + // For the first call; pInfo is NULL - for the second call pInfo is different from NULL! + static com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo >* pInfo = NULL; + + if( pInfo == NULL ) + { + // Ready for multithreading + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; + // Control this pointer again, another instance can be faster then these! + if( pInfo == NULL ) + { + // Create structure of propertysetinfo for baseclass "OPropertySetHelper". + // (Use method "getInfoHelper()".) + static com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); + pInfo = &xInfo; + } + } + + return (*pInfo); +} + +const com::sun::star::uno::Sequence< com::sun::star::beans::Property > UIElementWrapperBase::impl_getStaticPropertyDescriptor() +{ + // Create a new static property array to initialize sequence! + // Table of all predefined properties of this class. Its used from OPropertySetHelper-class! + // Don't forget to change the defines (see begin of this file), if you add, change or delete a property in this list!!! + // It's necessary for methods of OPropertySetHelper. + // ATTENTION: + // YOU MUST SORT FOLLOW TABLE BY NAME ALPHABETICAL !!! + + static const com::sun::star::beans::Property pProperties[] = + { + com::sun::star::beans::Property( UIELEMENT_PROPNAME_FRAME , UIELEMENT_PROPHANDLE_FRAME , ::getCppuType((Reference< XFrame >*)NULL), com::sun::star::beans::PropertyAttribute::TRANSIENT | com::sun::star::beans::PropertyAttribute::READONLY ), + com::sun::star::beans::Property( UIELEMENT_PROPNAME_RESOURCEURL , UIELEMENT_PROPHANDLE_RESOURCEURL , ::getCppuType((sal_Int16*)NULL), com::sun::star::beans::PropertyAttribute::TRANSIENT | com::sun::star::beans::PropertyAttribute::READONLY ), + com::sun::star::beans::Property( UIELEMENT_PROPNAME_TYPE , UIELEMENT_PROPHANDLE_TYPE , ::getCppuType((const ::rtl::OUString*)NULL), com::sun::star::beans::PropertyAttribute::TRANSIENT | com::sun::star::beans::PropertyAttribute::READONLY ) + }; + // Use it to initialize sequence! + static const com::sun::star::uno::Sequence< com::sun::star::beans::Property > lPropertyDescriptor( pProperties, UIELEMENT_PROPCOUNT ); + // Return static "PropertyDescriptor" + return lPropertyDescriptor; +} + +} diff --git a/framework/source/fwe/interaction/preventduplicateinteraction.cxx b/framework/source/fwe/interaction/preventduplicateinteraction.cxx new file mode 100644 index 000000000000..7bc2201a3a27 --- /dev/null +++ b/framework/source/fwe/interaction/preventduplicateinteraction.cxx @@ -0,0 +1,294 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "framework/preventduplicateinteraction.hxx" + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/task/XInteractionRetry.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +namespace framework{ + +namespace css = ::com::sun::star; + +//_________________________________________________________________________________________________________________ +// exported const +//_________________________________________________________________________________________________________________ + +#define IMPLEMENTATIONNAME_UIINTERACTIONHANDLER ::rtl::OUString::createFromAscii("com.sun.star.comp.uui.UUIInteractionHandler") + +//_________________________________________________________________________________________________________________ +// exported definitions +//_________________________________________________________________________________________________________________ + +//_________________________________________________________________________________________________________________ + +PreventDuplicateInteraction::PreventDuplicateInteraction(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) + : ThreadHelpBase2() + , m_xSMGR(xSMGR) +{ +} + +//_________________________________________________________________________________________________________________ + +PreventDuplicateInteraction::~PreventDuplicateInteraction() +{ +} + +//_________________________________________________________________________________________________________________ + +void PreventDuplicateInteraction::setHandler(const css::uno::Reference< css::task::XInteractionHandler >& xHandler) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + m_xHandler = xHandler; + aLock.clear(); + // <- SAFE +} + +//_________________________________________________________________________________________________________________ + +void PreventDuplicateInteraction::useDefaultUUIHandler() +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; + aLock.clear(); + // <- SAFE + + css::uno::Reference< css::task::XInteractionHandler > xHandler( + xSMGR->createInstance(IMPLEMENTATIONNAME_UIINTERACTIONHANDLER), + css::uno::UNO_QUERY_THROW); + + // SAFE -> + aLock.reset(); + m_xHandler = xHandler; + aLock.clear(); + // <- SAFE +} + +//_________________________________________________________________________________________________________________ +css::uno::Any SAL_CALL PreventDuplicateInteraction::queryInterface( const css::uno::Type& aType ) + throw (css::uno::RuntimeException) +{ + if ( aType.equals( XInteractionHandler2::static_type() ) ) + { + ::osl::ResettableMutexGuard aLock(m_aLock); + css::uno::Reference< css::task::XInteractionHandler2 > xHandler( m_xHandler, css::uno::UNO_QUERY ); + if ( !xHandler.is() ) + return css::uno::Any(); + } + return ::cppu::WeakImplHelper1< css::task::XInteractionHandler2 >::queryInterface( aType ); +} + +//_________________________________________________________________________________________________________________ + +void SAL_CALL PreventDuplicateInteraction::handle(const css::uno::Reference< css::task::XInteractionRequest >& xRequest) + throw(css::uno::RuntimeException) +{ + css::uno::Any aRequest = xRequest->getRequest(); + sal_Bool bHandleIt = sal_True; + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + InteractionList::iterator pIt; + for ( pIt = m_lInteractionRules.begin(); + pIt != m_lInteractionRules.end() ; + ++pIt ) + { + InteractionInfo& rInfo = *pIt; + + if (aRequest.isExtractableTo(rInfo.m_aInteraction)) + { + ++rInfo.m_nCallCount; + rInfo.m_xRequest = xRequest; + bHandleIt = (rInfo.m_nCallCount <= rInfo.m_nMaxCount); + break; + } + } + + css::uno::Reference< css::task::XInteractionHandler > xHandler = m_xHandler; + + aLock.clear(); + // <- SAFE + + if ( + (bHandleIt ) && + (xHandler.is()) + ) + { + xHandler->handle(xRequest); + } + else + { + const css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > lContinuations = xRequest->getContinuations(); + sal_Int32 c = lContinuations.getLength(); + sal_Int32 i = 0; + for (i=0; i<c; ++i) + { + css::uno::Reference< css::task::XInteractionAbort > xAbort(lContinuations[i], css::uno::UNO_QUERY); + if (xAbort.is()) + { + xAbort->select(); + break; + } + } + } +} + +//_________________________________________________________________________________________________________________ + +::sal_Bool SAL_CALL PreventDuplicateInteraction::handleInteractionRequest( const css::uno::Reference< css::task::XInteractionRequest >& xRequest ) + throw (css::uno::RuntimeException) +{ + css::uno::Any aRequest = xRequest->getRequest(); + sal_Bool bHandleIt = sal_True; + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + InteractionList::iterator pIt; + for ( pIt = m_lInteractionRules.begin(); + pIt != m_lInteractionRules.end() ; + ++pIt ) + { + InteractionInfo& rInfo = *pIt; + + if (aRequest.isExtractableTo(rInfo.m_aInteraction)) + { + ++rInfo.m_nCallCount; + rInfo.m_xRequest = xRequest; + bHandleIt = (rInfo.m_nCallCount <= rInfo.m_nMaxCount); + break; + } + } + + css::uno::Reference< css::task::XInteractionHandler2 > xHandler( m_xHandler, css::uno::UNO_QUERY ); + OSL_ENSURE( xHandler.is() || !m_xHandler.is(), + "PreventDuplicateInteraction::handleInteractionRequest: inconsistency!" ); + + aLock.clear(); + // <- SAFE + + if ( + (bHandleIt ) && + (xHandler.is()) + ) + { + return xHandler->handleInteractionRequest(xRequest); + } + else + { + const css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > lContinuations = xRequest->getContinuations(); + sal_Int32 c = lContinuations.getLength(); + sal_Int32 i = 0; + for (i=0; i<c; ++i) + { + css::uno::Reference< css::task::XInteractionAbort > xAbort(lContinuations[i], css::uno::UNO_QUERY); + if (xAbort.is()) + { + xAbort->select(); + break; + } + } + } + return false; +} + +//_________________________________________________________________________________________________________________ + +void PreventDuplicateInteraction::addInteractionRule(const PreventDuplicateInteraction::InteractionInfo& aInteractionInfo) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + InteractionList::iterator pIt; + for ( pIt = m_lInteractionRules.begin(); + pIt != m_lInteractionRules.end() ; + ++pIt ) + { + InteractionInfo& rInfo = *pIt; + if (rInfo.m_aInteraction == aInteractionInfo.m_aInteraction) + { + rInfo.m_nMaxCount = aInteractionInfo.m_nMaxCount ; + rInfo.m_nCallCount = aInteractionInfo.m_nCallCount; + return; + } + } + + m_lInteractionRules.push_back(aInteractionInfo); + + aLock.clear(); + // <- SAFE +} + +//_________________________________________________________________________________________________________________ + +sal_Bool PreventDuplicateInteraction::getInteractionInfo(const css::uno::Type& aInteraction, + PreventDuplicateInteraction::InteractionInfo* pReturn ) const +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + PreventDuplicateInteraction::InteractionList::const_iterator pIt; + for ( pIt = m_lInteractionRules.begin(); + pIt != m_lInteractionRules.end() ; + ++pIt ) + { + const PreventDuplicateInteraction::InteractionInfo& rInfo = *pIt; + if (rInfo.m_aInteraction == aInteraction) + { + *pReturn = rInfo; + return sal_True; + } + } + + aLock.clear(); + // <- SAFE + + return sal_False; +} + +} // namespace framework diff --git a/framework/source/fwe/xml/eventsconfiguration.cxx b/framework/source/fwe/xml/eventsconfiguration.cxx new file mode 100644 index 000000000000..873682f60345 --- /dev/null +++ b/framework/source/fwe/xml/eventsconfiguration.cxx @@ -0,0 +1,165 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <framework/eventsconfiguration.hxx> +#include <xml/eventsdocumenthandler.hxx> +#include <services.h> + +#ifndef __FRAMEWORK_XML_SAXNAMESPACEFILTER_HXX_ +#include <xml/saxnamespacefilter.hxx> +#endif + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#ifndef _UNOTOOLS_PROCESSFACTORY_HXX +#include <comphelper/processfactory.hxx> +#endif +#include <unotools/streamwrap.hxx> +#include <tools/debug.hxx> + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::io; + + +namespace framework +{ + +static Reference< XParser > GetSaxParser( + // #110897# + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory + ) +{ + //Reference< XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); + //return Reference< XParser >( xServiceManager->createInstance( SERVICENAME_SAXPARSER), UNO_QUERY); + return Reference< XParser >( xServiceFactory->createInstance( SERVICENAME_SAXPARSER), UNO_QUERY); +} + +static Reference< XDocumentHandler > GetSaxWriter( + // #110897# + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory + ) +{ + //Reference< XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); + //return Reference< XDocumentHandler >( xServiceManager->createInstance( SERVICENAME_SAXWRITER), UNO_QUERY) ; + return Reference< XDocumentHandler >( xServiceFactory->createInstance( SERVICENAME_SAXWRITER), UNO_QUERY) ; +} + +// #110897# +sal_Bool EventsConfiguration::LoadEventsConfig( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory, + SvStream& rInStream, EventsConfig& aItems ) +{ + Reference< XParser > xParser( GetSaxParser( xServiceFactory ) ); + Reference< XInputStream > xInputStream( + (::cppu::OWeakObject *)new utl::OInputStreamWrapper( rInStream ), + UNO_QUERY ); + + // connect stream to input stream to the parser + InputSource aInputSource; + + aInputSource.aInputStream = xInputStream; + + // create namespace filter and set events document handler inside to support xml namespaces + Reference< XDocumentHandler > xDocHandler( new OReadEventsDocumentHandler( aItems )); + Reference< XDocumentHandler > xFilter( new SaxNamespaceFilter( xDocHandler )); + + // connect parser and filter + xParser->setDocumentHandler( xFilter ); + + try + { + xParser->parseStream( aInputSource ); + return sal_True; + } + catch ( RuntimeException& ) + { + return sal_False; + } + catch( SAXException& ) + { + return sal_False; + } + catch( ::com::sun::star::io::IOException& ) + { + return sal_False; + } +} + +// #110897# +sal_Bool EventsConfiguration::StoreEventsConfig( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory, + SvStream& rOutStream, const EventsConfig& aItems ) +{ + Reference< XDocumentHandler > xWriter( GetSaxWriter( xServiceFactory ) ); + + Reference< XOutputStream > xOutputStream( + (::cppu::OWeakObject *)new utl::OOutputStreamWrapper( rOutStream ), + UNO_QUERY ); + + Reference< ::com::sun::star::io::XActiveDataSource> xDataSource( xWriter , UNO_QUERY ); + xDataSource->setOutputStream( xOutputStream ); + + try + { + OWriteEventsDocumentHandler aWriteEventsDocumentHandler( aItems, xWriter ); + aWriteEventsDocumentHandler.WriteEventsDocument(); + return sal_True; + } + catch ( RuntimeException& ) + { + return sal_False; + } + catch ( SAXException& ) + { + return sal_False; + } + catch ( ::com::sun::star::io::IOException& ) + { + return sal_False; + } +} + +} + diff --git a/framework/source/fwe/xml/eventsdocumenthandler.cxx b/framework/source/fwe/xml/eventsdocumenthandler.cxx new file mode 100644 index 000000000000..ad21937fcc5d --- /dev/null +++ b/framework/source/fwe/xml/eventsdocumenthandler.cxx @@ -0,0 +1,553 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <framework/fwedllapi.h> +#include <stdio.h> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + +#include <threadhelp/resetableguard.hxx> +#include <xml/eventsdocumenthandler.hxx> +#include <macros/debug.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ + +#ifndef __COM_SUN_STAR_XML_SAX_XEXTENDEDDOCUMENTHANDLER_HPP_ +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#endif + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#include <sal/config.h> +#include <vcl/svapp.hxx> +#include <vcl/toolbox.hxx> + +#include <comphelper/attributelist.hxx> + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::xml::sax; + + +#define XMLNS_EVENT "http://openoffice.org/2001/event" +#define XMLNS_XLINK "http://www.w3.org/1999/xlink" +#define XMLNS_EVENT_PREFIX "event:" +#define XMLNS_XLINK_PREFIX "xlink:" + +#define ATTRIBUTE_XMLNS_EVENT "xmlns:event" +#define ATTRIBUTE_XMLNS_XLINK "xmlns:xlink" + +#define XMLNS_FILTER_SEPARATOR "^" + +#define ELEMENT_EVENTS "events" +#define ELEMENT_EVENT "event" + +#define ATTRIBUTE_LANGUAGE "language" +#define ATTRIBUTE_LIBRARY "library" +#define ATTRIBUTE_NAME "name" +#define ATTRIBUTE_HREF "href" +#define ATTRIBUTE_TYPE "type" +#define ATTRIBUTE_MACRONAME "macro-name" + +#define ELEMENT_NS_EVENTS "event:events" +#define ELEMENT_NS_EVENT "event:event" + +#define ATTRIBUTE_TYPE_CDATA "CDATA" + +#define EVENTS_DOCTYPE "<!DOCTYPE event:events PUBLIC \"-//OpenOffice.org//DTD OfficeDocument 1.0//EN\" \"event.dtd\">" + +// Property names for events +#define PROP_EVENT_TYPE "EventType" +#define PROP_LIBRARY "Library" +#define PROP_SCRIPT "Script" +#define PROP_MACRO_NAME "MacroName" +#define STAR_BASIC "StarBasic" +#define JAVA_SCRIPT "JavaScript" + + +namespace framework +{ + +struct EventEntryProperty +{ + OReadEventsDocumentHandler::Event_XML_Namespace nNamespace; + char aEntryName[20]; +}; + +static EventEntryProperty EventEntries[OReadEventsDocumentHandler::EV_XML_ENTRY_COUNT] = +{ + { OReadEventsDocumentHandler::EV_NS_EVENT, ELEMENT_EVENTS }, + { OReadEventsDocumentHandler::EV_NS_EVENT, ELEMENT_EVENT }, + { OReadEventsDocumentHandler::EV_NS_EVENT, ATTRIBUTE_LANGUAGE }, + { OReadEventsDocumentHandler::EV_NS_EVENT, ATTRIBUTE_NAME }, + { OReadEventsDocumentHandler::EV_NS_XLINK, ATTRIBUTE_HREF }, + { OReadEventsDocumentHandler::EV_NS_XLINK, ATTRIBUTE_TYPE }, + { OReadEventsDocumentHandler::EV_NS_EVENT, ATTRIBUTE_MACRONAME }, + { OReadEventsDocumentHandler::EV_NS_EVENT, ATTRIBUTE_LIBRARY } +}; + + +OReadEventsDocumentHandler::OReadEventsDocumentHandler( EventsConfig& aItems ) : + ThreadHelpBase( &Application::GetSolarMutex() ), + m_aEventItems( aItems ) +{ + ::rtl::OUString aNamespaceEvent( RTL_CONSTASCII_USTRINGPARAM( XMLNS_EVENT )); + ::rtl::OUString aNamespaceXLink( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK )); + ::rtl::OUString aSeparator( RTL_CONSTASCII_USTRINGPARAM( XMLNS_FILTER_SEPARATOR )); + + // create hash map + for ( int i = 0; i < (int)EV_XML_ENTRY_COUNT; i++ ) + { + if ( EventEntries[i].nNamespace == EV_NS_EVENT ) + { + ::rtl::OUString temp( aNamespaceEvent ); + temp += aSeparator; + temp += ::rtl::OUString::createFromAscii( EventEntries[i].aEntryName ); + m_aEventsMap.insert( EventsHashMap::value_type( temp, (Events_XML_Entry)i ) ); + } + else + { + ::rtl::OUString temp( aNamespaceXLink ); + temp += aSeparator; + temp += ::rtl::OUString::createFromAscii( EventEntries[i].aEntryName ); + m_aEventsMap.insert( EventsHashMap::value_type( temp, (Events_XML_Entry)i ) ); + } + } + + m_bEventsStartFound = sal_False; + m_bEventsEndFound = sal_False; + m_bEventStartFound = sal_False; +} + +OReadEventsDocumentHandler::~OReadEventsDocumentHandler() +{ +} + +// XDocumentHandler +void SAL_CALL OReadEventsDocumentHandler::startDocument(void) +throw ( SAXException, RuntimeException ) +{ +} + +void SAL_CALL OReadEventsDocumentHandler::endDocument(void) +throw( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + if (( m_bEventsStartFound && !m_bEventsEndFound ) || + ( !m_bEventsStartFound && m_bEventsEndFound ) ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No matching start or end element 'event:events' found!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } +} + +void SAL_CALL OReadEventsDocumentHandler::startElement( + const ::rtl::OUString& aName, const Reference< XAttributeList > &xAttribs ) +throw( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + EventsHashMap::const_iterator pEventEntry = m_aEventsMap.find( aName ); + if ( pEventEntry != m_aEventsMap.end() ) + { + switch ( pEventEntry->second ) + { + case EV_ELEMENT_EVENTS: + { + if ( m_bEventsStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'event:events' cannot be embeded into 'event:events'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bEventsStartFound = sal_True; + } + break; + + case EV_ELEMENT_EVENT: + { + if ( !m_bEventsStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'event:event' must be embeded into element 'event:events'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + if ( m_bEventStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element event:event is not a container!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + ::rtl::OUString aLanguage; + ::rtl::OUString aURL; + ::rtl::OUString aMacroName; + ::rtl::OUString aLibrary; + ::rtl::OUString aEventName; + + m_bEventStartFound = sal_True; + + long nIndex = m_aEventItems.aEventNames.getLength(); + long nPropCount = 2; // every event config entry needs at least 2 properties + Sequence< PropertyValue > aEventProperties( nPropCount ); + + m_aEventItems.aEventNames.realloc( nIndex + 1 ); + + for ( sal_Int16 n = 0; n < xAttribs->getLength(); n++ ) + { + pEventEntry = m_aEventsMap.find( xAttribs->getNameByIndex( n ) ); + if ( pEventEntry != m_aEventsMap.end() ) + { + switch ( pEventEntry->second ) + { + case EV_ATTRIBUTE_TYPE: + { + aLanguage = xAttribs->getValueByIndex( n ); + } + break; + + case EV_ATTRIBUTE_NAME: + { + aEventName = xAttribs->getValueByIndex( n ); + } + break; + + case XL_ATTRIBUTE_HREF: + { + aURL = xAttribs->getValueByIndex( n ); + } + break; + + case EV_ATTRIBUTE_MACRONAME: + { + aMacroName = xAttribs->getValueByIndex( n ); + } + break; + + case EV_ATTRIBUTE_LIBRARY: + { + aLibrary = xAttribs->getValueByIndex( n ); + } + break; + + default: + break; // nothing to do + } + } + } // for + + ::rtl::OUString aRequiredAttributeName; + if ( aLanguage.getLength() == 0 ) + aRequiredAttributeName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TYPE )); + else if ( aEventName.getLength() == 0 ) + aRequiredAttributeName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NAME )); + + // check for missing attribute values + if ( aRequiredAttributeName.getLength() > 0 ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Required attribute ")); + aErrorMessage += aRequiredAttributeName; + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " must have a value!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + Any a; + + // set properties + a <<= aLanguage; + aEventProperties[0].Value <<= a; + aEventProperties[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PROP_EVENT_TYPE )); + + a <<= aMacroName; + aEventProperties[1].Value <<= a; + aEventProperties[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PROP_MACRO_NAME )); + + if ( aLibrary.getLength() > 0 ) + { + ++nPropCount; + aEventProperties.realloc( nPropCount ); + a <<= aLibrary; + aEventProperties[nPropCount-1].Value <<= a; + aEventProperties[nPropCount-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PROP_LIBRARY )); + } + + if ( aURL.getLength() > 0 ) + { + ++nPropCount; + aEventProperties.realloc( nPropCount ); + a <<= aURL; + aEventProperties[nPropCount-1].Value <<= a; + aEventProperties[nPropCount-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PROP_SCRIPT )); + } + + // set event name + m_aEventItems.aEventNames[ nIndex ] = aEventName; + + m_aEventItems.aEventsProperties.realloc( nIndex + 1 ); + a <<= aEventProperties; + m_aEventItems.aEventsProperties[ nIndex ] = a; + } + break; + + default: + break; + } + } +} + +void SAL_CALL OReadEventsDocumentHandler::endElement(const ::rtl::OUString& aName) +throw( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + EventsHashMap::const_iterator pEventEntry = m_aEventsMap.find( aName ); + if ( pEventEntry != m_aEventsMap.end() ) + { + switch ( pEventEntry->second ) + { + case EV_ELEMENT_EVENTS: + { + if ( !m_bEventsStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "End element 'event:events' found, but no start element" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bEventsStartFound = sal_False; + } + break; + + case EV_ELEMENT_EVENT: + { + if ( !m_bEventStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "End element 'event:event' found, but no start element" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bEventStartFound = sal_False; + } + break; + + default: + break; // impossible case + } + } +} + +void SAL_CALL OReadEventsDocumentHandler::characters(const ::rtl::OUString&) +throw( SAXException, RuntimeException ) +{ +} + +void SAL_CALL OReadEventsDocumentHandler::ignorableWhitespace(const ::rtl::OUString&) +throw( SAXException, RuntimeException ) +{ +} + +void SAL_CALL OReadEventsDocumentHandler::processingInstruction( + const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/ ) +throw( SAXException, RuntimeException ) +{ +} + +void SAL_CALL OReadEventsDocumentHandler::setDocumentLocator( + const Reference< XLocator > &xLocator) +throw( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + m_xLocator = xLocator; +} + +::rtl::OUString OReadEventsDocumentHandler::getErrorLineString() +{ + ResetableGuard aGuard( m_aLock ); + + char buffer[32]; + + if ( m_xLocator.is() ) + { + snprintf( buffer, sizeof(buffer), "Line: %ld - ", static_cast<long>(m_xLocator->getLineNumber() )); + return ::rtl::OUString::createFromAscii( buffer ); + } + else + return ::rtl::OUString(); +} + + +//_________________________________________________________________________________________________________________ +// OWriteEventsDocumentHandler +//_________________________________________________________________________________________________________________ + +OWriteEventsDocumentHandler::OWriteEventsDocumentHandler( + const EventsConfig& aItems, + Reference< XDocumentHandler > rWriteDocumentHandler ) : + ThreadHelpBase( &Application::GetSolarMutex() ), + m_aItems( aItems ), + m_xWriteDocumentHandler( rWriteDocumentHandler ) +{ + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + m_xEmptyList = Reference< XAttributeList >( (XAttributeList *) pList, UNO_QUERY ); + m_aAttributeType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TYPE_CDATA )); + m_aXMLXlinkNS = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK_PREFIX )); + m_aXMLEventNS = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_EVENT_PREFIX )); +} + +OWriteEventsDocumentHandler::~OWriteEventsDocumentHandler() +{ +} + +void OWriteEventsDocumentHandler::WriteEventsDocument() throw +( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + m_xWriteDocumentHandler->startDocument(); + + // write DOCTYPE line! + Reference< XExtendedDocumentHandler > xExtendedDocHandler( m_xWriteDocumentHandler, UNO_QUERY ); + if ( xExtendedDocHandler.is() ) + { + xExtendedDocHandler->unknown( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( EVENTS_DOCTYPE )) ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + } + + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + Reference< XAttributeList > xList( (XAttributeList *) pList , UNO_QUERY ); + + pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XMLNS_EVENT )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_EVENT )) ); + pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XMLNS_XLINK )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK )) ); + + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_EVENTS )), pList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + + Sequence< PropertyValue > aEventProperties; + + for ( int i = 0; i < m_aItems.aEventNames.getLength(); i++ ) + { + if ( m_aItems.aEventsProperties[i] >>= aEventProperties ) + WriteEvent( m_aItems.aEventNames[i], aEventProperties ); + } + + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_EVENTS )) ); + + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endDocument(); +} + +//_________________________________________________________________________________________________________________ +// protected member functions +//_________________________________________________________________________________________________________________ + +void OWriteEventsDocumentHandler::WriteEvent( const ::rtl::OUString& aEventName, const Sequence< PropertyValue >& aPropertyValues ) throw +( SAXException, RuntimeException ) +{ + if ( aPropertyValues.getLength() > 0 ) + { + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + Reference< XAttributeList > xList( (XAttributeList *) pList , UNO_QUERY ); + + if ( m_aAttributeURL.getLength() == 0 ) + { + m_aAttributeURL = m_aXMLXlinkNS; + m_aAttributeURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_HREF )); + m_aAttributeLinkType = m_aXMLXlinkNS; + m_aAttributeLinkType += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TYPE )); + m_aAttributeLanguage = m_aXMLEventNS; + m_aAttributeLanguage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_LANGUAGE )); + m_aAttributeMacroName = m_aXMLEventNS; + m_aAttributeMacroName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_MACRONAME )); + m_aAttributeLibrary = m_aXMLEventNS; + m_aAttributeLibrary += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_LIBRARY )); + m_aAttributeName = m_aXMLEventNS; + m_aAttributeName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NAME )); + } + + pList->AddAttribute( m_aAttributeName, m_aAttributeType, aEventName ); + + sal_Bool bURLSet = sal_False; + ::rtl::OUString aValue; + ::rtl::OUString aName; + + // save attributes + for ( int i = 0; i < aPropertyValues.getLength(); i++ ) + { + aPropertyValues[i].Value >>= aValue; + if ( aPropertyValues[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( PROP_EVENT_TYPE ))) + pList->AddAttribute( m_aAttributeLanguage, m_aAttributeType, aValue ); + else if ( aPropertyValues[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( PROP_MACRO_NAME )) && + aValue.getLength() > 0 ) + pList->AddAttribute( m_aAttributeMacroName, m_aAttributeType, aValue ); + else if ( aPropertyValues[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( PROP_LIBRARY )) && + aValue.getLength() > 0 ) + pList->AddAttribute( m_aAttributeLibrary, m_aAttributeType, aValue ); + else if ( aPropertyValues[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( PROP_SCRIPT ))) + { + pList->AddAttribute( m_aAttributeURL, m_aAttributeType, aValue ); + bURLSet = sal_True; + } + } + + if ( bURLSet ) + pList->AddAttribute( m_aAttributeLinkType, m_aAttributeType, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "simple" )) ); + + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_EVENT )), xList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_EVENT )) ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + } +} + +} // namespace framework + diff --git a/framework/source/fwe/xml/imagesconfiguration.cxx b/framework/source/fwe/xml/imagesconfiguration.cxx new file mode 100644 index 000000000000..d561a76d5995 --- /dev/null +++ b/framework/source/fwe/xml/imagesconfiguration.cxx @@ -0,0 +1,238 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <framework/imagesconfiguration.hxx> +#include <services.h> + +#ifndef __FRAMEWORK_CLASSES_IMAGESDOCUMENTHANDLER_HXX_ +#include <xml/imagesdocumenthandler.hxx> +#endif +#include <xml/saxnamespacefilter.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#ifndef _UNOTOOLS_PROCESSFACTORY_HXX +#include <comphelper/processfactory.hxx> +#endif +#include <unotools/streamwrap.hxx> +#include <tools/debug.hxx> + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::io; + + +namespace framework +{ + +SV_IMPL_PTRARR( ImageItemListDescriptor, ImageItemDescriptorPtr ); +SV_IMPL_PTRARR( ExternalImageItemListDescriptor, ExternalImageItemDescriptorPtr ); +SV_IMPL_PTRARR( ImageListDescriptor, ImageListItemDescriptorPtr ); + +static Reference< XParser > GetSaxParser( + // #110897# + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory + ) +{ + //Reference< XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); + //return Reference< XParser >( xServiceManager->createInstance( SERVICENAME_SAXPARSER), UNO_QUERY); + return Reference< XParser >( xServiceFactory->createInstance( SERVICENAME_SAXPARSER), UNO_QUERY); +} + +static Reference< XDocumentHandler > GetSaxWriter( + // #110897# + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory + ) +{ + //Reference< XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); + //return Reference< XDocumentHandler >( xServiceManager->createInstance( SERVICENAME_SAXWRITER), UNO_QUERY) ; + return Reference< XDocumentHandler >( xServiceFactory->createInstance( SERVICENAME_SAXWRITER), UNO_QUERY) ; +} + +// #110897# +sal_Bool ImagesConfiguration::LoadImages( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory, + SvStream& rInStream, ImageListsDescriptor& aItems ) +{ + Reference< XParser > xParser( GetSaxParser( xServiceFactory ) ); + Reference< XInputStream > xInputStream( + (::cppu::OWeakObject *)new utl::OInputStreamWrapper( rInStream ), + UNO_QUERY ); + + // connect stream to input stream to the parser + InputSource aInputSource; + + aInputSource.aInputStream = xInputStream; + + // create namespace filter and set document handler inside to support xml namespaces + Reference< XDocumentHandler > xDocHandler( new OReadImagesDocumentHandler( aItems )); + Reference< XDocumentHandler > xFilter( new SaxNamespaceFilter( xDocHandler )); + + // connect parser and filter + xParser->setDocumentHandler( xFilter ); + + try + { + xParser->parseStream( aInputSource ); + return sal_True; + } + catch ( RuntimeException& ) + { + return sal_False; + } + catch( SAXException& ) + { + return sal_False; + } + catch( ::com::sun::star::io::IOException& ) + { + return sal_False; + } +} + + +// #110897# +sal_Bool ImagesConfiguration::StoreImages( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory, + SvStream& rOutStream, const ImageListsDescriptor& aItems ) +{ + Reference< XDocumentHandler > xWriter( GetSaxWriter( xServiceFactory ) ); + + Reference< XOutputStream > xOutputStream( + (::cppu::OWeakObject *)new utl::OOutputStreamWrapper( rOutStream ), + UNO_QUERY ); + + Reference< ::com::sun::star::io::XActiveDataSource> xDataSource( xWriter , UNO_QUERY ); + xDataSource->setOutputStream( xOutputStream ); + + try + { + OWriteImagesDocumentHandler aWriteImagesDocumentHandler( aItems, xWriter ); + aWriteImagesDocumentHandler.WriteImagesDocument(); + return sal_True; + } + catch ( RuntimeException& ) + { + return sal_False; + } + catch ( SAXException& ) + { + return sal_False; + } + catch ( ::com::sun::star::io::IOException& ) + { + return sal_False; + } +} + +sal_Bool ImagesConfiguration::LoadImages( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rInputStream, + ImageListsDescriptor& rItems ) +{ + Reference< XParser > xParser( GetSaxParser( xServiceFactory ) ); + + // connect stream to input stream to the parser + InputSource aInputSource; + + aInputSource.aInputStream = rInputStream; + + // create namespace filter and set document handler inside to support xml namespaces + Reference< XDocumentHandler > xDocHandler( new OReadImagesDocumentHandler( rItems )); + Reference< XDocumentHandler > xFilter( new SaxNamespaceFilter( xDocHandler )); + + // connect parser and filter + xParser->setDocumentHandler( xFilter ); + + try + { + xParser->parseStream( aInputSource ); + return sal_True; + } + catch ( RuntimeException& ) + { + return sal_False; + } + catch( SAXException& ) + { + return sal_False; + } + catch( ::com::sun::star::io::IOException& ) + { + return sal_False; + } +} + +sal_Bool ImagesConfiguration::StoreImages( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& rOutputStream, + const ImageListsDescriptor& rItems ) +{ + Reference< XDocumentHandler > xWriter( GetSaxWriter( xServiceFactory ) ); + + Reference< ::com::sun::star::io::XActiveDataSource> xDataSource( xWriter , UNO_QUERY ); + xDataSource->setOutputStream( rOutputStream ); + + try + { + OWriteImagesDocumentHandler aWriteImagesDocumentHandler( rItems, xWriter ); + aWriteImagesDocumentHandler.WriteImagesDocument(); + return sal_True; + } + catch ( RuntimeException& ) + { + return sal_False; + } + catch ( SAXException& ) + { + return sal_False; + } + catch ( ::com::sun::star::io::IOException& ) + { + return sal_False; + } +} + +} + diff --git a/framework/source/fwe/xml/imagesdocumenthandler.cxx b/framework/source/fwe/xml/imagesdocumenthandler.cxx new file mode 100644 index 000000000000..cdf20958332a --- /dev/null +++ b/framework/source/fwe/xml/imagesdocumenthandler.cxx @@ -0,0 +1,851 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <stdio.h> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + +#include <threadhelp/resetableguard.hxx> +#include <xml/imagesdocumenthandler.hxx> +#include <macros/debug.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ + +#ifndef __COM_SUN_STAR_XML_SAX_XEXTENDEDDOCUMENTHANDLER_HPP_ +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#endif + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <vcl/svapp.hxx> +#include <vcl/toolbox.hxx> +#include <rtl/ustrbuf.hxx> + +#include <comphelper/attributelist.hxx> + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +#define ELEMENT_IMAGECONTAINER "imagescontainer" +#define ELEMENT_IMAGES "images" +#define ELEMENT_ENTRY "entry" +#define ELEMENT_EXTERNALIMAGES "externalimages" +#define ELEMENT_EXTERNALENTRY "externalentry" + +#define ELEMENT_NS_IMAGESCONTAINER "image:imagescontainer" +#define ELEMENT_NS_IMAGES "image:images" +#define ELEMENT_NS_ENTRY "image:entry" +#define ELEMENT_NS_EXTERNALIMAGES "image:externalimages" +#define ELEMENT_NS_EXTERNALENTRY "image:externalentry" + +#define ATTRIBUTE_HREF "href" +#define ATTRIBUTE_MASKCOLOR "maskcolor" +#define ATTRIBUTE_COMMAND "command" +#define ATTRIBUTE_BITMAPINDEX "bitmap-index" +#define ATTRIBUTE_MASKURL "maskurl" +#define ATTRIBUTE_MASKMODE "maskmode" +#define ATTRIBUTE_HIGHCONTRASTURL "highcontrasturl" +#define ATTRIBUTE_HIGHCONTRASTMASKURL "highcontrastmaskurl" +#define ATTRIBUTE_TYPE_CDATA "CDATA" + +#define ATTRIBUTE_MASKMODE_BITMAP "maskbitmap" +#define ATTRIBUTE_MASKMODE_COLOR "maskcolor" + +#define ATTRIBUTE_XMLNS_IMAGE "xmlns:image" +#define ATTRIBUTE_XMLNS_XLINK "xmlns:xlink" + +#define ATTRIBUTE_XLINK_TYPE "xlink:type" +#define ATTRIBUTE_XLINK_TYPE_VALUE "simple" + +#define XMLNS_IMAGE "http://openoffice.org/2001/image" +#define XMLNS_XLINK "http://www.w3.org/1999/xlink" +#define XMLNS_IMAGE_PREFIX "image:" +#define XMLNS_XLINK_PREFIX "xlink:" + +#define XMLNS_FILTER_SEPARATOR "^" + +#define IMAGES_DOCTYPE "<!DOCTYPE image:imagecontainer PUBLIC \"-//OpenOffice.org//DTD OfficeDocument 1.0//EN\" \"image.dtd\">" + +namespace framework +{ + +struct ImageXMLEntryProperty +{ + OReadImagesDocumentHandler::Image_XML_Namespace nNamespace; + char aEntryName[20]; +}; + +ImageXMLEntryProperty ImagesEntries[OReadImagesDocumentHandler::IMG_XML_ENTRY_COUNT] = +{ + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ELEMENT_IMAGECONTAINER }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ELEMENT_IMAGES }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ELEMENT_ENTRY }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ELEMENT_EXTERNALIMAGES }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ELEMENT_EXTERNALENTRY }, + { OReadImagesDocumentHandler::IMG_NS_XLINK, ATTRIBUTE_HREF }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ATTRIBUTE_MASKCOLOR }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ATTRIBUTE_COMMAND }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ATTRIBUTE_BITMAPINDEX }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ATTRIBUTE_MASKURL }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ATTRIBUTE_MASKMODE }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ATTRIBUTE_HIGHCONTRASTURL }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ATTRIBUTE_HIGHCONTRASTMASKURL } +}; + + +OReadImagesDocumentHandler::OReadImagesDocumentHandler( ImageListsDescriptor& aItems ) : + ThreadHelpBase( &Application::GetSolarMutex() ), + m_aImageList( aItems ), + m_pImages( 0 ), + m_pExternalImages( 0 ) +{ + m_aImageList.pImageList = NULL; + m_aImageList.pExternalImageList = NULL; + + m_nHashMaskModeBitmap = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_MASKMODE_BITMAP )).hashCode(); + m_nHashMaskModeColor = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_MASKMODE_COLOR )).hashCode(); + + // create hash map to speed up lookup + for ( int i = 0; i < (int)IMG_XML_ENTRY_COUNT; i++ ) + { + ::rtl::OUStringBuffer temp( 20 ); + + if ( ImagesEntries[i].nNamespace == IMG_NS_IMAGE ) + temp.appendAscii( XMLNS_IMAGE ); + else + temp.appendAscii( XMLNS_XLINK ); + + temp.appendAscii( XMLNS_FILTER_SEPARATOR ); + temp.appendAscii( ImagesEntries[i].aEntryName ); + m_aImageMap.insert( ImageHashMap::value_type( temp.makeStringAndClear(), (Image_XML_Entry)i ) ); + } + + // reset states + m_bImageContainerStartFound = sal_False; + m_bImageContainerEndFound = sal_False; + m_bImagesStartFound = sal_False; + m_bImagesEndFound = sal_False; + m_bImageStartFound = sal_False; + m_bExternalImagesStartFound = sal_False; + m_bExternalImagesEndFound = sal_False; + m_bExternalImageStartFound = sal_False; +} + +OReadImagesDocumentHandler::~OReadImagesDocumentHandler() +{ +} + +// XDocumentHandler +void SAL_CALL OReadImagesDocumentHandler::startDocument(void) +throw ( SAXException, RuntimeException ) +{ +} + +void SAL_CALL OReadImagesDocumentHandler::endDocument(void) +throw( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + if (( m_bImageContainerStartFound && !m_bImageContainerEndFound ) || + ( !m_bImageContainerStartFound && m_bImageContainerEndFound ) ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No matching start or end element 'image:imagecontainer' found!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } +} + +void SAL_CALL OReadImagesDocumentHandler::startElement( + const ::rtl::OUString& aName, const Reference< XAttributeList > &xAttribs ) +throw( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + ImageHashMap::const_iterator pImageEntry = m_aImageMap.find( aName ) ; + if ( pImageEntry != m_aImageMap.end() ) + { + switch ( pImageEntry->second ) + { + case IMG_ELEMENT_IMAGECONTAINER: + { + // image:imagecontainer element (container element for all further image elements) + if ( m_bImageContainerStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'image:imagecontainer' cannot be embeded into 'image:imagecontainer'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bImageContainerStartFound = sal_True; + } + break; + + case IMG_ELEMENT_IMAGES: + { + if ( !m_bImageContainerStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'image:images' must be embeded into element 'image:imagecontainer'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + if ( m_bImagesStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'image:images' cannot be embeded into 'image:images'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + if ( !m_aImageList.pImageList ) + m_aImageList.pImageList = new ImageListDescriptor; + + m_bImagesStartFound = sal_True; + m_pImages = new ImageListItemDescriptor; + + for ( sal_Int16 n = 0; n < xAttribs->getLength(); n++ ) + { + pImageEntry = m_aImageMap.find( xAttribs->getNameByIndex( n ) ); + if ( pImageEntry != m_aImageMap.end() ) + { + switch ( pImageEntry->second ) + { + case IMG_ATTRIBUTE_HREF: + { + m_pImages->aURL = xAttribs->getValueByIndex( n ); + } + break; + + case IMG_ATTRIBUTE_MASKCOLOR: + { + ::rtl::OUString aColor = xAttribs->getValueByIndex( n ); + + if ( aColor.getLength() > 0 ) + { + if ( aColor.getStr()[0] == '#' ) + { + // the color value is given as #rrggbb and used the hexadecimal system!! + sal_uInt32 nColor = aColor.copy( 1 ).toInt32( 16 ); + + m_pImages->aMaskColor = Color( COLORDATA_RGB( nColor ) ); + } + } + } + break; + + case IMG_ATTRIBUTE_MASKURL: + { + m_pImages->aMaskURL = xAttribs->getValueByIndex( n ); + } + break; + + case IMG_ATTRIBUTE_MASKMODE: + { + sal_Int32 nHashCode = xAttribs->getValueByIndex( n ).hashCode(); + if ( nHashCode == m_nHashMaskModeBitmap ) + m_pImages->nMaskMode = ImageMaskMode_Bitmap; + else if ( nHashCode == m_nHashMaskModeColor ) + m_pImages->nMaskMode = ImageMaskMode_Color; + else + { + delete m_pImages; + m_pImages = NULL; + + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Attribute image:maskmode must be 'maskcolor' or 'maskbitmap'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } + break; + + case IMG_ATTRIBUTE_HIGHCONTRASTURL: + { + m_pImages->aHighContrastURL = xAttribs->getValueByIndex( n ); + } + break; + + case IMG_ATTRIBUTE_HIGHCONTRASTMASKURL: + { + m_pImages->aHighContrastMaskURL = xAttribs->getValueByIndex( n ); + } + break; + + default: + break; + } + } + } // for + + if ( m_pImages->aURL.Len() == 0 ) + { + delete m_pImages; + m_pImages = NULL; + + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Required attribute xlink:href must have a value!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } + break; + + case IMG_ELEMENT_ENTRY: + { + // Check that image:entry is embeded into image:images! + if ( !m_bImagesStartFound ) + { + delete m_pImages; + m_pImages = NULL; + + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'image:entry' must be embeded into element 'image:images'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + if ( !m_pImages->pImageItemList ) + m_pImages->pImageItemList = new ImageItemListDescriptor; + + m_bImageStartFound = sal_True; + + // Create new image item descriptor + ImageItemDescriptor* pItem = new ImageItemDescriptor; + pItem->nIndex = -1; + + // Read attributes for this image definition + for ( sal_Int16 n = 0; n < xAttribs->getLength(); n++ ) + { + pImageEntry = m_aImageMap.find( xAttribs->getNameByIndex( n ) ); + if ( pImageEntry != m_aImageMap.end() ) + { + switch ( pImageEntry->second ) + { + case IMG_ATTRIBUTE_COMMAND: + { + pItem->aCommandURL = xAttribs->getValueByIndex( n ); + } + break; + + case IMG_ATTRIBUTE_BITMAPINDEX: + { + pItem->nIndex = xAttribs->getValueByIndex( n ).toInt32(); + } + break; + + default: + break; + } + } + } + + // Check required attribute "bitmap-index" + if ( pItem->nIndex < 0 ) + { + delete pItem; + delete m_pImages; + m_pImages = NULL; + + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Required attribute 'image:bitmap-index' must have a value >= 0!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + // Check required attribute "command" + if ( pItem->aCommandURL.Len() == 0 ) + { + delete pItem; + delete m_pImages; + m_pImages = NULL; + + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Required attribute 'image:command' must have a value!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + if ( m_pImages ) + m_pImages->pImageItemList->Insert( pItem, m_pImages->pImageItemList->Count() ); + } + break; + + case IMG_ELEMENT_EXTERNALIMAGES: + { + // Check that image:externalimages is embeded into image:imagecontainer + if ( !m_bImageContainerStartFound ) + { + delete m_pImages; + m_pImages = NULL; + + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'image:externalimages' must be embeded into element 'image:imagecontainer'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + // Check that image:externalentry is NOT embeded into image:externalentry + if ( m_bExternalImagesStartFound ) + { + delete m_pImages; + m_pImages = NULL; + + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'image:externalimages' cannot be embeded into 'image:externalimages'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + // Create unique external image container + m_bExternalImagesStartFound = sal_True; + m_pExternalImages = new ExternalImageItemListDescriptor; + } + break; + + case IMG_ELEMENT_EXTERNALENTRY: + { + if ( !m_bExternalImagesStartFound ) + { + delete m_pImages; + delete m_pExternalImages; + m_pImages = NULL; + m_pExternalImages = NULL; + + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'image:externalentry' must be embeded into 'image:externalimages'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + if ( m_bExternalImageStartFound ) + { + delete m_pImages; + delete m_pExternalImages; + m_pImages = NULL; + m_pExternalImages = NULL; + + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'image:externalentry' cannot be embeded into 'image:externalentry'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bExternalImageStartFound = sal_True; + + ExternalImageItemDescriptor* pItem = new ExternalImageItemDescriptor; + + // Read attributes for this external image definition + for ( sal_Int16 n = 0; n < xAttribs->getLength(); n++ ) + { + pImageEntry = m_aImageMap.find( xAttribs->getNameByIndex( n ) ); + if ( pImageEntry != m_aImageMap.end() ) + { + switch ( pImageEntry->second ) + { + case IMG_ATTRIBUTE_COMMAND: + { + pItem->aCommandURL = xAttribs->getValueByIndex( n ); + } + break; + + case IMG_ATTRIBUTE_HREF: + { + pItem->aURL = xAttribs->getValueByIndex( n ); + } + break; + + default: + break; + } + } + } + + // Check required attribute "command" + if ( pItem->aCommandURL.Len() == 0 ) + { + delete pItem; + delete m_pImages; + delete m_pExternalImages; + m_pImages = NULL; + m_pExternalImages = NULL; + + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Required attribute 'image:command' must have a value!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + // Check required attribute "href" + if ( pItem->aURL.Len() == 0 ) + { + delete pItem; + delete m_pImages; + delete m_pExternalImages; + m_pImages = NULL; + m_pExternalImages = NULL; + + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Required attribute 'xlink:href' must have a value!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + if ( m_pExternalImages ) + m_pExternalImages->Insert( pItem, m_pExternalImages->Count() ); + } + break; + + default: + break; + } + } +} + +void SAL_CALL OReadImagesDocumentHandler::endElement(const ::rtl::OUString& aName) +throw( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + ImageHashMap::const_iterator pImageEntry = m_aImageMap.find( aName ) ; + if ( pImageEntry != m_aImageMap.end() ) + { + switch ( pImageEntry->second ) + { + case IMG_ELEMENT_IMAGECONTAINER: + { + m_bImageContainerEndFound = sal_True; + } + break; + + case IMG_ELEMENT_IMAGES: + { + if ( m_pImages ) + { + if ( m_aImageList.pImageList ) + m_aImageList.pImageList->Insert( m_pImages, m_aImageList.pImageList->Count() ); + m_pImages = NULL; + } + m_bImagesStartFound = sal_False; + } + break; + + case IMG_ELEMENT_ENTRY: + { + m_bImageStartFound = sal_False; + } + break; + + case IMG_ELEMENT_EXTERNALIMAGES: + { + if ( m_pExternalImages && !m_aImageList.pExternalImageList ) + { + if ( !m_aImageList.pExternalImageList ) + m_aImageList.pExternalImageList = m_pExternalImages; + } + + m_bExternalImagesStartFound = sal_False; + m_pExternalImages = NULL; + } + break; + + case IMG_ELEMENT_EXTERNALENTRY: + { + m_bExternalImageStartFound = sal_False; + } + break; + + default: + break; + } + } +} + +void SAL_CALL OReadImagesDocumentHandler::characters(const ::rtl::OUString&) +throw( SAXException, RuntimeException ) +{ +} + +void SAL_CALL OReadImagesDocumentHandler::ignorableWhitespace(const ::rtl::OUString&) +throw( SAXException, RuntimeException ) +{ +} + +void SAL_CALL OReadImagesDocumentHandler::processingInstruction( + const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/ ) +throw( SAXException, RuntimeException ) +{ +} + +void SAL_CALL OReadImagesDocumentHandler::setDocumentLocator( + const Reference< XLocator > &xLocator) +throw( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + m_xLocator = xLocator; +} + +::rtl::OUString OReadImagesDocumentHandler::getErrorLineString() +{ + ResetableGuard aGuard( m_aLock ); + + char buffer[32]; + + if ( m_xLocator.is() ) + { + snprintf( buffer, sizeof(buffer), "Line: %ld - ", static_cast<long>( m_xLocator->getLineNumber() )); + return ::rtl::OUString::createFromAscii( buffer ); + } + else + return ::rtl::OUString(); +} + + +//_________________________________________________________________________________________________________________ +// OWriteImagesDocumentHandler +//_________________________________________________________________________________________________________________ + +OWriteImagesDocumentHandler::OWriteImagesDocumentHandler( + const ImageListsDescriptor& aItems, + Reference< XDocumentHandler > rWriteDocumentHandler ) : + ThreadHelpBase( &Application::GetSolarMutex() ), + m_aImageListsItems( aItems ), + m_xWriteDocumentHandler( rWriteDocumentHandler ) +{ + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + m_xEmptyList = Reference< XAttributeList >( (XAttributeList *) pList, UNO_QUERY ); + m_aAttributeType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TYPE_CDATA )); + m_aXMLImageNS = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_IMAGE_PREFIX )); + m_aXMLXlinkNS = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK_PREFIX )); + m_aAttributeXlinkType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XLINK_TYPE )); + m_aAttributeValueSimple = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XLINK_TYPE_VALUE )); +} + +OWriteImagesDocumentHandler::~OWriteImagesDocumentHandler() +{ +} + +void OWriteImagesDocumentHandler::WriteImagesDocument() throw +( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + m_xWriteDocumentHandler->startDocument(); + + // write DOCTYPE line! + Reference< XExtendedDocumentHandler > xExtendedDocHandler( m_xWriteDocumentHandler, UNO_QUERY ); + if ( xExtendedDocHandler.is() ) + { + xExtendedDocHandler->unknown( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMAGES_DOCTYPE )) ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + } + + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + Reference< XAttributeList > xList( (XAttributeList *) pList , UNO_QUERY ); + + pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XMLNS_IMAGE )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_IMAGE )) ); + + pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XMLNS_XLINK )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK )) ); + + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_IMAGESCONTAINER )), pList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + + if ( m_aImageListsItems.pImageList ) + { + ImageListDescriptor* pImageList = m_aImageListsItems.pImageList; + + for ( sal_uInt16 i = 0; i < m_aImageListsItems.pImageList->Count(); i++ ) + { + const ImageListItemDescriptor* pImageItems = (*pImageList)[i]; + WriteImageList( pImageItems ); + } + } + + if ( m_aImageListsItems.pExternalImageList ) + { + WriteExternalImageList( m_aImageListsItems.pExternalImageList ); + } + + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_IMAGESCONTAINER )) ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endDocument(); +} + +//_________________________________________________________________________________________________________________ +// protected member functions +//_________________________________________________________________________________________________________________ + +void OWriteImagesDocumentHandler::WriteImageList( const ImageListItemDescriptor* pImageList ) throw +( SAXException, RuntimeException ) +{ + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + Reference< XAttributeList > xList( (XAttributeList *) pList , UNO_QUERY ); + + // save required attributes + pList->AddAttribute( m_aAttributeXlinkType, + m_aAttributeType, + m_aAttributeValueSimple ); + + pList->AddAttribute( m_aXMLXlinkNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_HREF )), + m_aAttributeType, + pImageList->aURL ); + + if ( pImageList->nMaskMode == ImageMaskMode_Bitmap ) + { + pList->AddAttribute( m_aXMLImageNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_MASKMODE )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_MASKMODE_BITMAP )) ); + + pList->AddAttribute( m_aXMLImageNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_MASKURL )), + m_aAttributeType, + pImageList->aMaskURL ); + + if ( pImageList->aHighContrastMaskURL.Len() > 0 ) + { + pList->AddAttribute( m_aXMLImageNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_HIGHCONTRASTMASKURL )), + m_aAttributeType, + pImageList->aHighContrastMaskURL ); + } + } + else + { + ::rtl::OUStringBuffer aColorStrBuffer( 8 ); + sal_Int64 nValue = pImageList->aMaskColor.GetRGBColor(); + + aColorStrBuffer.appendAscii( "#" ); + aColorStrBuffer.append( ::rtl::OUString::valueOf( nValue, 16 )); + + pList->AddAttribute( m_aXMLImageNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_MASKCOLOR )), + m_aAttributeType, + aColorStrBuffer.makeStringAndClear() ); + + pList->AddAttribute( m_aXMLImageNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_MASKMODE )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_MASKMODE_COLOR )) ); + } + + if ( pImageList->aHighContrastURL.Len() > 0 ) + { + pList->AddAttribute( m_aXMLImageNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_HIGHCONTRASTURL )), + m_aAttributeType, + pImageList->aHighContrastURL ); + } + + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_IMAGES )), xList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + + ImageItemListDescriptor* pImageItemList = pImageList->pImageItemList; + if ( pImageItemList ) + { + for ( sal_uInt16 i = 0; i < pImageItemList->Count(); i++ ) + WriteImage( (*pImageItemList)[i] ); + } + + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_IMAGES )) ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); +} + +void OWriteImagesDocumentHandler::WriteImage( const ImageItemDescriptor* pImage ) throw +( SAXException, RuntimeException ) +{ + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + Reference< XAttributeList > xList( (XAttributeList *) pList , UNO_QUERY ); + + pList->AddAttribute( m_aXMLImageNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_BITMAPINDEX )), + m_aAttributeType, + ::rtl::OUString::valueOf( (sal_Int32)pImage->nIndex ) ); + + pList->AddAttribute( m_aXMLImageNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_COMMAND )), + m_aAttributeType, + pImage->aCommandURL ); + + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_ENTRY )), xList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_ENTRY )) ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); +} + +void OWriteImagesDocumentHandler::WriteExternalImageList( const ExternalImageItemListDescriptor* pExternalImageList ) throw +( SAXException, RuntimeException ) +{ + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_EXTERNALIMAGES )), m_xEmptyList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + + for ( sal_uInt16 i = 0; i < pExternalImageList->Count(); i++ ) + { + ExternalImageItemDescriptor* pItem = (*pExternalImageList)[i]; + WriteExternalImage( pItem ); + } + + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_EXTERNALIMAGES )) ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); +} + +void OWriteImagesDocumentHandler::WriteExternalImage( const ExternalImageItemDescriptor* pExternalImage ) throw +( SAXException, RuntimeException ) +{ + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + Reference< XAttributeList > xList( (XAttributeList *) pList , UNO_QUERY ); + + // save required attributes + pList->AddAttribute( m_aAttributeXlinkType, + m_aAttributeType, + m_aAttributeValueSimple ); + + if ( pExternalImage->aURL.Len() > 0 ) + { + pList->AddAttribute( m_aXMLXlinkNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_HREF )), + m_aAttributeType, + pExternalImage->aURL ); + } + + if ( pExternalImage->aCommandURL.Len() > 0 ) + { + pList->AddAttribute( m_aXMLImageNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_COMMAND )), + m_aAttributeType, + pExternalImage->aCommandURL ); + } + + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_EXTERNALENTRY )), xList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_EXTERNALENTRY )) ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); +} + +} // namespace framework + + + + diff --git a/framework/source/fwe/xml/menuconfiguration.cxx b/framework/source/fwe/xml/menuconfiguration.cxx new file mode 100644 index 000000000000..8a6d2cd1bafd --- /dev/null +++ b/framework/source/fwe/xml/menuconfiguration.cxx @@ -0,0 +1,187 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <framework/menuconfiguration.hxx> + +#ifndef __FRAMEWORK_CLASSES_BMKMENU_HXX_ +#include <framework/bmkmenu.hxx> +#endif +#include <framework/addonmenu.hxx> +#include <xml/menudocumenthandler.hxx> +#include <xml/saxnamespacefilter.hxx> +#include <services.h> + +#ifndef _FRAMEWORK_UIELEMENT_ROOTITEMCONTAINER_HXX_ +#include <uielement/rootitemcontainer.hxx> +#endif + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/frame/XFrame.hpp> + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::io; + +namespace framework +{ + +sal_Bool MenuConfiguration::IsPickListItemId( sal_uInt16 nId ) +{ + return (( START_ITEMID_PICKLIST <= nId ) && ( nId <= END_ITEMID_PICKLIST )); +} + +sal_Bool MenuConfiguration::IsWindowListItemId( sal_uInt16 nId ) +{ + return (( START_ITEMID_WINDOWLIST <= nId ) && ( nId <= END_ITEMID_WINDOWLIST )); +} + + +MenuConfiguration::MenuConfiguration( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rServiceManager ) +: m_rxServiceManager( rServiceManager ) +{ +} + + +MenuConfiguration::~MenuConfiguration() +{ +} + + +Reference< XIndexAccess > MenuConfiguration::CreateMenuBarConfigurationFromXML( + Reference< XInputStream >& rInputStream ) +throw ( WrappedTargetException ) +{ + Reference< XParser > xParser( m_rxServiceManager->createInstance(SERVICENAME_SAXPARSER),UNO_QUERY); + + // connect stream to input stream to the parser + InputSource aInputSource; + + aInputSource.aInputStream = rInputStream; + + + // create menu bar + Reference< XIndexContainer > xItemContainer( static_cast< cppu::OWeakObject *>( new RootItemContainer()), UNO_QUERY ); + + // create namespace filter and set menudocument handler inside to support xml namespaces + + // #110897# Reference< XDocumentHandler > xDocHandler( new OReadMenuDocumentHandler( xItemContainer )); + Reference< XDocumentHandler > xDocHandler( new OReadMenuDocumentHandler( m_rxServiceManager, xItemContainer )); + + Reference< XDocumentHandler > xFilter( new SaxNamespaceFilter( xDocHandler )); + + // connect parser and filter + xParser->setDocumentHandler( xFilter ); + + try + { + xParser->parseStream( aInputSource ); + return Reference< XIndexAccess >( xItemContainer, UNO_QUERY ); + } + catch ( RuntimeException& e ) + { + throw WrappedTargetException( e.Message, Reference< XInterface >(), Any() ); + } + catch( SAXException& e ) + { + SAXException aWrappedSAXException; + + if ( !( e.WrappedException >>= aWrappedSAXException )) + throw WrappedTargetException( e.Message, Reference< XInterface >(), Any() ); + else + throw WrappedTargetException( aWrappedSAXException.Message, Reference< XInterface >(), Any() ); + } + catch( ::com::sun::star::io::IOException& e ) + { + throw WrappedTargetException( e.Message, Reference< XInterface >(), Any() ); + } +} + +PopupMenu* MenuConfiguration::CreateBookmarkMenu( + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame, + const ::rtl::OUString& aURL ) +throw ( ::com::sun::star::lang::WrappedTargetException ) +{ + if ( aURL == BOOKMARK_NEWMENU ) + return new BmkMenu( rFrame, BmkMenu::BMK_NEWMENU ); + else if ( aURL == BOOKMARK_WIZARDMENU ) + return new BmkMenu( rFrame, BmkMenu::BMK_WIZARDMENU ); + else + return NULL; +} + +void MenuConfiguration::StoreMenuBarConfigurationToXML( + Reference< XIndexAccess >& rMenuBarConfiguration, + Reference< XOutputStream >& rOutputStream ) +throw ( WrappedTargetException ) +{ + Reference< XDocumentHandler > xWriter; + + xWriter = Reference< XDocumentHandler >( m_rxServiceManager->createInstance( + SERVICENAME_SAXWRITER), UNO_QUERY) ; + + Reference< XActiveDataSource> xDataSource( xWriter , UNO_QUERY ); + xDataSource->setOutputStream( rOutputStream ); + + try + { + OWriteMenuDocumentHandler aWriteMenuDocumentHandler( rMenuBarConfiguration, xWriter ); + aWriteMenuDocumentHandler.WriteMenuDocument(); + } + catch ( RuntimeException& e ) + { + throw WrappedTargetException( e.Message, Reference< XInterface >(), Any() ); + } + catch ( SAXException& e ) + { + throw WrappedTargetException( e.Message, Reference< XInterface >(), Any() ); + } + catch ( ::com::sun::star::io::IOException& e ) + { + throw WrappedTargetException( e.Message, Reference< XInterface >(), Any() ); + } +} + +} + diff --git a/framework/source/fwe/xml/menudocumenthandler.cxx b/framework/source/fwe/xml/menudocumenthandler.cxx new file mode 100644 index 000000000000..26ec3bf09372 --- /dev/null +++ b/framework/source/fwe/xml/menudocumenthandler.cxx @@ -0,0 +1,1022 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <stdio.h> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include <xml/menudocumenthandler.hxx> +#include <framework/menuconfiguration.hxx> +#include <framework/addonmenu.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ + +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#include <com/sun/star/lang/XSingleComponentFactory.hpp> +#include <com/sun/star/ui/ItemType.hpp> +#include <com/sun/star/ui/ItemStyle.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <comphelper/processfactory.hxx> +#include <rtl/logfile.hxx> +#include <comphelper/attributelist.hxx> + +//_________________________________________________________________________________________________________________ +// defines +//_________________________________________________________________________________________________________________ + +#define XMLNS_MENU "http://openoffice.org/2001/menu" +#define XMLNS_PREFIX "menu:" + +#define ELEMENT_MENUBAR "http://openoffice.org/2001/menu^menubar" +#define ELEMENT_MENU "http://openoffice.org/2001/menu^menu" +#define ELEMENT_MENUPOPUP "http://openoffice.org/2001/menu^menupopup" +#define ELEMENT_MENUITEM "http://openoffice.org/2001/menu^menuitem" +#define ELEMENT_MENUSEPARATOR "http://openoffice.org/2001/menu^menuseparator" + +#define ELEMENT_NS_MENUBAR "menu:menubar" +#define ELEMENT_NS_MENU "menu:menu" +#define ELEMENT_NS_MENUPOPUP "menu:menupopup" +#define ELEMENT_NS_MENUITEM "menu:menuitem" +#define ELEMENT_NS_MENUSEPARATOR "menu:menuseparator" + +#define ATTRIBUTE_ID "http://openoffice.org/2001/menu^id" +#define ATTRIBUTE_LABEL "http://openoffice.org/2001/menu^label" +#define ATTRIBUTE_HELPID "http://openoffice.org/2001/menu^helpid" +#define ATTRIBUTE_LINEBREAK "http://openoffice.org/2001/menu^linebreak" +#define ATTRIBUTE_STYLE "http://openoffice.org/2001/menu^style" + +#define ATTRIBUTE_NS_ID "menu:id" +#define ATTRIBUTE_NS_LABEL "menu:label" +#define ATTRIBUTE_NS_HELPID "menu:helpid" +#define ATTRIBUTE_NS_LINEBREAK "menu:linebreak" +#define ATTRIBUTE_NS_STYLE "menu:style" + +#define ATTRIBUTE_XMLNS_MENU "xmlns:menu" + +#define ATTRIBUTE_TYPE_CDATA "CDATA" + +#define MENUBAR_DOCTYPE "<!DOCTYPE menu:menubar PUBLIC \"-//OpenOffice.org//DTD OfficeDocument 1.0//EN\" \"menubar.dtd\">" + +#define ATTRIBUTE_ITEMSTYLE_TEXT "text" +#define ATTRIBUTE_ITEMSTYLE_IMAGE "image" +#define ATTRIBUTE_ITEMSTYLE_RADIO "radio" + +// Property names of a menu/menu item ItemDescriptor +static const char ITEM_DESCRIPTOR_COMMANDURL[] = "CommandURL"; +static const char ITEM_DESCRIPTOR_HELPURL[] = "HelpURL"; +static const char ITEM_DESCRIPTOR_CONTAINER[] = "ItemDescriptorContainer"; +static const char ITEM_DESCRIPTOR_LABEL[] = "Label"; +static const char ITEM_DESCRIPTOR_TYPE[] = "Type"; +static const char ITEM_DESCRIPTOR_STYLE[] = "Style"; + +// special popup menus (filled during runtime) must be saved as an empty popup menu or menuitem!!! +static const sal_Int32 CMD_PROTOCOL_SIZE = 5; +static const char CMD_PROTOCOL[] = ".uno:"; +static const char ADDDIRECT_CMD[] = ".uno:AddDirect" ; +static const char AUTOPILOTMENU_CMD[] = ".uno:AutoPilotMenu" ; +static const char FILEMENU_CMD[] = ".uno:Picklist" ; +static const char WINDOWMENU_CMD[] = ".uno:WindowList" ; + +//_________________________________________________________________________________________________________________ +// using namespaces +//_________________________________________________________________________________________________________________ + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::ui; + +namespace framework +{ + +struct MenuStyleItem +{ + sal_Int16 nBit; + const char* attrName; +}; + +MenuStyleItem MenuItemStyles[ ] = { + { ::com::sun::star::ui::ItemStyle::ICON, ATTRIBUTE_ITEMSTYLE_IMAGE }, + { ::com::sun::star::ui::ItemStyle::TEXT, ATTRIBUTE_ITEMSTYLE_TEXT }, + { ::com::sun::star::ui::ItemStyle::RADIO_CHECK, ATTRIBUTE_ITEMSTYLE_RADIO } +}; + + +sal_Int32 nMenuStyleItemEntries = sizeof( MenuItemStyles ) / sizeof( MenuItemStyles[ 0 ] ); + +static void ExtractMenuParameters( const Sequence< PropertyValue > rProp, + ::rtl::OUString& rCommandURL, + ::rtl::OUString& rLabel, + ::rtl::OUString& rHelpURL, + Reference< XIndexAccess >& rSubMenu, + sal_Int16& rType, + sal_Int16& rStyle ) +{ + for ( sal_Int32 i = 0; i < rProp.getLength(); i++ ) + { + if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_COMMANDURL )) + { + rProp[i].Value >>= rCommandURL; + rCommandURL = rCommandURL.intern(); + } + else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_HELPURL )) + { + rProp[i].Value >>= rHelpURL; + } + else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_CONTAINER )) + { + rProp[i].Value >>= rSubMenu; + } + else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_LABEL )) + { + rProp[i].Value >>= rLabel; + } + else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_TYPE )) + { + rProp[i].Value >>= rType; + } + else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_STYLE )) + { + rProp[i].Value >>= rStyle; + } + } +} + + +// ----------------------------------------------------------------------------- +// Base class implementation + +ReadMenuDocumentHandlerBase::ReadMenuDocumentHandlerBase() : + m_xLocator( 0 ), + m_xReader( 0 ), + m_aType( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_TYPE )), + m_aLabel( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_LABEL )), + m_aContainer( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_CONTAINER )), + m_aHelpURL( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_HELPURL )), + m_aCommandURL( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_COMMANDURL )), + m_aStyle( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_STYLE )) +{ +} + +ReadMenuDocumentHandlerBase::~ReadMenuDocumentHandlerBase() +{ +} + +void SAL_CALL ReadMenuDocumentHandlerBase::ignorableWhitespace( + const ::rtl::OUString& ) +throw( SAXException, RuntimeException ) +{ +} + +void SAL_CALL ReadMenuDocumentHandlerBase::processingInstruction( + const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/ ) +throw( SAXException, RuntimeException ) +{ +} + +void SAL_CALL ReadMenuDocumentHandlerBase::setDocumentLocator( + const Reference< XLocator > &xLocator) +throw( SAXException, RuntimeException ) +{ + m_xLocator = xLocator; +} + +::rtl::OUString ReadMenuDocumentHandlerBase::getErrorLineString() +{ + char buffer[32]; + + if ( m_xLocator.is() ) + { + snprintf( buffer, sizeof(buffer), "Line: %ld - ", static_cast<long>( m_xLocator->getLineNumber() )); + return ::rtl::OUString::createFromAscii( buffer ); + } + else + return ::rtl::OUString(); +} + +void ReadMenuDocumentHandlerBase::initPropertyCommon( + Sequence< PropertyValue > &rProps, const rtl::OUString &rCommandURL, + const rtl::OUString &rHelpId, const rtl::OUString &rLabel, sal_Int16 nItemStyleBits ) +{ + rProps[0].Name = m_aCommandURL; + rProps[1].Name = m_aHelpURL; + rProps[2].Name = m_aContainer; + rProps[3].Name = m_aLabel; + rProps[4].Name = m_aStyle; + rProps[5].Name = m_aType; + + // Common values + rProps[0].Value <<= rCommandURL.intern(); + rProps[1].Value <<= rHelpId; + rProps[2].Value <<= Reference< XIndexContainer >(); + rProps[3].Value <<= rLabel; + rProps[4].Value <<= nItemStyleBits; + rProps[5].Value <<= ::com::sun::star::ui::ItemType::DEFAULT; +} + +// ----------------------------------------------------------------------------- + +OReadMenuDocumentHandler::OReadMenuDocumentHandler( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory, + const Reference< XIndexContainer >& rMenuBarContainer ) +: m_nElementDepth( 0 ), + m_bMenuBarMode( sal_False ), + m_xMenuBarContainer( rMenuBarContainer ), + m_xContainerFactory( rMenuBarContainer, UNO_QUERY ), + mxServiceFactory(xServiceFactory) +{ +} + +// #110897# +const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& OReadMenuDocumentHandler::getServiceFactory() +{ + // #110897# + return mxServiceFactory; +} + +OReadMenuDocumentHandler::~OReadMenuDocumentHandler() +{ +} + + +void SAL_CALL OReadMenuDocumentHandler::startDocument(void) + throw ( SAXException, RuntimeException ) +{ +} + + +void SAL_CALL OReadMenuDocumentHandler::endDocument(void) + throw( SAXException, RuntimeException ) +{ + if ( m_nElementDepth > 0 ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "A closing element is missing!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } +} + + +void SAL_CALL OReadMenuDocumentHandler::startElement( + const ::rtl::OUString& aName, const Reference< XAttributeList > &xAttrList ) +throw( SAXException, RuntimeException ) +{ + if ( m_bMenuBarMode ) + { + ++m_nElementDepth; + m_xReader->startElement( aName, xAttrList ); + } + else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUBAR ))) + { + ++m_nElementDepth; + m_bMenuBarMode = sal_True; + + // #110897# m_xReader = Reference< XDocumentHandler >( new OReadMenuBarHandler( m_xMenuBarContainer, m_xContainerFactory )); + m_xReader = Reference< XDocumentHandler >( new OReadMenuBarHandler( getServiceFactory(), m_xMenuBarContainer, m_xContainerFactory )); + + m_xReader->startDocument(); + } +} + + +void SAL_CALL OReadMenuDocumentHandler::characters(const rtl::OUString&) +throw( SAXException, RuntimeException ) +{ +} + + +void SAL_CALL OReadMenuDocumentHandler::endElement( const ::rtl::OUString& aName ) + throw( SAXException, RuntimeException ) +{ + if ( m_bMenuBarMode ) + { + --m_nElementDepth; + m_xReader->endElement( aName ); + if ( 0 == m_nElementDepth ) + { + m_xReader->endDocument(); + m_xReader = Reference< XDocumentHandler >(); + m_bMenuBarMode = sal_False; + if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUBAR ))) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menubar expected!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } + } +} + + +// ----------------------------------------------------------------------------- + + +// #110897# +OReadMenuBarHandler::OReadMenuBarHandler( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory, + const Reference< XIndexContainer >& rMenuBarContainer, + const Reference< XSingleComponentFactory >& rFactory ) +: m_nElementDepth( 0 ), + m_bMenuMode( sal_False ), + m_xMenuBarContainer( rMenuBarContainer ), + m_xContainerFactory( rFactory ), + mxServiceFactory( xServiceFactory ) +{ +} + +// #110897# +const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& OReadMenuBarHandler::getServiceFactory() +{ + // #110897# + return mxServiceFactory; +} + +OReadMenuBarHandler::~OReadMenuBarHandler() +{ +} + + +void SAL_CALL OReadMenuBarHandler::startDocument(void) + throw ( SAXException, RuntimeException ) +{ +} + + +void SAL_CALL OReadMenuBarHandler::endDocument(void) + throw( SAXException, RuntimeException ) +{ +} + + +void SAL_CALL OReadMenuBarHandler::startElement( + const ::rtl::OUString& rName, const Reference< XAttributeList > &xAttrList ) +throw( SAXException, RuntimeException ) +{ + if ( m_bMenuMode ) + { + ++m_nElementDepth; + m_xReader->startElement( rName, xAttrList ); + } + else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENU ))) + { + ++m_nElementDepth; + + ::rtl::OUString aHelpId; + ::rtl::OUString aCommandId; + ::rtl::OUString aLabel; + sal_Int16 nItemBits(0); + + m_bMenuMode = sal_True; + + // Container must be factory to create sub container + Reference< XComponentContext > xComponentContext; + Reference< XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY ); + xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= + xComponentContext; + + Reference< XIndexContainer > xSubItemContainer; + if ( m_xContainerFactory.is() ) + xSubItemContainer = Reference< XIndexContainer >( m_xContainerFactory->createInstanceWithContext( xComponentContext ), UNO_QUERY ); + + if ( xSubItemContainer.is() ) + { + // read attributes for menu + for ( sal_Int16 i=0; i< xAttrList->getLength(); i++ ) + { + ::rtl::OUString aName = xAttrList->getNameByIndex( i ); + ::rtl::OUString aValue = xAttrList->getValueByIndex( i ); + if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ID ))) + aCommandId = aValue; + else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_LABEL ))) + aLabel = aValue; + else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_HELPID ))) + aHelpId = aValue; + else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_STYLE ))) + { + ::rtl::OUString aTemp( aValue ); + sal_Int32 nIndex = 0; + do + { + ::rtl::OUString aToken = aTemp.getToken( 0, '+', nIndex ); + if ( aToken.getLength() > 0 ) + { + if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_TEXT ) ) ) + nItemBits |= ::com::sun::star::ui::ItemStyle::TEXT; + else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_IMAGE ) ) ) + nItemBits |= ::com::sun::star::ui::ItemStyle::ICON; + else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_RADIO ) ) ) + nItemBits |= ::com::sun::star::ui::ItemStyle::RADIO_CHECK; + } + } + while ( nIndex >= 0 ); + } + } + + if ( aCommandId.getLength() > 0 ) + { + Sequence< PropertyValue > aSubMenuProp( 6 ); + initPropertyCommon( aSubMenuProp, aCommandId, aHelpId, aLabel, nItemBits ); + aSubMenuProp[2].Value <<= xSubItemContainer; + + m_xMenuBarContainer->insertByIndex( m_xMenuBarContainer->getCount(), makeAny( aSubMenuProp ) ); + } + else + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "attribute id for element menu required!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_xReader = Reference< XDocumentHandler >( new OReadMenuHandler( xSubItemContainer, m_xContainerFactory )); + m_xReader->startDocument(); + } + } + else + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "element menu expected!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } +} + + +void SAL_CALL OReadMenuBarHandler::characters(const rtl::OUString&) +throw( SAXException, RuntimeException ) +{ +} + + +void OReadMenuBarHandler::endElement( const ::rtl::OUString& aName ) + throw( SAXException, RuntimeException ) +{ + if ( m_bMenuMode ) + { + --m_nElementDepth; + if ( 0 == m_nElementDepth ) + { + m_xReader->endDocument(); + m_xReader = Reference< XDocumentHandler >(); + m_bMenuMode = sal_False; + if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENU ))) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menu expected!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } + else + m_xReader->endElement( aName ); + } +} + + +// ----------------------------------------------------------------------------- + + +OReadMenuHandler::OReadMenuHandler( + const Reference< XIndexContainer >& rMenuContainer, + const Reference< XSingleComponentFactory >& rFactory ) : + m_nElementDepth( 0 ), + m_bMenuPopupMode( sal_False ), + m_xMenuContainer( rMenuContainer ), + m_xContainerFactory( rFactory ) +{ +} + + +OReadMenuHandler::~OReadMenuHandler() +{ +} + + +void SAL_CALL OReadMenuHandler::startDocument(void) + throw ( SAXException, RuntimeException ) +{ +} + + +void SAL_CALL OReadMenuHandler::endDocument(void) + throw( SAXException, RuntimeException) +{ +} + + +void SAL_CALL OReadMenuHandler::startElement( + const ::rtl::OUString& aName, const Reference< XAttributeList > &xAttrList ) +throw( SAXException, RuntimeException ) +{ + if ( m_bMenuPopupMode ) + { + ++m_nElementDepth; + m_xReader->startElement( aName, xAttrList ); + } + else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUPOPUP ))) + { + ++m_nElementDepth; + m_bMenuPopupMode = sal_True; + m_xReader = Reference< XDocumentHandler >( new OReadMenuPopupHandler( m_xMenuContainer, m_xContainerFactory )); + m_xReader->startDocument(); + } + else + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "unknown element found!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } +} + + +void SAL_CALL OReadMenuHandler::characters(const rtl::OUString&) +throw( SAXException, RuntimeException ) +{ +} + + +void SAL_CALL OReadMenuHandler::endElement( const ::rtl::OUString& aName ) + throw( SAXException, RuntimeException ) +{ + if ( m_bMenuPopupMode ) + { + --m_nElementDepth; + if ( 0 == m_nElementDepth ) + { + m_xReader->endDocument(); + m_xReader = Reference< XDocumentHandler >(); + m_bMenuPopupMode = sal_False; + if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUPOPUP ))) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menupopup expected!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } + else + m_xReader->endElement( aName ); + } +} + + +// ----------------------------------------------------------------------------- + + +OReadMenuPopupHandler::OReadMenuPopupHandler( + const Reference< XIndexContainer >& rMenuContainer, + const Reference< XSingleComponentFactory >& rFactory ) : + m_nElementDepth( 0 ), + m_bMenuMode( sal_False ), + m_xMenuContainer( rMenuContainer ), + m_xContainerFactory( rFactory ), + m_nNextElementExpected( ELEM_CLOSE_NONE ) +{ +} + + +OReadMenuPopupHandler::~OReadMenuPopupHandler() +{ +} + + +void SAL_CALL OReadMenuPopupHandler::startDocument(void) + throw ( SAXException, RuntimeException ) +{ +} + + +void SAL_CALL OReadMenuPopupHandler::endDocument(void) + throw( SAXException, RuntimeException) +{ +} + +void SAL_CALL OReadMenuPopupHandler::startElement( + const ::rtl::OUString& rName, const Reference< XAttributeList > &xAttrList ) +throw( SAXException, RuntimeException ) +{ + ++m_nElementDepth; + + if ( m_bMenuMode ) + m_xReader->startElement( rName, xAttrList ); + else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENU ))) + { + ::rtl::OUString aHelpId; + ::rtl::OUString aCommandId; + ::rtl::OUString aLabel; + sal_Int16 nItemBits(0); + + m_bMenuMode = sal_True; + + // Container must be factory to create sub container + if ( !m_xComponentContext.is() ) + { + const Reference< XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW ); + m_xComponentContext.set(xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), UNO_QUERY_THROW ); + } + + Reference< XIndexContainer > xSubItemContainer; + if ( m_xContainerFactory.is() ) + xSubItemContainer = Reference< XIndexContainer >( m_xContainerFactory->createInstanceWithContext( m_xComponentContext ), UNO_QUERY ); + + // read attributes for menu + for ( sal_Int16 i=0; i< xAttrList->getLength(); i++ ) + { + ::rtl::OUString aName = xAttrList->getNameByIndex( i ); + ::rtl::OUString aValue = xAttrList->getValueByIndex( i ); + if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ID ))) + aCommandId = aValue; + else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_LABEL ))) + aLabel = aValue; + else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_HELPID ))) + aHelpId = aValue; + else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_STYLE ))) + { + ::rtl::OUString aTemp( aValue ); + sal_Int32 nIndex = 0; + do + { + ::rtl::OUString aToken = aTemp.getToken( 0, '+', nIndex ); + if ( aToken.getLength() > 0 ) + { + if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_TEXT ) ) ) + nItemBits |= ::com::sun::star::ui::ItemStyle::TEXT; + else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_IMAGE ) ) ) + nItemBits |= ::com::sun::star::ui::ItemStyle::ICON; + else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_RADIO ) ) ) + nItemBits |= ::com::sun::star::ui::ItemStyle::RADIO_CHECK; + } + } + while ( nIndex >= 0 ); + } + + } + + if ( aCommandId.getLength() > 0 ) + { + Sequence< PropertyValue > aSubMenuProp( 6 ); + initPropertyCommon( aSubMenuProp, aCommandId, aHelpId, aLabel, nItemBits ); + aSubMenuProp[2].Value <<= xSubItemContainer; + + m_xMenuContainer->insertByIndex( m_xMenuContainer->getCount(), makeAny( aSubMenuProp ) ); + } + else + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "attribute id for element menu required!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_xReader = Reference< XDocumentHandler >( new OReadMenuHandler( xSubItemContainer, m_xContainerFactory )); + m_xReader->startDocument(); + } + else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUITEM ))) + { + ::rtl::OUString aHelpId; + ::rtl::OUString aCommandId; + ::rtl::OUString aLabel; + sal_Int16 nItemBits(0); + // read attributes for menu item + for ( sal_Int16 i=0; i< xAttrList->getLength(); i++ ) + { + ::rtl::OUString aName = xAttrList->getNameByIndex( i ); + ::rtl::OUString aValue = xAttrList->getValueByIndex( i ); + if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ID ))) + aCommandId = aValue; + else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_LABEL ))) + aLabel = aValue; + else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_HELPID ))) + aHelpId = aValue; + else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_STYLE ))) + { + ::rtl::OUString aTemp( aValue ); + sal_Int32 nIndex = 0; + do + { + ::rtl::OUString aToken = aTemp.getToken( 0, '+', nIndex ); + if ( aToken.getLength() > 0 ) + { + if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_TEXT ) ) ) + nItemBits |= ::com::sun::star::ui::ItemStyle::TEXT; + else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_IMAGE ) ) ) + nItemBits |= ::com::sun::star::ui::ItemStyle::ICON; + else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_RADIO ) ) ) + nItemBits |= ::com::sun::star::ui::ItemStyle::RADIO_CHECK; + } + } + while ( nIndex >= 0 ); + } + + } + + if ( aCommandId.getLength() > 0 ) + { + Sequence< PropertyValue > aMenuItem( 6 ); + initPropertyCommon( aMenuItem, aCommandId, aHelpId, aLabel, nItemBits ); + aMenuItem[2].Value <<= Reference< XIndexContainer >(); + + m_xMenuContainer->insertByIndex( m_xMenuContainer->getCount(), makeAny( aMenuItem ) ); + } + + m_nNextElementExpected = ELEM_CLOSE_MENUITEM; + } + else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUSEPARATOR ))) + { + Sequence< PropertyValue > aMenuSeparator( 1 ); + aMenuSeparator[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_TYPE )); + aMenuSeparator[0].Value <<= ::com::sun::star::ui::ItemType::SEPARATOR_LINE; + + m_xMenuContainer->insertByIndex( m_xMenuContainer->getCount(), makeAny( aMenuSeparator ) ); + + m_nNextElementExpected = ELEM_CLOSE_MENUSEPARATOR; + } + else + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "unknown element found!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } +} + + +void SAL_CALL OReadMenuPopupHandler::characters(const rtl::OUString&) +throw( SAXException, RuntimeException ) +{ +} + + +void SAL_CALL OReadMenuPopupHandler::endElement( const ::rtl::OUString& aName ) + throw( SAXException, RuntimeException ) +{ + --m_nElementDepth; + if ( m_bMenuMode ) + { + if ( 0 == m_nElementDepth ) + { + m_xReader->endDocument(); + m_xReader = Reference< XDocumentHandler >(); + m_bMenuMode = sal_False; + if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENU ))) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menu expected!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } + else + m_xReader->endElement( aName ); + } + else + { + if ( m_nNextElementExpected == ELEM_CLOSE_MENUITEM ) + { + if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUITEM ))) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menuitem expected!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } + else if ( m_nNextElementExpected == ELEM_CLOSE_MENUSEPARATOR ) + { + if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUSEPARATOR ))) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menuseparator expected!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } + + m_nNextElementExpected = ELEM_CLOSE_NONE; + } +} + + +// --------------------------------- Write XML --------------------------------- + + +OWriteMenuDocumentHandler::OWriteMenuDocumentHandler( + const Reference< XIndexAccess >& rMenuBarContainer, + const Reference< XDocumentHandler >& rDocumentHandler ) : + m_xMenuBarContainer( rMenuBarContainer ), + m_xWriteDocumentHandler( rDocumentHandler ) +{ + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + m_xEmptyList = Reference< XAttributeList >( (XAttributeList *) pList, UNO_QUERY ); + m_aAttributeType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TYPE_CDATA )); +} + + +OWriteMenuDocumentHandler::~OWriteMenuDocumentHandler() +{ +} + + +void OWriteMenuDocumentHandler::WriteMenuDocument() +throw ( SAXException, RuntimeException ) +{ + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + Reference< XAttributeList > rList( (XAttributeList *) pList , UNO_QUERY ); + + m_xWriteDocumentHandler->startDocument(); + + // write DOCTYPE line! + Reference< XExtendedDocumentHandler > xExtendedDocHandler( m_xWriteDocumentHandler, UNO_QUERY ); + if ( xExtendedDocHandler.is() ) + { + xExtendedDocHandler->unknown( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( MENUBAR_DOCTYPE )) ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + } + + pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XMLNS_MENU )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_MENU )) ); + + pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_ID )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "menubar" )) ); + + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUBAR )), pList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + + WriteMenu( m_xMenuBarContainer ); + + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUBAR )) ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endDocument(); +} + + +void OWriteMenuDocumentHandler::WriteMenu( const Reference< XIndexAccess >& rMenuContainer ) +throw ( SAXException, RuntimeException ) +{ + sal_Int32 nItemCount = rMenuContainer->getCount(); + sal_Bool bSeparator = sal_False; + Any aAny; + + for ( sal_Int32 nItemPos = 0; nItemPos < nItemCount; nItemPos++ ) + { + Sequence< PropertyValue > aProps; + aAny = rMenuContainer->getByIndex( nItemPos ); + if ( aAny >>= aProps ) + { + ::rtl::OUString aCommandURL; + ::rtl::OUString aLabel; + ::rtl::OUString aHelpURL; + sal_Int16 nType( ::com::sun::star::ui::ItemType::DEFAULT ); + sal_Int16 nItemBits( 0 ); + Reference< XIndexAccess > xSubMenu; + + ExtractMenuParameters( aProps, aCommandURL, aLabel, aHelpURL, xSubMenu, nType, nItemBits ); + if ( xSubMenu.is() ) + { + if ( aCommandURL.equalsAscii( ADDDIRECT_CMD ) || + aCommandURL.equalsAscii( AUTOPILOTMENU_CMD )) + { + WriteMenuItem( aCommandURL, aLabel, aHelpURL, nItemBits ); + bSeparator = sal_False; + } + else if (( aCommandURL.getLength() > 0 ) && !AddonPopupMenu::IsCommandURLPrefix ( aCommandURL )) + { + ::comphelper::AttributeList* pListMenu = new ::comphelper::AttributeList; + Reference< XAttributeList > xListMenu( (XAttributeList *)pListMenu , UNO_QUERY ); + + pListMenu->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_ID )), + m_aAttributeType, + aCommandURL ); + + if ( !( aCommandURL.copy( CMD_PROTOCOL_SIZE ).equalsAscii( CMD_PROTOCOL ))) + pListMenu->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_LABEL )), + m_aAttributeType, + aLabel ); + + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENU )), xListMenu ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUPOPUP )), m_xEmptyList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + + WriteMenu( xSubMenu ); + + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUPOPUP )) ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENU )) ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + bSeparator = sal_False; + } + } + else + { + if ( nType == ::com::sun::star::ui::ItemType::DEFAULT ) + { + if ( aCommandURL.getLength() > 0 ) + { + bSeparator = sal_False; + WriteMenuItem( aCommandURL, aLabel, aHelpURL, nItemBits ); + } + } + else if ( !bSeparator ) + { + // Don't write two separators together + WriteMenuSeparator(); + bSeparator = sal_True; + } + } + } + } +} + + +void OWriteMenuDocumentHandler::WriteMenuItem( const ::rtl::OUString& aCommandURL, const ::rtl::OUString& aLabel, const ::rtl::OUString& aHelpURL, sal_Int16 nStyle ) +{ + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + Reference< XAttributeList > xList( (XAttributeList *) pList , UNO_QUERY ); + + pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_ID )), + m_aAttributeType, + aCommandURL ); + + if ( aHelpURL.getLength() > 0 ) + { + pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_HELPID )), + m_aAttributeType, + aHelpURL ); + } + + if (( aLabel.getLength() > 0 ) && !( aCommandURL.copy( CMD_PROTOCOL_SIZE ).equalsAscii( CMD_PROTOCOL ))) + { + pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_LABEL )), + m_aAttributeType, + aLabel ); + } + if (( nStyle > 0 ) && !( aCommandURL.copy( CMD_PROTOCOL_SIZE ).equalsAscii( CMD_PROTOCOL ))) + { + rtl::OUString aValue; + MenuStyleItem* pStyle = MenuItemStyles; + + for ( sal_Int32 nIndex = 0; nIndex < nMenuStyleItemEntries; ++nIndex, ++pStyle ) + { + if ( nStyle & pStyle->nBit ) + { + if ( aValue.getLength() ) + aValue = aValue.concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("+") ) ); + aValue += rtl::OUString::createFromAscii( pStyle->attrName ); + } + } + pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_STYLE )), + m_aAttributeType, + aValue ); + } + + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUITEM )), xList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUITEM )) ); +} + + +void OWriteMenuDocumentHandler::WriteMenuSeparator() +{ + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUSEPARATOR )), m_xEmptyList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUSEPARATOR )) ); +} + +} // namespace framework + diff --git a/framework/source/fwe/xml/saxnamespacefilter.cxx b/framework/source/fwe/xml/saxnamespacefilter.cxx new file mode 100644 index 000000000000..a92c58547e06 --- /dev/null +++ b/framework/source/fwe/xml/saxnamespacefilter.cxx @@ -0,0 +1,198 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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" + +/** Attention: stl headers must(!) be included at first. Otherwhise it can make trouble + with solaris headers ... +*/ +#include <vector> + +#include <stdio.h> + +#include <xml/saxnamespacefilter.hxx> + +#include <comphelper/attributelist.hxx> + +#include <vcl/svapp.hxx> +#include <rtl/logfile.hxx> + +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::uno; + +const ::rtl::OUString aXMLAttributeNamespace( RTL_CONSTASCII_USTRINGPARAM( "xmlns" )); +const ::rtl::OUString aXMLAttributeType( RTL_CONSTASCII_USTRINGPARAM( "CDATA" )); + +namespace framework{ + + +SaxNamespaceFilter::SaxNamespaceFilter( Reference< XDocumentHandler >& rSax1DocumentHandler ) : + ThreadHelpBase( &Application::GetSolarMutex() ), + m_xLocator( 0 ), + xDocumentHandler( rSax1DocumentHandler ), + m_nDepth( 0 ) +{ +} + +SaxNamespaceFilter::~SaxNamespaceFilter() +{ +} + +// XDocumentHandler +void SAL_CALL SaxNamespaceFilter::startDocument(void) + throw ( SAXException, RuntimeException ) +{ +} + +void SAL_CALL SaxNamespaceFilter::endDocument(void) + throw( SAXException, RuntimeException ) +{ +} + +void SAL_CALL SaxNamespaceFilter::startElement( + const rtl::OUString& rName, const Reference< XAttributeList > &xAttribs ) + throw( SAXException, RuntimeException ) +{ + XMLNamespaces aXMLNamespaces; + if ( !m_aNamespaceStack.empty() ) + aXMLNamespaces = m_aNamespaceStack.top(); + + ::comphelper::AttributeList* pNewList = new ::comphelper::AttributeList(); + + // examine all namespaces for this level + ::std::vector< sal_Int16 > aAttributeIndexes; + { + for ( sal_Int16 i=0; i< xAttribs->getLength(); i++ ) + { + ::rtl::OUString aName = xAttribs->getNameByIndex( i ); + if ( aName.compareTo( aXMLAttributeNamespace, aXMLAttributeNamespace.getLength() ) == 0 ) + aXMLNamespaces.addNamespace( aName, xAttribs->getValueByIndex( i )); + else + aAttributeIndexes.push_back( i ); + } + } + + // current namespaces for this level + m_aNamespaceStack.push( aXMLNamespaces ); + + try + { + // apply namespaces to all remaing attributes + for ( ::std::vector< sal_Int16 >::const_iterator i( + aAttributeIndexes.begin()); + i != aAttributeIndexes.end(); ++i ) + { + ::rtl::OUString aAttributeName = xAttribs->getNameByIndex( *i ); + ::rtl::OUString aValue = xAttribs->getValueByIndex( *i ); + ::rtl::OUString aNamespaceAttributeName = aXMLNamespaces.applyNSToAttributeName( aAttributeName ); + pNewList->AddAttribute( aNamespaceAttributeName, aXMLAttributeType, aValue ); + } + } + catch ( SAXException& e ) + { + e.Message = ::rtl::OUString( getErrorLineString() + e.Message ); + throw e; + } + + ::rtl::OUString aNamespaceElementName; + + try + { + aNamespaceElementName = aXMLNamespaces.applyNSToElementName( rName ); + } + catch ( SAXException& e ) + { + e.Message = ::rtl::OUString( getErrorLineString() + e.Message ); + throw e; + } + + xDocumentHandler->startElement( aNamespaceElementName, pNewList ); +} + +void SAL_CALL SaxNamespaceFilter::endElement(const rtl::OUString& aName) + throw( SAXException, RuntimeException ) +{ + XMLNamespaces& aXMLNamespaces = m_aNamespaceStack.top(); + ::rtl::OUString aNamespaceElementName; + + try + { + aNamespaceElementName = aXMLNamespaces.applyNSToElementName( aName ); + } + catch ( SAXException& e ) + { + e.Message = ::rtl::OUString( getErrorLineString() + e.Message ); + throw e; + } + + xDocumentHandler->endElement( aNamespaceElementName ); + m_aNamespaceStack.pop(); +} + +void SAL_CALL SaxNamespaceFilter::characters(const rtl::OUString& aChars) + throw( SAXException, RuntimeException ) +{ + xDocumentHandler->characters( aChars ); +} + +void SAL_CALL SaxNamespaceFilter::ignorableWhitespace(const rtl::OUString& aWhitespaces) + throw( SAXException, RuntimeException ) +{ + xDocumentHandler->ignorableWhitespace( aWhitespaces ); +} + +void SAL_CALL SaxNamespaceFilter::processingInstruction( + const rtl::OUString& aTarget, const rtl::OUString& aData) + throw( SAXException, RuntimeException ) +{ + xDocumentHandler->processingInstruction( aTarget, aData ); +} + +void SAL_CALL SaxNamespaceFilter::setDocumentLocator( + const Reference< XLocator > &xLocator) + throw( SAXException, RuntimeException ) +{ + m_xLocator = xLocator; + xDocumentHandler->setDocumentLocator( xLocator ); +} + +::rtl::OUString SaxNamespaceFilter::getErrorLineString() +{ + char buffer[32]; + + if ( m_xLocator.is() ) + { + snprintf( buffer, sizeof(buffer), "Line: %ld - ", static_cast<long>( m_xLocator->getLineNumber() )); + return ::rtl::OUString::createFromAscii( buffer ); + } + else + return ::rtl::OUString(); +} + +} // namespace + diff --git a/framework/source/fwe/xml/statusbarconfiguration.cxx b/framework/source/fwe/xml/statusbarconfiguration.cxx new file mode 100644 index 000000000000..0d79ef8fd461 --- /dev/null +++ b/framework/source/fwe/xml/statusbarconfiguration.cxx @@ -0,0 +1,166 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <framework/statusbarconfiguration.hxx> +#include <xml/statusbardocumenthandler.hxx> +#include <xml/saxnamespacefilter.hxx> +#include <services.h> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#ifndef _UNOTOOLS_PROCESSFACTORY_HXX +#include <comphelper/processfactory.hxx> +#endif +#include <unotools/streamwrap.hxx> +#include <tools/debug.hxx> + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::container; + + +namespace framework +{ + +SV_IMPL_PTRARR( StatusBarDescriptor, StatusBarItemDescriptorPtr); + +static Reference< XParser > GetSaxParser( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory + ) +{ + return Reference< XParser >( xServiceFactory->createInstance( SERVICENAME_SAXPARSER), UNO_QUERY); +} + +static Reference< XDocumentHandler > GetSaxWriter( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory + ) +{ + return Reference< XDocumentHandler >( xServiceFactory->createInstance( SERVICENAME_SAXWRITER), UNO_QUERY) ; +} + +sal_Bool StatusBarConfiguration::LoadStatusBar( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&, + SvStream&, StatusBarDescriptor& ) +{ + // obsolete - only support linkage of binary filters! + return sal_True; +} + +sal_Bool StatusBarConfiguration::StoreStatusBar( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&, + SvStream&, const StatusBarDescriptor& ) +{ + // obsolete - only support linkage of binary filters! + return sal_True; +} + +sal_Bool StatusBarConfiguration::LoadStatusBar( + const Reference< XMultiServiceFactory >& xServiceFactory, + const Reference< XInputStream >& xInputStream, + const Reference< XIndexContainer >& rStatusbarConfiguration ) +{ + Reference< XParser > xParser( GetSaxParser( xServiceFactory ) ); + + // connect stream to input stream to the parser + InputSource aInputSource; + aInputSource.aInputStream = xInputStream; + + // create namespace filter and set menudocument handler inside to support xml namespaces + Reference< XDocumentHandler > xDocHandler( new OReadStatusBarDocumentHandler( rStatusbarConfiguration )); + Reference< XDocumentHandler > xFilter( new SaxNamespaceFilter( xDocHandler )); + + // connect parser and filter + xParser->setDocumentHandler( xFilter ); + + try + { + xParser->parseStream( aInputSource ); + return sal_True; + } + catch ( RuntimeException& ) + { + return sal_False; + } + catch( SAXException& ) + { + return sal_False; + } + catch( ::com::sun::star::io::IOException& ) + { + return sal_False; + } +} + +sal_Bool StatusBarConfiguration::StoreStatusBar( + const Reference< XMultiServiceFactory >& xServiceFactory, + const Reference< XOutputStream >& xOutputStream, + const Reference< XIndexAccess >& rStatusbarConfiguration ) +{ + Reference< XDocumentHandler > xWriter( GetSaxWriter( xServiceFactory ) ); + Reference< ::com::sun::star::io::XActiveDataSource> xDataSource( xWriter , UNO_QUERY ); + xDataSource->setOutputStream( xOutputStream ); + + try + { + OWriteStatusBarDocumentHandler aWriteStatusBarDocumentHandler( rStatusbarConfiguration, xWriter ); + aWriteStatusBarDocumentHandler.WriteStatusBarDocument(); + return sal_True; + } + catch ( RuntimeException& ) + { + return sal_False; + } + catch ( SAXException& ) + { + return sal_False; + } + catch ( ::com::sun::star::io::IOException& ) + { + return sal_False; + } +} +} + diff --git a/framework/source/fwe/xml/statusbardocumenthandler.cxx b/framework/source/fwe/xml/statusbardocumenthandler.cxx new file mode 100644 index 000000000000..3d8d4bfc7c9a --- /dev/null +++ b/framework/source/fwe/xml/statusbardocumenthandler.cxx @@ -0,0 +1,698 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <stdio.h> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + +#include <threadhelp/resetableguard.hxx> +#include <xml/statusbardocumenthandler.hxx> +#include <macros/debug.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ + +#ifndef __COM_SUN_STAR_XML_SAX_XEXTENDEDDOCUMENTHANDLER_HPP_ +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#endif +#include <com/sun/star/ui/ItemStyle.hpp> +#include <com/sun/star/ui/ItemType.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <vcl/svapp.hxx> +#include <vcl/status.hxx> + +#include <comphelper/attributelist.hxx> + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::ui; +using namespace ::com::sun::star::container; + +#define XMLNS_STATUSBAR "http://openoffice.org/2001/statusbar" +#define XMLNS_XLINK "http://www.w3.org/1999/xlink" +#define XMLNS_STATUSBAR_PREFIX "statusbar:" +#define XMLNS_XLINK_PREFIX "xlink:" + +#define XMLNS_FILTER_SEPARATOR "^" + +#define ELEMENT_STATUSBAR "statusbar" +#define ELEMENT_STATUSBARITEM "statusbaritem" + +#define ATTRIBUTE_ALIGN "align" +#define ATTRIBUTE_STYLE "style" +#define ATTRIBUTE_URL "href" +#define ATTRIBUTE_WIDTH "width" +#define ATTRIBUTE_OFFSET "offset" +#define ATTRIBUTE_AUTOSIZE "autosize" +#define ATTRIBUTE_OWNERDRAW "ownerdraw" +#define ATTRIBUTE_HELPURL "helpid" + +#define ELEMENT_NS_STATUSBAR "statusbar:statusbar" +#define ELEMENT_NS_STATUSBARITEM "statusbar:statusbaritem" + +#define ATTRIBUTE_XMLNS_STATUSBAR "xmlns:statusbar" +#define ATTRIBUTE_XMLNS_XLINK "xmlns:xlink" + +#define ATTRIBUTE_TYPE_CDATA "CDATA" + +#define ATTRIBUTE_BOOLEAN_TRUE "true" +#define ATTRIBUTE_BOOLEAN_FALSE "false" + +#define ATTRIBUTE_ALIGN_LEFT "left" +#define ATTRIBUTE_ALIGN_RIGHT "right" +#define ATTRIBUTE_ALIGN_CENTER "center" + +#define ATTRIBUTE_STYLE_IN "in" +#define ATTRIBUTE_STYLE_OUT "out" +#define ATTRIBUTE_STYLE_FLAT "flat" + +#define STATUSBAR_DOCTYPE "<!DOCTYPE statusbar:statusbar PUBLIC \"-//OpenOffice.org//DTD OfficeDocument 1.0//EN\" \"statusbar.dtd\">" + +namespace framework +{ + +// Property names of a menu/menu item ItemDescriptor +static const char ITEM_DESCRIPTOR_COMMANDURL[] = "CommandURL"; +static const char ITEM_DESCRIPTOR_HELPURL[] = "HelpURL"; +static const char ITEM_DESCRIPTOR_OFFSET[] = "Offset"; +static const char ITEM_DESCRIPTOR_STYLE[] = "Style"; +static const char ITEM_DESCRIPTOR_WIDTH[] = "Width"; +static const char ITEM_DESCRIPTOR_TYPE[] = "Type"; + +static void ExtractStatusbarItemParameters( + const Sequence< PropertyValue > rProp, + ::rtl::OUString& rCommandURL, + ::rtl::OUString& rHelpURL, + sal_Int16& rOffset, + sal_Int16& rStyle, + sal_Int16& rWidth ) +{ + for ( sal_Int32 i = 0; i < rProp.getLength(); i++ ) + { + if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_COMMANDURL )) + { + rProp[i].Value >>= rCommandURL; + rCommandURL = rCommandURL.intern(); + } + else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_HELPURL )) + { + rProp[i].Value >>= rHelpURL; + } + else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_OFFSET )) + { + rProp[i].Value >>= rOffset; + } + else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_STYLE )) + { + rProp[i].Value >>= rStyle; + } + else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_WIDTH )) + { + rProp[i].Value >>= rWidth; + } + } +} + +struct StatusBarEntryProperty +{ + OReadStatusBarDocumentHandler::StatusBar_XML_Namespace nNamespace; + char aEntryName[20]; +}; + +StatusBarEntryProperty StatusBarEntries[OReadStatusBarDocumentHandler::SB_XML_ENTRY_COUNT] = +{ + { OReadStatusBarDocumentHandler::SB_NS_STATUSBAR, ELEMENT_STATUSBAR }, + { OReadStatusBarDocumentHandler::SB_NS_STATUSBAR, ELEMENT_STATUSBARITEM }, + { OReadStatusBarDocumentHandler::SB_NS_XLINK, ATTRIBUTE_URL }, + { OReadStatusBarDocumentHandler::SB_NS_STATUSBAR, ATTRIBUTE_ALIGN }, + { OReadStatusBarDocumentHandler::SB_NS_STATUSBAR, ATTRIBUTE_STYLE }, + { OReadStatusBarDocumentHandler::SB_NS_STATUSBAR, ATTRIBUTE_AUTOSIZE }, + { OReadStatusBarDocumentHandler::SB_NS_STATUSBAR, ATTRIBUTE_OWNERDRAW }, + { OReadStatusBarDocumentHandler::SB_NS_STATUSBAR, ATTRIBUTE_WIDTH }, + { OReadStatusBarDocumentHandler::SB_NS_STATUSBAR, ATTRIBUTE_OFFSET }, + { OReadStatusBarDocumentHandler::SB_NS_STATUSBAR, ATTRIBUTE_HELPURL } +}; + + +OReadStatusBarDocumentHandler::OReadStatusBarDocumentHandler( + const Reference< XIndexContainer >& rStatusBarItems ) : + ThreadHelpBase( &Application::GetSolarMutex() ), + m_aStatusBarItems( rStatusBarItems ) +{ + ::rtl::OUString aNamespaceStatusBar( RTL_CONSTASCII_USTRINGPARAM( XMLNS_STATUSBAR )); + ::rtl::OUString aNamespaceXLink( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK )); + ::rtl::OUString aSeparator( RTL_CONSTASCII_USTRINGPARAM( XMLNS_FILTER_SEPARATOR )); + + // create hash map + for ( int i = 0; i < (int)SB_XML_ENTRY_COUNT; i++ ) + { + if ( StatusBarEntries[i].nNamespace == SB_NS_STATUSBAR ) + { + ::rtl::OUString temp( aNamespaceStatusBar ); + temp += aSeparator; + temp += ::rtl::OUString::createFromAscii( StatusBarEntries[i].aEntryName ); + m_aStatusBarMap.insert( StatusBarHashMap::value_type( temp, (StatusBar_XML_Entry)i ) ); + } + else + { + ::rtl::OUString temp( aNamespaceXLink ); + temp += aSeparator; + temp += ::rtl::OUString::createFromAscii( StatusBarEntries[i].aEntryName ); + m_aStatusBarMap.insert( StatusBarHashMap::value_type( temp, (StatusBar_XML_Entry)i ) ); + } + } + + m_bStatusBarStartFound = sal_False; + m_bStatusBarEndFound = sal_False; + m_bStatusBarItemStartFound = sal_False; +} + +OReadStatusBarDocumentHandler::~OReadStatusBarDocumentHandler() +{ +} + +// XDocumentHandler +void SAL_CALL OReadStatusBarDocumentHandler::startDocument(void) +throw ( SAXException, RuntimeException ) +{ +} + +void SAL_CALL OReadStatusBarDocumentHandler::endDocument(void) +throw( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + if (( m_bStatusBarStartFound && !m_bStatusBarEndFound ) || + ( !m_bStatusBarStartFound && m_bStatusBarEndFound ) ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No matching start or end element 'statusbar' found!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } +} + +void SAL_CALL OReadStatusBarDocumentHandler::startElement( + const ::rtl::OUString& aName, const Reference< XAttributeList > &xAttribs ) +throw( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + StatusBarHashMap::const_iterator pStatusBarEntry = m_aStatusBarMap.find( aName ) ; + if ( pStatusBarEntry != m_aStatusBarMap.end() ) + { + switch ( pStatusBarEntry->second ) + { + case SB_ELEMENT_STATUSBAR: + { + if ( m_bStatusBarStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'statusbar:statusbar' cannot be embeded into 'statusbar:statusbar'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bStatusBarStartFound = sal_True; + } + break; + + case SB_ELEMENT_STATUSBARITEM: + { + if ( !m_bStatusBarStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'statusbar:statusbaritem' must be embeded into element 'statusbar:statusbar'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + if ( m_bStatusBarItemStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element statusbar:statusbaritem is not a container!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + ::rtl::OUString aCommandURL; + ::rtl::OUString aHelpURL; + sal_Int16 nItemBits( ItemStyle::ALIGN_CENTER|ItemStyle::DRAW_IN3D ); + sal_Int16 nWidth( 0 ); + sal_Int16 nOffset( STATUSBAR_OFFSET ); + sal_Bool bCommandURL( sal_False ); + + m_bStatusBarItemStartFound = sal_True; + for ( sal_Int16 n = 0; n < xAttribs->getLength(); n++ ) + { + pStatusBarEntry = m_aStatusBarMap.find( xAttribs->getNameByIndex( n ) ); + if ( pStatusBarEntry != m_aStatusBarMap.end() ) + { + switch ( pStatusBarEntry->second ) + { + case SB_ATTRIBUTE_URL: + { + bCommandURL = sal_True; + aCommandURL = xAttribs->getValueByIndex( n ); + } + break; + + case SB_ATTRIBUTE_ALIGN: + { + if ( xAttribs->getValueByIndex( n ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ALIGN_LEFT )) ) + { + nItemBits |= ItemStyle::ALIGN_LEFT; + nItemBits &= ~ItemStyle::ALIGN_CENTER; + } + else if ( xAttribs->getValueByIndex( n ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ALIGN_CENTER )) ) + { + nItemBits |= ItemStyle::ALIGN_CENTER; + nItemBits &= ~ItemStyle::ALIGN_LEFT; + } + else if ( xAttribs->getValueByIndex( n ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ALIGN_RIGHT )) ) + { + nItemBits |= ItemStyle::ALIGN_RIGHT; + } + else + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Attribute statusbar:align must have one value of 'left','right' or 'center'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } + break; + + case SB_ATTRIBUTE_STYLE: + { + if ( xAttribs->getValueByIndex( n ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_STYLE_IN )) ) + { + nItemBits |= ItemStyle::DRAW_IN3D; + nItemBits &= ~ItemStyle::DRAW_OUT3D; + } + else if ( xAttribs->getValueByIndex( n ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_STYLE_OUT )) ) + { + nItemBits |= ItemStyle::DRAW_OUT3D; + nItemBits &= ~ItemStyle::DRAW_IN3D; + } + else if ( xAttribs->getValueByIndex( n ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_STYLE_FLAT )) ) + { + nItemBits |= ItemStyle::DRAW_FLAT; + } + else + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Attribute statusbar:autosize must have value 'true' or 'false'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } + break; + + case SB_ATTRIBUTE_AUTOSIZE: + { + if ( xAttribs->getValueByIndex( n ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_BOOLEAN_TRUE )) ) + nItemBits |= ItemStyle::AUTO_SIZE; + else if ( xAttribs->getValueByIndex( n ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_BOOLEAN_FALSE )) ) + nItemBits &= ~ItemStyle::AUTO_SIZE; + else + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Attribute statusbar:autosize must have value 'true' or 'false'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } + break; + + case SB_ATTRIBUTE_OWNERDRAW: + { + if ( xAttribs->getValueByIndex( n ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_BOOLEAN_TRUE )) ) + nItemBits |= ItemStyle::OWNER_DRAW; + else if ( xAttribs->getValueByIndex( n ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_BOOLEAN_FALSE )) ) + nItemBits &= ~ItemStyle::OWNER_DRAW; + else + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Attribute statusbar:ownerdraw must have value 'true' or 'false'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } + break; + + case SB_ATTRIBUTE_WIDTH: + { + nWidth = (sal_Int16)(xAttribs->getValueByIndex( n ).toInt32()); + } + break; + + case SB_ATTRIBUTE_OFFSET: + { + nOffset = (sal_Int16)(xAttribs->getValueByIndex( n ).toInt32()); + } + break; + + case SB_ATTRIBUTE_HELPURL: + { + aHelpURL = xAttribs->getValueByIndex( n ); + } + break; + + default: + break; + } + } + } // for + + if ( !bCommandURL ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Required attribute statusbar:url must have a value!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + else + { + Sequence< PropertyValue > aStatusbarItemProp( 6 ); + aStatusbarItemProp[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_COMMANDURL )); + aStatusbarItemProp[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_HELPURL )); + aStatusbarItemProp[2].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_OFFSET )); + aStatusbarItemProp[3].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_STYLE )); + aStatusbarItemProp[4].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_WIDTH )); + aStatusbarItemProp[5].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_TYPE )); + + aStatusbarItemProp[0].Value <<= aCommandURL; + aStatusbarItemProp[1].Value <<= aHelpURL; + aStatusbarItemProp[2].Value <<= nOffset; + aStatusbarItemProp[3].Value <<= nItemBits; + aStatusbarItemProp[4].Value <<= nWidth; + aStatusbarItemProp[5].Value = makeAny( ::com::sun::star::ui::ItemType::DEFAULT ); + + m_aStatusBarItems->insertByIndex( m_aStatusBarItems->getCount(), makeAny( aStatusbarItemProp ) ); + } + } + break; + + default: + break; + } + } +} + +void SAL_CALL OReadStatusBarDocumentHandler::endElement(const ::rtl::OUString& aName) +throw( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + StatusBarHashMap::const_iterator pStatusBarEntry = m_aStatusBarMap.find( aName ) ; + if ( pStatusBarEntry != m_aStatusBarMap.end() ) + { + switch ( pStatusBarEntry->second ) + { + case SB_ELEMENT_STATUSBAR: + { + if ( !m_bStatusBarStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "End element 'statusbar' found, but no start element 'statusbar'" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bStatusBarStartFound = sal_False; + } + break; + + case SB_ELEMENT_STATUSBARITEM: + { + if ( !m_bStatusBarItemStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "End element 'statusbar:statusbaritem' found, but no start element 'statusbar:statusbaritem'" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bStatusBarItemStartFound = sal_False; + } + break; + + default: + break; + } + } +} + +void SAL_CALL OReadStatusBarDocumentHandler::characters(const ::rtl::OUString&) +throw( SAXException, RuntimeException ) +{ +} + +void SAL_CALL OReadStatusBarDocumentHandler::ignorableWhitespace(const ::rtl::OUString&) +throw( SAXException, RuntimeException ) +{ +} + +void SAL_CALL OReadStatusBarDocumentHandler::processingInstruction( + const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/ ) +throw( SAXException, RuntimeException ) +{ +} + +void SAL_CALL OReadStatusBarDocumentHandler::setDocumentLocator( + const Reference< XLocator > &xLocator) +throw( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + m_xLocator = xLocator; +} + +::rtl::OUString OReadStatusBarDocumentHandler::getErrorLineString() +{ + ResetableGuard aGuard( m_aLock ); + + char buffer[32]; + + if ( m_xLocator.is() ) + { + snprintf( buffer, sizeof(buffer), "Line: %ld - ", static_cast<long>( m_xLocator->getLineNumber() )); + return ::rtl::OUString::createFromAscii( buffer ); + } + else + return ::rtl::OUString(); +} + + +//_________________________________________________________________________________________________________________ +// OWriteStatusBarDocumentHandler +//_________________________________________________________________________________________________________________ + +OWriteStatusBarDocumentHandler::OWriteStatusBarDocumentHandler( + const Reference< XIndexAccess >& aStatusBarItems, + const Reference< XDocumentHandler >& rWriteDocumentHandler ) : + ThreadHelpBase( &Application::GetSolarMutex() ), + m_aStatusBarItems( aStatusBarItems ), + m_xWriteDocumentHandler( rWriteDocumentHandler ) +{ + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + m_xEmptyList = Reference< XAttributeList >( (XAttributeList *) pList, UNO_QUERY ); + m_aAttributeType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TYPE_CDATA )); + m_aXMLXlinkNS = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK_PREFIX )); + m_aXMLStatusBarNS = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_STATUSBAR_PREFIX )); +} + +OWriteStatusBarDocumentHandler::~OWriteStatusBarDocumentHandler() +{ +} + +void OWriteStatusBarDocumentHandler::WriteStatusBarDocument() throw +( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + m_xWriteDocumentHandler->startDocument(); + + // write DOCTYPE line! + Reference< XExtendedDocumentHandler > xExtendedDocHandler( m_xWriteDocumentHandler, UNO_QUERY ); + if ( xExtendedDocHandler.is() ) + { + xExtendedDocHandler->unknown( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STATUSBAR_DOCTYPE )) ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + } + + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + Reference< XAttributeList > xList( (XAttributeList *) pList , UNO_QUERY ); + + pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XMLNS_STATUSBAR )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_STATUSBAR )) ); + + pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XMLNS_XLINK )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK )) ); + + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_STATUSBAR )), pList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + + sal_Int32 nItemCount = m_aStatusBarItems->getCount(); + Any aAny; + + for ( sal_Int32 nItemPos = 0; nItemPos < nItemCount; nItemPos++ ) + { + Sequence< PropertyValue > aProps; + aAny = m_aStatusBarItems->getByIndex( nItemPos ); + if ( aAny >>= aProps ) + { + ::rtl::OUString aCommandURL; + ::rtl::OUString aHelpURL; + sal_Int16 nStyle( ItemStyle::ALIGN_CENTER|ItemStyle::DRAW_IN3D ); + sal_Int16 nWidth( 0 ); + sal_Int16 nOffset( STATUSBAR_OFFSET ); + + ExtractStatusbarItemParameters( + aProps, + aCommandURL, + aHelpURL, + nOffset, + nStyle, + nWidth ); + + if ( aCommandURL.getLength() > 0 ) + WriteStatusBarItem( aCommandURL, aHelpURL, nOffset, nStyle, nWidth ); + } + } + + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_STATUSBAR )) ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endDocument(); +} + +//_________________________________________________________________________________________________________________ +// protected member functions +//_________________________________________________________________________________________________________________ + +void OWriteStatusBarDocumentHandler::WriteStatusBarItem( + const rtl::OUString& rCommandURL, + const rtl::OUString& /*rHelpURL*/, + sal_Int16 nOffset, + sal_Int16 nStyle, + sal_Int16 nWidth ) +throw ( SAXException, RuntimeException ) +{ + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + Reference< XAttributeList > xList( (XAttributeList *) pList , UNO_QUERY ); + + if ( m_aAttributeURL.getLength() == 0 ) + { + m_aAttributeURL = m_aXMLXlinkNS; + m_aAttributeURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_URL )); + } + + // save required attribute (URL) + pList->AddAttribute( m_aAttributeURL, m_aAttributeType, rCommandURL ); + + // alignment + if ( nStyle & ItemStyle::ALIGN_RIGHT ) + { + pList->AddAttribute( m_aXMLStatusBarNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_ALIGN )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_ALIGN_RIGHT )) ); + } + else if ( nStyle & ItemStyle::ALIGN_CENTER ) + { + pList->AddAttribute( m_aXMLStatusBarNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_ALIGN )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_ALIGN_CENTER )) ); + } + else + { + pList->AddAttribute( m_aXMLStatusBarNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_ALIGN )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_ALIGN_LEFT )) ); + } + + // style ( SIB_IN is default ) + if ( nStyle & ItemStyle::DRAW_FLAT ) + { + pList->AddAttribute( m_aXMLStatusBarNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_STYLE )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_STYLE_FLAT )) ); + } + else if ( nStyle & ItemStyle::DRAW_OUT3D ) + { + pList->AddAttribute( m_aXMLStatusBarNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_STYLE )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_STYLE_OUT )) ); + } + + // autosize (default sal_False) + if ( nStyle & ItemStyle::AUTO_SIZE ) + { + pList->AddAttribute( m_aXMLStatusBarNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_AUTOSIZE )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_BOOLEAN_TRUE )) ); + } + + // ownerdraw (default sal_False) + if ( nStyle & ItemStyle::OWNER_DRAW ) + { + pList->AddAttribute( m_aXMLStatusBarNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_OWNERDRAW )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_BOOLEAN_TRUE )) ); + } + + // width (default 0) + if ( nWidth > 0 ) + { + pList->AddAttribute( m_aXMLStatusBarNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_WIDTH )), + m_aAttributeType, + ::rtl::OUString::valueOf( (sal_Int32)nWidth ) ); + } + + // offset (default STATUSBAR_OFFSET) + if ( nOffset != STATUSBAR_OFFSET ) + { + pList->AddAttribute( m_aXMLStatusBarNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_OFFSET )), + m_aAttributeType, + ::rtl::OUString::valueOf( (sal_Int32)nOffset ) ); + } + + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_STATUSBARITEM )), xList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_STATUSBARITEM )) ); +} + +} // namespace framework + diff --git a/framework/source/fwe/xml/toolboxconfiguration.cxx b/framework/source/fwe/xml/toolboxconfiguration.cxx new file mode 100644 index 000000000000..994354a7e1a8 --- /dev/null +++ b/framework/source/fwe/xml/toolboxconfiguration.cxx @@ -0,0 +1,156 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <framework/toolboxconfiguration.hxx> +#include <xml/toolboxdocumenthandler.hxx> +#include <xml/saxnamespacefilter.hxx> +#include <services.h> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#ifndef _UNOTOOLS_PROCESSFACTORY_HXX +#include <comphelper/processfactory.hxx> +#endif +#include <unotools/streamwrap.hxx> +#include <tools/debug.hxx> + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::container; + + +namespace framework +{ + +static Reference< XParser > GetSaxParser( + // #110897# + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory + ) +{ + return Reference< XParser >( xServiceFactory->createInstance( SERVICENAME_SAXPARSER), UNO_QUERY); +} + +static Reference< XDocumentHandler > GetSaxWriter( + // #110897# + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory + ) +{ + return Reference< XDocumentHandler >( xServiceFactory->createInstance( SERVICENAME_SAXWRITER), UNO_QUERY) ; +} + +// #110897# +sal_Bool ToolBoxConfiguration::LoadToolBox( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rInputStream, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer >& rToolbarConfiguration ) +{ + Reference< XParser > xParser( GetSaxParser( xServiceFactory ) ); + + // connect stream to input stream to the parser + InputSource aInputSource; + + aInputSource.aInputStream = rInputStream; + + // create namespace filter and set menudocument handler inside to support xml namespaces + Reference< XDocumentHandler > xDocHandler( new OReadToolBoxDocumentHandler( rToolbarConfiguration )); + Reference< XDocumentHandler > xFilter( new SaxNamespaceFilter( xDocHandler )); + + // connect parser and filter + xParser->setDocumentHandler( xFilter ); + + try + { + xParser->parseStream( aInputSource ); + return sal_True; + } + catch ( RuntimeException& ) + { + return sal_False; + } + catch( SAXException& ) + { + return sal_False; + } + catch( ::com::sun::star::io::IOException& ) + { + return sal_False; + } +} + + +// #110897# +sal_Bool ToolBoxConfiguration::StoreToolBox( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& rOutputStream, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& rToolbarConfiguration ) +{ + Reference< XDocumentHandler > xWriter( GetSaxWriter( xServiceFactory ) ); + + Reference< ::com::sun::star::io::XActiveDataSource> xDataSource( xWriter , UNO_QUERY ); + xDataSource->setOutputStream( rOutputStream ); + + try + { + OWriteToolBoxDocumentHandler aWriteToolBoxDocumentHandler( rToolbarConfiguration, xWriter ); + aWriteToolBoxDocumentHandler.WriteToolBoxDocument(); + return sal_True; + } + catch ( RuntimeException& ) + { + return sal_False; + } + catch ( SAXException& ) + { + return sal_False; + } + catch ( ::com::sun::star::io::IOException& ) + { + return sal_False; + } +} + +} + diff --git a/framework/source/fwe/xml/toolboxdocumenthandler.cxx b/framework/source/fwe/xml/toolboxdocumenthandler.cxx new file mode 100644 index 000000000000..b41f50339343 --- /dev/null +++ b/framework/source/fwe/xml/toolboxdocumenthandler.cxx @@ -0,0 +1,901 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <stdio.h> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + +#include <threadhelp/resetableguard.hxx> +#include <xml/toolboxdocumenthandler.hxx> +#include <macros/debug.hxx> +#include <xml/toolboxconfigurationdefines.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#include <com/sun/star/ui/ItemType.hpp> +#include <com/sun/star/ui/ItemStyle.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ + +#include <sal/config.h> +#include <vcl/svapp.hxx> +#include <vcl/toolbox.hxx> +#include <rtl/ustrbuf.hxx> + +#include <comphelper/attributelist.hxx> + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::xml::sax; + + +#define TOOLBAR_DOCTYPE "<!DOCTYPE toolbar:toolbar PUBLIC \"-//OpenOffice.org//DTD OfficeDocument 1.0//EN\" \"toolbar.dtd\">" + +namespace framework +{ + +// Property names of a menu/menu item ItemDescriptor +static const char ITEM_DESCRIPTOR_COMMANDURL[] = "CommandURL"; +static const char ITEM_DESCRIPTOR_HELPURL[] = "HelpURL"; +static const char ITEM_DESCRIPTOR_TOOLTIP[] = "Tooltip"; +static const char ITEM_DESCRIPTOR_LABEL[] = "Label"; +static const char ITEM_DESCRIPTOR_TYPE[] = "Type"; +static const char ITEM_DESCRIPTOR_STYLE[] = "Style"; +static const char ITEM_DESCRIPTOR_VISIBLE[] = "IsVisible"; +static const char ITEM_DESCRIPTOR_WIDTH[] = "Width"; + +static void ExtractToolbarParameters( const Sequence< PropertyValue > rProp, + ::rtl::OUString& rCommandURL, + ::rtl::OUString& rLabel, + ::rtl::OUString& rHelpURL, + ::rtl::OUString& rTooltip, + sal_Int16& rStyle, + sal_Int16& rWidth, + sal_Bool& rVisible, + sal_Int16& rType ) +{ + for ( sal_Int32 i = 0; i < rProp.getLength(); i++ ) + { + if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_COMMANDURL )) + { + rProp[i].Value >>= rCommandURL; + rCommandURL = rCommandURL.intern(); + } + else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_HELPURL )) + rProp[i].Value >>= rHelpURL; + else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_TOOLTIP )) + rProp[i].Value >>= rTooltip; + else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_LABEL )) + rProp[i].Value >>= rLabel; + else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_TYPE )) + rProp[i].Value >>= rType; + else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_VISIBLE )) + rProp[i].Value >>= rVisible; + else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_WIDTH )) + rProp[i].Value >>= rWidth; + else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_STYLE )) + rProp[i].Value >>= rStyle; + } +} + +struct ToolboxStyleItem +{ + sal_Int16 nBit; + const char* attrName; +}; + +ToolboxStyleItem Styles[ ] = { + { ::com::sun::star::ui::ItemStyle::RADIO_CHECK, ATTRIBUTE_ITEMSTYLE_RADIO }, + { ::com::sun::star::ui::ItemStyle::ALIGN_LEFT, ATTRIBUTE_ITEMSTYLE_LEFT }, + { ::com::sun::star::ui::ItemStyle::AUTO_SIZE, ATTRIBUTE_ITEMSTYLE_AUTO }, + { ::com::sun::star::ui::ItemStyle::REPEAT, ATTRIBUTE_ITEMSTYLE_REPEAT }, + { ::com::sun::star::ui::ItemStyle::DROPDOWN_ONLY, ATTRIBUTE_ITEMSTYLE_DROPDOWNONLY }, + { ::com::sun::star::ui::ItemStyle::DROP_DOWN, ATTRIBUTE_ITEMSTYLE_DROPDOWN }, + { ::com::sun::star::ui::ItemStyle::ICON, ATTRIBUTE_ITEMSTYLE_IMAGE }, + { ::com::sun::star::ui::ItemStyle::TEXT, ATTRIBUTE_ITEMSTYLE_TEXT }, +}; + +sal_Int32 nStyleItemEntries = sizeof( Styles ) / sizeof( Styles[ 0 ] ); + +struct ToolBarEntryProperty +{ + OReadToolBoxDocumentHandler::ToolBox_XML_Namespace nNamespace; + char aEntryName[20]; +}; + +ToolBarEntryProperty ToolBoxEntries[OReadToolBoxDocumentHandler::TB_XML_ENTRY_COUNT] = +{ + { OReadToolBoxDocumentHandler::TB_NS_TOOLBAR, ELEMENT_TOOLBAR }, + { OReadToolBoxDocumentHandler::TB_NS_TOOLBAR, ELEMENT_TOOLBARITEM }, + { OReadToolBoxDocumentHandler::TB_NS_TOOLBAR, ELEMENT_TOOLBARSPACE }, + { OReadToolBoxDocumentHandler::TB_NS_TOOLBAR, ELEMENT_TOOLBARBREAK }, + { OReadToolBoxDocumentHandler::TB_NS_TOOLBAR, ELEMENT_TOOLBARSEPARATOR }, + { OReadToolBoxDocumentHandler::TB_NS_TOOLBAR, ATTRIBUTE_TEXT }, + { OReadToolBoxDocumentHandler::TB_NS_TOOLBAR, ATTRIBUTE_BITMAP }, + { OReadToolBoxDocumentHandler::TB_NS_XLINK, ATTRIBUTE_URL }, + { OReadToolBoxDocumentHandler::TB_NS_TOOLBAR, ATTRIBUTE_ITEMBITS }, + { OReadToolBoxDocumentHandler::TB_NS_TOOLBAR, ATTRIBUTE_VISIBLE }, + { OReadToolBoxDocumentHandler::TB_NS_TOOLBAR, ATTRIBUTE_WIDTH }, + { OReadToolBoxDocumentHandler::TB_NS_TOOLBAR, ATTRIBUTE_USER }, + { OReadToolBoxDocumentHandler::TB_NS_TOOLBAR, ATTRIBUTE_HELPID }, + { OReadToolBoxDocumentHandler::TB_NS_TOOLBAR, ATTRIBUTE_ITEMSTYLE }, + { OReadToolBoxDocumentHandler::TB_NS_TOOLBAR, ATTRIBUTE_UINAME }, + { OReadToolBoxDocumentHandler::TB_NS_TOOLBAR, ATTRIBUTE_TOOLTIP }, +}; + +OReadToolBoxDocumentHandler::OReadToolBoxDocumentHandler( const Reference< XIndexContainer >& rItemContainer ) : + ThreadHelpBase( &Application::GetSolarMutex() ), + m_rItemContainer( rItemContainer ), + m_aType( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_TYPE )), + m_aLabel( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_LABEL )), + m_aStyle( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_STYLE )), + m_aHelpURL( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_HELPURL )), + m_aTooltip( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_TOOLTIP )), + m_aIsVisible( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_VISIBLE )), + m_aCommandURL( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_COMMANDURL )) + { + ::rtl::OUString aNamespaceToolBar( RTL_CONSTASCII_USTRINGPARAM( XMLNS_TOOLBAR )); + ::rtl::OUString aNamespaceXLink( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK )); + ::rtl::OUString aSeparator( RTL_CONSTASCII_USTRINGPARAM( XMLNS_FILTER_SEPARATOR )); + + // create hash map + for ( int i = 0; i < (int)TB_XML_ENTRY_COUNT; i++ ) + { + if ( ToolBoxEntries[i].nNamespace == TB_NS_TOOLBAR ) + { + ::rtl::OUString temp( aNamespaceToolBar ); + temp += aSeparator; + temp += ::rtl::OUString::createFromAscii( ToolBoxEntries[i].aEntryName ); + m_aToolBoxMap.insert( ToolBoxHashMap::value_type( temp, (ToolBox_XML_Entry)i ) ); + } + else + { + ::rtl::OUString temp( aNamespaceXLink ); + temp += aSeparator; + temp += ::rtl::OUString::createFromAscii( ToolBoxEntries[i].aEntryName ); + m_aToolBoxMap.insert( ToolBoxHashMap::value_type( temp, (ToolBox_XML_Entry)i ) ); + } + } + + // pre-calculate a hash code for all style strings to speed up xml read process + m_nHashCode_Style_Radio = ::rtl::OUString::createFromAscii( ATTRIBUTE_ITEMSTYLE_RADIO ).hashCode(); + m_nHashCode_Style_Auto = ::rtl::OUString::createFromAscii( ATTRIBUTE_ITEMSTYLE_AUTO ).hashCode(); + m_nHashCode_Style_Left = ::rtl::OUString::createFromAscii( ATTRIBUTE_ITEMSTYLE_LEFT ).hashCode(); + m_nHashCode_Style_AutoSize = ::rtl::OUString::createFromAscii( ATTRIBUTE_ITEMSTYLE_AUTOSIZE ).hashCode(); + m_nHashCode_Style_DropDown = ::rtl::OUString::createFromAscii( ATTRIBUTE_ITEMSTYLE_DROPDOWN ).hashCode(); + m_nHashCode_Style_Repeat = ::rtl::OUString::createFromAscii( ATTRIBUTE_ITEMSTYLE_REPEAT ).hashCode(); + m_nHashCode_Style_DropDownOnly = ::rtl::OUString::createFromAscii( ATTRIBUTE_ITEMSTYLE_DROPDOWNONLY ).hashCode(); + m_nHashCode_Style_Text = ::rtl::OUString::createFromAscii( ATTRIBUTE_ITEMSTYLE_TEXT ).hashCode(); + m_nHashCode_Style_Image = ::rtl::OUString::createFromAscii( ATTRIBUTE_ITEMSTYLE_IMAGE ).hashCode(); + + m_bToolBarStartFound = sal_False; + m_bToolBarEndFound = sal_False; + m_bToolBarItemStartFound = sal_False; + m_bToolBarSpaceStartFound = sal_False; + m_bToolBarBreakStartFound = sal_False; + m_bToolBarSeparatorStartFound = sal_False; +} + +OReadToolBoxDocumentHandler::~OReadToolBoxDocumentHandler() +{ +} + +// XDocumentHandler +void SAL_CALL OReadToolBoxDocumentHandler::startDocument(void) +throw ( SAXException, RuntimeException ) +{ +} + +void SAL_CALL OReadToolBoxDocumentHandler::endDocument(void) +throw( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + if (( m_bToolBarStartFound && !m_bToolBarEndFound ) || + ( !m_bToolBarStartFound && m_bToolBarEndFound ) ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No matching start or end element 'toolbar' found!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } +} + +void SAL_CALL OReadToolBoxDocumentHandler::startElement( + const ::rtl::OUString& aName, const Reference< XAttributeList > &xAttribs ) +throw( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + ToolBoxHashMap::const_iterator pToolBoxEntry = m_aToolBoxMap.find( aName ) ; + if ( pToolBoxEntry != m_aToolBoxMap.end() ) + { + switch ( pToolBoxEntry->second ) + { + case TB_ELEMENT_TOOLBAR: + { + if ( m_bToolBarStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'toolbar:toolbar' cannot be embeded into 'toolbar:toolbar'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + else + { + // Check if we have a UI name set in our XML file + ::rtl::OUString aUIName; + for ( sal_Int16 n = 0; n < xAttribs->getLength(); n++ ) + { + pToolBoxEntry = m_aToolBoxMap.find( xAttribs->getNameByIndex( n ) ); + if ( pToolBoxEntry != m_aToolBoxMap.end() ) + { + switch ( pToolBoxEntry->second ) + { + case TB_ATTRIBUTE_UINAME: + aUIName = xAttribs->getValueByIndex( n ); + break; + default: + break; + } + } + } + + if ( aUIName.getLength() > 0 ) + { + // Try to set UI name as a container property + Reference< XPropertySet > xPropSet( m_rItemContainer, UNO_QUERY ); + if ( xPropSet.is() ) + { + try + { + xPropSet->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UIName" )), makeAny( aUIName ) ); + } + catch ( UnknownPropertyException& ) + { + } + } + } + } + + m_bToolBarStartFound = sal_True; + } + break; + + case TB_ELEMENT_TOOLBARITEM: + { + if ( !m_bToolBarStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'toolbar:toolbaritem' must be embeded into element 'toolbar:toolbar'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + if ( m_bToolBarSeparatorStartFound || + m_bToolBarBreakStartFound || + m_bToolBarSpaceStartFound || + m_bToolBarItemStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element toolbar:toolbaritem is not a container!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + ::rtl::OUString aAttribute; + sal_Bool bAttributeURL = sal_False; + + m_bToolBarItemStartFound = sal_True; + ::rtl::OUString aLabel; + ::rtl::OUString aCommandURL; + ::rtl::OUString aHelpURL; + ::rtl::OUString aTooltip; + ::rtl::OUString aBitmapName; + sal_uInt16 nItemBits( 0 ); + sal_uInt16 nWidth( 0 ); + sal_uInt16 nUserDef( 0 ); + sal_Bool bVisible( sal_True ); + + for ( sal_Int16 n = 0; n < xAttribs->getLength(); n++ ) + { + pToolBoxEntry = m_aToolBoxMap.find( xAttribs->getNameByIndex( n ) ); + if ( pToolBoxEntry != m_aToolBoxMap.end() ) + { + switch ( pToolBoxEntry->second ) + { + case TB_ATTRIBUTE_TEXT: + { + aLabel = xAttribs->getValueByIndex( n ); + } + break; + + case TB_ATTRIBUTE_BITMAP: + { + aBitmapName = xAttribs->getValueByIndex( n ); + } + break; + + case TB_ATTRIBUTE_URL: + { + bAttributeURL = sal_True; + aCommandURL = xAttribs->getValueByIndex( n ).intern(); + } + break; + + case TB_ATTRIBUTE_ITEMBITS: + { + nItemBits = (sal_uInt16)(xAttribs->getValueByIndex( n ).toInt32()); + } + break; + + case TB_ATTRIBUTE_VISIBLE: + { + if ( xAttribs->getValueByIndex( n ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_BOOLEAN_TRUE )) ) + bVisible = sal_True; + else if ( xAttribs->getValueByIndex( n ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_BOOLEAN_FALSE )) ) + bVisible = sal_False; + else + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Attribute toolbar:visible must have value 'true' or 'false'!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } + break; + + case TB_ATTRIBUTE_WIDTH: + { + nWidth = (sal_uInt16)(xAttribs->getValueByIndex( n ).toInt32()); + } + break; + + case TB_ATTRIBUTE_USER: + { + nUserDef = (sal_uInt16)(xAttribs->getValueByIndex( n ).toInt32()); + } + break; + + case TB_ATTRIBUTE_HELPID: + { + aHelpURL = xAttribs->getValueByIndex( n ); + } + break; + + case TB_ATTRIBUTE_TOOLTIP: + { + aTooltip = xAttribs->getValueByIndex( n ); + } + break; + + case TB_ATTRIBUTE_STYLE: + { + // read space seperated item style list + ::rtl::OUString aTemp = xAttribs->getValueByIndex( n ); + sal_Int32 nIndex = 0; + + do + { + ::rtl::OUString aToken = aTemp.getToken( 0, ' ', nIndex ); + if ( aToken.getLength() > 0 ) + { + sal_Int32 nHashCode = aToken.hashCode(); + if ( nHashCode == m_nHashCode_Style_Radio ) + nItemBits |= ::com::sun::star::ui::ItemStyle::RADIO_CHECK; + else if ( nHashCode == m_nHashCode_Style_Left ) + nItemBits |= ::com::sun::star::ui::ItemStyle::ALIGN_LEFT; + else if ( nHashCode == m_nHashCode_Style_AutoSize ) + nItemBits |= ::com::sun::star::ui::ItemStyle::AUTO_SIZE; + else if ( nHashCode == m_nHashCode_Style_DropDown ) + nItemBits |= ::com::sun::star::ui::ItemStyle::DROP_DOWN; + else if ( nHashCode == m_nHashCode_Style_Repeat ) + nItemBits |= ::com::sun::star::ui::ItemStyle::REPEAT; + else if ( nHashCode == m_nHashCode_Style_DropDownOnly ) + nItemBits |= ::com::sun::star::ui::ItemStyle::DROPDOWN_ONLY; + else if ( nHashCode == m_nHashCode_Style_DropDown ) + nItemBits |= ::com::sun::star::ui::ItemStyle::DROP_DOWN; + else if ( nHashCode == m_nHashCode_Style_Text ) + nItemBits |= ::com::sun::star::ui::ItemStyle::TEXT; + else if ( nHashCode == m_nHashCode_Style_Image ) + nItemBits |= ::com::sun::star::ui::ItemStyle::ICON; + } + } + while ( nIndex >= 0 ); + } + break; + + default: + break; + } + } + } // for + + if ( !bAttributeURL ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Required attribute toolbar:url must have a value!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + if ( aCommandURL.getLength() > 0 ) + { + Sequence< PropertyValue > aToolbarItemProp( 7 ); + aToolbarItemProp[0].Name = m_aCommandURL; + aToolbarItemProp[1].Name = m_aHelpURL; + aToolbarItemProp[2].Name = m_aLabel; + aToolbarItemProp[3].Name = m_aType; + aToolbarItemProp[4].Name = m_aStyle; + aToolbarItemProp[5].Name = m_aIsVisible; + aToolbarItemProp[6].Name = m_aTooltip; + + aToolbarItemProp[0].Value <<= aCommandURL; + aToolbarItemProp[1].Value <<= aHelpURL; + aToolbarItemProp[2].Value <<= aLabel; + aToolbarItemProp[3].Value = makeAny( ::com::sun::star::ui::ItemType::DEFAULT ); + aToolbarItemProp[4].Value <<= nItemBits; + aToolbarItemProp[5].Value <<= bVisible; + aToolbarItemProp[6].Value <<= aTooltip; + + m_rItemContainer->insertByIndex( m_rItemContainer->getCount(), makeAny( aToolbarItemProp ) ); + } + } + break; + + case TB_ELEMENT_TOOLBARSPACE: + { + if ( m_bToolBarSeparatorStartFound || + m_bToolBarBreakStartFound || + m_bToolBarSpaceStartFound || + m_bToolBarItemStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element toolbar:toolbarspace is not a container!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bToolBarSpaceStartFound = sal_True; + + Sequence< PropertyValue > aToolbarItemProp( 2 ); + aToolbarItemProp[0].Name = m_aCommandURL; + aToolbarItemProp[1].Name = m_aType; + + aToolbarItemProp[0].Value <<= rtl::OUString(); + aToolbarItemProp[1].Value <<= ::com::sun::star::ui::ItemType::SEPARATOR_SPACE; + + m_rItemContainer->insertByIndex( m_rItemContainer->getCount(), makeAny( aToolbarItemProp ) ); + } + break; + + case TB_ELEMENT_TOOLBARBREAK: + { + if ( m_bToolBarSeparatorStartFound || + m_bToolBarBreakStartFound || + m_bToolBarSpaceStartFound || + m_bToolBarItemStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element toolbar:toolbarbreak is not a container!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bToolBarBreakStartFound = sal_True; + + Sequence< PropertyValue > aToolbarItemProp( 2 ); + aToolbarItemProp[0].Name = m_aCommandURL; + aToolbarItemProp[1].Name = m_aType; + + aToolbarItemProp[0].Value <<= rtl::OUString(); + aToolbarItemProp[1].Value <<= ::com::sun::star::ui::ItemType::SEPARATOR_LINEBREAK; + + m_rItemContainer->insertByIndex( m_rItemContainer->getCount(), makeAny( aToolbarItemProp ) ); + } + break; + + case TB_ELEMENT_TOOLBARSEPARATOR: + { + if ( m_bToolBarSeparatorStartFound || + m_bToolBarBreakStartFound || + m_bToolBarSpaceStartFound || + m_bToolBarItemStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element toolbar:toolbarseparator is not a container!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bToolBarSeparatorStartFound = sal_True; + + Sequence< PropertyValue > aToolbarItemProp( 2 ); + aToolbarItemProp[0].Name = m_aCommandURL; + aToolbarItemProp[1].Name = m_aType; + + aToolbarItemProp[0].Value <<= rtl::OUString(); + aToolbarItemProp[1].Value <<= ::com::sun::star::ui::ItemType::SEPARATOR_LINE; + + m_rItemContainer->insertByIndex( m_rItemContainer->getCount(), makeAny( aToolbarItemProp ) ); + } + break; + + default: + break; + } + } +} + +void SAL_CALL OReadToolBoxDocumentHandler::endElement(const ::rtl::OUString& aName) +throw( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + ToolBoxHashMap::const_iterator pToolBoxEntry = m_aToolBoxMap.find( aName ) ; + if ( pToolBoxEntry != m_aToolBoxMap.end() ) + { + switch ( pToolBoxEntry->second ) + { + case TB_ELEMENT_TOOLBAR: + { + if ( !m_bToolBarStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "End element 'toolbar' found, but no start element 'toolbar'" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bToolBarStartFound = sal_False; + } + break; + + case TB_ELEMENT_TOOLBARITEM: + { + if ( !m_bToolBarItemStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "End element 'toolbar:toolbaritem' found, but no start element 'toolbar:toolbaritem'" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bToolBarItemStartFound = sal_False; + } + break; + + case TB_ELEMENT_TOOLBARBREAK: + { + if ( !m_bToolBarBreakStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "End element 'toolbar:toolbarbreak' found, but no start element 'toolbar:toolbarbreak'" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bToolBarBreakStartFound = sal_False; + } + break; + + case TB_ELEMENT_TOOLBARSPACE: + { + if ( !m_bToolBarSpaceStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "End element 'toolbar:toolbarspace' found, but no start element 'toolbar:toolbarspace'" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bToolBarSpaceStartFound = sal_False; + } + break; + + case TB_ELEMENT_TOOLBARSEPARATOR: + { + if ( !m_bToolBarSeparatorStartFound ) + { + ::rtl::OUString aErrorMessage = getErrorLineString(); + aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "End element 'toolbar:toolbarseparator' found, but no start element 'toolbar:toolbarseparator'" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bToolBarSeparatorStartFound = sal_False; + } + break; + + default: + break; + } + } +} + +void SAL_CALL OReadToolBoxDocumentHandler::characters(const ::rtl::OUString&) +throw( SAXException, RuntimeException ) +{ +} + +void SAL_CALL OReadToolBoxDocumentHandler::ignorableWhitespace(const ::rtl::OUString&) +throw( SAXException, RuntimeException ) +{ +} + +void SAL_CALL OReadToolBoxDocumentHandler::processingInstruction( + const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/ ) +throw( SAXException, RuntimeException ) +{ +} + +void SAL_CALL OReadToolBoxDocumentHandler::setDocumentLocator( + const Reference< XLocator > &xLocator) +throw( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + m_xLocator = xLocator; +} + +::rtl::OUString OReadToolBoxDocumentHandler::getErrorLineString() +{ + ResetableGuard aGuard( m_aLock ); + + char buffer[32]; + + if ( m_xLocator.is() ) + { + snprintf( buffer, sizeof(buffer), "Line: %ld - ", static_cast<long>( m_xLocator->getLineNumber() )); + return ::rtl::OUString::createFromAscii( buffer ); + } + else + return ::rtl::OUString(); +} + + +//_________________________________________________________________________________________________________________ +// OWriteToolBoxDocumentHandler +//_________________________________________________________________________________________________________________ + +OWriteToolBoxDocumentHandler::OWriteToolBoxDocumentHandler( + const Reference< XIndexAccess >& rItemAccess, + Reference< XDocumentHandler >& rWriteDocumentHandler ) : + ThreadHelpBase( &Application::GetSolarMutex() ), + m_xWriteDocumentHandler( rWriteDocumentHandler ), + m_rItemAccess( rItemAccess ) +{ + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + m_xEmptyList = Reference< XAttributeList >( (XAttributeList *) pList, UNO_QUERY ); + m_aAttributeType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TYPE_CDATA )); + m_aXMLXlinkNS = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK_PREFIX )); + m_aXMLToolbarNS = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_TOOLBAR_PREFIX )); +} + +OWriteToolBoxDocumentHandler::~OWriteToolBoxDocumentHandler() +{ +} + +void OWriteToolBoxDocumentHandler::WriteToolBoxDocument() throw +( SAXException, RuntimeException ) +{ + ResetableGuard aGuard( m_aLock ); + + m_xWriteDocumentHandler->startDocument(); + + // write DOCTYPE line! + Reference< XExtendedDocumentHandler > xExtendedDocHandler( m_xWriteDocumentHandler, UNO_QUERY ); + if ( xExtendedDocHandler.is() ) + { + xExtendedDocHandler->unknown( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( TOOLBAR_DOCTYPE )) ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + } + + ::rtl::OUString aUIName; + Reference< XPropertySet > xPropSet( m_rItemAccess, UNO_QUERY ); + if ( xPropSet.is() ) + { + try + { + xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UIName" ))) >>= aUIName; + } + catch ( UnknownPropertyException& ) + { + } + } + + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + Reference< XAttributeList > xList( (XAttributeList *) pList , UNO_QUERY ); + + pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XMLNS_TOOLBAR )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_TOOLBAR )) ); + + pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XMLNS_XLINK )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK )) ); + + if ( aUIName.getLength() > 0 ) + pList->AddAttribute( m_aXMLToolbarNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_UINAME )), + m_aAttributeType, + aUIName ); + + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_TOOLBAR )), pList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + + sal_Int32 nItemCount = m_rItemAccess->getCount(); + Any aAny; + + for ( sal_Int32 nItemPos = 0; nItemPos < nItemCount; nItemPos++ ) + { + Sequence< PropertyValue > aProps; + aAny = m_rItemAccess->getByIndex( nItemPos ); + if ( aAny >>= aProps ) + { + ::rtl::OUString aCommandURL; + ::rtl::OUString aLabel; + ::rtl::OUString aHelpURL; + ::rtl::OUString aTooltip; + sal_Bool bVisible( sal_True ); + sal_Int16 nType( ::com::sun::star::ui::ItemType::DEFAULT ); + sal_Int16 nWidth( 0 ); + sal_Int16 nStyle( 0 ); + + ExtractToolbarParameters( aProps, aCommandURL, aLabel, aHelpURL, aTooltip, nStyle, nWidth, bVisible, nType ); + if ( nType == ::com::sun::star::ui::ItemType::DEFAULT ) + WriteToolBoxItem( aCommandURL, aLabel, aHelpURL, aTooltip, nStyle, nWidth, bVisible ); + else if ( nType == ::com::sun::star::ui::ItemType::SEPARATOR_SPACE ) + WriteToolBoxSpace(); + else if ( nType == ::com::sun::star::ui::ItemType::SEPARATOR_LINE ) + WriteToolBoxSeparator(); + else if ( nType == ::com::sun::star::ui::ItemType::SEPARATOR_LINEBREAK ) + WriteToolBoxBreak(); + } + } + + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_TOOLBAR )) ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endDocument(); +} + +//_________________________________________________________________________________________________________________ +// protected member functions +//_________________________________________________________________________________________________________________ + +void OWriteToolBoxDocumentHandler::WriteToolBoxItem( + const ::rtl::OUString& rCommandURL, + const ::rtl::OUString& rLabel, + const ::rtl::OUString& rHelpURL, + const ::rtl::OUString& rTooltip, + sal_Int16 nStyle, + sal_Int16 nWidth, + sal_Bool bVisible ) +throw ( SAXException, RuntimeException ) +{ + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + Reference< XAttributeList > xList( (XAttributeList *) pList , UNO_QUERY ); + + if ( m_aAttributeURL.getLength() == 0 ) + { + m_aAttributeURL = m_aXMLXlinkNS; + m_aAttributeURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_URL )); + } + + // save required attribute (URL) + pList->AddAttribute( m_aAttributeURL, m_aAttributeType, rCommandURL ); + + if ( rLabel.getLength() > 0 ) + { + pList->AddAttribute( m_aXMLToolbarNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TEXT )), + m_aAttributeType, + rLabel ); + } + + if ( bVisible == sal_False ) + { + pList->AddAttribute( m_aXMLToolbarNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_VISIBLE )), + m_aAttributeType, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_BOOLEAN_FALSE )) ); + } + + if ( rHelpURL.getLength() > 0 ) + { + pList->AddAttribute( m_aXMLToolbarNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_HELPID )), + m_aAttributeType, + rHelpURL ); + } + + if ( rTooltip.getLength() > 0 ) + { + pList->AddAttribute( m_aXMLToolbarNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TOOLTIP )), + m_aAttributeType, + rTooltip ); + } + + if ( nStyle > 0 ) + { + rtl::OUString aValue; + ToolboxStyleItem* pStyle = Styles; + + for ( sal_Int32 nIndex = 0; nIndex < nStyleItemEntries; ++nIndex, ++pStyle ) + { + if ( nStyle & pStyle->nBit ) + { + if ( aValue.getLength() ) + aValue = aValue.concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(" ") ) ); + aValue += rtl::OUString::createFromAscii( pStyle->attrName ); + } + } + pList->AddAttribute( m_aXMLToolbarNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_ITEMSTYLE )), + m_aAttributeType, + aValue ); + } + + if ( nWidth > 0 ) + { + pList->AddAttribute( m_aXMLToolbarNS + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_WIDTH )), + m_aAttributeType, + ::rtl::OUString::valueOf( sal_Int32( nWidth )) ); + } + + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_TOOLBARITEM )), xList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_TOOLBARITEM )) ); +} + +void OWriteToolBoxDocumentHandler::WriteToolBoxSpace() throw +( SAXException, RuntimeException ) +{ + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_TOOLBARSPACE )), m_xEmptyList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_TOOLBARSPACE )) ); +} + +void OWriteToolBoxDocumentHandler::WriteToolBoxBreak() throw +( SAXException, RuntimeException ) +{ + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_TOOLBARBREAK )), m_xEmptyList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_TOOLBARBREAK )) ); +} + +void OWriteToolBoxDocumentHandler::WriteToolBoxSeparator() throw +( SAXException, RuntimeException ) +{ + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_TOOLBARSEPARATOR )), m_xEmptyList ); + m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); + m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_TOOLBARSEPARATOR )) ); +} + +} // namespace framework + diff --git a/framework/source/fwe/xml/toolboxlayoutdocumenthandler.cxx b/framework/source/fwe/xml/toolboxlayoutdocumenthandler.cxx new file mode 100644 index 000000000000..645750dc3f51 --- /dev/null +++ b/framework/source/fwe/xml/toolboxlayoutdocumenthandler.cxx @@ -0,0 +1,58 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <stdio.h> + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ + +#include <threadhelp/resetableguard.hxx> +#include <xml/toolboxlayoutdocumenthandler.hxx> +#include <macros/debug.hxx> +#include <xml/toolboxconfigurationdefines.hxx> + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ + +#ifndef __COM_SUN_STAR_XML_SAX_XEXTENDEDDOCUMENTHANDLER_HPP_ +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#endif + +//_________________________________________________________________________________________________________________ +// other includes +//_________________________________________________________________________________________________________________ +#include <vcl/svapp.hxx> +#include <vcl/toolbox.hxx> + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ diff --git a/framework/source/fwe/xml/xmlnamespaces.cxx b/framework/source/fwe/xml/xmlnamespaces.cxx new file mode 100644 index 000000000000..fbaf51613d15 --- /dev/null +++ b/framework/source/fwe/xml/xmlnamespaces.cxx @@ -0,0 +1,191 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <xml/xmlnamespaces.hxx> + +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::uno; + +const ::rtl::OUString aXMLAttributeNamespace( RTL_CONSTASCII_USTRINGPARAM( "xmlns" )); + +namespace framework +{ + +XMLNamespaces::XMLNamespaces() +{ +} + +XMLNamespaces::XMLNamespaces( const XMLNamespaces& aXMLNamespaces ) +{ + m_aDefaultNamespace = aXMLNamespaces.m_aDefaultNamespace; + m_aNamespaceMap = aXMLNamespaces.m_aNamespaceMap; +} + +XMLNamespaces::~XMLNamespaces() +{ +} + +void XMLNamespaces::addNamespace( const ::rtl::OUString& aName, const ::rtl::OUString& aValue ) throw( SAXException ) +{ + NamespaceMap::iterator p; + ::rtl::OUString aNamespaceName( aName ); + sal_Int32 nXMLNamespaceLength = aXMLAttributeNamespace.getLength(); + + // delete preceding "xmlns" + if ( aNamespaceName.compareTo( aXMLAttributeNamespace, nXMLNamespaceLength ) == 0 ) + { + if ( aNamespaceName.getLength() == nXMLNamespaceLength ) + { + aNamespaceName = ::rtl::OUString(); + } + else if ( aNamespaceName.getLength() >= nXMLNamespaceLength+2 ) + { + aNamespaceName = aNamespaceName.copy( nXMLNamespaceLength+1 ); + } + else + { + // a xml namespace without name is not allowed (e.g. "xmlns:" ) + ::rtl::OUString aErrorMessage( RTL_CONSTASCII_USTRINGPARAM( "A xml namespace without name is not allowed!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } + + if ( aValue.getLength() == 0 && aNamespaceName.getLength() > 0 ) + { + // namespace should be reseted - as xml draft states this is only allowed + // for the default namespace - check and throw exception if check fails + ::rtl::OUString aErrorMessage( RTL_CONSTASCII_USTRINGPARAM( "Clearing xml namespace only allowed for default namespace!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + else + { + if ( aNamespaceName.getLength() == 0 ) + m_aDefaultNamespace = aValue; + else + { + p = m_aNamespaceMap.find( aNamespaceName ); + if ( p != m_aNamespaceMap.end() ) + { + // replace current namespace definition + m_aNamespaceMap.erase( p ); + m_aNamespaceMap.insert( NamespaceMap::value_type( aNamespaceName, aValue )); + } + else + { + m_aNamespaceMap.insert( NamespaceMap::value_type( aNamespaceName, aValue )); + } + } + } +} + +::rtl::OUString XMLNamespaces::applyNSToAttributeName( const ::rtl::OUString& aName ) const throw( SAXException ) +{ + // xml draft: there is no default namespace for attributes! + + int index; + if (( index = aName.indexOf( ':' )) > 0 ) + { + if ( aName.getLength() > index+1 ) + { + ::rtl::OUString aAttributeName = getNamespaceValue( aName.copy( 0, index ) ); + aAttributeName += ::rtl::OUString::createFromAscii( "^" ); + aAttributeName += aName.copy( index+1 ); + return aAttributeName; + } + else + { + // attribute with namespace but without name "namespace:" is not allowed!! + ::rtl::OUString aErrorMessage( RTL_CONSTASCII_USTRINGPARAM( "Attribute has no name only preceding namespace!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } + + return aName; +} + +::rtl::OUString XMLNamespaces::applyNSToElementName( const ::rtl::OUString& aName ) const throw( SAXException ) +{ + // xml draft: element names can have a default namespace + + int index = aName.indexOf( ':' ); + ::rtl::OUString aNamespace; + ::rtl::OUString aElementName = aName; + + if ( index > 0 ) + aNamespace = getNamespaceValue( aName.copy( 0, index ) ); + else + aNamespace = m_aDefaultNamespace; + + if ( aNamespace.getLength() > 0 ) + { + aElementName = aNamespace; + aElementName += ::rtl::OUString::createFromAscii( "^" ); + } + else + return aName; + + if ( index > 0 ) + { + if ( aName.getLength() > index+1 ) + aElementName += aName.copy( index+1 ); + else + { + // attribute with namespace but without a name is not allowed (e.g. "cfg:" ) + ::rtl::OUString aErrorMessage( RTL_CONSTASCII_USTRINGPARAM( "Attribute has no name only preceding namespace!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } + else + aElementName += aName; + + return aElementName; +} + +::rtl::OUString XMLNamespaces::getNamespaceValue( const ::rtl::OUString& aNamespace ) const throw( SAXException ) +{ + if ( aNamespace.getLength() == 0 ) + return m_aDefaultNamespace; + else + { + NamespaceMap::const_iterator p; + p = m_aNamespaceMap.find( aNamespace ); + if ( p != m_aNamespaceMap.end() ) + return p->second; + else + { + // namespace not defined => throw exception! + ::rtl::OUString aErrorMessage( RTL_CONSTASCII_USTRINGPARAM( "XML namespace used but not defined!" )); + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + } +} + +} + |