summaryrefslogtreecommitdiffstats
path: root/framework/source/fwe/classes
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--framework/source/fwe/classes/actiontriggercontainer.cxx137
-rw-r--r--framework/source/fwe/classes/actiontriggerpropertyset.cxx372
-rw-r--r--framework/source/fwe/classes/actiontriggerseparatorpropertyset.cxx246
-rw-r--r--framework/source/fwe/classes/addonmenu.cxx308
-rw-r--r--framework/source/fwe/classes/addonsoptions.cxx1957
-rw-r--r--framework/source/fwe/classes/framelistanalyzer.cxx260
-rw-r--r--framework/source/fwe/classes/fwkresid.cxx28
-rw-r--r--framework/source/fwe/classes/imagewrapper.cxx91
-rw-r--r--framework/source/fwe/classes/rootactiontriggercontainer.cxx264
-rw-r--r--framework/source/fwe/classes/sfxhelperfunctions.cxx155
10 files changed, 3818 insertions, 0 deletions
diff --git a/framework/source/fwe/classes/actiontriggercontainer.cxx b/framework/source/fwe/classes/actiontriggercontainer.cxx
new file mode 100644
index 000000000..331eb5cb9
--- /dev/null
+++ b/framework/source/fwe/classes/actiontriggercontainer.cxx
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <classes/actiontriggercontainer.hxx>
+#include <classes/actiontriggerpropertyset.hxx>
+#include <classes/actiontriggerseparatorpropertyset.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/supportsservice.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;
+
+namespace framework
+{
+
+ActionTriggerContainer::ActionTriggerContainer() :
+ PropertySetContainer()
+{
+}
+
+ActionTriggerContainer::~ActionTriggerContainer()
+{
+}
+
+// XInterface
+Any SAL_CALL ActionTriggerContainer::queryInterface( const Type& aType )
+{
+ Any a = ::cppu::queryInterface(
+ aType ,
+ static_cast< XMultiServiceFactory* >(this),
+ static_cast< XServiceInfo* >(this),
+ static_cast< XTypeProvider* >(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 OUString& aServiceSpecifier )
+{
+ if ( aServiceSpecifier == SERVICENAME_ACTIONTRIGGER )
+ return static_cast<OWeakObject *>( new ActionTriggerPropertySet());
+ else if ( aServiceSpecifier == SERVICENAME_ACTIONTRIGGERCONTAINER )
+ return static_cast<OWeakObject *>( new ActionTriggerContainer());
+ else if ( aServiceSpecifier == SERVICENAME_ACTIONTRIGGERSEPARATOR )
+ return static_cast<OWeakObject *>( new ActionTriggerSeparatorPropertySet());
+ else
+ throw css::uno::RuntimeException("Unknown service specifier!", static_cast<OWeakObject *>(this) );
+}
+
+Reference< XInterface > SAL_CALL ActionTriggerContainer::createInstanceWithArguments( const OUString& ServiceSpecifier, const Sequence< Any >& /*Arguments*/ )
+{
+ return createInstance( ServiceSpecifier );
+}
+
+Sequence< OUString > SAL_CALL ActionTriggerContainer::getAvailableServiceNames()
+{
+ Sequence< OUString > aSeq( 3 );
+
+ aSeq[0] = SERVICENAME_ACTIONTRIGGER;
+ aSeq[1] = SERVICENAME_ACTIONTRIGGERCONTAINER;
+ aSeq[2] = SERVICENAME_ACTIONTRIGGERSEPARATOR;
+
+ return aSeq;
+}
+
+// XServiceInfo
+OUString SAL_CALL ActionTriggerContainer::getImplementationName()
+{
+ return IMPLEMENTATIONNAME_ACTIONTRIGGERCONTAINER;
+}
+
+sal_Bool SAL_CALL ActionTriggerContainer::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Sequence< OUString > SAL_CALL ActionTriggerContainer::getSupportedServiceNames()
+{
+ Sequence< OUString > seqServiceNames { SERVICENAME_ACTIONTRIGGERCONTAINER };
+ return seqServiceNames;
+}
+
+// XTypeProvider
+Sequence< Type > SAL_CALL ActionTriggerContainer::getTypes()
+{
+ // Create a static typecollection ...
+ static ::cppu::OTypeCollection ourTypeCollection(
+ cppu::UnoType<XMultiServiceFactory>::get(),
+ cppu::UnoType<XIndexContainer>::get(),
+ cppu::UnoType<XServiceInfo>::get(),
+ cppu::UnoType<XTypeProvider>::get());
+
+ return ourTypeCollection.getTypes();
+}
+
+Sequence< sal_Int8 > SAL_CALL ActionTriggerContainer::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/fwe/classes/actiontriggerpropertyset.cxx b/framework/source/fwe/classes/actiontriggerpropertyset.cxx
new file mode 100644
index 000000000..128f5815b
--- /dev/null
+++ b/framework/source/fwe/classes/actiontriggerpropertyset.cxx
@@ -0,0 +1,372 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <classes/actiontriggerpropertyset.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <cppuhelper/proptypehlp.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/supportsservice.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 >;
+
+namespace {
+
+// 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()
+ : OBroadcastHelper ( m_aMutex )
+ , OPropertySetHelper ( *static_cast< OBroadcastHelper * >(this) )
+ , OWeakObject ()
+{
+}
+
+ActionTriggerPropertySet::~ActionTriggerPropertySet()
+{
+}
+
+// XInterface
+Any SAL_CALL ActionTriggerPropertySet::queryInterface( const Type& aType )
+{
+ Any a = ::cppu::queryInterface(
+ aType,
+ static_cast< XServiceInfo* >(this),
+ static_cast< XTypeProvider* >(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
+OUString SAL_CALL ActionTriggerPropertySet::getImplementationName()
+{
+ return IMPLEMENTATIONNAME_ACTIONTRIGGER;
+}
+
+sal_Bool SAL_CALL ActionTriggerPropertySet::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Sequence< OUString > SAL_CALL ActionTriggerPropertySet::getSupportedServiceNames()
+{
+ Sequence<OUString> seqServiceNames { SERVICENAME_ACTIONTRIGGER };
+ return seqServiceNames;
+}
+
+// XTypeProvider
+Sequence< Type > SAL_CALL ActionTriggerPropertySet::getTypes()
+{
+ // Create a static typecollection ...
+ static ::cppu::OTypeCollection ourTypeCollection(
+ cppu::UnoType<XPropertySet>::get(),
+ cppu::UnoType<XFastPropertySet>::get(),
+ cppu::UnoType<XMultiPropertySet>::get(),
+ cppu::UnoType<XServiceInfo>::get(),
+ cppu::UnoType<XTypeProvider>::get());
+
+
+ return ourTypeCollection.getTypes();
+}
+
+Sequence< sal_Int8 > SAL_CALL ActionTriggerPropertySet::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+sal_Bool SAL_CALL ActionTriggerPropertySet::convertFastPropertyValue(
+ Any& aConvertedValue,
+ Any& aOldValue,
+ sal_Int32 nHandle,
+ const Any& aValue )
+{
+ // 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)
+ bool bReturn = 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 )
+{
+ SolarMutexGuard aGuard;
+
+ // 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
+{
+ SolarMutexGuard aGuard;
+
+ // 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()
+{
+ // Define static member to give structure of properties to baseclass "OPropertySetHelper".
+ // "impl_getStaticPropertyDescriptor" is a non exported and static function, who will define a static propertytable.
+ // "true" say: Table is sorted by name.
+ static OPropertyArrayHelper ourInfoHelper( impl_getStaticPropertyDescriptor(), true );
+
+ return ourInfoHelper;
+}
+
+Reference< XPropertySetInfo > SAL_CALL ActionTriggerPropertySet::getPropertySetInfo()
+{
+ // Create structure of propertysetinfo for baseclass "OPropertySetHelper".
+ // (Use method "getInfoHelper()".)
+ static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+
+ return xInfo;
+}
+
+Sequence< Property > ActionTriggerPropertySet::impl_getStaticPropertyDescriptor()
+{
+ return
+ {
+ Property( "CommandURL" , HANDLE_COMMANDURL , cppu::UnoType<OUString>::get(), PropertyAttribute::TRANSIENT ),
+ Property( "HelpURL" , HANDLE_HELPURL , cppu::UnoType<OUString>::get(), PropertyAttribute::TRANSIENT ),
+ Property( "Image" , HANDLE_IMAGE , cppu::UnoType<XBitmap>::get(), PropertyAttribute::TRANSIENT ),
+ Property( "SubContainer" , HANDLE_SUBCONTAINER , cppu::UnoType<OUString>::get(), PropertyAttribute::TRANSIENT ),
+ Property( "Text" , HANDLE_TEXT , cppu::UnoType<XInterface>::get(), PropertyAttribute::TRANSIENT )
+ };
+}
+
+bool ActionTriggerPropertySet::impl_tryToChangeProperty(
+ const OUString& sCurrentValue ,
+ const Any& aNewValue ,
+ Any& aOldValue ,
+ Any& aConvertedValue )
+{
+ // Set default return value if method failed.
+ bool bReturn = false;
+ // Get new value from any.
+ // IllegalArgumentException() can be thrown!
+ 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 = true;
+ }
+ else
+ {
+ // ... clear information of return parameter!
+ aOldValue.clear ();
+ aConvertedValue.clear ();
+ // Return NOTHING - "value will not be change ..."
+ bReturn = false;
+ }
+
+ return bReturn;
+}
+
+bool ActionTriggerPropertySet::impl_tryToChangeProperty(
+ const Reference< XBitmap >& aCurrentValue ,
+ const Any& aNewValue ,
+ Any& aOldValue ,
+ Any& aConvertedValue )
+{
+ // Set default return value if method failed.
+ bool bReturn = 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 = true;
+ }
+ else
+ {
+ // ... clear information of return parameter!
+ aOldValue.clear ();
+ aConvertedValue.clear ();
+ // Return NOTHING - "value will not be change ..."
+ bReturn = false;
+ }
+
+ return bReturn;
+}
+
+bool ActionTriggerPropertySet::impl_tryToChangeProperty(
+ const Reference< XInterface >& aCurrentValue ,
+ const Any& aNewValue ,
+ Any& aOldValue ,
+ Any& aConvertedValue )
+{
+ // Set default return value if method failed.
+ bool bReturn = 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 = true;
+ }
+ else
+ {
+ // ... clear information of return parameter!
+ aOldValue.clear ();
+ aConvertedValue.clear ();
+ // Return NOTHING - "value will not be change ..."
+ bReturn = false;
+ }
+
+ return bReturn;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/fwe/classes/actiontriggerseparatorpropertyset.cxx b/framework/source/fwe/classes/actiontriggerseparatorpropertyset.cxx
new file mode 100644
index 000000000..eb9d6d2ec
--- /dev/null
+++ b/framework/source/fwe/classes/actiontriggerseparatorpropertyset.cxx
@@ -0,0 +1,246 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <classes/actiontriggerseparatorpropertyset.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <cppuhelper/proptypehlp.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/queryinterface.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;
+
+namespace {
+
+// 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()
+ : OBroadcastHelper ( m_aMutex )
+ , OPropertySetHelper ( *static_cast< OBroadcastHelper * >(this) )
+ , OWeakObject ()
+ , m_nSeparatorType( 0 )
+{
+}
+
+ActionTriggerSeparatorPropertySet::~ActionTriggerSeparatorPropertySet()
+{
+}
+
+// XInterface
+Any SAL_CALL ActionTriggerSeparatorPropertySet::queryInterface( const Type& aType )
+{
+ Any a = ::cppu::queryInterface(
+ aType,
+ static_cast< XServiceInfo* >(this),
+ static_cast< XTypeProvider* >(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
+OUString SAL_CALL ActionTriggerSeparatorPropertySet::getImplementationName()
+{
+ return IMPLEMENTATIONNAME_ACTIONTRIGGERSEPARATOR;
+}
+
+sal_Bool SAL_CALL ActionTriggerSeparatorPropertySet::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Sequence< OUString > SAL_CALL ActionTriggerSeparatorPropertySet::getSupportedServiceNames()
+{
+ Sequence<OUString> seqServiceNames { SERVICENAME_ACTIONTRIGGERSEPARATOR };
+ return seqServiceNames;
+}
+
+// XTypeProvider
+Sequence< Type > SAL_CALL ActionTriggerSeparatorPropertySet::getTypes()
+{
+ // Create a static typecollection ...
+ static ::cppu::OTypeCollection ourTypeCollection(
+ cppu::UnoType<XPropertySet>::get(),
+ cppu::UnoType<XFastPropertySet>::get(),
+ cppu::UnoType<XMultiPropertySet>::get(),
+ cppu::UnoType<XServiceInfo>::get(),
+ cppu::UnoType<XTypeProvider>::get());
+
+ return ourTypeCollection.getTypes();
+}
+
+Sequence< sal_Int8 > SAL_CALL ActionTriggerSeparatorPropertySet::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+sal_Bool SAL_CALL ActionTriggerSeparatorPropertySet::convertFastPropertyValue(
+ Any& aConvertedValue,
+ Any& aOldValue,
+ sal_Int32 nHandle,
+ const Any& aValue )
+{
+ // 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)
+ bool bReturn = 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 )
+{
+ SolarMutexGuard aGuard;
+
+ // 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
+{
+ SolarMutexGuard aGuard;
+
+ // 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()
+{
+ // Define static member to give structure of properties to baseclass "OPropertySetHelper".
+ // "impl_getStaticPropertyDescriptor" is a non exported and static function, who will define a static propertytable.
+ // "true" indicates: Table is sorted by name.
+ static OPropertyArrayHelper ourInfoHelper( impl_getStaticPropertyDescriptor(), true );
+
+ return ourInfoHelper;
+}
+
+Reference< XPropertySetInfo > SAL_CALL ActionTriggerSeparatorPropertySet::getPropertySetInfo()
+{
+ // Create structure of propertysetinfo for baseclass "OPropertySetHelper".
+ // (Use method "getInfoHelper()".)
+ static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+
+ return xInfo;
+}
+
+Sequence< Property > ActionTriggerSeparatorPropertySet::impl_getStaticPropertyDescriptor()
+{
+ return
+ {
+ Property( "SeparatorType", HANDLE_TYPE, cppu::UnoType<sal_Int16>::get(), PropertyAttribute::TRANSIENT )
+ };
+}
+
+bool ActionTriggerSeparatorPropertySet::impl_tryToChangeProperty(
+ sal_Int16 aCurrentValue ,
+ const Any& aNewValue ,
+ Any& aOldValue ,
+ Any& aConvertedValue )
+{
+ // Set default return value if method failed.
+ bool bReturn = 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 = true;
+ }
+ else
+ {
+ // ... clear information of return parameter!
+ aOldValue.clear ();
+ aConvertedValue.clear ();
+ // Return NOTHING - "value will not be change ..."
+ bReturn = false;
+ }
+
+ return bReturn;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/fwe/classes/addonmenu.cxx b/framework/source/fwe/classes/addonmenu.cxx
new file mode 100644
index 000000000..80ac7c0e0
--- /dev/null
+++ b/framework/source/fwe/classes/addonmenu.cxx
@@ -0,0 +1,308 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <addonmenu.hxx>
+#include <framework/addonsoptions.hxx>
+#include <menuconfiguration.hxx>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <vcl/commandinfoprovider.hxx>
+#include <vcl/menu.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::beans;
+
+namespace framework
+{
+
+bool AddonMenuManager::HasAddonMenuElements()
+{
+ return AddonsOptions().HasAddonsMenu();
+}
+
+// Create the Add-Ons menu
+VclPtr<PopupMenu> AddonMenuManager::CreateAddonMenu( const Reference< XFrame >& rFrame )
+{
+ AddonsOptions aOptions;
+ VclPtr<PopupMenu> pAddonMenu;
+ sal_uInt16 nUniqueMenuId = ADDONMENU_ITEMID_START;
+
+ const Sequence< Sequence< PropertyValue > >& rAddonMenuEntries = aOptions.GetAddonsMenu();
+ if ( rAddonMenuEntries.hasElements() )
+ {
+ pAddonMenu = VclPtr<PopupMenu>::Create();
+ OUString aModuleIdentifier = vcl::CommandInfoProvider::GetModuleIdentifier( rFrame );
+ AddonMenuManager::BuildMenu( pAddonMenu, MENU_APPEND, nUniqueMenuId, rAddonMenuEntries, rFrame, aModuleIdentifier );
+
+ // Don't return an empty Add-On menu
+ if ( pAddonMenu->GetItemCount() == 0 )
+ {
+ pAddonMenu.disposeAndClear();
+ }
+ }
+
+ 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 const * pMenu, const OUString& aCommand )
+{
+ sal_uInt16 nPos = 0;
+ OUString 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 const * pMergeMenuBar )
+{
+ if ( !pMergeMenuBar )
+ return;
+
+ PopupMenu* pHelpMenu(nullptr);
+ sal_uInt16 nId = FindMenuId(pMergeMenuBar, ".uno:HelpMenu");
+ if ( nId != USHRT_MAX )
+ pHelpMenu = pMergeMenuBar->GetPopupMenu( nId );
+
+ if ( !pHelpMenu )
+ return;
+
+ // Add-Ons help menu items should be inserted after the "registration" menu item
+ sal_uInt16 nItemCount = pHelpMenu->GetItemCount();
+ sal_uInt16 nInsSepAfterPos = MENU_APPEND;
+ sal_uInt16 nUniqueMenuId = ADDONMENU_ITEMID_START;
+ AddonsOptions aOptions;
+
+ // try to detect the about menu item with the command URL
+ nId = FindMenuId(pHelpMenu, ".uno:About");
+ sal_uInt16 nInsPos = pHelpMenu->GetItemPos( nId );
+
+ const Sequence< Sequence< PropertyValue > >& rAddonHelpMenuEntries = aOptions.GetAddonsHelpMenu();
+
+ if ( nInsPos < nItemCount && pHelpMenu->GetItemType( nInsPos ) != MenuItemType::SEPARATOR )
+ nInsSepAfterPos = nInsPos;
+
+ OUString aModuleIdentifier = vcl::CommandInfoProvider::GetModuleIdentifier(rFrame);
+ AddonMenuManager::BuildMenu( pHelpMenu, nInsPos, nUniqueMenuId, rAddonHelpMenuEntries, rFrame, aModuleIdentifier );
+
+ if ( pHelpMenu->GetItemCount() > nItemCount )
+ {
+ if ( nInsSepAfterPos < MENU_APPEND )
+ {
+ nInsSepAfterPos += ( pHelpMenu->GetItemCount() - nItemCount );
+ if ( pHelpMenu->GetItemType( nInsSepAfterPos ) != MenuItemType::SEPARATOR )
+ pHelpMenu->InsertSeparator(OString(), nInsSepAfterPos);
+ }
+ pHelpMenu->InsertSeparator(OString(), nItemCount);
+ }
+}
+
+// Merge the addon popup menus into the given menu bar at the provided pos.
+void AddonMenuManager::MergeAddonPopupMenus( const Reference< XFrame >& rFrame,
+ sal_uInt16 nMergeAtPos,
+ MenuBar* pMergeMenuBar )
+{
+ if ( !pMergeMenuBar )
+ return;
+
+ AddonsOptions aAddonsOptions;
+ sal_uInt16 nInsertPos = nMergeAtPos;
+
+ OUString aTitle;
+ OUString aURL;
+ OUString aTarget;
+ OUString aImageId;
+ OUString aContext;
+ Sequence< Sequence< PropertyValue > > aAddonSubMenu;
+ sal_uInt16 nUniqueMenuId = ADDONMENU_ITEMID_START;
+
+ OUString aModuleIdentifier = vcl::CommandInfoProvider::GetModuleIdentifier(rFrame);
+
+ const Sequence< Sequence< PropertyValue > >& rAddonMenuEntries = aAddonsOptions.GetAddonsMenuBarPart();
+ for ( const Sequence< PropertyValue >& rEntry : rAddonMenuEntries )
+ {
+ AddonMenuManager::GetMenuEntry( rEntry,
+ aTitle,
+ aURL,
+ aTarget,
+ aImageId,
+ aContext,
+ aAddonSubMenu );
+ if ( !aTitle.isEmpty() &&
+ !aURL.isEmpty() &&
+ aAddonSubMenu.hasElements() &&
+ AddonMenuManager::IsCorrectContext( aModuleIdentifier, aContext ))
+ {
+ sal_uInt16 nId = nUniqueMenuId++;
+ VclPtrInstance<PopupMenu> pAddonPopupMenu;
+
+ AddonMenuManager::BuildMenu( pAddonPopupMenu, MENU_APPEND, nUniqueMenuId, aAddonSubMenu, rFrame, aModuleIdentifier );
+
+ if ( pAddonPopupMenu->GetItemCount() > 0 )
+ {
+ pMergeMenuBar->InsertItem( nId, aTitle, MenuItemBits::NONE, OString(), nInsertPos++ );
+ pMergeMenuBar->SetPopupMenu( nId, pAddonPopupMenu );
+
+ // Store the command URL into the VCL menu bar for later identification
+ pMergeMenuBar->SetItemCommand( nId, aURL );
+ }
+ else
+ pAddonPopupMenu.disposeAndClear();
+ }
+ }
+}
+
+// Insert the menu and sub menu entries into pCurrentMenu with the aAddonMenuDefinition provided
+void AddonMenuManager::BuildMenu( PopupMenu* pCurrentMenu,
+ sal_uInt16 nInsPos,
+ sal_uInt16& nUniqueMenuId,
+ const Sequence< Sequence< PropertyValue > >& aAddonMenuDefinition,
+ const Reference< XFrame >& rFrame,
+ const OUString& rModuleIdentifier )
+{
+ Sequence< Sequence< PropertyValue > > aAddonSubMenu;
+ bool bInsertSeparator = false;
+ sal_uInt32 i = 0;
+ sal_uInt32 nElements = 0;
+ sal_uInt32 nCount = aAddonMenuDefinition.getLength();
+
+ OUString aTitle;
+ OUString aURL;
+ OUString aTarget;
+ OUString aImageId;
+ OUString aContext;
+
+ for ( i = 0; i < nCount; ++i )
+ {
+ GetMenuEntry( aAddonMenuDefinition[i], aTitle, aURL, aTarget, aImageId, aContext, aAddonSubMenu );
+
+ if ( !IsCorrectContext( rModuleIdentifier, aContext ) || ( aTitle.isEmpty() && aURL.isEmpty() ))
+ continue;
+
+ if ( aURL == "private:separator" )
+ bInsertSeparator = true;
+ else
+ {
+ VclPtr<PopupMenu> pSubMenu;
+ if ( aAddonSubMenu.hasElements() )
+ {
+ pSubMenu = VclPtr<PopupMenu>::Create();
+ AddonMenuManager::BuildMenu( pSubMenu, MENU_APPEND, nUniqueMenuId, aAddonSubMenu, rFrame, rModuleIdentifier );
+
+ // Don't create a menu item for an empty sub menu
+ if ( pSubMenu->GetItemCount() == 0 )
+ {
+ pSubMenu.disposeAndClear();
+ 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 = false;
+ pCurrentMenu->InsertSeparator(OString(), nInsPos);
+ nInsPos = AddonMenuManager::GetNextPos( nInsPos );
+ }
+
+ sal_uInt16 nId = nUniqueMenuId++;
+ pCurrentMenu->InsertItem(nId, aTitle, MenuItemBits::NONE, OString(), 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!
+ void* nAttributePtr = MenuAttributes::CreateAttribute(aTarget, aImageId);
+ pCurrentMenu->SetUserValue(nId, nAttributePtr, MenuAttributes::ReleaseAttribute);
+ 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,
+ OUString& rTitle,
+ OUString& rURL,
+ OUString& rTarget,
+ OUString& rImageId,
+ OUString& rContext,
+ Sequence< Sequence< PropertyValue > >& rAddonSubMenu )
+{
+ // Reset submenu parameter
+ rAddonSubMenu = Sequence< Sequence< PropertyValue > >();
+
+ for ( const PropertyValue& rEntry : rAddonMenuEntry )
+ {
+ OUString aMenuEntryPropName = rEntry.Name;
+ if ( aMenuEntryPropName == ADDONSMENUITEM_STRING_URL )
+ rEntry.Value >>= rURL;
+ else if ( aMenuEntryPropName == ADDONSMENUITEM_STRING_TITLE )
+ rEntry.Value >>= rTitle;
+ else if ( aMenuEntryPropName == ADDONSMENUITEM_STRING_TARGET )
+ rEntry.Value >>= rTarget;
+ else if ( aMenuEntryPropName == ADDONSMENUITEM_STRING_IMAGEIDENTIFIER )
+ rEntry.Value >>= rImageId;
+ else if ( aMenuEntryPropName == ADDONSMENUITEM_STRING_SUBMENU )
+ rEntry.Value >>= rAddonSubMenu;
+ else if ( aMenuEntryPropName == ADDONSMENUITEM_STRING_CONTEXT )
+ rEntry.Value >>= rContext;
+ }
+}
+
+// Check if the context string matches the provided xModel context
+bool AddonMenuManager::IsCorrectContext( const OUString& rModuleIdentifier, const OUString& rContext )
+{
+ if ( rContext.isEmpty() )
+ return true;
+
+ if ( !rModuleIdentifier.isEmpty() )
+ {
+ sal_Int32 nIndex = rContext.indexOf( rModuleIdentifier );
+ return ( nIndex >= 0 );
+ }
+
+ return false;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/fwe/classes/addonsoptions.cxx b/framework/source/fwe/classes/addonsoptions.cxx
new file mode 100644
index 000000000..725bec2f5
--- /dev/null
+++ b/framework/source/fwe/classes/addonsoptions.cxx
@@ -0,0 +1,1957 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <framework/addonsoptions.hxx>
+#include <o3tl/safeint.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/configitem.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <tools/stream.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <comphelper/getexpandeduri.hxx>
+#include <comphelper/processfactory.hxx>
+#include <vcl/dibtools.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <vcl/toolbox.hxx>
+#include <vcl/svapp.hxx>
+
+#include <algorithm>
+#include <unordered_map>
+#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;
+using namespace ::com::sun::star;
+
+#define ROOTNODE_ADDONMENU "Office.Addons"
+#define PATHDELIMITER OUString("/" )
+#define SEPARATOR_URL "private:separator"
+
+#define PROPERTYNAME_URL ADDONSMENUITEM_STRING_URL
+#define PROPERTYNAME_TITLE ADDONSMENUITEM_STRING_TITLE
+#define PROPERTYNAME_TARGET ADDONSMENUITEM_STRING_TARGET
+#define PROPERTYNAME_IMAGEIDENTIFIER ADDONSMENUITEM_STRING_IMAGEIDENTIFIER
+#define PROPERTYNAME_CONTEXT ADDONSMENUITEM_STRING_CONTEXT
+#define PROPERTYNAME_SUBMENU ADDONSMENUITEM_STRING_SUBMENU
+
+#define IMAGES_NODENAME "UserDefinedImages"
+
+// 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 INDEX_ALIGN 8
+#define INDEX_AUTOSIZE 9
+#define INDEX_OWNERDRAW 10
+#define INDEX_MANDATORY 11
+#define INDEX_STYLE 12
+#define PROPERTYCOUNT_INDEX 13
+
+// 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_NOTEBOOKBARITEM 8
+#define OFFSET_NOTEBOOKBARITEM_URL 0
+#define OFFSET_NOTEBOOKBARITEM_TITLE 1
+#define OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER 2
+#define OFFSET_NOTEBOOKBARITEM_TARGET 3
+#define OFFSET_NOTEBOOKBARITEM_CONTEXT 4
+#define OFFSET_NOTEBOOKBARITEM_CONTROLTYPE 5
+#define OFFSET_NOTEBOOKBARITEM_WIDTH 6
+#define OFFSET_NOTEBOOKBARITEM_STYLE 7
+
+// The following order is mandatory. Please add properties at the end!
+#define PROPERTYCOUNT_STATUSBARITEM 8
+#define OFFSET_STATUSBARITEM_URL 0
+#define OFFSET_STATUSBARITEM_TITLE 1
+#define OFFSET_STATUSBARITEM_CONTEXT 2
+#define OFFSET_STATUSBARITEM_ALIGN 3
+#define OFFSET_STATUSBARITEM_AUTOSIZE 4
+#define OFFSET_STATUSBARITEM_OWNERDRAW 5
+#define OFFSET_STATUSBARITEM_MANDATORY 6
+#define OFFSET_STATUSBARITEM_WIDTH 7
+
+// 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 PROPERTYCOUNT_MERGE_NOTEBOOKBAR 7
+#define OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBAR 0
+#define OFFSET_MERGENOTEBOOKBAR_MERGEPOINT 1
+#define OFFSET_MERGENOTEBOOKBAR_MERGECOMMAND 2
+#define OFFSET_MERGENOTEBOOKBAR_MERGECOMMANDPARAMETER 3
+#define OFFSET_MERGENOTEBOOKBAR_MERGEFALLBACK 4
+#define OFFSET_MERGENOTEBOOKBAR_MERGECONTEXT 5
+#define OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBARITEMS 6
+
+#define PROPERTYCOUNT_MERGE_STATUSBAR 6
+#define OFFSET_MERGESTATUSBAR_MERGEPOINT 0
+#define OFFSET_MERGESTATUSBAR_MERGECOMMAND 1
+#define OFFSET_MERGESTATUSBAR_MERGECOMMANDPARAMETER 2
+#define OFFSET_MERGESTATUSBAR_MERGEFALLBACK 3
+#define OFFSET_MERGESTATUSBAR_MERGECONTEXT 4
+#define OFFSET_MERGESTATUSBAR_STATUSBARITEMS 5
+
+// 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();
+ virtual ~AddonsOptions_Impl() override;
+
+ // overridden methods of baseclass
+
+ /*-****************************************************************************************************
+ @short called for notify of configmanager
+ @descr This 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.
+ *//*-*****************************************************************************************************/
+
+ virtual void Notify( const Sequence< OUString >& lPropertyNames ) override;
+
+ // 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!
+ *//*-*****************************************************************************************************/
+
+ bool HasAddonsMenu () const;
+ sal_Int32 GetAddonsToolBarCount() const;
+ sal_Int32 GetAddonsNotebookBarCount() const;
+ const Sequence< Sequence< PropertyValue > >& GetAddonsMenu () const { return m_aCachedMenuProperties;}
+ const Sequence< Sequence< PropertyValue > >& GetAddonsMenuBarPart () const { return m_aCachedMenuBarPartProperties;}
+ const Sequence< Sequence< PropertyValue > >& GetAddonsToolBarPart ( sal_uInt32 nIndex ) const;
+ const Sequence< Sequence< PropertyValue > >& GetAddonsNotebookBarPart ( sal_uInt32 nIndex ) const;
+ OUString GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const;
+ OUString GetAddonsNotebookBarResourceName( sal_uInt32 nIndex ) const;
+ const Sequence< Sequence< PropertyValue > >& GetAddonsHelpMenu () const { return m_aCachedHelpMenuProperties;}
+ Image GetImageFromURL( const OUString& aURL, bool bBig, bool bNoScale );
+ const MergeMenuInstructionContainer& GetMergeMenuInstructions() const { return m_aCachedMergeMenuInsContainer;}
+ bool GetMergeToolbarInstructions( const OUString& rToolbarName, MergeToolbarInstructionContainer& rToolbarInstructions ) const;
+ bool GetMergeNotebookBarInstructions( const OUString& rNotebookBarName, MergeNotebookBarInstructionContainer& rNotebookBarInstructions ) const;
+ const MergeStatusbarInstructionContainer& GetMergeStatusbarInstructions() const { return m_aCachedStatusbarMergingInstructions;}
+ void ReadConfigurationData();
+
+ private:
+ enum ImageSize
+ {
+ IMGSIZE_SMALL = 0,
+ IMGSIZE_BIG
+ };
+
+ struct OneImageEntry
+ {
+ Image aScaled; ///< cached scaled image
+ Image aImage; ///< original un-scaled image
+ OUString aURL; ///< URL in case it is not loaded yet
+ };
+
+ struct ImageEntry
+ {
+ // if the image is set, it was embedded in some way,
+ // otherwise we use the associated URL to load on demand
+
+ // accessed in this order
+ OneImageEntry aSizeEntry[2];
+ ImageEntry() {}
+ void addImage(ImageSize eSize, const Image &rImage, const OUString &rURL);
+ };
+
+ typedef std::unordered_map< OUString, ImageEntry > ImageManager;
+ typedef std::unordered_map< OUString, sal_uInt32 > StringToIndexMap;
+ typedef std::vector< Sequence< Sequence< PropertyValue > > > AddonToolBars;
+ typedef std::vector< Sequence< Sequence< PropertyValue > > > AddonNotebookBars;
+ typedef std::unordered_map< OUString, MergeToolbarInstructionContainer > ToolbarMergingInstructions;
+ typedef std::unordered_map< OUString, MergeNotebookBarInstructionContainer > NotebookBarMergingInstructions;
+
+ /*-****************************************************************************************************
+ @short return list of key names of our configuration management which represent our module tree
+ @descr These methods return the current list of key names! We need it to get needed values from our
+ configuration management!
+ @param "nCount" , returns count of menu entries for "new"
+ @return A list of configuration key names is returned.
+ *//*-*****************************************************************************************************/
+
+ void ReadAddonMenuSet( Sequence< Sequence< PropertyValue > >& aAddonMenuSeq );
+ void ReadOfficeMenuBarSet( Sequence< Sequence< PropertyValue > >& aAddonOfficeMenuBarSeq );
+ void ReadOfficeToolBarSet( AddonToolBars& rAddonOfficeToolBars, std::vector< OUString >& rAddonOfficeToolBarResNames );
+ bool ReadToolBarItemSet( const OUString& rToolBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& aAddonOfficeToolBarSeq );
+ void ReadOfficeNotebookBarSet( AddonNotebookBars& rAddonOfficeNotebookBars, std::vector< OUString >& rAddonOfficeNotebookBarResNames );
+ bool ReadNotebookBarItemSet( const OUString& rNotebookBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& aAddonOfficeNotebookBarSeq );
+
+ void ReadOfficeHelpSet( Sequence< Sequence< PropertyValue > >& aAddonOfficeHelpMenuSeq );
+ void ReadImages( ImageManager& aImageManager );
+ void ReadMenuMergeInstructions( MergeMenuInstructionContainer& rContainer );
+ void ReadToolbarMergeInstructions( ToolbarMergingInstructions& rToolbarMergeMap );
+ void ReadNotebookBarMergeInstructions( NotebookBarMergingInstructions& rNotebookBarMergeMap );
+ void ReadStatusbarMergeInstructions( MergeStatusbarInstructionContainer& rContainer );
+
+ void ReadMergeMenuData( const OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeMenu );
+ bool ReadMergeToolbarData( const OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeToolbarItems );
+ bool ReadMergeNotebookBarData( const OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeNotebookBarItems );
+ bool ReadMergeStatusbarData( const OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeStatusbar );
+ bool ReadMenuItem( const OUString& aMenuItemNodeName, Sequence< PropertyValue >& aMenuItem, bool bIgnoreSubMenu = false );
+ bool ReadPopupMenu( const OUString& aPopupMenuNodeName, Sequence< PropertyValue >& aPopupMenu );
+ void AppendPopupMenu( Sequence< PropertyValue >& aTargetPopupMenu, const Sequence< PropertyValue >& rSourcePopupMenu );
+ bool ReadToolBarItem( const OUString& aToolBarItemNodeName, Sequence< PropertyValue >& aToolBarItem );
+ bool ReadNotebookBarItem( const OUString& aNotebookBarItemNodeName, Sequence< PropertyValue >& aNotebookBarItem );
+
+ bool ReadStatusBarItem( const OUString& aStatusbarItemNodeName, Sequence< PropertyValue >& aStatusbarItem );
+ std::unique_ptr<ImageEntry> ReadImageData( const OUString& aImagesNodeName );
+ void ReadAndAssociateImages( const OUString& aURL, const OUString& aImageId );
+ Image ReadImageFromURL( const OUString& aURL );
+ bool HasAssociatedImages( const OUString& aURL );
+ void SubstituteVariables( OUString& aURL );
+
+ void ReadSubMenuEntries( const Sequence< OUString >& aSubMenuNodeNames, Sequence< Sequence< PropertyValue > >& rSubMenu );
+ OUString GeneratePrefixURL();
+
+ Sequence< OUString > GetPropertyNamesMenuItem( const OUString& aPropertyRootNode ) const;
+ Sequence< OUString > GetPropertyNamesPopupMenu( const OUString& aPropertyRootNode ) const;
+ Sequence< OUString > GetPropertyNamesToolBarItem( const OUString& aPropertyRootNode ) const;
+ Sequence< OUString > GetPropertyNamesNotebookBarItem( const OUString& aPropertyRootNode ) const;
+
+ Sequence< OUString > GetPropertyNamesStatusbarItem( const OUString& aPropertyRootNode ) const;
+ Sequence< OUString > GetPropertyNamesImages( const OUString& aPropertyRootNode ) const;
+ bool CreateImageFromSequence( Image& rImage, Sequence< sal_Int8 >& rBitmapDataSeq ) const;
+
+ DECL_LINK(NotifyEvent, void*, void);
+
+ virtual void ImplCommit() override;
+
+ // private member
+
+ private:
+ sal_Int32 m_nRootAddonPopupMenuId;
+ OUString m_aPropNames[PROPERTYCOUNT_INDEX];
+ OUString m_aPropImagesNames[PROPERTYCOUNT_IMAGES];
+ OUString m_aPropMergeMenuNames[PROPERTYCOUNT_MERGE_MENUBAR];
+ OUString m_aPropMergeToolbarNames[PROPERTYCOUNT_MERGE_TOOLBAR];
+ OUString m_aPropMergeNotebookBarNames[PROPERTYCOUNT_MERGE_NOTEBOOKBAR];
+ OUString m_aPropMergeStatusbarNames[PROPERTYCOUNT_MERGE_STATUSBAR];
+ OUString m_aPathDelimiter;
+ OUString m_aRootAddonPopupMenuURLPrexfix;
+ Sequence< Sequence< PropertyValue > > m_aCachedMenuProperties;
+ Sequence< Sequence< PropertyValue > > m_aCachedMenuBarPartProperties;
+ AddonToolBars m_aCachedToolBarPartProperties;
+ AddonNotebookBars m_aCachedNotebookBarPartProperties;
+ std::vector< OUString > m_aCachedToolBarPartResourceNames;
+ std::vector< OUString > m_aCachedNotebookBarPartResourceNames;
+ Sequence< Sequence< PropertyValue > > m_aCachedHelpMenuProperties;
+ ImageManager m_aImageManager;
+ Sequence< Sequence< PropertyValue > > m_aEmptyAddonToolBar;
+ Sequence< Sequence< PropertyValue > > m_aEmptyAddonNotebookBar;
+ MergeMenuInstructionContainer m_aCachedMergeMenuInsContainer;
+ ToolbarMergingInstructions m_aCachedToolbarMergingInstructions;
+ NotebookBarMergingInstructions m_aCachedNotebookBarMergingInstructions;
+ MergeStatusbarInstructionContainer m_aCachedStatusbarMergingInstructions;
+};
+
+void AddonsOptions_Impl::ImageEntry::addImage(ImageSize eSize,
+ const Image &rImage,
+ const OUString &rURL)
+{
+ aSizeEntry[static_cast<int>(eSize)].aImage = rImage;
+ aSizeEntry[static_cast<int>(eSize)].aURL = rURL;
+}
+
+// constructor
+
+AddonsOptions_Impl::AddonsOptions_Impl()
+ // Init baseclasses first
+ : ConfigItem( ROOTNODE_ADDONMENU ),
+ m_nRootAddonPopupMenuId( 0 ),
+ m_aPathDelimiter( PATHDELIMITER ),
+ m_aRootAddonPopupMenuURLPrexfix( ADDONSPOPUPMENU_URL_PREFIX_STR )
+{
+ // 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 ] = "ControlType";
+ m_aPropNames[ INDEX_WIDTH ] = "Width";
+ m_aPropNames[ INDEX_ALIGN ] = "Alignment";
+ m_aPropNames[ INDEX_AUTOSIZE ] = "AutoSize";
+ m_aPropNames[ INDEX_OWNERDRAW ] = "OwnerDraw";
+ m_aPropNames[ INDEX_MANDATORY ] = "Mandatory";
+ m_aPropNames[ INDEX_STYLE ] = "Style";
+
+ // initialize array with fixed images property names
+ m_aPropImagesNames[ OFFSET_IMAGES_SMALL ] = "ImageSmall";
+ m_aPropImagesNames[ OFFSET_IMAGES_BIG ] = "ImageBig";
+ m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC ] = "ImageSmallHC";
+ m_aPropImagesNames[ OFFSET_IMAGES_BIGHC ] = "ImageBigHC";
+ m_aPropImagesNames[ OFFSET_IMAGES_SMALL_URL ] = "ImageSmallURL";
+ m_aPropImagesNames[ OFFSET_IMAGES_BIG_URL ] = "ImageBigURL";
+ m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC_URL ] = "ImageSmallHCURL";
+ m_aPropImagesNames[ OFFSET_IMAGES_BIGHC_URL ] = "ImageBigHCURL";
+
+ // initialize array with fixed merge menu property names
+ m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT ] = "MergePoint";
+ m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND ] = "MergeCommand";
+ m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
+ m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ] = "MergeFallback";
+ m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT ] = "MergeContext";
+ m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS ] = "MenuItems";
+
+ m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBAR ] = "MergeToolBar";
+ m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEPOINT ] = "MergePoint";
+ m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMAND ] = "MergeCommand";
+ m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
+ m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEFALLBACK ] = "MergeFallback";
+ m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECONTEXT ] = "MergeContext";
+ m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBARITEMS ] = "ToolBarItems";
+
+ m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBAR ] = "MergeNotebookBar";
+ m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGEPOINT ] = "MergePoint";
+ m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGECOMMAND ] = "MergeCommand";
+ m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
+ m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGEFALLBACK ] = "MergeFallback";
+ m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGECONTEXT ] = "MergeContext";
+ m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBARITEMS ] = "NotebookBarItems";
+
+ m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGEPOINT ] = "MergePoint";
+ m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGECOMMAND ] = "MergeCommand";
+ m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
+ m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGEFALLBACK ] = "MergeFallback";
+ m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGECONTEXT ] = "MergeContext";
+ m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_STATUSBARITEMS ] = "StatusBarItems";
+
+ ReadConfigurationData();
+
+ // Enable notification mechanism of our baseclass.
+ // We need it to get information about changes outside these class on our used configuration keys!
+ Sequence<OUString> aNotifySeq { "AddonUI" };
+ EnableNotification( aNotifySeq );
+}
+
+// destructor
+
+AddonsOptions_Impl::~AddonsOptions_Impl()
+{
+ assert(!IsModified()); // should have been committed
+}
+
+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_aCachedNotebookBarPartProperties = AddonNotebookBars();
+ m_aCachedHelpMenuProperties = Sequence< Sequence< PropertyValue > >();
+ m_aCachedToolBarPartResourceNames.clear();
+ m_aCachedNotebookBarPartResourceNames.clear();
+ m_aImageManager = ImageManager();
+
+ ReadAddonMenuSet( m_aCachedMenuProperties );
+ ReadOfficeMenuBarSet( m_aCachedMenuBarPartProperties );
+ ReadOfficeToolBarSet( m_aCachedToolBarPartProperties, m_aCachedToolBarPartResourceNames );
+ ReadOfficeNotebookBarSet( m_aCachedNotebookBarPartProperties, m_aCachedNotebookBarPartResourceNames );
+
+ ReadOfficeHelpSet( m_aCachedHelpMenuProperties );
+ ReadImages( m_aImageManager );
+
+ m_aCachedMergeMenuInsContainer.clear();
+ m_aCachedToolbarMergingInstructions.clear();
+ m_aCachedNotebookBarMergingInstructions.clear();
+ m_aCachedStatusbarMergingInstructions.clear();
+
+ ReadMenuMergeInstructions( m_aCachedMergeMenuInsContainer );
+ ReadToolbarMergeInstructions( m_aCachedToolbarMergingInstructions );
+ ReadNotebookBarMergeInstructions( m_aCachedNotebookBarMergingInstructions );
+ ReadStatusbarMergeInstructions( m_aCachedStatusbarMergingInstructions );
+}
+
+// public method
+
+void AddonsOptions_Impl::Notify( const Sequence< OUString >& /*lPropertyNames*/ )
+{
+ Application::PostUserEvent(LINK(this, AddonsOptions_Impl, NotifyEvent));
+}
+
+// public method
+
+void AddonsOptions_Impl::ImplCommit()
+{
+ SAL_WARN("fwk", "AddonsOptions_Impl::ImplCommit(): Not implemented yet!");
+}
+
+// public method
+
+bool AddonsOptions_Impl::HasAddonsMenu() const
+{
+ return m_aCachedMenuProperties.hasElements();
+}
+
+// public method
+
+sal_Int32 AddonsOptions_Impl::GetAddonsToolBarCount() const
+{
+ return m_aCachedToolBarPartProperties.size();
+}
+
+// public method
+
+sal_Int32 AddonsOptions_Impl::GetAddonsNotebookBarCount() const
+{
+ return m_aCachedNotebookBarPartProperties.size();
+}
+
+// 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 Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsNotebookBarPart( sal_uInt32 nIndex ) const
+{
+ if ( /*nIndex >= 0 &&*/ nIndex < m_aCachedNotebookBarPartProperties.size() )
+ return m_aCachedNotebookBarPartProperties[nIndex];
+ else
+ return m_aEmptyAddonNotebookBar;
+}
+
+// public method
+
+OUString AddonsOptions_Impl::GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const
+{
+ if ( nIndex < m_aCachedToolBarPartResourceNames.size() )
+ return m_aCachedToolBarPartResourceNames[nIndex];
+ else
+ return OUString();
+}
+
+// public method
+
+OUString AddonsOptions_Impl::GetAddonsNotebookBarResourceName( sal_uInt32 nIndex ) const
+{
+ if ( nIndex < m_aCachedNotebookBarPartResourceNames.size() )
+ return m_aCachedNotebookBarPartResourceNames[nIndex];
+ else
+ return OUString();
+}
+
+// public method
+
+bool AddonsOptions_Impl::GetMergeToolbarInstructions(
+ const 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
+
+bool AddonsOptions_Impl::GetMergeNotebookBarInstructions(
+ const OUString& rNotebookBarName,
+ MergeNotebookBarInstructionContainer& rNotebookBarInstructions ) const
+{
+ NotebookBarMergingInstructions::const_iterator pIter = m_aCachedNotebookBarMergingInstructions.find( rNotebookBarName );
+ if ( pIter != m_aCachedNotebookBarMergingInstructions.end() )
+ {
+ rNotebookBarInstructions = pIter->second;
+ return true;
+ }
+ else
+ return false;
+}
+
+// public method
+
+static Image ScaleImage( const Image &rImage, bool bBig )
+{
+ Size aSize = ToolBox::GetDefaultImageSize(bBig ? ToolBoxButtonSize::Large : ToolBoxButtonSize::Small);
+ BitmapEx aScaleBmp(rImage.GetBitmapEx());
+ SAL_INFO("fwk", "Addons: expensive scale image from "
+ << aScaleBmp.GetSizePixel() << " to " << aSize);
+ aScaleBmp.Scale(aSize, BmpScaleFlag::BestQuality);
+ return Image(aScaleBmp);
+}
+
+Image AddonsOptions_Impl::GetImageFromURL( const OUString& aURL, bool bBig, bool bNoScale )
+{
+ Image aImage;
+
+ SAL_INFO("fwk", "Expensive: Addons GetImageFromURL " << aURL <<
+ " big " << (bBig?"big":"little") <<
+ " scale " << (bNoScale ? "noscale" : "scale"));
+
+ ImageManager::iterator pIter = m_aImageManager.find(aURL);
+ if ( pIter != m_aImageManager.end() )
+ {
+ ImageSize eSize = bBig ? IMGSIZE_BIG : IMGSIZE_SMALL;
+ int nIdx = static_cast<int>(eSize);
+ int nOtherIdx = nIdx ? 0 : 1;
+
+ OneImageEntry& rSizeEntry = pIter->second.aSizeEntry[nIdx];
+ OneImageEntry& rOtherEntry = pIter->second.aSizeEntry[nOtherIdx];
+ // actually read the image ...
+ if (!rSizeEntry.aImage)
+ rSizeEntry.aImage = ReadImageFromURL(rSizeEntry.aURL);
+
+ if (!rSizeEntry.aImage)
+ { // try the other size and scale it
+ aImage = ScaleImage(ReadImageFromURL(rOtherEntry.aURL), bBig);
+ rSizeEntry.aImage = aImage;
+ if (!rSizeEntry.aImage)
+ SAL_WARN("fwk", "failed to load addons image " << aURL);
+ }
+
+ // FIXME: bNoScale is not terribly meaningful or useful
+
+ if (!aImage && bNoScale)
+ aImage = rSizeEntry.aImage;
+
+ if (!aImage && !!rSizeEntry.aScaled)
+ aImage = rSizeEntry.aScaled;
+
+ else // scale to the correct size for the theme / toolbox
+ {
+ aImage = rSizeEntry.aImage;
+ if (!aImage) // use and scale the other if one size is missing
+ aImage = rOtherEntry.aImage;
+
+ aImage = ScaleImage(aImage, bBig);
+ rSizeEntry.aScaled = aImage; // cache for next time
+ }
+ }
+
+ return aImage;
+}
+
+void AddonsOptions_Impl::ReadAddonMenuSet( Sequence< Sequence< PropertyValue > >& rAddonMenuSeq )
+{
+ // Read the AddonMenu set and fill property sequences
+ OUString aAddonMenuNodeName( "AddonUI/AddonMenu" );
+ Sequence< OUString > aAddonMenuNodeSeq = GetNodeNames( aAddonMenuNodeName );
+ 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++ )
+ {
+ 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;
+ }
+ }
+}
+
+void AddonsOptions_Impl::ReadOfficeHelpSet( Sequence< Sequence< PropertyValue > >& rAddonOfficeHelpMenuSeq )
+{
+ // Read the AddonMenu set and fill property sequences
+ OUString aAddonHelpMenuNodeName( "AddonUI/OfficeHelp" );
+ Sequence< OUString > aAddonHelpMenuNodeSeq = GetNodeNames( aAddonHelpMenuNodeName );
+ 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++ )
+ {
+ OUString aRootMenuItemNode( aAddonHelpMenuItemNode + aAddonHelpMenuNodeSeq[n] );
+
+ // Read the MenuItem
+ if ( ReadMenuItem( aRootMenuItemNode, aMenuItem, true ) )
+ {
+ // Successfully read a menu item, append to our list
+ sal_uInt32 nMenuItemCount = rAddonOfficeHelpMenuSeq.getLength() + 1;
+ rAddonOfficeHelpMenuSeq.realloc( nMenuItemCount );
+ rAddonOfficeHelpMenuSeq[nIndex++] = aMenuItem;
+ }
+ }
+}
+
+void AddonsOptions_Impl::ReadOfficeMenuBarSet( Sequence< Sequence< PropertyValue > >& rAddonOfficeMenuBarSeq )
+{
+ // Read the OfficeMenuBar set and fill property sequences
+ OUString aAddonMenuBarNodeName( "AddonUI/OfficeMenuBar" );
+ Sequence< OUString > aAddonMenuBarNodeSeq = GetNodeNames( aAddonMenuBarNodeName );
+ 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++ )
+ {
+ OUString aPopupMenuNode( aAddonMenuBarNode + aAddonMenuBarNodeSeq[n] );
+
+ // Read the MenuItem
+ if ( ReadPopupMenu( aPopupMenuNode, aPopupMenu ) )
+ {
+ // Successfully read a popup menu, append to our list
+ 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.emplace( aPopupTitle, nIndex );
+ ++nIndex;
+ }
+ }
+ }
+ }
+}
+
+void AddonsOptions_Impl::ReadOfficeToolBarSet( AddonToolBars& rAddonOfficeToolBars, std::vector< OUString >& rAddonOfficeToolBarResNames )
+{
+ // Read the OfficeToolBar set and fill property sequences
+ OUString aAddonToolBarNodeName( "AddonUI/OfficeToolBar" );
+ Sequence< OUString > aAddonToolBarNodeSeq = GetNodeNames( aAddonToolBarNodeName );
+ OUString aAddonToolBarNode( aAddonToolBarNodeName + m_aPathDelimiter );
+
+ sal_uInt32 nCount = aAddonToolBarNodeSeq.getLength();
+
+ for ( sal_uInt32 n = 0; n < nCount; n++ )
+ {
+ OUString aToolBarItemNode( aAddonToolBarNode + aAddonToolBarNodeSeq[n] );
+ rAddonOfficeToolBarResNames.push_back( aAddonToolBarNodeSeq[n] );
+ rAddonOfficeToolBars.push_back( m_aEmptyAddonToolBar );
+ ReadToolBarItemSet( aToolBarItemNode, rAddonOfficeToolBars[n] );
+ }
+}
+
+bool AddonsOptions_Impl::ReadToolBarItemSet( const OUString& rToolBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& rAddonOfficeToolBarSeq )
+{
+ sal_uInt32 nToolBarItemCount = rAddonOfficeToolBarSeq.getLength();
+ OUString aAddonToolBarItemSetNode( rToolBarItemSetNodeName + m_aPathDelimiter );
+ Sequence< 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++ )
+ {
+ OUString aToolBarItemNode( aAddonToolBarItemSetNode + aAddonToolBarItemSetNodeSeq[n] );
+
+ // Read the ToolBarItem
+ if ( ReadToolBarItem( aToolBarItemNode, aToolBarItem ) )
+ {
+ // Successfully read a toolbar item, append to our list
+ sal_uInt32 nAddonCount = rAddonOfficeToolBarSeq.getLength();
+ rAddonOfficeToolBarSeq.realloc( nAddonCount+1 );
+ rAddonOfficeToolBarSeq[nAddonCount] = aToolBarItem;
+ }
+ }
+
+ return ( o3tl::make_unsigned(rAddonOfficeToolBarSeq.getLength()) > nToolBarItemCount );
+}
+
+void AddonsOptions_Impl::ReadOfficeNotebookBarSet(
+ AddonNotebookBars& rAddonOfficeNotebookBars,
+ std::vector<OUString>& rAddonOfficeNotebookBarResNames)
+{
+ // Read the OfficeToolBar set and fill property sequences
+ OUString aAddonNotebookBarNodeName("AddonUI/OfficeNotebookBar");
+ Sequence<OUString> aAddonNotebookBarNodeSeq = GetNodeNames(aAddonNotebookBarNodeName);
+ OUString aAddonNotebookBarNode(aAddonNotebookBarNodeName + m_aPathDelimiter);
+
+ sal_uInt32 nCount = aAddonNotebookBarNodeSeq.getLength();
+
+ for (sal_uInt32 n = 0; n < nCount; n++)
+ {
+ OUString aNotebookBarItemNode(aAddonNotebookBarNode + aAddonNotebookBarNodeSeq[n]);
+ rAddonOfficeNotebookBarResNames.push_back(aAddonNotebookBarNodeSeq[n]);
+ rAddonOfficeNotebookBars.push_back(m_aEmptyAddonNotebookBar);
+ ReadNotebookBarItemSet(aNotebookBarItemNode, rAddonOfficeNotebookBars[n]);
+ }
+}
+
+bool AddonsOptions_Impl::ReadNotebookBarItemSet(
+ const OUString& rNotebookBarItemSetNodeName,
+ Sequence<Sequence<PropertyValue>>& rAddonOfficeNotebookBarSeq)
+{
+ sal_uInt32 nNotebookBarItemCount = rAddonOfficeNotebookBarSeq.getLength();
+ OUString aAddonNotebookBarItemSetNode(rNotebookBarItemSetNodeName + m_aPathDelimiter);
+ Sequence<OUString> aAddonNotebookBarItemSetNodeSeq = GetNodeNames(rNotebookBarItemSetNodeName);
+ Sequence<PropertyValue> aNotebookBarItem(PROPERTYCOUNT_NOTEBOOKBARITEM);
+
+ // Init the property value sequence
+ aNotebookBarItem[OFFSET_NOTEBOOKBARITEM_URL].Name = m_aPropNames[INDEX_URL];
+ aNotebookBarItem[OFFSET_NOTEBOOKBARITEM_TITLE].Name = m_aPropNames[INDEX_TITLE];
+ aNotebookBarItem[OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER].Name
+ = m_aPropNames[INDEX_IMAGEIDENTIFIER];
+ aNotebookBarItem[OFFSET_NOTEBOOKBARITEM_TARGET].Name = m_aPropNames[INDEX_TARGET];
+ aNotebookBarItem[OFFSET_NOTEBOOKBARITEM_CONTEXT].Name = m_aPropNames[INDEX_CONTEXT];
+ aNotebookBarItem[OFFSET_NOTEBOOKBARITEM_CONTROLTYPE].Name = m_aPropNames[INDEX_CONTROLTYPE];
+ aNotebookBarItem[OFFSET_NOTEBOOKBARITEM_WIDTH].Name = m_aPropNames[INDEX_WIDTH];
+ aNotebookBarItem[OFFSET_NOTEBOOKBARITEM_STYLE].Name = m_aPropNames[INDEX_STYLE];
+
+ sal_uInt32 nCount = aAddonNotebookBarItemSetNodeSeq.getLength();
+ for (sal_uInt32 n = 0; n < nCount; n++)
+ {
+ OUString aNotebookBarItemNode(aAddonNotebookBarItemSetNode
+ + aAddonNotebookBarItemSetNodeSeq[n]);
+ // Read the NotebookBarItem
+ if (ReadNotebookBarItem(aNotebookBarItemNode, aNotebookBarItem))
+ {
+ // Successfully read a toolbar item, append to our list
+ sal_uInt32 nAddonCount = rAddonOfficeNotebookBarSeq.getLength();
+ rAddonOfficeNotebookBarSeq.realloc(nAddonCount + 1);
+ rAddonOfficeNotebookBarSeq[nAddonCount] = aNotebookBarItem;
+ }
+ }
+
+ return (o3tl::make_unsigned(rAddonOfficeNotebookBarSeq.getLength())
+ > nNotebookBarItemCount);
+}
+
+void AddonsOptions_Impl::ReadImages( ImageManager& aImageManager )
+{
+ // Read the user-defined Images set and fill image manager
+ OUString aAddonImagesNodeName( "AddonUI/Images" );
+ Sequence< OUString > aAddonImagesNodeSeq = GetNodeNames( aAddonImagesNodeName );
+ OUString aAddonImagesNode( aAddonImagesNodeName + m_aPathDelimiter );
+
+ sal_uInt32 nCount = aAddonImagesNodeSeq.getLength();
+
+ // Init the property value sequence
+ Sequence< OUString > aAddonImageItemNodePropNames( 1 );
+ OUString aURL;
+
+ for ( sal_uInt32 n = 0; n < nCount; n++ )
+ {
+ OUString aImagesItemNode( aAddonImagesNode + aAddonImagesNodeSeq[n] );
+
+ // Create sequence for data access
+ aAddonImageItemNodePropNames[0] = aImagesItemNode +
+ m_aPathDelimiter +
+ m_aPropNames[ OFFSET_MENUITEM_URL ];
+
+ Sequence< Any > aAddonImageItemNodeValues = GetProperties( aAddonImageItemNodePropNames );
+
+ // An user-defined image entry must have a URL. As "ImageIdentifier" has a higher priority
+ // we also check if we already have an images association.
+ if (( aAddonImageItemNodeValues[0] >>= aURL ) &&
+ !aURL.isEmpty() &&
+ !HasAssociatedImages( aURL ))
+ {
+ OUString aImagesUserDefinedItemNode = aImagesItemNode +
+ m_aPathDelimiter +
+ IMAGES_NODENAME +
+ m_aPathDelimiter;
+
+ // Read a user-defined images data
+ std::unique_ptr<ImageEntry> pImageEntry = ReadImageData( aImagesUserDefinedItemNode );
+ if ( pImageEntry )
+ {
+ // Successfully read a user-defined images item, put it into our image manager
+ aImageManager.emplace( aURL, std::move(*pImageEntry) );
+ }
+ }
+ }
+}
+
+OUString AddonsOptions_Impl::GeneratePrefixURL()
+{
+ // Create a 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.
+ OUString aPopupMenuURL;
+ OUStringBuffer aBuf( m_aRootAddonPopupMenuURLPrexfix.getLength() + 3 );
+ aBuf.append( m_aRootAddonPopupMenuURLPrexfix );
+ aBuf.append( OUString::number( ++m_nRootAddonPopupMenuId ));
+ aPopupMenuURL = aBuf.makeStringAndClear();
+ return aPopupMenuURL;
+}
+
+void AddonsOptions_Impl::ReadMenuMergeInstructions( MergeMenuInstructionContainer& aContainer )
+{
+ const OUString aMenuMergeRootName( "AddonUI/OfficeMenuBarMerging/" );
+
+ Sequence< OUString > aAddonMergeNodesSeq = GetNodeNames( aMenuMergeRootName );
+
+ sal_uInt32 nCount = aAddonMergeNodesSeq.getLength();
+
+ // Init the property value sequence
+ Sequence< OUString > aNodePropNames( 5 );
+
+ for ( sal_uInt32 i = 0; i < nCount; i++ )
+ {
+ OUString aMergeAddonInstructions( aMenuMergeRootName + aAddonMergeNodesSeq[i] );
+
+ Sequence< OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
+ sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength();
+
+ for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
+ {
+ OUStringBuffer aMergeAddonInstructionBase( aMergeAddonInstructions );
+ aMergeAddonInstructionBase.append( m_aPathDelimiter );
+ aMergeAddonInstructionBase.append( aAddonInstMergeNodesSeq[j] );
+ aMergeAddonInstructionBase.append( m_aPathDelimiter );
+
+ // Create sequence for data access
+ 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;
+
+ OUString aMergeMenuBase = aMergeAddonInstructionBase.makeStringAndClear();
+ ReadMergeMenuData( aMergeMenuBase, aMergeMenuInstruction.aMergeMenu );
+
+ aContainer.push_back( aMergeMenuInstruction );
+ }
+ }
+}
+
+void AddonsOptions_Impl::ReadMergeMenuData( const OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeMenu )
+{
+ OUString aMergeMenuBaseNode( aMergeAddonInstructionBase+m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS ] );
+
+ Sequence< OUString > aSubMenuNodeNames = GetNodeNames( aMergeMenuBaseNode );
+ aMergeMenuBaseNode += m_aPathDelimiter;
+
+ // extend the node names to have full path strings
+ for ( OUString& rName : aSubMenuNodeNames )
+ rName = aMergeMenuBaseNode + rName;
+
+ ReadSubMenuEntries( aSubMenuNodeNames, rMergeMenu );
+}
+
+void AddonsOptions_Impl::ReadToolbarMergeInstructions( ToolbarMergingInstructions& rCachedToolbarMergingInstructions )
+{
+ const OUString aToolbarMergeRootName( "AddonUI/OfficeToolbarMerging/" );
+
+ Sequence< OUString > aAddonMergeNodesSeq = GetNodeNames( aToolbarMergeRootName );
+ sal_uInt32 nCount = aAddonMergeNodesSeq.getLength();
+
+ // Init the property value sequence
+ Sequence< OUString > aNodePropNames( 6 );
+
+ for ( sal_uInt32 i = 0; i < nCount; i++ )
+ {
+ OUString aMergeAddonInstructions( aToolbarMergeRootName + aAddonMergeNodesSeq[i] );
+
+ Sequence< OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
+ sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength();
+
+ for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
+ {
+ OUStringBuffer aMergeAddonInstructionBase( aMergeAddonInstructions );
+ aMergeAddonInstructionBase.append( m_aPathDelimiter );
+ aMergeAddonInstructionBase.append( aAddonInstMergeNodesSeq[j] );
+ aMergeAddonInstructionBase.append( m_aPathDelimiter );
+
+ // Create sequence for data access
+ 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 );
+ }
+ }
+}
+
+bool AddonsOptions_Impl::ReadMergeToolbarData( const OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeToolbarItems )
+{
+ OUString aMergeToolbarBaseNode = aMergeAddonInstructionBase +
+ m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBARITEMS ];
+
+ return ReadToolBarItemSet( aMergeToolbarBaseNode, rMergeToolbarItems );
+}
+
+void AddonsOptions_Impl::ReadNotebookBarMergeInstructions(
+ NotebookBarMergingInstructions& rCachedNotebookBarMergingInstructions)
+{
+ const OUString aNotebookBarMergeRootName("AddonUI/OfficeNotebookBarMerging/");
+
+ Sequence<OUString> aAddonMergeNodesSeq = GetNodeNames(aNotebookBarMergeRootName);
+ sal_uInt32 nCount = aAddonMergeNodesSeq.getLength();
+
+ // Init the property value sequence
+ Sequence<OUString> aNodePropNames(6);
+
+ for (sal_uInt32 i = 0; i < nCount; i++)
+ {
+ OUString aMergeAddonInstructions(aNotebookBarMergeRootName + aAddonMergeNodesSeq[i]);
+
+ Sequence<OUString> aAddonInstMergeNodesSeq = GetNodeNames(aMergeAddonInstructions);
+ sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength();
+
+ for (sal_uInt32 j = 0; j < nCountAddons; j++)
+ {
+ OUStringBuffer aMergeAddonInstructionBase(aMergeAddonInstructions);
+ aMergeAddonInstructionBase.append(m_aPathDelimiter);
+ aMergeAddonInstructionBase.append(aAddonInstMergeNodesSeq[j]);
+ aMergeAddonInstructionBase.append(m_aPathDelimiter);
+
+ // Create sequence for data access
+ OUStringBuffer aBuffer(aMergeAddonInstructionBase);
+ aBuffer.append(m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBAR]);
+ aNodePropNames[0] = aBuffer.makeStringAndClear();
+
+ aBuffer = aMergeAddonInstructionBase;
+ aBuffer.append(m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGEPOINT]);
+ aNodePropNames[1] = aBuffer.makeStringAndClear();
+
+ aBuffer = aMergeAddonInstructionBase;
+ aBuffer.append(m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGECOMMAND]);
+ aNodePropNames[2] = aBuffer.makeStringAndClear();
+
+ aBuffer = aMergeAddonInstructionBase;
+ aBuffer.append(
+ m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGECOMMANDPARAMETER]);
+ aNodePropNames[3] = aBuffer.makeStringAndClear();
+
+ aBuffer = aMergeAddonInstructionBase;
+ aBuffer.append(m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGEFALLBACK]);
+ aNodePropNames[4] = aBuffer.makeStringAndClear();
+
+ aBuffer = aMergeAddonInstructionBase;
+ aBuffer.append(m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGECONTEXT]);
+ aNodePropNames[5] = aBuffer.makeStringAndClear();
+
+ Sequence<Any> aNodePropValues = GetProperties(aNodePropNames);
+
+ MergeNotebookBarInstruction aMergeNotebookBarInstruction;
+ aNodePropValues[0] >>= aMergeNotebookBarInstruction.aMergeNotebookBar;
+ aNodePropValues[1] >>= aMergeNotebookBarInstruction.aMergePoint;
+ aNodePropValues[2] >>= aMergeNotebookBarInstruction.aMergeCommand;
+ aNodePropValues[3] >>= aMergeNotebookBarInstruction.aMergeCommandParameter;
+ aNodePropValues[4] >>= aMergeNotebookBarInstruction.aMergeFallback;
+ aNodePropValues[5] >>= aMergeNotebookBarInstruction.aMergeContext;
+
+ ReadMergeNotebookBarData(aMergeAddonInstructionBase.makeStringAndClear(),
+ aMergeNotebookBarInstruction.aMergeNotebookBarItems);
+
+ MergeNotebookBarInstructionContainer& rVector
+ = rCachedNotebookBarMergingInstructions[aMergeNotebookBarInstruction
+ .aMergeNotebookBar];
+ rVector.push_back(aMergeNotebookBarInstruction);
+ }
+ }
+}
+
+bool AddonsOptions_Impl::ReadMergeNotebookBarData(
+ const OUString& aMergeAddonInstructionBase,
+ Sequence<Sequence<PropertyValue>>& rMergeNotebookBarItems)
+{
+ OUString aMergeNotebookBarBaseNode = aMergeAddonInstructionBase +
+ m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBARITEMS];
+
+ return ReadNotebookBarItemSet(aMergeNotebookBarBaseNode, rMergeNotebookBarItems);
+}
+
+void AddonsOptions_Impl::ReadStatusbarMergeInstructions( MergeStatusbarInstructionContainer& aContainer )
+{
+ const OUString aStatusbarMergeRootName( "AddonUI/OfficeStatusbarMerging/" );
+
+ Sequence< OUString > aAddonMergeNodesSeq = GetNodeNames( aStatusbarMergeRootName );
+ sal_uInt32 nCount = aAddonMergeNodesSeq.getLength();
+
+ Sequence< OUString > aNodePropNames( 5 );
+
+ for ( sal_uInt32 i = 0; i < nCount; i++ )
+ {
+ OUString aMergeAddonInstructions( aStatusbarMergeRootName + aAddonMergeNodesSeq[i] );
+
+ Sequence< OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
+ sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength();
+
+ for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
+ {
+ OUStringBuffer aMergeAddonInstructionBase( aMergeAddonInstructions );
+ aMergeAddonInstructionBase.append( m_aPathDelimiter );
+ aMergeAddonInstructionBase.append( aAddonInstMergeNodesSeq[j] );
+ aMergeAddonInstructionBase.append( m_aPathDelimiter );
+
+ // Create sequence for data access
+ OUStringBuffer aBuffer( aMergeAddonInstructionBase );
+ aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGEPOINT ] );
+ aNodePropNames[0] = aBuffer.makeStringAndClear();
+
+ aBuffer = aMergeAddonInstructionBase;
+ aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGECOMMAND ] );
+ aNodePropNames[1] = aBuffer.makeStringAndClear();
+
+ aBuffer = aMergeAddonInstructionBase;
+ aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGECOMMANDPARAMETER ] );
+ aNodePropNames[2] = aBuffer.makeStringAndClear();
+
+ aBuffer = aMergeAddonInstructionBase;
+ aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGEFALLBACK ] );
+ aNodePropNames[3] = aBuffer.makeStringAndClear();
+
+ aBuffer = aMergeAddonInstructionBase;
+ aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGECONTEXT ] );
+ aNodePropNames[4] = aBuffer.makeStringAndClear();
+
+ Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );
+
+ MergeStatusbarInstruction aMergeStatusbarInstruction;
+ aNodePropValues[0] >>= aMergeStatusbarInstruction.aMergePoint;
+ aNodePropValues[1] >>= aMergeStatusbarInstruction.aMergeCommand;
+ aNodePropValues[2] >>= aMergeStatusbarInstruction.aMergeCommandParameter;
+ // aNodePropValues[3] >>= aMergeStatusbarInstruction.aMergeFallback;
+ aNodePropValues[4] >>= aMergeStatusbarInstruction.aMergeContext;
+
+ ReadMergeStatusbarData( aMergeAddonInstructionBase.makeStringAndClear(),
+ aMergeStatusbarInstruction.aMergeStatusbarItems );
+
+ aContainer.push_back( aMergeStatusbarInstruction );
+ }
+ }
+}
+
+bool AddonsOptions_Impl::ReadMergeStatusbarData(
+ const OUString& aMergeAddonInstructionBase,
+ Sequence< Sequence< PropertyValue > >& rMergeStatusbarItems )
+{
+ sal_uInt32 nStatusbarItemCount = rMergeStatusbarItems.getLength();
+
+ OUString aMergeStatusbarBaseNode = aMergeAddonInstructionBase +
+ m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_STATUSBARITEMS ];
+
+ OUString aAddonStatusbarItemSetNode( aMergeStatusbarBaseNode + m_aPathDelimiter );
+ Sequence< OUString > aAddonStatusbarItemSetNodeSeq = GetNodeNames( aMergeStatusbarBaseNode );
+
+ Sequence< PropertyValue > aStatusbarItem( PROPERTYCOUNT_STATUSBARITEM );
+ aStatusbarItem[ OFFSET_STATUSBARITEM_URL ].Name = m_aPropNames[ INDEX_URL ];
+ aStatusbarItem[ OFFSET_STATUSBARITEM_TITLE ].Name = m_aPropNames[ INDEX_TITLE ];
+ aStatusbarItem[ OFFSET_STATUSBARITEM_CONTEXT ].Name = m_aPropNames[ INDEX_CONTEXT ];
+ aStatusbarItem[ OFFSET_STATUSBARITEM_ALIGN ].Name = m_aPropNames[ INDEX_ALIGN ];
+ aStatusbarItem[ OFFSET_STATUSBARITEM_AUTOSIZE ].Name = m_aPropNames[ INDEX_AUTOSIZE ];
+ aStatusbarItem[ OFFSET_STATUSBARITEM_OWNERDRAW ].Name = m_aPropNames[ INDEX_OWNERDRAW ];
+ aStatusbarItem[ OFFSET_STATUSBARITEM_MANDATORY ].Name = m_aPropNames[ INDEX_MANDATORY ];
+ aStatusbarItem[ OFFSET_STATUSBARITEM_WIDTH ].Name = m_aPropNames[ INDEX_WIDTH ];
+
+ sal_uInt32 nCount = aAddonStatusbarItemSetNodeSeq.getLength();
+ for ( sal_uInt32 n = 0; n < nCount; n++ )
+ {
+ OUString aStatusbarItemNode( aAddonStatusbarItemSetNode + aAddonStatusbarItemSetNodeSeq[n] );
+
+ if ( ReadStatusBarItem( aStatusbarItemNode, aStatusbarItem ) )
+ {
+ sal_uInt32 nAddonCount = rMergeStatusbarItems.getLength();
+ rMergeStatusbarItems.realloc( nAddonCount+1 );
+ rMergeStatusbarItems[nAddonCount] = aStatusbarItem;
+ }
+ }
+
+ return ( o3tl::make_unsigned(rMergeStatusbarItems.getLength()) > nStatusbarItemCount );
+}
+
+bool AddonsOptions_Impl::ReadStatusBarItem(
+ const OUString& aStatusarItemNodeName,
+ Sequence< PropertyValue >& aStatusbarItem )
+{
+ bool bResult( false );
+ OUString aURL;
+ OUString aAddonStatusbarItemTreeNode( aStatusarItemNodeName + m_aPathDelimiter );
+
+ Sequence< Any > aStatusbarItemNodePropValues = GetProperties( GetPropertyNamesStatusbarItem( aAddonStatusbarItemTreeNode ) );
+
+ // Command URL is required
+ if (( aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_URL ] >>= aURL ) && aURL.getLength() > 0 )
+ {
+ aStatusbarItem[ OFFSET_STATUSBARITEM_URL ].Value <<= aURL;
+ aStatusbarItem[ OFFSET_STATUSBARITEM_TITLE ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_TITLE ];
+ aStatusbarItem[ OFFSET_STATUSBARITEM_CONTEXT ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_CONTEXT ];
+ aStatusbarItem[ OFFSET_STATUSBARITEM_ALIGN ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_ALIGN ];
+ aStatusbarItem[ OFFSET_STATUSBARITEM_AUTOSIZE ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_AUTOSIZE ];
+ aStatusbarItem[ OFFSET_STATUSBARITEM_OWNERDRAW ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_OWNERDRAW ];
+ aStatusbarItem[ OFFSET_STATUSBARITEM_MANDATORY ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_MANDATORY ];
+
+ // Configuration uses hyper for long. Therefore transform into sal_Int32
+ sal_Int64 nValue( 0 );
+ aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_WIDTH ] >>= nValue;
+ aStatusbarItem[ OFFSET_STATUSBARITEM_WIDTH ].Value <<= sal_Int32( nValue );
+
+ bResult = true;
+ }
+
+ return bResult;
+}
+
+bool AddonsOptions_Impl::ReadMenuItem( const OUString& aMenuNodeName, Sequence< PropertyValue >& aMenuItem, bool bIgnoreSubMenu )
+{
+ bool bResult = false;
+ OUString aStrValue;
+ OUString aAddonMenuItemTreeNode( aMenuNodeName + m_aPathDelimiter );
+
+ Sequence< Any > aMenuItemNodePropValues = GetProperties( GetPropertyNamesMenuItem( aAddonMenuItemTreeNode ) );
+ if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_TITLE ] >>= aStrValue ) && !aStrValue.isEmpty() )
+ {
+ aMenuItem[ OFFSET_MENUITEM_TITLE ].Value <<= aStrValue;
+
+ OUString aRootSubMenuName( aAddonMenuItemTreeNode + m_aPropNames[ INDEX_SUBMENU ] );
+ Sequence< OUString > aRootSubMenuNodeNames = GetNodeNames( aRootSubMenuName );
+ if ( aRootSubMenuNodeNames.hasElements() && !bIgnoreSubMenu )
+ {
+ // Set a unique prefixed Add-On popup menu URL so it can be identified later
+ OUString aPopupMenuURL = GeneratePrefixURL();
+ 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 <<= OUString();
+ 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;
+ OUString aSubMenuRootNodeName( aRootSubMenuName + m_aPathDelimiter );
+ for ( OUString& rName : aRootSubMenuNodeNames )
+ rName = aSubMenuRootNodeName + rName;
+ ReadSubMenuEntries( aRootSubMenuNodeNames, aSubMenuSeq );
+ aMenuItem[ OFFSET_MENUITEM_SUBMENU ].Value <<= aSubMenuSeq;
+ bResult = true;
+ }
+ else if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_URL ] >>= aStrValue ) && !aStrValue.isEmpty() )
+ {
+ // A simple menu item => read the other properties;
+ 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 = true;
+ }
+ }
+ else if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_URL ] >>= aStrValue ) &&
+ aStrValue == SEPARATOR_URL )
+ {
+ // Separator
+ aMenuItem[ OFFSET_MENUITEM_URL ].Value <<= aStrValue;
+ aMenuItem[ OFFSET_MENUITEM_TARGET ].Value <<= OUString();
+ aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Value <<= OUString();
+ aMenuItem[ OFFSET_MENUITEM_CONTEXT ].Value <<= OUString();
+ aMenuItem[ OFFSET_MENUITEM_SUBMENU ].Value <<= Sequence< Sequence< PropertyValue > >(); // Submenu set!
+ bResult = true;
+ }
+
+ return bResult;
+}
+
+bool AddonsOptions_Impl::ReadPopupMenu( const OUString& aPopupMenuNodeName, Sequence< PropertyValue >& aPopupMenu )
+{
+ bool bResult = false;
+ OUString aStrValue;
+ OUString aAddonPopupMenuTreeNode( aPopupMenuNodeName + m_aPathDelimiter );
+
+ Sequence< Any > aPopupMenuNodePropValues = GetProperties( GetPropertyNamesPopupMenu( aAddonPopupMenuTreeNode ) );
+ if (( aPopupMenuNodePropValues[ OFFSET_POPUPMENU_TITLE ] >>= aStrValue ) &&
+ !aStrValue.isEmpty() )
+ {
+ aPopupMenu[ OFFSET_POPUPMENU_TITLE ].Value <<= aStrValue;
+
+ OUString aRootSubMenuName( aAddonPopupMenuTreeNode + m_aPropNames[ INDEX_SUBMENU ] );
+ Sequence< OUString > aRootSubMenuNodeNames = GetNodeNames( aRootSubMenuName );
+ if ( aRootSubMenuNodeNames.hasElements() )
+ {
+ // A top-level popup menu needs a title
+ // Set a unique prefixed Add-On popup menu URL so it can be identified later
+ 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;
+ OUString aSubMenuRootNodeName( aRootSubMenuName + m_aPathDelimiter );
+ for ( OUString& rName : aRootSubMenuNodeNames )
+ rName = aSubMenuRootNodeName + rName;
+ ReadSubMenuEntries( aRootSubMenuNodeNames, aSubMenuSeq );
+ aPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value <<= aSubMenuSeq;
+ bResult = true;
+ }
+ }
+
+ return bResult;
+}
+
+void 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 ( Sequence<PropertyValue> const & rSeq : std::as_const(aSourceSubMenuSeq) )
+ aTargetSubMenuSeq[nIndex++] = rSeq;
+ rTargetPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value <<= aTargetSubMenuSeq;
+ }
+}
+
+bool AddonsOptions_Impl::ReadToolBarItem( const OUString& aToolBarItemNodeName, Sequence< PropertyValue >& aToolBarItem )
+{
+ bool bResult = false;
+ OUString aTitle;
+ OUString aURL;
+ OUString aAddonToolBarItemTreeNode( aToolBarItemNodeName + m_aPathDelimiter );
+
+ Sequence< Any > aToolBarItemNodePropValues = GetProperties( GetPropertyNamesToolBarItem( aAddonToolBarItemTreeNode ) );
+
+ // A toolbar item must have a command URL
+ if (( aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_URL ] >>= aURL ) && !aURL.isEmpty() )
+ {
+ if ( aURL == SEPARATOR_URL )
+ {
+ // A separator toolbar item only needs a URL
+ aToolBarItem[ OFFSET_TOOLBARITEM_URL ].Value <<= aURL;
+ aToolBarItem[ OFFSET_TOOLBARITEM_TITLE ].Value <<= OUString();
+ aToolBarItem[ OFFSET_TOOLBARITEM_TARGET ].Value <<= OUString();
+ aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ].Value <<= OUString();
+ aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT ].Value <<= OUString();
+ aToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE ].Value <<= OUString();
+ aToolBarItem[ OFFSET_TOOLBARITEM_WIDTH ].Value <<= sal_Int32( 0 );
+
+ bResult = true;
+ }
+ else if (( aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_TITLE ] >>= aTitle ) && !aTitle.isEmpty() )
+ {
+ // A normal toolbar item must also have title => read the other properties;
+ 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 = true;
+ }
+ }
+
+ return bResult;
+}
+
+bool AddonsOptions_Impl::ReadNotebookBarItem( const OUString& aNotebookBarItemNodeName, Sequence< PropertyValue >& aNotebookBarItem )
+{
+ bool bResult = false;
+ OUString aTitle;
+ OUString aURL;
+ OUString aAddonNotebookBarItemTreeNode( aNotebookBarItemNodeName + m_aPathDelimiter );
+
+ Sequence< Any > aNotebookBarItemNodePropValues = GetProperties( GetPropertyNamesNotebookBarItem( aAddonNotebookBarItemTreeNode ) );
+
+ // A toolbar item must have a command URL
+ if (( aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_URL ] >>= aURL ) && !aURL.isEmpty() )
+ {
+ if ( aURL == SEPARATOR_URL )
+ {
+ // A separator toolbar item only needs a URL
+ aNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_URL ].Value <<= aURL;
+ aNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_TITLE ].Value <<= OUString();
+ aNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_TARGET ].Value <<= OUString();
+ aNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER ].Value <<= OUString();
+ aNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_CONTEXT ].Value <<= OUString();
+ aNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_CONTROLTYPE ].Value <<= OUString();
+ aNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_WIDTH ].Value <<= sal_Int32( 0 );
+ aNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_STYLE ].Value <<= OUString();
+
+ bResult = true;
+ }
+ else if (( aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_TITLE ] >>= aTitle ) && !aTitle.isEmpty() )
+ {
+ // A normal toolbar item must also have title => read the other properties;
+ OUString aImageId;
+
+ // Try to map a user-defined image URL to our internal private image URL
+ aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER ] >>= aImageId;
+ ReadAndAssociateImages( aURL, aImageId );
+
+ aNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_URL ].Value <<= aURL;
+ aNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_TITLE ].Value <<= aTitle;
+ aNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_TARGET ].Value = aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_TARGET ];
+ aNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER ].Value <<= aImageId;
+ aNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_CONTEXT ].Value = aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_CONTEXT ];
+ aNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_CONTROLTYPE ].Value = aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_CONTROLTYPE ];
+
+ // Configuration uses hyper for long. Therefore transform into sal_Int32
+ sal_Int64 nValue( 0 );
+ aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_WIDTH ] >>= nValue;
+ aNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_WIDTH ].Value <<= sal_Int32( nValue );
+ aNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_STYLE ].Value = aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_STYLE ];
+
+ bResult = true;
+ }
+ }
+
+ return bResult;
+}
+
+void AddonsOptions_Impl::ReadSubMenuEntries( const Sequence< 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;
+ }
+ }
+}
+
+bool AddonsOptions_Impl::HasAssociatedImages( const OUString& aURL )
+{
+ // FIXME: potentially this is not so useful in a world of delayed image loading
+ ImageManager::const_iterator pIter = m_aImageManager.find( aURL );
+ return ( pIter != m_aImageManager.end() );
+}
+
+void AddonsOptions_Impl::SubstituteVariables( OUString& aURL )
+{
+ aURL = comphelper::getExpandedUri(
+ comphelper::getProcessComponentContext(), aURL);
+}
+
+Image AddonsOptions_Impl::ReadImageFromURL(const OUString& aImageURL)
+{
+ Image aImage;
+
+ std::unique_ptr<SvStream> pStream = UcbStreamHelper::CreateStream( aImageURL, StreamMode::STD_READ );
+ if ( pStream && ( pStream->GetErrorCode() == ERRCODE_NONE ))
+ {
+ // Use graphic class to also support more graphic formats (bmp,png,...)
+ Graphic aGraphic;
+
+ GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
+ rGF.ImportGraphic( aGraphic, OUString(), *pStream );
+
+ BitmapEx aBitmapEx = aGraphic.GetBitmapEx();
+
+ Size aBmpSize = aBitmapEx.GetSizePixel();
+ if ( !aBmpSize.IsEmpty() )
+ {
+ // Support non-transparent bitmaps to be downward compatible with OOo 1.1.x addons
+ if( !aBitmapEx.IsTransparent() )
+ aBitmapEx = BitmapEx( aBitmapEx.GetBitmap(), COL_LIGHTMAGENTA );
+
+ aImage = Image(aBitmapEx);
+ }
+ }
+
+ return aImage;
+}
+
+void AddonsOptions_Impl::ReadAndAssociateImages( const OUString& aURL, const OUString& aImageId )
+{
+ if ( aImageId.isEmpty() )
+ return;
+
+ ImageEntry aImageEntry;
+ OUString aImageURL( aImageId );
+
+ SubstituteVariables( aImageURL );
+
+ // Loop to create the two possible image names and try to read the bitmap files
+ static const char* aExtArray[] = { "_16", "_26" };
+ for ( size_t i = 0; i < SAL_N_ELEMENTS(aExtArray); i++ )
+ {
+ OUStringBuffer aFileURL( aImageURL );
+ aFileURL.appendAscii( aExtArray[i] );
+ aFileURL.append( ".bmp" );
+
+ aImageEntry.addImage( !i ? IMGSIZE_SMALL : IMGSIZE_BIG,
+ Image(), aFileURL.makeStringAndClear() );
+ }
+
+ m_aImageManager.emplace( aURL, aImageEntry );
+}
+
+std::unique_ptr<AddonsOptions_Impl::ImageEntry> AddonsOptions_Impl::ReadImageData( const OUString& aImagesNodeName )
+{
+ Sequence< OUString > aImageDataNodeNames = GetPropertyNamesImages( aImagesNodeName );
+ Sequence< Any > aPropertyData;
+ Sequence< sal_Int8 > aImageDataSeq;
+ OUString aImageURL;
+
+ std::unique_ptr<ImageEntry> pEntry;
+
+ // 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.hasElements() &&
+ ( CreateImageFromSequence( aImage, aImageDataSeq ) ) )
+ {
+ if ( !pEntry )
+ pEntry.reset(new ImageEntry);
+ pEntry->addImage(i == OFFSET_IMAGES_SMALL ? IMGSIZE_SMALL : IMGSIZE_BIG, aImage, "");
+ }
+ }
+ else
+ {
+ if(!pEntry)
+ pEntry.reset(new ImageEntry());
+
+ // Retrieve image data from an external bitmap file. Make sure that embedded image data
+ // has a higher priority.
+ aPropertyData[i] >>= aImageURL;
+
+ SubstituteVariables( aImageURL );
+
+ pEntry->addImage(IMGSIZE_BIG, Image(), aImageURL);
+ }
+ }
+
+ return pEntry;
+}
+
+bool AddonsOptions_Impl::CreateImageFromSequence( Image& rImage, Sequence< sal_Int8 >& rBitmapDataSeq ) const
+{
+ bool bResult = false;
+
+ if ( rBitmapDataSeq.hasElements() )
+ {
+ SvMemoryStream aMemStream( rBitmapDataSeq.getArray(), rBitmapDataSeq.getLength(), StreamMode::STD_READ );
+ BitmapEx aBitmapEx;
+
+ ReadDIBBitmapEx(aBitmapEx, aMemStream);
+
+ 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 = true;
+ }
+
+ return bResult;
+}
+
+Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesMenuItem( const OUString& aPropertyRootNode ) const
+{
+ Sequence< OUString > lResult( PROPERTYCOUNT_MENUITEM );
+
+ // Create property names dependent from the root node name
+ lResult[OFFSET_MENUITEM_URL] = aPropertyRootNode + m_aPropNames[ INDEX_URL ];
+ lResult[OFFSET_MENUITEM_TITLE] = aPropertyRootNode + m_aPropNames[ INDEX_TITLE ];
+ lResult[OFFSET_MENUITEM_IMAGEIDENTIFIER] = aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER ];
+ lResult[OFFSET_MENUITEM_TARGET] = aPropertyRootNode + m_aPropNames[ INDEX_TARGET ];
+ lResult[OFFSET_MENUITEM_CONTEXT] = aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ];
+ lResult[OFFSET_MENUITEM_SUBMENU] = aPropertyRootNode + m_aPropNames[ INDEX_SUBMENU ];
+
+ return lResult;
+}
+
+Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesPopupMenu( const OUString& aPropertyRootNode ) const
+{
+ // The URL is automatically set and not read from the configuration.
+ Sequence< OUString > lResult( PROPERTYCOUNT_POPUPMENU-1 );
+
+ // Create property names dependent from the root node name
+ lResult[OFFSET_POPUPMENU_TITLE] = aPropertyRootNode + m_aPropNames[ INDEX_TITLE ];
+ lResult[OFFSET_POPUPMENU_CONTEXT] = aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ];
+ lResult[OFFSET_POPUPMENU_SUBMENU] = aPropertyRootNode + m_aPropNames[ INDEX_SUBMENU ];
+
+ return lResult;
+}
+
+Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesToolBarItem( const OUString& aPropertyRootNode ) const
+{
+ Sequence< OUString > lResult( PROPERTYCOUNT_TOOLBARITEM );
+
+ // Create property names dependent from the root node name
+ lResult[0] = aPropertyRootNode + m_aPropNames[ INDEX_URL ];
+ lResult[1] = aPropertyRootNode + m_aPropNames[ INDEX_TITLE ];
+ lResult[2] = aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER];
+ lResult[3] = aPropertyRootNode + m_aPropNames[ INDEX_TARGET ];
+ lResult[4] = aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ];
+ lResult[5] = aPropertyRootNode + m_aPropNames[ INDEX_CONTROLTYPE ];
+ lResult[6] = aPropertyRootNode + m_aPropNames[ INDEX_WIDTH ];
+
+ return lResult;
+}
+
+Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesNotebookBarItem( const OUString& aPropertyRootNode ) const
+{
+ Sequence< OUString > lResult( PROPERTYCOUNT_NOTEBOOKBARITEM );
+
+ // Create property names dependent from the root node name
+ lResult[0] = aPropertyRootNode + m_aPropNames[ INDEX_URL ];
+ lResult[1] = aPropertyRootNode + m_aPropNames[ INDEX_TITLE ];
+ lResult[2] = aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER];
+ lResult[3] = aPropertyRootNode + m_aPropNames[ INDEX_TARGET ];
+ lResult[4] = aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ];
+ lResult[5] = aPropertyRootNode + m_aPropNames[ INDEX_CONTROLTYPE ];
+ lResult[6] = aPropertyRootNode + m_aPropNames[ INDEX_WIDTH ];
+ lResult[7] = aPropertyRootNode + m_aPropNames[ INDEX_STYLE ];
+
+ return lResult;
+}
+
+Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesStatusbarItem(
+ const OUString& aPropertyRootNode ) const
+{
+ Sequence< OUString > lResult( PROPERTYCOUNT_STATUSBARITEM );
+
+ lResult[0] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_URL ] );
+ lResult[1] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_TITLE ] );
+ lResult[2] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ] );
+ lResult[3] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_ALIGN ] );
+ lResult[4] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_AUTOSIZE ] );
+ lResult[5] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_OWNERDRAW ] );
+ lResult[6] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_MANDATORY ] );
+ lResult[7] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_WIDTH ] );
+
+ return lResult;
+}
+
+Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesImages( const OUString& aPropertyRootNode ) const
+{
+ Sequence< OUString > lResult( PROPERTYCOUNT_IMAGES );
+
+ // Create property names dependent from the root node name
+ lResult[0] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALL ];
+ lResult[1] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIG ];
+ lResult[2] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC ];
+ lResult[3] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIGHC ];
+ lResult[4] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALL_URL ];
+ lResult[5] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIG_URL ];
+ lResult[6] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC_URL];
+ lResult[7] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIGHC_URL ];
+
+ return lResult;
+}
+
+namespace{
+ //global
+ std::weak_ptr<AddonsOptions_Impl> g_pAddonsOptions;
+}
+
+AddonsOptions::AddonsOptions()
+{
+ // Global access, must be guarded (multithreading!).
+ MutexGuard aGuard( GetOwnStaticMutex() );
+
+ m_pImpl = g_pAddonsOptions.lock();
+ if( !m_pImpl )
+ {
+ m_pImpl = std::make_shared<AddonsOptions_Impl>();
+ g_pAddonsOptions = m_pImpl;
+ }
+}
+
+AddonsOptions::~AddonsOptions()
+{
+ // Global access, must be guarded (multithreading!)
+ MutexGuard aGuard( GetOwnStaticMutex() );
+
+ m_pImpl.reset();
+}
+
+// public method
+
+bool AddonsOptions::HasAddonsMenu() const
+{
+ MutexGuard aGuard( GetOwnStaticMutex() );
+ return m_pImpl->HasAddonsMenu();
+}
+
+// public method
+
+sal_Int32 AddonsOptions::GetAddonsToolBarCount() const
+{
+ MutexGuard aGuard( GetOwnStaticMutex() );
+ return m_pImpl->GetAddonsToolBarCount();
+}
+
+// public method
+
+sal_Int32 AddonsOptions::GetAddonsNotebookBarCount() const
+{
+ MutexGuard aGuard( GetOwnStaticMutex() );
+ return m_pImpl->GetAddonsNotebookBarCount();
+}
+
+// public method
+
+const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsMenu() const
+{
+ MutexGuard aGuard( GetOwnStaticMutex() );
+ return m_pImpl->GetAddonsMenu();
+}
+
+// public method
+
+const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsMenuBarPart() const
+{
+ MutexGuard aGuard( GetOwnStaticMutex() );
+ return m_pImpl->GetAddonsMenuBarPart();
+}
+
+// public method
+
+const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsToolBarPart( sal_uInt32 nIndex ) const
+{
+ MutexGuard aGuard( GetOwnStaticMutex() );
+ return m_pImpl->GetAddonsToolBarPart( nIndex );
+}
+
+// public method
+
+const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsNotebookBarPart( sal_uInt32 nIndex ) const
+{
+ MutexGuard aGuard( GetOwnStaticMutex() );
+ return m_pImpl->GetAddonsNotebookBarPart( nIndex );
+}
+
+// public method
+
+OUString AddonsOptions::GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const
+{
+ MutexGuard aGuard( GetOwnStaticMutex() );
+ return m_pImpl->GetAddonsToolbarResourceName( nIndex );
+}
+
+// public method
+
+OUString AddonsOptions::GetAddonsNotebookBarResourceName( sal_uInt32 nIndex ) const
+{
+ MutexGuard aGuard( GetOwnStaticMutex() );
+ return m_pImpl->GetAddonsNotebookBarResourceName( nIndex );
+}
+
+// public method
+
+const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsHelpMenu() const
+{
+ MutexGuard aGuard( GetOwnStaticMutex() );
+ return m_pImpl->GetAddonsHelpMenu();
+}
+
+// public method
+
+const MergeMenuInstructionContainer& AddonsOptions::GetMergeMenuInstructions() const
+{
+ MutexGuard aGuard( GetOwnStaticMutex() );
+ return m_pImpl->GetMergeMenuInstructions();
+}
+
+// public method
+
+bool AddonsOptions::GetMergeToolbarInstructions(
+ const OUString& rToolbarName,
+ MergeToolbarInstructionContainer& rToolbarInstructions ) const
+{
+ MutexGuard aGuard( GetOwnStaticMutex() );
+ return m_pImpl->GetMergeToolbarInstructions(
+ rToolbarName, rToolbarInstructions );
+}
+
+// public method
+
+bool AddonsOptions::GetMergeNotebookBarInstructions(
+ const OUString& rNotebookBarName,
+ MergeNotebookBarInstructionContainer& rNotebookBarInstructions ) const
+{
+ MutexGuard aGuard( GetOwnStaticMutex() );
+ return m_pImpl->GetMergeNotebookBarInstructions(
+ rNotebookBarName, rNotebookBarInstructions );
+}
+
+//public method
+
+const MergeStatusbarInstructionContainer& AddonsOptions::GetMergeStatusbarInstructions() const
+{
+ MutexGuard aGuard( GetOwnStaticMutex() );
+ return m_pImpl->GetMergeStatusbarInstructions();
+}
+
+// public method
+
+Image AddonsOptions::GetImageFromURL( const OUString& aURL, bool bBig, bool bNoScale ) const
+{
+ MutexGuard aGuard( GetOwnStaticMutex() );
+ return m_pImpl->GetImageFromURL( aURL, bBig, bNoScale );
+}
+
+// public method
+
+Image AddonsOptions::GetImageFromURL( const OUString& aURL, bool bBig ) const
+{
+ return GetImageFromURL( aURL, bBig, false );
+}
+
+Mutex& AddonsOptions::GetOwnStaticMutex()
+{
+ // Create static mutex variable.
+ static Mutex ourMutex;
+
+ return ourMutex;
+}
+
+IMPL_LINK_NOARG(AddonsOptions_Impl, NotifyEvent, void*, void)
+{
+ MutexGuard aGuard(AddonsOptions::GetOwnStaticMutex());
+ ReadConfigurationData();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/fwe/classes/framelistanalyzer.cxx b/framework/source/fwe/classes/framelistanalyzer.cxx
new file mode 100644
index 000000000..55edf3147
--- /dev/null
+++ b/framework/source/fwe/classes/framelistanalyzer.cxx
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <framework/framelistanalyzer.hxx>
+
+#include <targets.h>
+#include <properties.h>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/frame/ModuleManager.hpp>
+#include <com/sun/star/frame/UnknownModuleException.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <tools/diagnose_ex.h>
+#include <sal/log.hxx>
+
+namespace framework{
+
+FrameListAnalyzer::FrameListAnalyzer( const css::uno::Reference< css::frame::XFramesSupplier >& xSupplier ,
+ const css::uno::Reference< css::frame::XFrame >& xReferenceFrame ,
+ FrameAnalyzerFlags 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 necessary to collect top frames here only. Otherwise 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 refer to the same model.
+ These frames must be closed then. But all other frames must be untouched.
+ In case the request was "CloseWin" these split 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
+ separately. 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 = false;
+ m_bReferenceIsHelp = false;
+ m_bReferenceIsBacking = false;
+ m_xHelp.clear();
+ m_xBackingComponent.clear();
+
+ // try to get the task container by using the given supplier
+ css::uno::Reference< css::container::XIndexAccess > xFrameContainer = m_xSupplier->getFrames();
+
+ // 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.resize(nCount);
+ m_lOtherHiddenFrames.resize(nCount);
+ m_lModelFrames.resize(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.
+ // Suppress this step, if right detect mode isn't set.
+ css::uno::Reference< css::frame::XModel > xReferenceModel;
+ if (m_eDetectMode & FrameAnalyzerFlags::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 really needed.
+ css::uno::Reference< css::beans::XPropertySet > xSet(m_xReferenceFrame, css::uno::UNO_QUERY);
+ if ( (m_eDetectMode & FrameAnalyzerFlags::Hidden) && xSet.is() )
+ {
+ xSet->getPropertyValue(FRAME_PROPNAME_ASCII_ISHIDDEN) >>= m_bReferenceIsHidden;
+ }
+
+ // check, if the reference frame includes the backing component.
+ // But look, if this analyze step is really needed.
+ if ((m_eDetectMode & FrameAnalyzerFlags::BackingComponent) && m_xReferenceFrame.is() )
+ {
+ try
+ {
+ css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
+ css::uno::Reference< css::frame::XModuleManager2 > xModuleMgr = css::frame::ModuleManager::create(xContext);
+ OUString sModule = xModuleMgr->identify(m_xReferenceFrame);
+ m_bReferenceIsBacking = sModule == "com.sun.star.frame.StartModule";
+ }
+ catch(const css::frame::UnknownModuleException&)
+ {
+ }
+ catch(const css::uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("fwk");
+ }
+ }
+
+ // check, if the reference frame includes the help module.
+ // But look, if this analyze step is really needed.
+ if (
+ (m_eDetectMode & FrameAnalyzerFlags::Help) &&
+ (m_xReferenceFrame.is() ) &&
+ (m_xReferenceFrame->getName() == SPECIALTARGET_HELPTASK)
+ )
+ {
+ m_bReferenceIsHelp = 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;
+
+ if (
+ (m_eDetectMode & FrameAnalyzerFlags::Zombie) &&
+ (
+ (!xFrame->getContainerWindow().is()) ||
+ (!xFrame->getComponentWindow().is())
+ )
+ )
+ {
+ SAL_INFO("fwk", "FrameListAnalyzer::impl_analyze(): ZOMBIE!");
+ }
+
+ // a) Is it the special help task?
+ // Return it separated from any return list.
+ if (
+ (m_eDetectMode & FrameAnalyzerFlags::Help) &&
+ (xFrame->getName()==SPECIALTARGET_HELPTASK)
+ )
+ {
+ m_xHelp = xFrame;
+ continue;
+ }
+
+ // b) Or is includes this task the special backing component?
+ // Return it separated from any return list.
+ // But check if the reference task itself is the backing frame.
+ // Our user must know it to decide right.
+ if (m_eDetectMode & FrameAnalyzerFlags::BackingComponent)
+ {
+ try
+ {
+ css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
+ css::uno::Reference< css::frame::XModuleManager2 > xModuleMgr = css::frame::ModuleManager::create(xContext);
+ OUString sModule = xModuleMgr->identify(xFrame);
+ if (sModule == "com.sun.star.frame.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 & FrameAnalyzerFlags::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 its
+ // visible state ... if it's allowed to do so.
+
+ bool bHidden = false;
+ if (m_eDetectMode & FrameAnalyzerFlags::Hidden)
+ {
+ xSet.set(xFrame, css::uno::UNO_QUERY);
+ if (xSet.is())
+ {
+ xSet->getPropertyValue(FRAME_PROPNAME_ASCII_ISHIDDEN) >>= bHidden;
+ }
+ }
+
+ if (bHidden)
+ {
+ m_lOtherHiddenFrames[nHiddenStep] = xFrame;
+ ++nHiddenStep;
+ }
+ else
+ {
+ m_lOtherVisibleFrames[nVisibleStep] = xFrame;
+ ++nVisibleStep;
+ }
+ }
+ }
+ catch (const css::lang::IndexOutOfBoundsException&)
+ {
+ // stop copying if index seems to be wrong.
+ // This interface can't really guarantee its count for multithreaded
+ // environments. So it can occur!
+ }
+
+ // 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.resize(nVisibleStep);
+ m_lOtherHiddenFrames.resize(nHiddenStep);
+ m_lModelFrames.resize(nModelStep);
+}
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/fwe/classes/fwkresid.cxx b/framework/source/fwe/classes/fwkresid.cxx
new file mode 100644
index 000000000..b6dcaecff
--- /dev/null
+++ b/framework/source/fwe/classes/fwkresid.cxx
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <classes/fwkresid.hxx>
+#include <unotools/resmgr.hxx>
+
+OUString FwkResId(const char* pId)
+{
+ return Translate::get(pId, Translate::Create("fwk"));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/fwe/classes/imagewrapper.cxx b/framework/source/fwe/classes/imagewrapper.cxx
new file mode 100644
index 000000000..b95bbbc34
--- /dev/null
+++ b/framework/source/fwe/classes/imagewrapper.cxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <classes/imagewrapper.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/BitmapTools.hxx>
+#include <tools/stream.hxx>
+#include <vcl/dibtools.hxx>
+
+using namespace com::sun::star::lang;
+using namespace com::sun::star::uno;
+
+namespace framework
+{
+
+static Sequence< sal_Int8 > const & impl_getStaticIdentifier()
+{
+ static const sal_uInt8 pGUID[16] = { 0x46, 0xAD, 0x69, 0xFB, 0xA7, 0xBE, 0x44, 0x83, 0xB2, 0xA7, 0xB3, 0xEC, 0x59, 0x4A, 0xB7, 0x00 };
+ static css::uno::Sequence< sal_Int8 > seqID(reinterpret_cast<const sal_Int8*>(pGUID), 16);
+ return seqID;
+}
+
+ImageWrapper::ImageWrapper( const Image& aImage ) : m_aImage( aImage )
+{
+}
+
+ImageWrapper::~ImageWrapper()
+{
+}
+
+Sequence< sal_Int8 > const & ImageWrapper::GetUnoTunnelId()
+{
+ return impl_getStaticIdentifier();
+}
+
+// XBitmap
+css::awt::Size SAL_CALL ImageWrapper::getSize()
+{
+ SolarMutexGuard aGuard;
+
+ BitmapEx aBitmapEx( m_aImage.GetBitmapEx() );
+ Size aBitmapSize( aBitmapEx.GetSizePixel() );
+
+ return css::awt::Size( aBitmapSize.Width(), aBitmapSize.Height() );
+}
+
+Sequence< sal_Int8 > SAL_CALL ImageWrapper::getDIB()
+{
+ SolarMutexGuard aGuard;
+
+ SvMemoryStream aMem;
+ WriteDIB(m_aImage.GetBitmapEx().GetBitmap(), aMem, false, true);
+ return Sequence< sal_Int8 >( static_cast<sal_Int8 const *>(aMem.GetData()), aMem.Tell() );
+}
+
+Sequence< sal_Int8 > SAL_CALL ImageWrapper::getMaskDIB()
+{
+ SolarMutexGuard aGuard;
+
+ return vcl::bitmap::GetMaskDIB(m_aImage.GetBitmapEx());
+}
+
+// XUnoTunnel
+sal_Int64 SAL_CALL ImageWrapper::getSomething( const Sequence< sal_Int8 >& aIdentifier )
+{
+ if ( aIdentifier == impl_getStaticIdentifier() )
+ return reinterpret_cast< sal_Int64 >( this );
+ else
+ return 0;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/fwe/classes/rootactiontriggercontainer.cxx b/framework/source/fwe/classes/rootactiontriggercontainer.cxx
new file mode 100644
index 000000000..8ce69fde7
--- /dev/null
+++ b/framework/source/fwe/classes/rootactiontriggercontainer.cxx
@@ -0,0 +1,264 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <classes/rootactiontriggercontainer.hxx>
+#include <classes/actiontriggercontainer.hxx>
+#include <classes/actiontriggerpropertyset.hxx>
+#include <classes/actiontriggerseparatorpropertyset.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <framework/actiontriggerhelper.hxx>
+#include <vcl/svapp.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 > const & impl_getStaticIdentifier()
+{
+ static const sal_uInt8 pGUID[16] = { 0x17, 0x0F, 0xA2, 0xC9, 0xCA, 0x50, 0x4A, 0xD3, 0xA6, 0x3B, 0x39, 0x99, 0xC5, 0x96, 0x43, 0x27 };
+ static css::uno::Sequence< sal_Int8 > seqID(reinterpret_cast<const sal_Int8*>(pGUID), 16);
+ return seqID;
+}
+
+RootActionTriggerContainer::RootActionTriggerContainer( const Menu* pMenu, const OUString* pMenuIdentifier ) :
+ PropertySetContainer()
+ , m_bContainerCreated( false )
+ , m_pMenu( pMenu )
+ , m_pMenuIdentifier( pMenuIdentifier )
+{
+}
+
+RootActionTriggerContainer::~RootActionTriggerContainer()
+{
+}
+
+// XInterface
+Any SAL_CALL RootActionTriggerContainer::queryInterface( const Type& aType )
+{
+ Any a = ::cppu::queryInterface(
+ aType ,
+ static_cast< XMultiServiceFactory* >(this),
+ static_cast< XServiceInfo* >(this),
+ static_cast< XUnoTunnel* >(this),
+ static_cast< XTypeProvider* >(this),
+ 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 OUString& aServiceSpecifier )
+{
+ if ( aServiceSpecifier == SERVICENAME_ACTIONTRIGGER )
+ return static_cast<OWeakObject *>( new ActionTriggerPropertySet());
+ else if ( aServiceSpecifier == SERVICENAME_ACTIONTRIGGERCONTAINER )
+ return static_cast<OWeakObject *>( new ActionTriggerContainer());
+ else if ( aServiceSpecifier == SERVICENAME_ACTIONTRIGGERSEPARATOR )
+ return static_cast<OWeakObject *>( new ActionTriggerSeparatorPropertySet());
+ else
+ throw css::uno::RuntimeException("Unknown service specifier!", static_cast<OWeakObject *>(this) );
+}
+
+Reference< XInterface > SAL_CALL RootActionTriggerContainer::createInstanceWithArguments( const OUString& ServiceSpecifier, const Sequence< Any >& /*Arguments*/ )
+{
+ return createInstance( ServiceSpecifier );
+}
+
+Sequence< OUString > SAL_CALL RootActionTriggerContainer::getAvailableServiceNames()
+{
+ Sequence< OUString > aSeq( 3 );
+
+ aSeq[0] = SERVICENAME_ACTIONTRIGGER;
+ aSeq[1] = SERVICENAME_ACTIONTRIGGERCONTAINER;
+ aSeq[2] = SERVICENAME_ACTIONTRIGGERSEPARATOR;
+
+ return aSeq;
+}
+
+// XIndexContainer
+void SAL_CALL RootActionTriggerContainer::insertByIndex( sal_Int32 Index, const Any& Element )
+{
+ SolarMutexGuard g;
+
+ if ( !m_bContainerCreated )
+ FillContainer();
+
+ PropertySetContainer::insertByIndex( Index, Element );
+}
+
+void SAL_CALL RootActionTriggerContainer::removeByIndex( sal_Int32 Index )
+{
+ SolarMutexGuard g;
+
+ if ( !m_bContainerCreated )
+ FillContainer();
+
+ PropertySetContainer::removeByIndex( Index );
+}
+
+// XIndexReplace
+void SAL_CALL RootActionTriggerContainer::replaceByIndex( sal_Int32 Index, const Any& Element )
+{
+ SolarMutexGuard g;
+
+ if ( !m_bContainerCreated )
+ FillContainer();
+
+ PropertySetContainer::replaceByIndex( Index, Element );
+}
+
+// XIndexAccess
+sal_Int32 SAL_CALL RootActionTriggerContainer::getCount()
+{
+ SolarMutexGuard g;
+
+ if ( !m_bContainerCreated )
+ {
+ if ( m_pMenu )
+ {
+ SolarMutexGuard aSolarMutexGuard;
+ return m_pMenu->GetItemCount();
+ }
+ else
+ return 0;
+ }
+ else
+ {
+ return PropertySetContainer::getCount();
+ }
+}
+
+Any SAL_CALL RootActionTriggerContainer::getByIndex( sal_Int32 Index )
+{
+ SolarMutexGuard g;
+
+ if ( !m_bContainerCreated )
+ FillContainer();
+
+ return PropertySetContainer::getByIndex( Index );
+}
+
+// XElementAccess
+Type SAL_CALL RootActionTriggerContainer::getElementType()
+{
+ return cppu::UnoType<XPropertySet>::get();
+}
+
+sal_Bool SAL_CALL RootActionTriggerContainer::hasElements()
+{
+ if ( m_pMenu )
+ {
+ SolarMutexGuard aSolarMutexGuard;
+ return ( m_pMenu->GetItemCount() > 0 );
+ }
+
+ return false;
+}
+
+// XServiceInfo
+OUString SAL_CALL RootActionTriggerContainer::getImplementationName()
+{
+ return IMPLEMENTATIONNAME_ROOTACTIONTRIGGERCONTAINER;
+}
+
+sal_Bool SAL_CALL RootActionTriggerContainer::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Sequence< OUString > SAL_CALL RootActionTriggerContainer::getSupportedServiceNames()
+{
+ Sequence< OUString > seqServiceNames { SERVICENAME_ACTIONTRIGGERCONTAINER };
+ return seqServiceNames;
+}
+
+// XUnoTunnel
+sal_Int64 SAL_CALL RootActionTriggerContainer::getSomething( const Sequence< sal_Int8 >& aIdentifier )
+{
+ if ( aIdentifier == impl_getStaticIdentifier() )
+ return reinterpret_cast< sal_Int64 >( this );
+ else
+ return 0;
+}
+
+// XTypeProvider
+Sequence< Type > SAL_CALL RootActionTriggerContainer::getTypes()
+{
+ // Create a static typecollection ...
+ static ::cppu::OTypeCollection ourTypeCollection(
+ cppu::UnoType<XMultiServiceFactory>::get(),
+ cppu::UnoType<XIndexContainer>::get(),
+ cppu::UnoType<XServiceInfo>::get(),
+ cppu::UnoType<XTypeProvider>::get(),
+ cppu::UnoType<XUnoTunnel>::get(),
+ cppu::UnoType<XNamed>::get());
+
+ return ourTypeCollection.getTypes();
+}
+
+Sequence< sal_Int8 > SAL_CALL RootActionTriggerContainer::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// private implementation helper
+void RootActionTriggerContainer::FillContainer()
+{
+ m_bContainerCreated = true;
+ ActionTriggerHelper::FillActionTriggerContainerFromMenu(
+ this,
+ m_pMenu );
+}
+OUString RootActionTriggerContainer::getName()
+{
+ OUString sRet;
+ if( m_pMenuIdentifier )
+ sRet = *m_pMenuIdentifier;
+ return sRet;
+}
+
+void RootActionTriggerContainer::setName( const OUString& )
+{
+ throw RuntimeException();
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/fwe/classes/sfxhelperfunctions.cxx b/framework/source/fwe/classes/sfxhelperfunctions.cxx
new file mode 100644
index 000000000..c6fe0bf03
--- /dev/null
+++ b/framework/source/fwe/classes/sfxhelperfunctions.cxx
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <framework/sfxhelperfunctions.hxx>
+#include <framework/ContextChangeEventMultiplexerTunnel.hxx>
+#include <helper/mischelper.hxx>
+
+static pfunc_setToolBoxControllerCreator pToolBoxControllerCreator = nullptr;
+static pfunc_setStatusBarControllerCreator pStatusBarControllerCreator = nullptr;
+static pfunc_getRefreshToolbars pRefreshToolbars = nullptr;
+static pfunc_createDockingWindow pCreateDockingWindow = nullptr;
+static pfunc_isDockingWindowVisible pIsDockingWindowVisible = nullptr;
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::frame;
+
+namespace framework
+{
+
+pfunc_setToolBoxControllerCreator SetToolBoxControllerCreator( pfunc_setToolBoxControllerCreator pSetToolBoxControllerCreator )
+{
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ pfunc_setToolBoxControllerCreator pOldSetToolBoxControllerCreator = pToolBoxControllerCreator;
+ pToolBoxControllerCreator = pSetToolBoxControllerCreator;
+ return pOldSetToolBoxControllerCreator;
+}
+
+svt::ToolboxController* CreateToolBoxController( const Reference< XFrame >& rFrame, ToolBox* pToolbox, unsigned short nID, const OUString& aCommandURL )
+{
+ pfunc_setToolBoxControllerCreator pFactory = nullptr;
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ pFactory = pToolBoxControllerCreator;
+ }
+
+ if ( pFactory )
+ return (*pFactory)( rFrame, pToolbox, nID, aCommandURL );
+ else
+ return nullptr;
+}
+
+pfunc_setStatusBarControllerCreator SetStatusBarControllerCreator( pfunc_setStatusBarControllerCreator pSetStatusBarControllerCreator )
+{
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ pfunc_setStatusBarControllerCreator pOldSetStatusBarControllerCreator = pSetStatusBarControllerCreator;
+ pStatusBarControllerCreator = pSetStatusBarControllerCreator;
+ return pOldSetStatusBarControllerCreator;
+}
+
+svt::StatusbarController* CreateStatusBarController( const Reference< XFrame >& rFrame, StatusBar* pStatusBar, unsigned short nID, const OUString& aCommandURL )
+{
+ pfunc_setStatusBarControllerCreator pFactory = nullptr;
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ pFactory = pStatusBarControllerCreator;
+ }
+
+ if ( pFactory )
+ return (*pFactory)( rFrame, pStatusBar, nID, aCommandURL );
+ else
+ return nullptr;
+}
+
+pfunc_getRefreshToolbars SetRefreshToolbars( pfunc_getRefreshToolbars pNewRefreshToolbarsFunc )
+{
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ pfunc_getRefreshToolbars pOldFunc = pRefreshToolbars;
+ pRefreshToolbars = pNewRefreshToolbarsFunc;
+
+ return pOldFunc;
+}
+
+void RefreshToolbars( css::uno::Reference< css::frame::XFrame > const & rFrame )
+{
+ pfunc_getRefreshToolbars pCallback = nullptr;
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ pCallback = pRefreshToolbars;
+ }
+
+ if ( pCallback )
+ (*pCallback)( rFrame );
+}
+
+pfunc_createDockingWindow SetDockingWindowCreator( pfunc_createDockingWindow pNewCreateDockingWindow )
+{
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ pfunc_createDockingWindow pOldFunc = pCreateDockingWindow;
+ pCreateDockingWindow = pNewCreateDockingWindow;
+
+ return pOldFunc;
+}
+
+void CreateDockingWindow( const css::uno::Reference< css::frame::XFrame >& rFrame, const OUString& rResourceURL )
+{
+ pfunc_createDockingWindow pFactory = nullptr;
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ pFactory = pCreateDockingWindow;
+ }
+
+ if ( pFactory )
+ (*pFactory)( rFrame, rResourceURL );
+}
+
+pfunc_isDockingWindowVisible SetIsDockingWindowVisible( pfunc_isDockingWindowVisible pNewIsDockingWindowVisible)
+{
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ pfunc_isDockingWindowVisible pOldFunc = pIsDockingWindowVisible;
+ pIsDockingWindowVisible = pNewIsDockingWindowVisible;
+
+ return pOldFunc;
+}
+
+bool IsDockingWindowVisible( const css::uno::Reference< css::frame::XFrame >& rFrame, const OUString& rResourceURL )
+{
+ pfunc_isDockingWindowVisible pCall = nullptr;
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ pCall = pIsDockingWindowVisible;
+ }
+
+ if ( pCall )
+ return (*pCall)( rFrame, rResourceURL );
+ else
+ return false;
+}
+
+using namespace ::com::sun::star;
+uno::Reference<ui::XContextChangeEventListener> GetFirstListenerWith(
+ uno::Reference<uno::XInterface> const& xEventFocus,
+ std::function<bool (uno::Reference<ui::XContextChangeEventListener> const&)> const& rPredicate)
+{
+ return GetFirstListenerWith_Impl(xEventFocus, rPredicate);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */