summaryrefslogtreecommitdiffstats
path: root/svtools/source/config
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /svtools/source/config
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'svtools/source/config')
-rw-r--r--svtools/source/config/accessibilityoptions.cxx390
-rw-r--r--svtools/source/config/apearcfg.cxx198
-rw-r--r--svtools/source/config/colorcfg.cxx607
-rw-r--r--svtools/source/config/extcolorcfg.cxx665
-rw-r--r--svtools/source/config/fontsubstconfig.cxx155
-rw-r--r--svtools/source/config/htmlcfg.cxx89
-rw-r--r--svtools/source/config/itemholder2.cxx140
-rw-r--r--svtools/source/config/itemholder2.hxx64
-rw-r--r--svtools/source/config/languagetoolcfg.cxx164
-rw-r--r--svtools/source/config/miscopt.cxx456
-rw-r--r--svtools/source/config/optionsdrawinglayer.cxx263
-rw-r--r--svtools/source/config/printoptions.cxx171
-rw-r--r--svtools/source/config/slidesorterbaropt.cxx425
-rw-r--r--svtools/source/config/test/test.cxx215
14 files changed, 4002 insertions, 0 deletions
diff --git a/svtools/source/config/accessibilityoptions.cxx b/svtools/source/config/accessibilityoptions.cxx
new file mode 100644
index 000000000..4922326fa
--- /dev/null
+++ b/svtools/source/config/accessibilityoptions.cxx
@@ -0,0 +1,390 @@
+/* -*- 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 <svtools/accessibilityoptions.hxx>
+
+#include <unotools/configmgr.hxx>
+#include <com/sun/star/uno/Any.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <comphelper/configurationhelper.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <tools/diagnose_ex.h>
+#include <mutex>
+
+#include "itemholder2.hxx"
+
+using namespace utl;
+using namespace com::sun::star::uno;
+
+#define HELP_TIP_TIMEOUT 0xffff // max. timeout setting to pretend a non-timeout
+
+// class SvtAccessibilityOptions_Impl ---------------------------------------------
+
+class SvtAccessibilityOptions_Impl
+{
+private:
+ css::uno::Reference< css::container::XNameAccess > m_xCfg;
+ css::uno::Reference< css::beans::XPropertySet > m_xNode;
+
+public:
+ SvtAccessibilityOptions_Impl();
+
+ void SetVCLSettings();
+ bool GetIsHelpTipsDisappear() const;
+ bool GetIsAllowAnimatedGraphics() const;
+ bool GetIsAllowAnimatedText() const;
+ bool GetIsAutomaticFontColor() const;
+ sal_Int16 GetHelpTipSeconds() const;
+ bool IsSelectionInReadonly() const;
+ sal_Int16 GetEdgeBlending() const;
+ sal_Int16 GetListBoxMaximumLineCount() const;
+ sal_Int16 GetColorValueSetColumnCount() const;
+ bool GetPreviewUsesCheckeredBackground() const;
+};
+
+// initialization of static members --------------------------------------
+
+SvtAccessibilityOptions_Impl* SvtAccessibilityOptions::sm_pSingleImplConfig =nullptr;
+sal_Int32 SvtAccessibilityOptions::sm_nAccessibilityRefCount(0);
+
+namespace
+{
+ std::mutex& SingletonMutex()
+ {
+ static std::mutex SINGLETON;
+ return SINGLETON;
+ }
+}
+
+
+// class SvtAccessibilityOptions_Impl ---------------------------------------------
+
+SvtAccessibilityOptions_Impl::SvtAccessibilityOptions_Impl()
+{
+ try
+ {
+ m_xCfg.set(
+ ::comphelper::ConfigurationHelper::openConfig(
+ comphelper::getProcessComponentContext(),
+ "org.openoffice.Office.Common/Accessibility",
+ ::comphelper::EConfigurationModes::Standard ),
+ css::uno::UNO_QUERY);
+ m_xNode.set(m_xCfg, css::uno::UNO_QUERY);
+ }
+ catch(const css::uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.config");
+ m_xCfg.clear();
+ }
+}
+
+bool SvtAccessibilityOptions_Impl::GetIsHelpTipsDisappear() const
+{
+ bool bRet = true;
+
+ try
+ {
+ if(m_xNode.is())
+ m_xNode->getPropertyValue("IsHelpTipsDisappear") >>= bRet;
+ }
+ catch(const css::uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.config");
+ }
+
+ return bRet;
+}
+
+bool SvtAccessibilityOptions_Impl::GetIsAllowAnimatedGraphics() const
+{
+ bool bRet = true;
+
+ try
+ {
+ if(m_xNode.is())
+ m_xNode->getPropertyValue("IsAllowAnimatedGraphics") >>= bRet;
+ }
+ catch(const css::uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.config");
+ }
+
+ return bRet;
+}
+
+bool SvtAccessibilityOptions_Impl::GetIsAllowAnimatedText() const
+{
+ bool bRet = true;
+
+ try
+ {
+ static constexpr OUStringLiteral PROPNAME = u"IsAllowAnimatedText";
+ if(m_xNode.is())
+ m_xNode->getPropertyValue(PROPNAME) >>= bRet;
+ }
+ catch(const css::uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.config");
+ }
+
+ return bRet;
+}
+
+bool SvtAccessibilityOptions_Impl::GetIsAutomaticFontColor() const
+{
+ bool bRet = false;
+
+ try
+ {
+ if(m_xNode.is())
+ m_xNode->getPropertyValue("IsAutomaticFontColor") >>= bRet;
+ }
+ catch(const css::uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.config");
+ }
+
+ return bRet;
+}
+
+sal_Int16 SvtAccessibilityOptions_Impl::GetHelpTipSeconds() const
+{
+ sal_Int16 nRet = 4;
+
+ try
+ {
+ if(m_xNode.is())
+ m_xNode->getPropertyValue("HelpTipSeconds") >>= nRet;
+ }
+ catch(const css::uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.config");
+ }
+
+ return nRet;
+}
+
+bool SvtAccessibilityOptions_Impl::IsSelectionInReadonly() const
+{
+ bool bRet = false;
+
+ try
+ {
+ if(m_xNode.is())
+ m_xNode->getPropertyValue("IsSelectionInReadonly") >>= bRet;
+ }
+ catch(const css::uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.config");
+ }
+
+ return bRet;
+}
+
+sal_Int16 SvtAccessibilityOptions_Impl::GetEdgeBlending() const
+{
+ sal_Int16 nRet = 35;
+
+ try
+ {
+ if(m_xNode.is())
+ m_xNode->getPropertyValue("EdgeBlending") >>= nRet;
+ }
+ catch(const css::uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.config");
+ }
+
+ return nRet;
+}
+
+sal_Int16 SvtAccessibilityOptions_Impl::GetListBoxMaximumLineCount() const
+{
+ sal_Int16 nRet = 25;
+
+ try
+ {
+ if(m_xNode.is())
+ m_xNode->getPropertyValue("ListBoxMaximumLineCount") >>= nRet;
+ }
+ catch(const css::uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.config");
+ }
+
+ return nRet;
+}
+
+sal_Int16 SvtAccessibilityOptions_Impl::GetColorValueSetColumnCount() const
+{
+#ifdef IOS
+ return 4;
+#else
+ sal_Int16 nRet = 12;
+
+ try
+ {
+ if(m_xNode.is())
+ m_xNode->getPropertyValue("ColorValueSetColumnCount") >>= nRet;
+ }
+ catch(const css::uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.config");
+ }
+
+ return nRet;
+#endif
+}
+
+bool SvtAccessibilityOptions_Impl::GetPreviewUsesCheckeredBackground() const
+{
+ bool bRet = false;
+
+ try
+ {
+ if(m_xNode.is())
+ m_xNode->getPropertyValue("PreviewUsesCheckeredBackground") >>= bRet;
+ }
+ catch(const css::uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.config");
+ }
+
+ return bRet;
+}
+
+void SvtAccessibilityOptions_Impl::SetVCLSettings()
+{
+ AllSettings aAllSettings(Application::GetSettings());
+ StyleSettings aStyleSettings(aAllSettings.GetStyleSettings());
+ HelpSettings aHelpSettings(aAllSettings.GetHelpSettings());
+ bool StyleSettingsChanged(false);
+
+ aHelpSettings.SetTipTimeout( GetIsHelpTipsDisappear() ? GetHelpTipSeconds() * 1000 : HELP_TIP_TIMEOUT);
+ aAllSettings.SetHelpSettings(aHelpSettings);
+
+ const sal_Int16 nEdgeBlendingCountA(GetEdgeBlending());
+ OSL_ENSURE(nEdgeBlendingCountA >= 0, "OOps, negative values for EdgeBlending are not allowed (!)");
+ const sal_uInt16 nEdgeBlendingCountB(static_cast< sal_uInt16 >(nEdgeBlendingCountA >= 0 ? nEdgeBlendingCountA : 0));
+
+ if(aStyleSettings.GetEdgeBlending() != nEdgeBlendingCountB)
+ {
+ aStyleSettings.SetEdgeBlending(nEdgeBlendingCountB);
+ StyleSettingsChanged = true;
+ }
+
+ const sal_Int16 nMaxLineCountA(GetListBoxMaximumLineCount());
+ OSL_ENSURE(nMaxLineCountA >= 0, "OOps, negative values for ListBoxMaximumLineCount are not allowed (!)");
+ const sal_uInt16 nMaxLineCountB(static_cast< sal_uInt16 >(nMaxLineCountA >= 0 ? nMaxLineCountA : 0));
+
+ if(aStyleSettings.GetListBoxMaximumLineCount() != nMaxLineCountB)
+ {
+ aStyleSettings.SetListBoxMaximumLineCount(nMaxLineCountB);
+ StyleSettingsChanged = true;
+ }
+
+ const sal_Int16 nMaxColumnCountA(GetColorValueSetColumnCount());
+ OSL_ENSURE(nMaxColumnCountA >= 0, "OOps, negative values for ColorValueSetColumnCount are not allowed (!)");
+ const sal_uInt16 nMaxColumnCountB(static_cast< sal_uInt16 >(nMaxColumnCountA >= 0 ? nMaxColumnCountA : 0));
+
+ if(aStyleSettings.GetColorValueSetColumnCount() != nMaxColumnCountB)
+ {
+ aStyleSettings.SetColorValueSetColumnCount(nMaxColumnCountB);
+ StyleSettingsChanged = true;
+ }
+
+ const bool bPreviewUsesCheckeredBackground(GetPreviewUsesCheckeredBackground());
+
+ if(aStyleSettings.GetPreviewUsesCheckeredBackground() != bPreviewUsesCheckeredBackground)
+ {
+ aStyleSettings.SetPreviewUsesCheckeredBackground(bPreviewUsesCheckeredBackground);
+ StyleSettingsChanged = true;
+ }
+
+ if(StyleSettingsChanged)
+ {
+ aAllSettings.SetStyleSettings(aStyleSettings);
+ Application::MergeSystemSettings(aAllSettings);
+ }
+
+ Application::SetSettings(aAllSettings);
+}
+
+// class SvtAccessibilityOptions --------------------------------------------------
+
+SvtAccessibilityOptions::SvtAccessibilityOptions()
+{
+ if (!utl::ConfigManager::IsFuzzing())
+ {
+ std::unique_lock aGuard( SingletonMutex() );
+ if(!sm_pSingleImplConfig)
+ {
+ sm_pSingleImplConfig = new SvtAccessibilityOptions_Impl;
+ aGuard.unlock(); // because holdConfigItem will call this constructor
+ svtools::ItemHolder2::holdConfigItem(EItem::AccessibilityOptions);
+ }
+ ++sm_nAccessibilityRefCount;
+ }
+ //StartListening( *sm_pSingleImplConfig, sal_True );
+}
+
+SvtAccessibilityOptions::~SvtAccessibilityOptions()
+{
+ //EndListening( *sm_pSingleImplConfig, sal_True );
+ std::unique_lock aGuard( SingletonMutex() );
+ if( !--sm_nAccessibilityRefCount )
+ {
+ //if( sm_pSingleImplConfig->IsModified() )
+ // sm_pSingleImplConfig->Commit();
+ delete sm_pSingleImplConfig;
+ sm_pSingleImplConfig = nullptr;
+ }
+}
+
+bool SvtAccessibilityOptions::GetIsAllowAnimatedGraphics() const
+{
+ return sm_pSingleImplConfig->GetIsAllowAnimatedGraphics();
+}
+bool SvtAccessibilityOptions::GetIsAllowAnimatedText() const
+{
+ return sm_pSingleImplConfig->GetIsAllowAnimatedText();
+}
+bool SvtAccessibilityOptions::GetIsAutomaticFontColor() const
+{
+ return sm_pSingleImplConfig->GetIsAutomaticFontColor();
+}
+bool SvtAccessibilityOptions::IsSelectionInReadonly() const
+{
+ return sm_pSingleImplConfig->IsSelectionInReadonly();
+}
+
+
+void SvtAccessibilityOptions::SetVCLSettings()
+{
+ sm_pSingleImplConfig->SetVCLSettings();
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/config/apearcfg.cxx b/svtools/source/config/apearcfg.cxx
new file mode 100644
index 000000000..35670657e
--- /dev/null
+++ b/svtools/source/config/apearcfg.cxx
@@ -0,0 +1,198 @@
+/* -*- 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 <svtools/apearcfg.hxx>
+
+#include <o3tl/any.hxx>
+#include <tools/debug.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+
+#include <com/sun/star/uno/Sequence.hxx>
+
+#define DEFAULT_DRAGMODE DragMode::SystemDep
+#define DEFAULT_SNAPMODE SnapType::ToButton
+#define DEFAULT_AAMINHEIGHT 8
+
+using namespace ::com::sun::star::uno;
+
+bool SvtTabAppearanceCfg::bInitialized = false;
+
+SvtTabAppearanceCfg::SvtTabAppearanceCfg()
+ :ConfigItem("Office.Common/View")
+ ,nDragMode ( DEFAULT_DRAGMODE )
+ ,nSnapMode ( DEFAULT_SNAPMODE )
+ ,nMiddleMouse ( MouseMiddleButtonAction::AutoScroll )
+ ,nAAMinPixelHeight ( DEFAULT_AAMINHEIGHT )
+ ,bFontAntialiasing ( true )
+ ,bMenuMouseFollow ( false )
+{
+ const Sequence<OUString>& rNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(rNames);
+ const Any* pValues = aValues.getConstArray();
+ DBG_ASSERT(aValues.getLength() == rNames.getLength(), "GetProperties failed");
+
+ if(aValues.getLength() != rNames.getLength())
+ return;
+
+ for(int nProp = 0; nProp < rNames.getLength(); ++nProp, ++pValues)
+ {
+ if(pValues->hasValue())
+ {
+ switch(nProp)
+ {
+ case 0: //"Window/Drag"
+ {
+ short nTmp;
+ if (*pValues >>= nTmp)
+ nDragMode = static_cast<DragMode>(nTmp);
+ break;
+ }
+ case 1: bMenuMouseFollow = *o3tl::doAccess<bool>(*pValues); break; //"Menu/FollowMouse",
+ case 2:
+ {
+ short nTmp;
+ if (*pValues >>= nTmp)
+ nSnapMode = static_cast<SnapType>(nTmp); //"Dialog/MousePositioning",
+ break;
+ }
+ case 3: { short nTmp = 0; *pValues >>= nTmp; nMiddleMouse = static_cast<MouseMiddleButtonAction>(nTmp); break; } //"Dialog/MiddleMouseButton",
+ case 4: bFontAntialiasing = *o3tl::doAccess<bool>(*pValues); break; // "FontAntialiasing/Enabled",
+ case 5: *pValues >>= nAAMinPixelHeight; break; // "FontAntialiasing/MinPixelHeight",
+ }
+ }
+ }
+}
+
+SvtTabAppearanceCfg::~SvtTabAppearanceCfg( )
+{
+}
+
+const Sequence<OUString>& SvtTabAppearanceCfg::GetPropertyNames()
+{
+ static Sequence<OUString> const aNames
+ {
+ "Window/Drag" // 0
+ ,"Menu/FollowMouse" // 1
+ ,"Dialog/MousePositioning" // 2
+ ,"Dialog/MiddleMouseButton" // 3
+ ,"FontAntiAliasing/Enabled" // 4
+ ,"FontAntiAliasing/MinPixelHeight" // 5
+ };
+ return aNames;
+}
+
+void SvtTabAppearanceCfg::ImplCommit()
+{
+ const Sequence<OUString>& rNames = GetPropertyNames();
+ Sequence<Any> aValues(rNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ for(int nProp = 0; nProp < rNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case 0: pValues[nProp] <<= static_cast<short>(nDragMode); break; // "Window/Drag",
+ case 1: pValues[nProp] <<= bMenuMouseFollow; break; // "Menu/FollowMouse",
+ case 2: pValues[nProp] <<= static_cast<short>(nSnapMode); break; // "Dialog/MousePositioning",
+ case 3: pValues[nProp] <<= static_cast<short>(nMiddleMouse); break; // "Dialog/MiddleMouseButton",
+ case 4: pValues[nProp] <<= bFontAntialiasing; break; // "FontAntialiasing/Enabled",
+ case 5: pValues[nProp] <<= nAAMinPixelHeight; break; // "FontAntialiasing/MinPixelHeight",
+ }
+ }
+ PutProperties(rNames, aValues);
+}
+
+void SvtTabAppearanceCfg::Notify( const css::uno::Sequence< OUString >& )
+{
+}
+
+void SvtTabAppearanceCfg::SetSnapMode ( SnapType nSet )
+{
+ nSnapMode = nSet;
+ SetModified();
+}
+
+void SvtTabAppearanceCfg::SetMiddleMouseButton ( MouseMiddleButtonAction nSet )
+{
+ nMiddleMouse = nSet;
+ SetModified();
+}
+
+void SvtTabAppearanceCfg::SetApplicationDefaults ( Application* pApp )
+{
+ AllSettings hAppSettings = Application::GetSettings();
+ StyleSettings hAppStyle = hAppSettings.GetStyleSettings();
+
+ // Look & Feel
+
+ // SetStandard...Styles() resets the UseSystemUIFonts flag,
+ // but we don't want to change it now, so save the flag before ...
+ bool bUseSystemUIFonts = hAppStyle.GetUseSystemUIFonts();
+ hAppStyle.SetStandardStyles();
+ // and set it here
+ hAppStyle.SetUseSystemUIFonts( bUseSystemUIFonts );
+
+ // font anti aliasing
+ hAppStyle.SetAntialiasingMinPixelHeight( nAAMinPixelHeight );
+ hAppStyle.SetDisplayOptions( bFontAntialiasing ? DisplayOptions::NONE : DisplayOptions::AADisable );
+
+ // Mouse Snap
+
+ MouseSettings hMouseSettings = hAppSettings.GetMouseSettings();
+ MouseSettingsOptions nMouseOptions = hMouseSettings.GetOptions();
+
+ nMouseOptions &= ~ MouseSettingsOptions(MouseSettingsOptions::AutoCenterPos | MouseSettingsOptions::AutoDefBtnPos);
+
+ switch ( nSnapMode )
+ {
+ case SnapType::ToButton:
+ nMouseOptions |= MouseSettingsOptions::AutoDefBtnPos;
+ break;
+ case SnapType::ToMiddle:
+ nMouseOptions |= MouseSettingsOptions::AutoCenterPos;
+ break;
+ case SnapType::NONE:
+ default:
+ break;
+ }
+ hMouseSettings.SetOptions(nMouseOptions);
+ hMouseSettings.SetMiddleButtonAction(nMiddleMouse);
+
+ // Merge and Publish Settings
+
+ MouseFollowFlags nFollow = hMouseSettings.GetFollow();
+ if(bMenuMouseFollow)
+ nFollow |= MouseFollowFlags::Menu;
+ else
+ nFollow &= ~MouseFollowFlags::Menu;
+ hMouseSettings.SetFollow( nFollow );
+
+ hAppSettings.SetMouseSettings( hMouseSettings );
+
+ hAppSettings.SetStyleSettings( hAppStyle );
+ Application::MergeSystemSettings ( hAppSettings ); // Allow system-settings to apply
+ pApp->OverrideSystemSettings ( hAppSettings );
+
+ Application::SetSettings ( hAppSettings );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/config/colorcfg.cxx b/svtools/source/config/colorcfg.cxx
new file mode 100644
index 000000000..72556dd10
--- /dev/null
+++ b/svtools/source/config/colorcfg.cxx
@@ -0,0 +1,607 @@
+/* -*- 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 <sal/config.h>
+
+#include <string_view>
+
+#include <svtools/colorcfg.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <comphelper/processfactory.hxx>
+#include <unotools/configitem.hxx>
+#include <unotools/confignode.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/configpaths.hxx>
+#include <com/sun/star/uno/Sequence.h>
+#include <svl/poolitem.hxx>
+#include <mutex>
+
+#include "itemholder2.hxx"
+
+#include <vcl/svapp.hxx>
+#include <vcl/event.hxx>
+#include <vcl/settings.hxx>
+
+
+using namespace utl;
+using namespace com::sun::star;
+
+const char g_sIsVisible[] = "/IsVisible";
+
+
+namespace svtools
+{
+
+static sal_Int32 nColorRefCount_Impl = 0;
+namespace
+{
+ std::mutex& ColorMutex_Impl()
+ {
+ static std::mutex SINGLETON;
+ return SINGLETON;
+ }
+}
+
+ColorConfig_Impl* ColorConfig::m_pImpl = nullptr;
+
+class ColorConfig_Impl : public utl::ConfigItem
+{
+ ColorConfigValue m_aConfigValues[ColorConfigEntryCount];
+ OUString m_sLoadedScheme;
+ bool m_bAutoDetectSystemHC;
+
+ virtual void ImplCommit() override;
+
+public:
+ explicit ColorConfig_Impl();
+ virtual ~ColorConfig_Impl() override;
+
+ void Load(const OUString& rScheme);
+ void CommitCurrentSchemeName();
+ //changes the name of the current scheme but doesn't load it!
+ void SetCurrentSchemeName(const OUString& rSchemeName) {m_sLoadedScheme = rSchemeName;}
+ virtual void Notify( const uno::Sequence<OUString>& aPropertyNames) override;
+
+ const ColorConfigValue& GetColorConfigValue(ColorConfigEntry eValue) const
+ {return m_aConfigValues[eValue];}
+ void SetColorConfigValue(ColorConfigEntry eValue,
+ const ColorConfigValue& rValue );
+
+ const OUString& GetLoadedScheme() const {return m_sLoadedScheme;}
+
+ uno::Sequence< OUString> GetSchemeNames();
+
+ void AddScheme(const OUString& rNode);
+ void RemoveScheme(const OUString& rNode);
+ using ConfigItem::SetModified;
+ using ConfigItem::ClearModified;
+ void SettingsChanged();
+ bool GetAutoDetectSystemHC() const {return m_bAutoDetectSystemHC;}
+
+ DECL_LINK( DataChangedEventListener, VclSimpleEvent&, void );
+
+ void ImplUpdateApplicationSettings();
+};
+
+namespace {
+
+uno::Sequence< OUString> GetPropertyNames(std::u16string_view rScheme)
+{
+ struct ColorConfigEntryData_Impl
+ {
+ std::u16string_view cName;
+ bool bCanBeVisible;
+ };
+ static const ColorConfigEntryData_Impl cNames[] =
+ {
+ { std::u16string_view(u"/DocColor") ,false },
+ { std::u16string_view(u"/DocBoundaries") ,true },
+ { std::u16string_view(u"/AppBackground") ,false },
+ { std::u16string_view(u"/ObjectBoundaries"),true },
+ { std::u16string_view(u"/TableBoundaries") ,true },
+ { std::u16string_view(u"/FontColor") ,false },
+ { std::u16string_view(u"/Links") ,true },
+ { std::u16string_view(u"/LinksVisited") ,true },
+ { std::u16string_view(u"/Spell") ,false },
+ { std::u16string_view(u"/SmartTags") ,false },
+ { std::u16string_view(u"/Shadow") , true },
+ { std::u16string_view(u"/WriterTextGrid") ,false },
+ { std::u16string_view(u"/WriterFieldShadings"),true },
+ { std::u16string_view(u"/WriterIdxShadings") ,true },
+ { std::u16string_view(u"/WriterDirectCursor") ,true },
+ { std::u16string_view(u"/WriterScriptIndicator") ,false },
+ { std::u16string_view(u"/WriterSectionBoundaries") ,true },
+ { std::u16string_view(u"/WriterHeaderFooterMark") ,false },
+ { std::u16string_view(u"/WriterPageBreaks") ,false },
+ { std::u16string_view(u"/HTMLSGML") ,false },
+ { std::u16string_view(u"/HTMLComment") ,false },
+ { std::u16string_view(u"/HTMLKeyword") ,false },
+ { std::u16string_view(u"/HTMLUnknown") ,false },
+ { std::u16string_view(u"/CalcGrid") ,false },
+ { std::u16string_view(u"/CalcPageBreak"), false },
+ { std::u16string_view(u"/CalcPageBreakManual"), false },
+ { std::u16string_view(u"/CalcPageBreakAutomatic"), false },
+ { std::u16string_view(u"/CalcHiddenColRow"), true },
+ { std::u16string_view(u"/CalcDetective") ,false },
+ { std::u16string_view(u"/CalcDetectiveError") ,false },
+ { std::u16string_view(u"/CalcReference") ,false },
+ { std::u16string_view(u"/CalcNotesBackground") ,false },
+ { std::u16string_view(u"/CalcValue") ,false },
+ { std::u16string_view(u"/CalcFormula") ,false },
+ { std::u16string_view(u"/CalcText") ,false },
+ { std::u16string_view(u"/CalcProtectedBackground") ,false },
+ { std::u16string_view(u"/DrawGrid") ,true },
+ { std::u16string_view(u"/BASICIdentifier"), false },
+ { std::u16string_view(u"/BASICComment") , false },
+ { std::u16string_view(u"/BASICNumber") , false },
+ { std::u16string_view(u"/BASICString") , false },
+ { std::u16string_view(u"/BASICOperator") , false },
+ { std::u16string_view(u"/BASICKeyword") , false },
+ { std::u16string_view(u"/BASICError"), false },
+ { std::u16string_view(u"/SQLIdentifier"), false },
+ { std::u16string_view(u"/SQLNumber"), false },
+ { std::u16string_view(u"/SQLString"), false },
+ { std::u16string_view(u"/SQLOperator"), false },
+ { std::u16string_view(u"/SQLKeyword"), false },
+ { std::u16string_view(u"/SQLParameter"), false },
+ { std::u16string_view(u"/SQLComment"), false }
+ };
+
+ uno::Sequence<OUString> aNames(2 * ColorConfigEntryCount);
+ OUString* pNames = aNames.getArray();
+ int nIndex = 0;
+ OUString sBase = "ColorSchemes/"
+ + utl::wrapConfigurationElementName(rScheme);
+ for(sal_Int32 i = 0; i < ColorConfigEntryCount; ++i)
+ {
+ OUString sBaseName = sBase + cNames[i].cName;
+ pNames[nIndex++] = sBaseName + "/Color";
+ if(cNames[i].bCanBeVisible)
+ {
+ pNames[nIndex++] = sBaseName + g_sIsVisible;
+ }
+ }
+ aNames.realloc(nIndex);
+ return aNames;
+}
+
+}
+
+ColorConfig_Impl::ColorConfig_Impl() :
+ ConfigItem("Office.UI/ColorScheme"),
+ m_bAutoDetectSystemHC(true)
+{
+ //try to register on the root node - if possible
+ uno::Sequence < OUString > aNames(1);
+ EnableNotification( aNames );
+
+ if (!utl::ConfigManager::IsFuzzing())
+ Load(OUString());
+
+ ImplUpdateApplicationSettings();
+
+ ::Application::AddEventListener( LINK(this, ColorConfig_Impl, DataChangedEventListener) );
+
+}
+
+ColorConfig_Impl::~ColorConfig_Impl()
+{
+ ::Application::RemoveEventListener( LINK(this, ColorConfig_Impl, DataChangedEventListener) );
+}
+
+void ColorConfig_Impl::Load(const OUString& rScheme)
+{
+ OUString sScheme(rScheme);
+ if(sScheme.isEmpty())
+ {
+ //detect current scheme name
+ uno::Sequence < OUString > aCurrent { "CurrentColorScheme" };
+ uno::Sequence< uno::Any > aCurrentVal = GetProperties( aCurrent );
+ aCurrentVal.getConstArray()[0] >>= sScheme;
+ }
+ m_sLoadedScheme = sScheme;
+
+ uno::Sequence < OUString > aColorNames = GetPropertyNames(sScheme);
+ uno::Sequence< uno::Any > aColors = GetProperties( aColorNames );
+ const uno::Any* pColors = aColors.getConstArray();
+ const OUString* pColorNames = aColorNames.getConstArray();
+ sal_Int32 nIndex = 0;
+ for(int i = 0; i < ColorConfigEntryCount && aColors.getLength() > nIndex; ++i)
+ {
+ if(pColors[nIndex].hasValue())
+ {
+ Color nTmp;
+ pColors[nIndex] >>= nTmp;
+ m_aConfigValues[i].nColor = nTmp;
+ }
+ else
+ m_aConfigValues[i].nColor = COL_AUTO;
+ nIndex++;
+ if(nIndex >= aColors.getLength())
+ break;
+ //test for visibility property
+ if(pColorNames[nIndex].endsWith(g_sIsVisible))
+ m_aConfigValues[i].bIsVisible = Any2Bool(pColors[nIndex++]);
+ }
+ // fdo#71511: check if we are running in a11y autodetect
+ {
+ utl::OConfigurationNode aNode = utl::OConfigurationTreeRoot::tryCreateWithComponentContext(comphelper::getProcessComponentContext(),"org.openoffice.Office.Common/Accessibility" );
+ if(aNode.isValid())
+ {
+ uno::Any aValue = aNode.getNodeValue(OUString("AutoDetectSystemHC"));
+ aValue >>= m_bAutoDetectSystemHC;
+ }
+ }
+}
+
+void ColorConfig_Impl::Notify( const uno::Sequence<OUString>& )
+{
+ //loading via notification always uses the default setting
+ Load(OUString());
+ NotifyListeners(ConfigurationHints::NONE);
+}
+
+void ColorConfig_Impl::ImplCommit()
+{
+ uno::Sequence < OUString > aColorNames = GetPropertyNames(m_sLoadedScheme);
+ uno::Sequence < beans::PropertyValue > aPropValues(aColorNames.getLength());
+ beans::PropertyValue* pPropValues = aPropValues.getArray();
+ const OUString* pColorNames = aColorNames.getConstArray();
+ sal_Int32 nIndex = 0;
+ for(int i = 0; i < ColorConfigEntryCount && aColorNames.getLength() > nIndex; ++i)
+ {
+ pPropValues[nIndex].Name = pColorNames[nIndex];
+ //save automatic colors as void value
+ if(m_aConfigValues[i].nColor != COL_AUTO)
+ pPropValues[nIndex].Value <<= m_aConfigValues[i].nColor;
+
+ nIndex++;
+ if(nIndex >= aColorNames.getLength())
+ break;
+ //test for visibility property
+ if(pColorNames[nIndex].endsWith(g_sIsVisible))
+ {
+ pPropValues[nIndex].Name = pColorNames[nIndex];
+ pPropValues[nIndex].Value <<= m_aConfigValues[i].bIsVisible;
+ nIndex++;
+ }
+ }
+ SetSetProperties("ColorSchemes", aPropValues);
+
+ CommitCurrentSchemeName();
+}
+
+void ColorConfig_Impl::CommitCurrentSchemeName()
+{
+ //save current scheme name
+ uno::Sequence < OUString > aCurrent { "CurrentColorScheme" };
+ uno::Sequence< uno::Any > aCurrentVal(1);
+ aCurrentVal.getArray()[0] <<= m_sLoadedScheme;
+ PutProperties(aCurrent, aCurrentVal);
+}
+
+void ColorConfig_Impl::SetColorConfigValue(ColorConfigEntry eValue, const ColorConfigValue& rValue )
+{
+ if(rValue != m_aConfigValues[eValue])
+ {
+ m_aConfigValues[eValue] = rValue;
+ SetModified();
+ }
+}
+
+uno::Sequence< OUString> ColorConfig_Impl::GetSchemeNames()
+{
+ return GetNodeNames("ColorSchemes");
+}
+
+void ColorConfig_Impl::AddScheme(const OUString& rScheme)
+{
+ if(ConfigItem::AddNode("ColorSchemes", rScheme))
+ {
+ m_sLoadedScheme = rScheme;
+ Commit();
+ }
+}
+
+void ColorConfig_Impl::RemoveScheme(const OUString& rScheme)
+{
+ uno::Sequence< OUString > aElements { rScheme };
+ ClearNodeElements("ColorSchemes", aElements);
+}
+
+void ColorConfig_Impl::SettingsChanged()
+{
+ SolarMutexGuard aVclGuard;
+
+ ImplUpdateApplicationSettings();
+
+ NotifyListeners(ConfigurationHints::NONE);
+}
+
+IMPL_LINK( ColorConfig_Impl, DataChangedEventListener, VclSimpleEvent&, rEvent, void )
+{
+ if ( rEvent.GetId() == VclEventId::ApplicationDataChanged )
+ {
+ DataChangedEvent* pData = static_cast<DataChangedEvent*>(static_cast<VclWindowEvent&>(rEvent).GetData());
+ if ( (pData->GetType() == DataChangedEventType::SETTINGS) &&
+ (pData->GetFlags() & AllSettingsFlags::STYLE) )
+ {
+ SettingsChanged();
+ }
+ }
+}
+
+
+/** updates the font color in the vcl window settings */
+void ColorConfig_Impl::ImplUpdateApplicationSettings()
+{
+ Application* pApp = GetpApp();
+ if( !pApp )
+ return;
+
+ AllSettings aSettings = Application::GetSettings();
+ StyleSettings aStyleSettings( aSettings.GetStyleSettings() );
+
+ ColorConfigValue aRet = GetColorConfigValue(svtools::FONTCOLOR);
+ if(COL_AUTO == aRet.nColor)
+ aRet.nColor = ColorConfig::GetDefaultColor(svtools::FONTCOLOR);
+
+ Color aFontColor(aRet.nColor);
+
+ if( aStyleSettings.GetFontColor() != aFontColor )
+ {
+ aStyleSettings.SetFontColor( aFontColor );
+
+ aSettings.SetStyleSettings( aStyleSettings );
+ Application::SetSettings( aSettings );
+ }
+}
+
+ColorConfig::ColorConfig()
+{
+ if (utl::ConfigManager::IsFuzzing())
+ return;
+ std::unique_lock aGuard( ColorMutex_Impl() );
+ if ( !m_pImpl )
+ {
+ m_pImpl = new ColorConfig_Impl;
+ aGuard.unlock(); // because holdConfigItem will call this constructor
+ svtools::ItemHolder2::holdConfigItem(EItem::ColorConfig);
+ }
+ ++nColorRefCount_Impl;
+ m_pImpl->AddListener(this);
+}
+
+ColorConfig::~ColorConfig()
+{
+ if (utl::ConfigManager::IsFuzzing())
+ return;
+ std::unique_lock aGuard( ColorMutex_Impl() );
+ m_pImpl->RemoveListener(this);
+ if(!--nColorRefCount_Impl)
+ {
+ delete m_pImpl;
+ m_pImpl = nullptr;
+ }
+}
+
+Color ColorConfig::GetDefaultColor(ColorConfigEntry eEntry)
+{
+ static const Color aAutoColors[] =
+ {
+ COL_WHITE, // DOCCOLOR
+ COL_LIGHTGRAY, // DOCBOUNDARIES
+ Color(0xDFDFDE), // APPBACKGROUND
+ COL_LIGHTGRAY, // OBJECTBOUNDARIES
+ COL_LIGHTGRAY, // TABLEBOUNDARIES
+ COL_BLACK, // FONTCOLOR
+ COL_BLUE, // LINKS
+ Color(0x0000cc), // LINKSVISITED
+ COL_LIGHTRED, // SPELL
+ COL_LIGHTMAGENTA, // SMARTTAGS
+ COL_GRAY, // SHADOWCOLOR
+ COL_LIGHTGRAY, // WRITERTEXTGRID
+ COL_LIGHTGRAY, // WRITERFIELDSHADIN
+ COL_LIGHTGRAY, // WRITERIDXSHADINGS
+ COL_BLACK, // WRITERDIRECTCURSOR
+ COL_GREEN, //WRITERSCRIPTINDICATOR
+ COL_LIGHTGRAY, //WRITERSECTIONBOUNDARIES
+ Color(0x0369a3), //WRITERHEADERFOOTERMARK,
+ COL_BLUE, //WRITERPAGEBREAKS,
+ COL_LIGHTBLUE, // HTMLSGML
+ COL_LIGHTGREEN, // HTMLCOMMENT
+ COL_LIGHTRED, // HTMLKEYWORD
+ COL_GRAY, // HTMLUNKNOWN
+ COL_GRAY3, // CALCGRID
+ COL_BLUE, //CALCPAGEBREAK
+ Color(0x2300dc), //CALCPAGEBREAKMANUAL
+ COL_GRAY7, //CALCPAGEBREAKAUTOMATIC
+ Color(0x2300dc), //CALCHIDDENCOLROW
+ COL_LIGHTBLUE, // CALCDETECTIVE
+ COL_LIGHTRED, // CALCDETECTIVEERROR
+ Color(0xef0fff), // CALCREFERENCE
+ Color(0xffffc0), // CALCNOTESBACKGROUND
+ COL_LIGHTBLUE, // CALCVALUE
+ COL_GREEN, // CALCFORMULA
+ COL_BLACK, // CALCTEXT
+ COL_LIGHTGRAY, // CALCPROTECTEDBACKGROUND
+ COL_GRAY7, // DRAWGRID
+ COL_GREEN, // BASICIDENTIFIER,
+ COL_GRAY, // BASICCOMMENT,
+ COL_LIGHTRED, // BASICNUMBER,
+ COL_LIGHTRED, // BASICSTRING,
+ COL_BLUE, // BASICOPERATOR,
+ COL_BLUE, // BASICKEYWORD,
+ COL_RED, //BASICERROR
+ Color(0x009900), // SQLIDENTIFIER
+ COL_BLACK, // SQLNUMBER
+ Color(0xCE7B00), // SQLSTRING
+ COL_BLACK, // SQLOPERATOR
+ Color(0x0000E6), // SQLKEYWORD
+ Color(0x259D9D), // SQLPARAMETER
+ COL_GRAY, // SQLCOMMENT
+ };
+ Color aRet;
+ switch(eEntry)
+ {
+ case APPBACKGROUND :
+ aRet = Application::GetSettings().GetStyleSettings().GetWorkspaceColor();
+ break;
+
+ case LINKS :
+ aRet = Application::GetSettings().GetStyleSettings().GetLinkColor();
+ break;
+
+ case LINKSVISITED :
+ aRet = Application::GetSettings().GetStyleSettings().GetVisitedLinkColor();
+ break;
+
+ default:
+ aRet = aAutoColors[eEntry];
+ }
+ // fdo#71511: if in autodetected a11y HC mode, do pull background color from theme
+ if(m_pImpl && m_pImpl->GetAutoDetectSystemHC())
+ {
+ switch(eEntry)
+ {
+ case DOCCOLOR :
+ aRet = Application::GetSettings().GetStyleSettings().GetWindowColor();
+ break;
+ case FONTCOLOR :
+ aRet = Application::GetSettings().GetStyleSettings().GetWindowTextColor();
+ break;
+ default:
+ break;
+ }
+ }
+ return aRet;
+}
+
+ColorConfigValue ColorConfig::GetColorValue(ColorConfigEntry eEntry, bool bSmart) const
+{
+ ColorConfigValue aRet;
+
+ if (m_pImpl)
+ aRet = m_pImpl->GetColorConfigValue(eEntry);
+
+ if (bSmart && aRet.nColor == COL_AUTO)
+ aRet.nColor = ColorConfig::GetDefaultColor(eEntry);
+
+ return aRet;
+}
+
+EditableColorConfig::EditableColorConfig() :
+ m_pImpl(new ColorConfig_Impl),
+ m_bModified(false)
+{
+ m_pImpl->BlockBroadcasts(true);
+}
+
+EditableColorConfig::~EditableColorConfig()
+{
+ m_pImpl->BlockBroadcasts(false);
+ if(m_bModified)
+ m_pImpl->SetModified();
+ if(m_pImpl->IsModified())
+ m_pImpl->Commit();
+}
+
+uno::Sequence< OUString > EditableColorConfig::GetSchemeNames() const
+{
+ return m_pImpl->GetSchemeNames();
+}
+
+void EditableColorConfig::DeleteScheme(const OUString& rScheme )
+{
+ m_pImpl->RemoveScheme(rScheme);
+}
+
+void EditableColorConfig::AddScheme(const OUString& rScheme )
+{
+ m_pImpl->AddScheme(rScheme);
+}
+
+void EditableColorConfig::LoadScheme(const OUString& rScheme )
+{
+ if(m_bModified)
+ m_pImpl->SetModified();
+ if(m_pImpl->IsModified())
+ m_pImpl->Commit();
+ m_bModified = false;
+ m_pImpl->Load(rScheme);
+ //the name of the loaded scheme has to be committed separately
+ m_pImpl->CommitCurrentSchemeName();
+}
+
+const OUString& EditableColorConfig::GetCurrentSchemeName()const
+{
+ return m_pImpl->GetLoadedScheme();
+}
+
+// Changes the name of the current scheme but doesn't load it!
+void EditableColorConfig::SetCurrentSchemeName(const OUString& rScheme)
+{
+ m_pImpl->SetCurrentSchemeName(rScheme);
+ m_pImpl->CommitCurrentSchemeName();
+}
+
+const ColorConfigValue& EditableColorConfig::GetColorValue(
+ ColorConfigEntry eEntry)const
+{
+ return m_pImpl->GetColorConfigValue(eEntry);
+}
+
+void EditableColorConfig::SetColorValue(
+ ColorConfigEntry eEntry, const ColorConfigValue& rValue)
+{
+ m_pImpl->SetColorConfigValue(eEntry, rValue);
+ m_pImpl->ClearModified();
+ m_bModified = true;
+}
+
+void EditableColorConfig::SetModified()
+{
+ m_bModified = true;
+}
+
+void EditableColorConfig::Commit()
+{
+ if(m_bModified)
+ m_pImpl->SetModified();
+ if(m_pImpl->IsModified())
+ m_pImpl->Commit();
+ m_bModified = false;
+}
+
+void EditableColorConfig::DisableBroadcast()
+{
+ m_pImpl->BlockBroadcasts(true);
+}
+
+void EditableColorConfig::EnableBroadcast()
+{
+ m_pImpl->BlockBroadcasts(false);
+}
+
+
+}//namespace svtools
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/config/extcolorcfg.cxx b/svtools/source/config/extcolorcfg.cxx
new file mode 100644
index 000000000..5a5e2c6c0
--- /dev/null
+++ b/svtools/source/config/extcolorcfg.cxx
@@ -0,0 +1,665 @@
+/* -*- 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 <sal/config.h>
+
+#include <map>
+#include <string_view>
+
+#include <svtools/extcolorcfg.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <tools/color.hxx>
+#include <unotools/configitem.hxx>
+#include <com/sun/star/uno/Sequence.h>
+#include <comphelper/sequence.hxx>
+#include <svl/hint.hxx>
+#include <mutex>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <o3tl/string_view.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/event.hxx>
+
+
+using namespace utl;
+using namespace com::sun::star;
+
+
+namespace svtools
+{
+
+static sal_Int32 nExtendedColorRefCount_Impl = 0;
+namespace
+{
+ std::mutex& ColorMutex_Impl()
+ {
+ static std::mutex SINGLETON;
+ return SINGLETON;
+ }
+}
+
+ExtendedColorConfig_Impl* ExtendedColorConfig::m_pImpl = nullptr;
+
+class ExtendedColorConfig_Impl : public utl::ConfigItem, public SfxBroadcaster
+{
+ typedef std::map<OUString, OUString> TDisplayNames;
+ typedef std::map<OUString, ExtendedColorConfigValue> TConfigValues;
+ typedef ::std::vector<TConfigValues::iterator> TMapPos;
+ typedef ::std::pair< TConfigValues, TMapPos > TComponentMapping;
+ typedef std::map<OUString, TComponentMapping> TComponents;
+ TComponents m_aConfigValues;
+ TDisplayNames m_aComponentDisplayNames;
+ ::std::vector<TComponents::iterator> m_aConfigValuesPos;
+
+ OUString m_sLoadedScheme;
+ bool m_bIsBroadcastEnabled;
+ static bool m_bLockBroadcast;
+ static bool m_bBroadcastWhenUnlocked;
+
+ uno::Sequence< OUString> GetPropertyNames(const OUString& rScheme);
+ void FillComponentColors(const uno::Sequence < OUString >& _rComponents,const TDisplayNames& _rDisplayNames);
+
+ virtual void ImplCommit() override;
+
+public:
+ explicit ExtendedColorConfig_Impl();
+ virtual ~ExtendedColorConfig_Impl() override;
+
+ void Load(const OUString& rScheme);
+ void CommitCurrentSchemeName();
+ //changes the name of the current scheme but doesn't load it!
+ void SetCurrentSchemeName(const OUString& rSchemeName) {m_sLoadedScheme = rSchemeName;}
+ bool ExistsScheme(std::u16string_view _sSchemeName);
+ virtual void Notify( const uno::Sequence<OUString>& aPropertyNames) override;
+
+ sal_Int32 GetComponentCount() const;
+ OUString GetComponentName(sal_uInt32 _nPos) const;
+ OUString GetComponentDisplayName(const OUString& _sComponentName) const;
+ sal_Int32 GetComponentColorCount(const OUString& _sName) const;
+ ExtendedColorConfigValue GetComponentColorConfigValue(const OUString& _sName,sal_uInt32 _nPos) const;
+
+ ExtendedColorConfigValue GetColorConfigValue(const OUString& _sComponentName,const OUString& _sName)
+ {
+ TComponents::iterator aFind = m_aConfigValues.find(_sComponentName);
+ if ( aFind != m_aConfigValues.end() )
+ {
+ TConfigValues::iterator aFind2 = aFind->second.first.find(_sName);
+ if ( aFind2 != aFind->second.first.end() )
+ return aFind2->second;
+ }
+#if OSL_DEBUG_LEVEL > 0
+ SAL_WARN( "svtools", "Could find the required config:\n"
+ "component: " << _sComponentName
+ << "\nname: " << _sName );
+#endif
+ return ExtendedColorConfigValue();
+ }
+ void SetColorConfigValue(const OUString& _sName,
+ const ExtendedColorConfigValue& rValue );
+
+ void AddScheme(const OUString& rNode);
+ void RemoveScheme(const OUString& rNode);
+ using ConfigItem::SetModified;
+ using ConfigItem::ClearModified;
+ void SettingsChanged();
+
+ static void DisableBroadcast();
+ static void EnableBroadcast();
+
+ static void LockBroadcast();
+ static void UnlockBroadcast();
+
+ DECL_LINK( DataChangedEventListener, VclSimpleEvent&, void );
+};
+
+uno::Sequence< OUString> ExtendedColorConfig_Impl::GetPropertyNames(const OUString& rScheme)
+{
+ uno::Sequence< OUString> aNames(GetNodeNames(rScheme));
+ for(OUString & i : asNonConstRange(aNames))
+ {
+ i = rScheme + "/" + i;
+ }
+ return aNames;
+}
+
+sal_Int32 ExtendedColorConfig_Impl::GetComponentCount() const
+{
+ return m_aConfigValues.size();
+}
+
+sal_Int32 ExtendedColorConfig_Impl::GetComponentColorCount(const OUString& _sName) const
+{
+ sal_Int32 nSize = 0;
+ TComponents::const_iterator aFind = m_aConfigValues.find(_sName);
+ if ( aFind != m_aConfigValues.end() )
+ {
+ nSize = aFind->second.first.size();
+ }
+ return nSize;
+}
+
+ExtendedColorConfigValue ExtendedColorConfig_Impl::GetComponentColorConfigValue(const OUString& _sName,sal_uInt32 _nPos) const
+{
+ TComponents::const_iterator aFind = m_aConfigValues.find(_sName);
+ if ( aFind != m_aConfigValues.end() )
+ {
+ if ( _nPos < aFind->second.second.size() )
+ {
+ return aFind->second.second[_nPos]->second;
+ }
+ }
+ return ExtendedColorConfigValue();
+}
+
+OUString ExtendedColorConfig_Impl::GetComponentDisplayName(const OUString& _sComponentName) const
+{
+ OUString sRet;
+ TDisplayNames::const_iterator aFind = m_aComponentDisplayNames.find(_sComponentName);
+ if ( aFind != m_aComponentDisplayNames.end() )
+ sRet = aFind->second;
+ return sRet;
+}
+
+OUString ExtendedColorConfig_Impl::GetComponentName(sal_uInt32 _nPos) const
+{
+ OUString sRet;
+ if ( _nPos < m_aConfigValuesPos.size() )
+ sRet = m_aConfigValuesPos[_nPos]->first;
+ return sRet;
+}
+
+bool ExtendedColorConfig_Impl::m_bLockBroadcast = false;
+bool ExtendedColorConfig_Impl::m_bBroadcastWhenUnlocked = false;
+ExtendedColorConfig_Impl::ExtendedColorConfig_Impl() :
+ ConfigItem("Office.ExtendedColorScheme"),
+ m_bIsBroadcastEnabled(true)
+{
+ //try to register on the root node - if possible
+ uno::Sequence < OUString > aNames(1);
+ EnableNotification( aNames );
+ Load(OUString());
+
+ ::Application::AddEventListener( LINK(this, ExtendedColorConfig_Impl, DataChangedEventListener) );
+
+}
+
+ExtendedColorConfig_Impl::~ExtendedColorConfig_Impl()
+{
+ ::Application::RemoveEventListener( LINK(this, ExtendedColorConfig_Impl, DataChangedEventListener) );
+}
+
+void ExtendedColorConfig_Impl::DisableBroadcast()
+{
+ if ( ExtendedColorConfig::m_pImpl )
+ ExtendedColorConfig::m_pImpl->m_bIsBroadcastEnabled = false;
+}
+
+void ExtendedColorConfig_Impl::EnableBroadcast()
+{
+ if ( ExtendedColorConfig::m_pImpl )
+ ExtendedColorConfig::m_pImpl->m_bIsBroadcastEnabled = true;
+}
+
+static void lcl_addString(uno::Sequence < OUString >& _rSeq,std::u16string_view _sAdd)
+{
+ for(OUString & i : asNonConstRange(_rSeq))
+ i += _sAdd;
+}
+
+void ExtendedColorConfig_Impl::Load(const OUString& rScheme)
+{
+ m_aComponentDisplayNames.clear();
+ m_aConfigValuesPos.clear();
+ m_aConfigValues.clear();
+
+ // fill display names
+ TDisplayNames aDisplayNameMap;
+ uno::Sequence < OUString > aComponentNames = GetPropertyNames("EntryNames");
+ OUString sDisplayName("/DisplayName");
+ for(OUString & componentName : asNonConstRange(aComponentNames))
+ {
+ uno::Sequence< uno::Any > aComponentDisplayNamesValue = GetProperties( { componentName + sDisplayName } );
+ OUString sComponentDisplayName;
+ if ( aComponentDisplayNamesValue.hasElements() && (aComponentDisplayNamesValue[0] >>= sComponentDisplayName) )
+ {
+ m_aComponentDisplayNames.emplace(componentName.getToken(1, '/'),sComponentDisplayName);
+ }
+
+ componentName += "/Entries";
+ uno::Sequence < OUString > aDisplayNames = GetPropertyNames(componentName);
+ lcl_addString(aDisplayNames,sDisplayName);
+
+ uno::Sequence< uno::Any > aDisplayNamesValue = GetProperties( aDisplayNames );
+
+ const OUString* pDispIter = aDisplayNames.getConstArray();
+ const OUString* pDispEnd = pDispIter + aDisplayNames.getLength();
+ for(sal_Int32 j = 0;pDispIter != pDispEnd;++pDispIter,++j)
+ {
+ sal_Int32 nIndex = 0;
+ o3tl::getToken(*pDispIter, 0, '/', nIndex);
+ std::u16string_view sName = pDispIter->subView(nIndex);
+ sName = sName.substr(0, sName.rfind(sDisplayName));
+ OUString sCurrentDisplayName;
+ aDisplayNamesValue[j] >>= sCurrentDisplayName;
+ aDisplayNameMap.emplace(OUString(sName),sCurrentDisplayName);
+ }
+ }
+
+ // load color settings
+ OUString sScheme(rScheme);
+
+ if(sScheme.isEmpty())
+ {
+ //detect current scheme name
+ uno::Sequence < OUString > aCurrent { "ExtendedColorScheme/CurrentColorScheme" };
+ uno::Sequence< uno::Any > aCurrentVal = GetProperties( aCurrent );
+ aCurrentVal.getConstArray()[0] >>= sScheme;
+ } // if(!sScheme.getLength())
+
+ m_sLoadedScheme = sScheme;
+ OUString sBase = "ExtendedColorScheme/ColorSchemes/"
+ + sScheme;
+
+ bool bFound = ExistsScheme(sScheme);
+ if ( bFound )
+ {
+ aComponentNames = GetPropertyNames(sBase);
+ FillComponentColors(aComponentNames,aDisplayNameMap);
+ }
+
+ if ( m_sLoadedScheme.isEmpty() )
+ m_sLoadedScheme = "default";
+
+ if ( sScheme != "default" )
+ {
+ if ( ExistsScheme(u"default") )
+ {
+ aComponentNames = GetPropertyNames("ExtendedColorScheme/ColorSchemes/default");
+ FillComponentColors(aComponentNames,aDisplayNameMap);
+ }
+ }
+ if ( !bFound && !sScheme.isEmpty() )
+ {
+ AddScheme(sScheme);
+ CommitCurrentSchemeName();
+ }
+}
+
+void ExtendedColorConfig_Impl::FillComponentColors(const uno::Sequence < OUString >& _rComponents,const TDisplayNames& _rDisplayNames)
+{
+ static const OUStringLiteral sColorEntries(u"/Entries");
+ for(OUString const & component : _rComponents)
+ {
+ OUString sComponentName = component.copy(component.lastIndexOf('/')+1);
+ if ( m_aConfigValues.find(sComponentName) == m_aConfigValues.end() )
+ {
+ OUString sEntry = component + sColorEntries;
+
+ uno::Sequence < OUString > aColorNames = GetPropertyNames(sEntry);
+ uno::Sequence < OUString > aDefaultColorNames = aColorNames;
+
+ static const OUStringLiteral sColor(u"/Color");
+ lcl_addString(aColorNames,sColor);
+ lcl_addString(aDefaultColorNames,u"/DefaultColor");
+ uno::Sequence< uno::Any > aColors = GetProperties( aColorNames );
+ const uno::Any* pColors = aColors.getConstArray();
+
+ uno::Sequence< uno::Any > aDefaultColors = GetProperties( aDefaultColorNames );
+ bool bDefaultColorFound = aDefaultColors.hasElements();
+ const uno::Any* pDefaultColors = aDefaultColors.getConstArray();
+
+ OUString* pColorIter = aColorNames.getArray();
+ OUString* pColorEnd = pColorIter + aColorNames.getLength();
+
+ m_aConfigValuesPos.push_back(m_aConfigValues.emplace(sComponentName,TComponentMapping(TConfigValues(),TMapPos())).first);
+ TConfigValues& aConfigValues = (*m_aConfigValuesPos.rbegin())->second.first;
+ TMapPos& aConfigValuesPos = (*m_aConfigValuesPos.rbegin())->second.second;
+ for(int i = 0; pColorIter != pColorEnd; ++pColorIter ,++i)
+ {
+ if ( aConfigValues.find(*pColorIter) == aConfigValues.end() )
+ {
+ sal_Int32 nIndex = 0;
+ o3tl::getToken(*pColorIter, 2, '/', nIndex);
+ OUString sName(pColorIter->copy(nIndex)),sDisplayName;
+ OUString sTemp = sName.copy(0,sName.lastIndexOf(sColor));
+
+ TDisplayNames::const_iterator aFind = _rDisplayNames.find(sTemp);
+ sName = sName.getToken(2, '/');
+ OSL_ENSURE(aFind != _rDisplayNames.end(),"DisplayName is not in EntryNames config list!");
+ if ( aFind != _rDisplayNames.end() )
+ sDisplayName = aFind->second;
+
+ OSL_ENSURE(pColors[i].hasValue(),"Color config entry has NIL as color value set!");
+ OSL_ENSURE(pDefaultColors[i].hasValue(),"Color config entry has NIL as color value set!");
+ Color nColor, nDefaultColor;
+ pColors[i] >>= nColor;
+ if ( bDefaultColorFound )
+ pDefaultColors[i] >>= nDefaultColor;
+ else
+ nDefaultColor = nColor;
+ ExtendedColorConfigValue aValue(sName,sDisplayName,nColor,nDefaultColor);
+ aConfigValuesPos.push_back(aConfigValues.emplace(sName,aValue).first);
+ }
+ } // for(int i = 0; pColorIter != pColorEnd; ++pColorIter ,++i)
+ }
+ }
+}
+
+void ExtendedColorConfig_Impl::Notify( const uno::Sequence<OUString>& /*rPropertyNames*/)
+{
+ //loading via notification always uses the default setting
+ Load(OUString());
+
+ SolarMutexGuard aVclGuard;
+
+ if(m_bLockBroadcast)
+ {
+ m_bBroadcastWhenUnlocked = true;
+ }
+ else
+ Broadcast(SfxHint(SfxHintId::ColorsChanged));
+}
+
+void ExtendedColorConfig_Impl::ImplCommit()
+{
+ if ( m_sLoadedScheme.isEmpty() )
+ return;
+ static const OUStringLiteral sColorEntries(u"Entries");
+ static const OUStringLiteral sColor(u"/Color");
+ OUString sBase = "ExtendedColorScheme/ColorSchemes/"
+ + m_sLoadedScheme;
+ static const OUStringLiteral s_sSep(u"/");
+
+ for (auto const& configValue : m_aConfigValues)
+ {
+ if ( ConfigItem::AddNode(sBase, configValue.first) )
+ {
+ OUString sNode = sBase
+ + s_sSep
+ + configValue.first
+ //ConfigItem::AddNode(sNode, sColorEntries);
+ + s_sSep
+ + sColorEntries;
+
+ uno::Sequence < beans::PropertyValue > aPropValues(configValue.second.first.size());
+ beans::PropertyValue* pPropValues = aPropValues.getArray();
+ for (auto const& elem : configValue.second.first)
+ {
+ pPropValues->Name = sNode + s_sSep + elem.first;
+ ConfigItem::AddNode(sNode, elem.first);
+ pPropValues->Name += sColor;
+ pPropValues->Value <<= elem.second.getColor();
+ // the default color will never be changed
+ ++pPropValues;
+ }
+ SetSetProperties("ExtendedColorScheme/ColorSchemes", aPropValues);
+ }
+ }
+
+ CommitCurrentSchemeName();
+}
+
+void ExtendedColorConfig_Impl::CommitCurrentSchemeName()
+{
+ //save current scheme name
+ uno::Sequence < OUString > aCurrent { "ExtendedColorScheme/CurrentColorScheme" };
+ uno::Sequence< uno::Any > aCurrentVal(1);
+ aCurrentVal.getArray()[0] <<= m_sLoadedScheme;
+ PutProperties(aCurrent, aCurrentVal);
+}
+
+bool ExtendedColorConfig_Impl::ExistsScheme(std::u16string_view _sSchemeName)
+{
+ OUString sBase("ExtendedColorScheme/ColorSchemes");
+
+ uno::Sequence < OUString > aComponentNames = GetPropertyNames(sBase);
+ sBase += OUString::Concat("/") + _sSchemeName;
+ return comphelper::findValue(aComponentNames, sBase) != -1;
+}
+
+void ExtendedColorConfig_Impl::SetColorConfigValue(const OUString& _sName, const ExtendedColorConfigValue& rValue )
+{
+ TComponents::iterator aFind = m_aConfigValues.find(_sName);
+ if ( aFind != m_aConfigValues.end() )
+ {
+ TConfigValues::iterator aFind2 = aFind->second.first.find(rValue.getName());
+ if ( aFind2 != aFind->second.first.end() )
+ aFind2->second = rValue;
+ SetModified();
+ }
+}
+
+void ExtendedColorConfig_Impl::AddScheme(const OUString& rScheme)
+{
+ if(ConfigItem::AddNode("ExtendedColorScheme/ColorSchemes", rScheme))
+ {
+ m_sLoadedScheme = rScheme;
+ Commit();
+ }
+}
+
+void ExtendedColorConfig_Impl::RemoveScheme(const OUString& rScheme)
+{
+ uno::Sequence< OUString > aElements { rScheme };
+ ClearNodeElements("ExtendedColorScheme/ColorSchemes", aElements);
+}
+
+void ExtendedColorConfig_Impl::SettingsChanged()
+{
+ SolarMutexGuard aVclGuard;
+
+ Broadcast( SfxHint( SfxHintId::ColorsChanged ) );
+}
+
+void ExtendedColorConfig_Impl::LockBroadcast()
+{
+ m_bLockBroadcast = true;
+}
+
+void ExtendedColorConfig_Impl::UnlockBroadcast()
+{
+ if ( m_bBroadcastWhenUnlocked )
+ {
+ m_bBroadcastWhenUnlocked = ExtendedColorConfig::m_pImpl != nullptr;
+ if ( m_bBroadcastWhenUnlocked )
+ {
+ if (ExtendedColorConfig::m_pImpl->m_bIsBroadcastEnabled)
+ {
+ m_bBroadcastWhenUnlocked = false;
+ ExtendedColorConfig::m_pImpl->Broadcast(SfxHint(SfxHintId::ColorsChanged));
+ }
+ }
+ }
+ m_bLockBroadcast = false;
+}
+
+IMPL_LINK( ExtendedColorConfig_Impl, DataChangedEventListener, VclSimpleEvent&, rEvent, void )
+{
+ if ( rEvent.GetId() == VclEventId::ApplicationDataChanged )
+ {
+ DataChangedEvent* pData = static_cast<DataChangedEvent*>(static_cast<VclWindowEvent&>(rEvent).GetData());
+ if ( (pData->GetType() == DataChangedEventType::SETTINGS) &&
+ (pData->GetFlags() & AllSettingsFlags::STYLE) )
+ {
+ SettingsChanged();
+ }
+ }
+}
+
+
+ExtendedColorConfig::ExtendedColorConfig()
+{
+ std::unique_lock aGuard( ColorMutex_Impl() );
+ if ( !m_pImpl )
+ m_pImpl = new ExtendedColorConfig_Impl;
+ ++nExtendedColorRefCount_Impl;
+ StartListening( *m_pImpl);
+}
+
+ExtendedColorConfig::~ExtendedColorConfig()
+{
+ std::unique_lock aGuard( ColorMutex_Impl() );
+ EndListening( *m_pImpl);
+ if(!--nExtendedColorRefCount_Impl)
+ {
+ delete m_pImpl;
+ m_pImpl = nullptr;
+ }
+}
+
+ExtendedColorConfigValue ExtendedColorConfig::GetColorValue(const OUString& _sComponentName,const OUString& _sName)const
+{
+ return m_pImpl->GetColorConfigValue(_sComponentName,_sName);
+}
+
+sal_Int32 ExtendedColorConfig::GetComponentCount() const
+{
+ return m_pImpl->GetComponentCount();
+}
+
+sal_Int32 ExtendedColorConfig::GetComponentColorCount(const OUString& _sName) const
+{
+ return m_pImpl->GetComponentColorCount(_sName);
+}
+
+ExtendedColorConfigValue ExtendedColorConfig::GetComponentColorConfigValue(const OUString& _sName,sal_uInt32 _nPos) const
+{
+ return m_pImpl->GetComponentColorConfigValue(_sName,_nPos);
+}
+
+OUString ExtendedColorConfig::GetComponentName(sal_uInt32 _nPos) const
+{
+ return m_pImpl->GetComponentName(_nPos);
+}
+
+OUString ExtendedColorConfig::GetComponentDisplayName(const OUString& _sComponentName) const
+{
+ return m_pImpl->GetComponentDisplayName(_sComponentName);
+}
+
+void ExtendedColorConfig::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
+{
+ SolarMutexGuard aVclGuard;
+
+ Broadcast( rHint );
+}
+
+EditableExtendedColorConfig::EditableExtendedColorConfig() :
+ m_pImpl(new ExtendedColorConfig_Impl),
+ m_bModified(false)
+{
+ ExtendedColorConfig_Impl::LockBroadcast();
+}
+
+EditableExtendedColorConfig::~EditableExtendedColorConfig()
+{
+ ExtendedColorConfig_Impl::UnlockBroadcast();
+ if(m_bModified)
+ m_pImpl->SetModified();
+ if(m_pImpl->IsModified())
+ m_pImpl->Commit();
+}
+
+void EditableExtendedColorConfig::DeleteScheme(const OUString& rScheme )
+{
+ m_pImpl->RemoveScheme(rScheme);
+}
+
+void EditableExtendedColorConfig::AddScheme(const OUString& rScheme )
+{
+ m_pImpl->AddScheme(rScheme);
+}
+
+void EditableExtendedColorConfig::LoadScheme(const OUString& rScheme )
+{
+ if(m_bModified)
+ m_pImpl->SetModified();
+ if(m_pImpl->IsModified())
+ m_pImpl->Commit();
+ m_bModified = false;
+ m_pImpl->Load(rScheme);
+ //the name of the loaded scheme has to be committed separately
+ m_pImpl->CommitCurrentSchemeName();
+}
+
+// Changes the name of the current scheme but doesn't load it!
+void EditableExtendedColorConfig::SetCurrentSchemeName(const OUString& rScheme)
+{
+ m_pImpl->SetCurrentSchemeName(rScheme);
+ m_pImpl->CommitCurrentSchemeName();
+}
+
+void EditableExtendedColorConfig::SetColorValue(
+ const OUString& _sName, const ExtendedColorConfigValue& rValue)
+{
+ m_pImpl->SetColorConfigValue(_sName, rValue);
+ m_pImpl->ClearModified();
+ m_bModified = true;
+}
+
+void EditableExtendedColorConfig::SetModified()
+{
+ m_bModified = true;
+}
+
+void EditableExtendedColorConfig::Commit()
+{
+ if(m_bModified)
+ m_pImpl->SetModified();
+ if(m_pImpl->IsModified())
+ m_pImpl->Commit();
+ m_bModified = false;
+}
+
+void EditableExtendedColorConfig::DisableBroadcast()
+{
+ ExtendedColorConfig_Impl::DisableBroadcast();
+}
+
+void EditableExtendedColorConfig::EnableBroadcast()
+{
+ ExtendedColorConfig_Impl::EnableBroadcast();
+}
+
+sal_Int32 EditableExtendedColorConfig::GetComponentCount() const
+{
+ return m_pImpl->GetComponentCount();
+}
+
+sal_Int32 EditableExtendedColorConfig::GetComponentColorCount(const OUString& _sName) const
+{
+ return m_pImpl->GetComponentColorCount(_sName);
+}
+
+ExtendedColorConfigValue EditableExtendedColorConfig::GetComponentColorConfigValue(const OUString& _sName,sal_uInt32 _nPos) const
+{
+ return m_pImpl->GetComponentColorConfigValue(_sName,_nPos);
+}
+
+OUString EditableExtendedColorConfig::GetComponentName(sal_uInt32 _nPos) const
+{
+ return m_pImpl->GetComponentName(_nPos);
+}
+}//namespace svtools
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/config/fontsubstconfig.cxx b/svtools/source/config/fontsubstconfig.cxx
new file mode 100644
index 000000000..6d7323bb0
--- /dev/null
+++ b/svtools/source/config/fontsubstconfig.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 <svtools/fontsubstconfig.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <o3tl/any.hxx>
+#include <tools/debug.hxx>
+#include <vcl/outdev.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/configitem.hxx>
+
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::beans;
+
+
+constexpr OUStringLiteral cReplacement = u"Replacement";
+constexpr OUStringLiteral cFontPairs = u"FontPairs";
+
+constexpr OUStringLiteral cReplaceFont = u"ReplaceFont";
+constexpr OUStringLiteral cSubstituteFont= u"SubstituteFont";
+constexpr OUStringLiteral cOnScreenOnly = u"OnScreenOnly";
+constexpr OUStringLiteral cAlways = u"Always";
+
+namespace svtools
+{
+
+bool IsFontSubstitutionsEnabled()
+{
+ bool bIsEnabled = false;
+ Reference<css::container::XHierarchicalNameAccess> xHierarchyAccess = utl::ConfigManager::acquireTree(u"Office.Common/Font/Substitution");
+ Any aVal = xHierarchyAccess->getByHierarchicalName(cReplacement);
+
+ DBG_ASSERT(aVal.hasValue(), "no value available");
+ if(aVal.hasValue())
+ bIsEnabled = *o3tl::doAccess<bool>(aVal);
+ return bIsEnabled;
+}
+
+std::vector<SubstitutionStruct> GetFontSubstitutions()
+{
+ Reference<css::container::XHierarchicalNameAccess> xHierarchyAccess = utl::ConfigManager::acquireTree(u"Office.Common/Font/Substitution");
+
+ const Sequence<OUString> aNodeNames = utl::ConfigItem::GetNodeNames(xHierarchyAccess, cFontPairs, utl::ConfigNameFormat::LocalPath);
+ Sequence<OUString> aPropNames(aNodeNames.getLength() * 4);
+ OUString* pNames = aPropNames.getArray();
+ sal_Int32 nName = 0;
+ for(const OUString& rNodeName : aNodeNames)
+ {
+ OUString sStart = cFontPairs + "/" + rNodeName + "/";
+ pNames[nName++] = sStart + cReplaceFont;
+ pNames[nName++] = sStart + cSubstituteFont;
+ pNames[nName++] = sStart + cAlways;
+ pNames[nName++] = sStart + cOnScreenOnly;
+ }
+ Sequence<Any> aNodeValues = utl::ConfigItem::GetProperties(xHierarchyAccess, aPropNames, /*bAllLocales*/false);
+ const Any* pNodeValues = aNodeValues.getConstArray();
+ nName = 0;
+ std::vector<SubstitutionStruct> aSubstArr;
+ for(sal_Int32 nNode = 0; nNode < aNodeNames.getLength(); nNode++)
+ {
+ SubstitutionStruct aInsert;
+ pNodeValues[nName++] >>= aInsert.sFont;
+ pNodeValues[nName++] >>= aInsert.sReplaceBy;
+ aInsert.bReplaceAlways = *o3tl::doAccess<bool>(pNodeValues[nName++]);
+ aInsert.bReplaceOnScreenOnly = *o3tl::doAccess<bool>(pNodeValues[nName++]);
+ aSubstArr.push_back(aInsert);
+ }
+ return aSubstArr;
+}
+
+void SetFontSubstitutions(bool bIsEnabled, std::vector<SubstitutionStruct> const & aSubstArr)
+{
+ Reference<css::container::XHierarchicalNameAccess> xHierarchyAccess = utl::ConfigManager::acquireTree(u"Office.Common/Font/Substitution");
+ utl::ConfigItem::PutProperties(xHierarchyAccess, {cReplacement}, {css::uno::Any(bIsEnabled)}, /*bAllLocales*/false);
+
+ OUString sNode(cFontPairs);
+ if(aSubstArr.empty())
+ {
+ utl::ConfigItem::ClearNodeSet(xHierarchyAccess, sNode);
+ return;
+ }
+
+ Sequence<PropertyValue> aSetValues(4 * aSubstArr.size());
+ PropertyValue* pSetValues = aSetValues.getArray();
+ sal_Int32 nSetValue = 0;
+
+ const OUString sReplaceFont(cReplaceFont);
+ const OUString sSubstituteFont(cSubstituteFont);
+ const OUString sAlways(cAlways);
+ const OUString sOnScreenOnly(cOnScreenOnly);
+
+ for(size_t i = 0; i < aSubstArr.size(); i++)
+ {
+ OUString sPrefix = sNode + "/_" + OUString::number(i) + "/";
+
+ const SubstitutionStruct& rSubst = aSubstArr[i];
+ pSetValues[nSetValue].Name = sPrefix; pSetValues[nSetValue].Name += sReplaceFont;
+ pSetValues[nSetValue++].Value <<= rSubst.sFont;
+ pSetValues[nSetValue].Name = sPrefix; pSetValues[nSetValue].Name += sSubstituteFont;
+ pSetValues[nSetValue++].Value <<= rSubst.sReplaceBy;
+ pSetValues[nSetValue].Name = sPrefix; pSetValues[nSetValue].Name += sAlways;
+ pSetValues[nSetValue++].Value <<= rSubst.bReplaceAlways;
+ pSetValues[nSetValue].Name = sPrefix; pSetValues[nSetValue].Name += sOnScreenOnly;
+ pSetValues[nSetValue++].Value <<= rSubst.bReplaceOnScreenOnly;
+ }
+ utl::ConfigItem::ReplaceSetProperties(xHierarchyAccess, sNode, aSetValues, /*bAllLocales*/false);
+}
+
+void ApplyFontSubstitutionsToVcl()
+{
+ OutputDevice::BeginFontSubstitution();
+
+ // remove old substitutions
+ OutputDevice::RemoveFontsSubstitute();
+
+ const bool bIsEnabled = IsFontSubstitutionsEnabled();
+ std::vector<SubstitutionStruct> aSubst = GetFontSubstitutions();
+
+ // read new substitutions
+ if (bIsEnabled)
+ for (const SubstitutionStruct & rSub : aSubst)
+ {
+ AddFontSubstituteFlags nFlags = AddFontSubstituteFlags::NONE;
+ if(rSub.bReplaceAlways)
+ nFlags |= AddFontSubstituteFlags::ALWAYS;
+ if(rSub.bReplaceOnScreenOnly)
+ nFlags |= AddFontSubstituteFlags::ScreenOnly;
+ OutputDevice::AddFontSubstitute( rSub.sFont, rSub.sReplaceBy, nFlags );
+ }
+
+ OutputDevice::EndFontSubstitution();
+}
+
+} // namespace svtools
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/config/htmlcfg.cxx b/svtools/source/config/htmlcfg.cxx
new file mode 100644
index 000000000..983d85e4b
--- /dev/null
+++ b/svtools/source/config/htmlcfg.cxx
@@ -0,0 +1,89 @@
+/* -*- 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 <sal/config.h>
+
+#include <svtools/htmlcfg.hxx>
+#include <unotools/syslocale.hxx>
+#include <officecfg/Office/Common.hxx>
+
+namespace SvxHtmlOptions
+{
+sal_uInt16 GetFontSize(sal_uInt16 nPos)
+{
+ switch (nPos)
+ {
+ case 0:
+ return officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_1::get();
+ case 1:
+ return officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_2::get();
+ case 2:
+ return officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_3::get();
+ case 3:
+ return officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_4::get();
+ case 4:
+ return officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_5::get();
+ case 5:
+ return officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_6::get();
+ case 6:
+ return officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_7::get();
+ }
+ assert(false);
+ return 0;
+}
+
+sal_uInt16 GetExportMode()
+{
+ sal_Int32 nExpMode = officecfg::Office::Common::Filter::HTML::Export::Browser::get();
+ switch (nExpMode)
+ {
+ case 1:
+ nExpMode = HTML_CFG_MSIE;
+ break;
+ case 3:
+ nExpMode = HTML_CFG_WRITER;
+ break;
+ case 4:
+ nExpMode = HTML_CFG_NS40;
+ break;
+ default:
+ nExpMode = HTML_CFG_NS40;
+ break;
+ }
+ return nExpMode;
+}
+
+bool IsPrintLayoutExtension()
+{
+ bool bRet = officecfg::Office::Common::Filter::HTML::Export::PrintLayout::get();
+ switch (GetExportMode())
+ {
+ case HTML_CFG_MSIE:
+ case HTML_CFG_NS40:
+ case HTML_CFG_WRITER:
+ break;
+ default:
+ bRet = false;
+ }
+ return bRet;
+}
+
+} // namespace SvxHtmlOptions
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/config/itemholder2.cxx b/svtools/source/config/itemholder2.cxx
new file mode 100644
index 000000000..8880655d3
--- /dev/null
+++ b/svtools/source/config/itemholder2.cxx
@@ -0,0 +1,140 @@
+/* -*- 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 "itemholder2.hxx"
+
+#include <osl/diagnose.h>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/configuration/theDefaultProvider.hpp>
+
+#include <svtools/accessibilityoptions.hxx>
+#include <svtools/colorcfg.hxx>
+#include <unotools/options.hxx>
+#include <svtools/miscopt.hxx>
+#include <tools/diagnose_ex.h>
+#include <rtl/ref.hxx>
+
+namespace svtools {
+
+ItemHolder2::ItemHolder2()
+{
+ try
+ {
+ css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
+ css::uno::Reference< css::lang::XComponent > xCfg(
+ css::configuration::theDefaultProvider::get( xContext ),
+ css::uno::UNO_QUERY_THROW );
+ xCfg->addEventListener(static_cast< css::lang::XEventListener* >(this));
+ }
+ catch(const css::uno::RuntimeException&)
+ {
+ throw;
+ }
+#ifdef DBG_UTIL
+ catch(const css::uno::Exception&)
+ {
+ static bool bMessage = true;
+ if(bMessage)
+ {
+ bMessage = false;
+ TOOLS_WARN_EXCEPTION( "svtools", "CreateInstance with arguments" );
+ }
+ }
+#else
+ catch(css::uno::Exception&){}
+#endif
+}
+
+
+ItemHolder2::~ItemHolder2()
+{
+ impl_releaseAllItems();
+}
+
+
+void ItemHolder2::holdConfigItem(EItem eItem)
+{
+ static rtl::Reference<ItemHolder2> pHolder = new ItemHolder2();
+ pHolder->impl_addItem(eItem);
+}
+
+
+void SAL_CALL ItemHolder2::disposing(const css::lang::EventObject&)
+{
+ impl_releaseAllItems();
+}
+
+
+void ItemHolder2::impl_addItem(EItem eItem)
+{
+ std::scoped_lock aLock(m_aLock);
+
+ for ( auto const & rInfo : m_lItems )
+ {
+ if (rInfo.eItem == eItem)
+ return;
+ }
+
+ TItemInfo aNewItem;
+ aNewItem.eItem = eItem;
+ impl_newItem(aNewItem);
+ if (aNewItem.pItem)
+ m_lItems.emplace_back(std::move(aNewItem));
+}
+
+
+void ItemHolder2::impl_releaseAllItems()
+{
+ std::vector<TItemInfo> items;
+ {
+ std::scoped_lock aLock(m_aLock);
+ items.swap(m_lItems);
+ }
+
+ // items will be freed when the block exits
+}
+
+
+void ItemHolder2::impl_newItem(TItemInfo& rItem)
+{
+ switch(rItem.eItem)
+ {
+ case EItem::AccessibilityOptions :
+ rItem.pItem.reset( new SvtAccessibilityOptions() );
+ break;
+
+ case EItem::ColorConfig :
+ rItem.pItem.reset( new ::svtools::ColorConfig() );
+ break;
+
+ case EItem::MiscOptions :
+ rItem.pItem.reset( new SvtMiscOptions() );
+ break;
+
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+}
+
+} // namespace svtools
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/config/itemholder2.hxx b/svtools/source/config/itemholder2.hxx
new file mode 100644
index 000000000..3bb1a6871
--- /dev/null
+++ b/svtools/source/config/itemholder2.hxx
@@ -0,0 +1,64 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <unotools/itemholderbase.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/lang/XEventListener.hpp>
+#include <mutex>
+
+namespace svtools {
+
+
+class ItemHolder2 : public ::cppu::WeakImplHelper< css::lang::XEventListener >
+{
+
+ // member
+ private:
+ std::mutex m_aLock;
+ std::vector<TItemInfo> m_lItems;
+
+
+ // c++ interface
+ public:
+
+ ItemHolder2();
+ virtual ~ItemHolder2() override;
+ static void holdConfigItem(EItem eItem);
+
+
+ // uno interface
+ public:
+
+ virtual void SAL_CALL disposing(const css::lang::EventObject& aEvent) override;
+
+
+ // helper
+ private:
+
+ void impl_addItem(EItem eItem);
+ void impl_releaseAllItems();
+ static void impl_newItem(TItemInfo& rItem);
+};
+
+} // namespace svtools
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/config/languagetoolcfg.cxx b/svtools/source/config/languagetoolcfg.cxx
new file mode 100644
index 000000000..9f81c8e78
--- /dev/null
+++ b/svtools/source/config/languagetoolcfg.cxx
@@ -0,0 +1,164 @@
+/* -*- 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 <sal/log.hxx>
+#include <sal/config.h>
+#include <svtools/languagetoolcfg.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <tools/debug.hxx>
+
+using namespace utl;
+using namespace com::sun::star::uno;
+
+struct LanguageToolOptions_Impl
+{
+ OUString sBaseURL;
+ OUString sUsername;
+ OUString sApiKey;
+ bool bEnabled;
+};
+
+const Sequence<OUString>& SvxLanguageToolOptions::GetPropertyNames()
+{
+ static Sequence<OUString> const aNames{
+ "LanguageTool/BaseURL",
+ "LanguageTool/Username",
+ "LanguageTool/ApiKey",
+ "LanguageTool/IsEnabled",
+ };
+ return aNames;
+}
+
+const OUString& SvxLanguageToolOptions::getBaseURL() const { return pImpl->sBaseURL; }
+
+void SvxLanguageToolOptions::setBaseURL(const OUString& rVal)
+{
+ pImpl->sBaseURL = rVal;
+ SetModified();
+}
+
+const OUString& SvxLanguageToolOptions::getUsername() const { return pImpl->sUsername; }
+
+void SvxLanguageToolOptions::setUsername(const OUString& rVal)
+{
+ pImpl->sUsername = rVal;
+ SetModified();
+}
+
+OUString SvxLanguageToolOptions::getLocaleListURL() const { return pImpl->sBaseURL + "/languages"; }
+
+OUString SvxLanguageToolOptions::getCheckerURL() const { return pImpl->sBaseURL + "/check"; }
+
+const OUString& SvxLanguageToolOptions::getApiKey() const { return pImpl->sApiKey; }
+
+void SvxLanguageToolOptions::setApiKey(const OUString& rVal)
+{
+ pImpl->sApiKey = rVal;
+ SetModified();
+}
+
+bool SvxLanguageToolOptions::getEnabled() const { return pImpl->bEnabled; }
+
+void SvxLanguageToolOptions::setEnabled(bool bEnabled)
+{
+ pImpl->bEnabled = bEnabled;
+ SetModified();
+}
+
+namespace
+{
+class theSvxLanguageToolOptions
+ : public rtl::Static<SvxLanguageToolOptions, theSvxLanguageToolOptions>
+{
+};
+}
+
+SvxLanguageToolOptions& SvxLanguageToolOptions::Get() { return theSvxLanguageToolOptions::get(); }
+
+SvxLanguageToolOptions::SvxLanguageToolOptions()
+ : ConfigItem("Office.Linguistic/GrammarChecking")
+ , pImpl(new LanguageToolOptions_Impl)
+{
+ Load(GetPropertyNames());
+}
+
+SvxLanguageToolOptions::~SvxLanguageToolOptions() {}
+void SvxLanguageToolOptions::Notify(const css::uno::Sequence<OUString>&)
+{
+ Load(GetPropertyNames());
+}
+
+void SvxLanguageToolOptions::Load(const css::uno::Sequence<OUString>& aNames)
+{
+ Sequence<Any> aValues = GetProperties(aNames);
+ const Any* pValues = aValues.getConstArray();
+ DBG_ASSERT(aValues.getLength() == aNames.getLength(), "GetProperties failed");
+ if (aValues.getLength() != aNames.getLength())
+ return;
+ for (int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ if (!pValues[nProp].hasValue())
+ continue;
+ switch (nProp)
+ {
+ case 0:
+ pValues[nProp] >>= pImpl->sBaseURL;
+ break;
+ case 1:
+ pValues[nProp] >>= pImpl->sUsername;
+ break;
+ case 2:
+ pValues[nProp] >>= pImpl->sApiKey;
+ break;
+ case 3:
+ pValues[nProp] >>= pImpl->bEnabled;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void SvxLanguageToolOptions::ImplCommit()
+{
+ const Sequence<OUString>& aNames = GetPropertyNames();
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+ for (int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ switch (nProp)
+ {
+ case 0:
+ pValues[nProp] <<= pImpl->sBaseURL;
+ break;
+ case 1:
+ pValues[nProp] <<= pImpl->sUsername;
+ break;
+ case 2:
+ pValues[nProp] <<= pImpl->sApiKey;
+ break;
+ case 3:
+ pValues[nProp] <<= pImpl->bEnabled;
+ break;
+ default:
+ break;
+ }
+ }
+ PutProperties(aNames, aValues);
+} \ No newline at end of file
diff --git a/svtools/source/config/miscopt.cxx b/svtools/source/config/miscopt.cxx
new file mode 100644
index 000000000..2462a5804
--- /dev/null
+++ b/svtools/source/config/miscopt.cxx
@@ -0,0 +1,456 @@
+/* -*- 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 <svtools/miscopt.hxx>
+#include <unotools/configitem.hxx>
+#include <tools/debug.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <comphelper/sequence.hxx>
+#include <tools/link.hxx>
+#include <osl/diagnose.h>
+
+#include "itemholder2.hxx"
+
+#include <svtools/imgdef.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+#include <mutex>
+#include <vector>
+
+using namespace ::utl ;
+using namespace ::osl ;
+using namespace ::com::sun::star::uno ;
+using namespace ::com::sun::star;
+
+constexpr OUStringLiteral ROOTNODE_MISC = u"Office.Common/Misc";
+
+// PROPERTYHANDLE defines must be sequential from zero for Commit/Load
+constexpr OUStringLiteral PROPERTYNAME_SYMBOLSET = u"SymbolSet";
+#define PROPERTYHANDLE_SYMBOLSET 0
+constexpr OUStringLiteral PROPERTYNAME_ICONTHEME = u"SymbolStyle";
+#define PROPERTYHANDLE_SYMBOLSTYLE 1
+
+static std::mutex & GetInitMutex()
+{
+ static std::mutex theSvtMiscOptionsMutex;
+ return theSvtMiscOptionsMutex;
+}
+
+
+class SvtMiscOptions_Impl : public ConfigItem
+{
+private:
+ ::std::vector<Link<LinkParamNone*,void>> aList;
+ sal_Int16 m_nSymbolsSize;
+ bool m_bIsSymbolsSizeRO;
+ bool m_bIsSymbolsStyleRO;
+ bool m_bIconThemeWasSetAutomatically;
+
+ virtual void ImplCommit() override;
+
+public:
+
+ SvtMiscOptions_Impl();
+ virtual ~SvtMiscOptions_Impl() override;
+
+ /*-****************************************************************************************************
+ @short called for notify of configmanager
+ @descr This method is called from the ConfigManager before the application ends or from the
+ PropertyChangeListener if the sub tree broadcasts changes. You must update your
+ internal values.
+
+ @seealso baseclass ConfigItem
+
+ @param "seqPropertyNames" is the list of properties which should be updated.
+ *//*-*****************************************************************************************************/
+
+ virtual void Notify( const Sequence< OUString >& seqPropertyNames ) override;
+
+ /** loads required data from the configuration. It's called in the constructor to
+ read all entries and form ::Notify to re-read changed settings
+
+ */
+ void Load( const Sequence< OUString >& rPropertyNames );
+
+ // public interface
+
+ sal_Int16 GetSymbolsSize() const
+ { return m_nSymbolsSize; }
+
+ void SetSymbolsSize( sal_Int16 nSet );
+
+ static OUString GetIconTheme();
+
+ enum class SetModifiedFlag { SET, DONT_SET };
+
+ /** Set the icon theme
+ *
+ * @param theme
+ * The name of the icon theme to use.
+ *
+ * @param setModified
+ * Whether to call SetModified() and CallListeners().
+ *
+ * @internal
+ * The @p setModified flag was introduced because the unittests fail if we call SetModified()
+ * during initialization in the constructor.
+ */
+ void
+ SetIconTheme(const OUString &theme, SetModifiedFlag setModified );
+
+ bool IconThemeWasSetAutomatically() const
+ {return m_bIconThemeWasSetAutomatically;}
+
+ void AddListenerLink( const Link<LinkParamNone*,void>& rLink );
+ void RemoveListenerLink( const Link<LinkParamNone*,void>& rLink );
+ void CallListeners();
+
+
+ // private methods
+
+
+private:
+
+ /*-****************************************************************************************************
+ @short return list of key names of our configuration management which represent our module tree
+ @descr These methods return a static const list of key names. We need it to get needed values from our
+ configuration management.
+ @return A list of needed configuration keys is returned.
+ *//*-*****************************************************************************************************/
+
+ static Sequence< OUString > GetPropertyNames();
+};
+
+
+// constructor
+
+SvtMiscOptions_Impl::SvtMiscOptions_Impl()
+ // Init baseclasses first
+ : ConfigItem( ROOTNODE_MISC )
+
+ , m_nSymbolsSize( 0 )
+ , m_bIsSymbolsSizeRO( false )
+ , m_bIsSymbolsStyleRO( false )
+ , m_bIconThemeWasSetAutomatically( false )
+{
+ // Use our static list of configuration keys to get his values.
+ Sequence< OUString > seqNames = GetPropertyNames ( );
+ Load( seqNames );
+ Sequence< Any > seqValues = GetProperties ( seqNames );
+ Sequence< sal_Bool > seqRO = GetReadOnlyStates ( seqNames );
+
+ // Safe impossible cases.
+ // We need values from ALL configuration keys.
+ // Follow assignment use order of values in relation to our list of key names!
+ DBG_ASSERT( !(seqNames.getLength()!=seqValues.getLength()), "SvtMiscOptions_Impl::SvtMiscOptions_Impl()\nI miss some values of configuration keys!\n" );
+
+ // Copy values from list in right order to our internal member.
+ sal_Int32 nPropertyCount = seqValues.getLength();
+ for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
+ {
+ if (!seqValues[nProperty].hasValue())
+ continue;
+ switch( nProperty )
+ {
+ case PROPERTYHANDLE_SYMBOLSET :
+ {
+ if( !(seqValues[nProperty] >>= m_nSymbolsSize) )
+ {
+ OSL_FAIL("Wrong type of \"Misc\\SymbolSet\"!" );
+ }
+ m_bIsSymbolsSizeRO = seqRO[nProperty];
+ break;
+ }
+
+ case PROPERTYHANDLE_SYMBOLSTYLE :
+ {
+ OUString aIconTheme;
+ if (seqValues[nProperty] >>= aIconTheme)
+ SetIconTheme(aIconTheme, SetModifiedFlag::DONT_SET);
+ else
+ OSL_FAIL("Wrong type of \"Misc\\SymbolStyle\"!" );
+
+ m_bIsSymbolsStyleRO = seqRO[nProperty];
+ break;
+ }
+
+ }
+ }
+
+ // Enable notification mechanism of our baseclass.
+ // We need it to get information about changes outside these class on our used configuration keys!
+ EnableNotification( seqNames );
+}
+
+
+// destructor
+
+SvtMiscOptions_Impl::~SvtMiscOptions_Impl()
+{
+ assert(!IsModified()); // should have been committed
+}
+
+void SvtMiscOptions_Impl::Load( const Sequence< OUString >& rPropertyNames )
+{
+ const uno::Sequence< OUString> aInternalPropertyNames( GetPropertyNames());
+ Sequence< Any > seqValues = GetProperties( rPropertyNames );
+
+ // Safe impossible cases.
+ // We need values from ALL configuration keys.
+ // Follow assignment use order of values in relation to our list of key names!
+ DBG_ASSERT( !(rPropertyNames.getLength()!=seqValues.getLength()), "SvtSecurityOptions_Impl::SvtSecurityOptions_Impl()\nI miss some values of configuration keys!\n" );
+
+ // Copy values from list in right order to our internal member.
+ sal_Int32 nPropertyCount = seqValues.getLength();
+ for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
+ {
+ if (!seqValues[nProperty].hasValue())
+ continue;
+ switch( comphelper::findValue(aInternalPropertyNames, rPropertyNames[nProperty]) )
+ {
+ case PROPERTYHANDLE_SYMBOLSET : {
+ if( !(seqValues[nProperty] >>= m_nSymbolsSize) )
+ {
+ OSL_FAIL("Wrong type of \"Misc\\SymbolSet\"!" );
+ }
+ }
+ break;
+ case PROPERTYHANDLE_SYMBOLSTYLE : {
+ OUString aIconTheme;
+ if (seqValues[nProperty] >>= aIconTheme)
+ SetIconTheme(aIconTheme, SetModifiedFlag::DONT_SET);
+ else
+ OSL_FAIL("Wrong type of \"Misc\\SymbolStyle\"!" );
+ }
+ break;
+ }
+ }
+}
+
+void SvtMiscOptions_Impl::AddListenerLink( const Link<LinkParamNone*,void>& rLink )
+{
+ aList.push_back( rLink );
+}
+
+void SvtMiscOptions_Impl::RemoveListenerLink( const Link<LinkParamNone*,void>& rLink )
+{
+ aList.erase(std::remove(aList.begin(), aList.end(), rLink), aList.end());
+}
+
+void SvtMiscOptions_Impl::CallListeners()
+{
+ for (auto const& elem : aList)
+ elem.Call( nullptr );
+}
+
+void SvtMiscOptions_Impl::SetSymbolsSize( sal_Int16 nSet )
+{
+ m_nSymbolsSize = nSet;
+ SetModified();
+ CallListeners();
+}
+
+OUString SvtMiscOptions_Impl::GetIconTheme()
+{
+ return Application::GetSettings().GetStyleSettings().DetermineIconTheme();
+}
+
+void
+SvtMiscOptions_Impl::SetIconTheme(const OUString &rName, SetModifiedFlag setModified)
+{
+ OUString aTheme(rName);
+ if (aTheme.isEmpty() || aTheme == "auto")
+ {
+ aTheme = Application::GetSettings().GetStyleSettings().GetAutomaticallyChosenIconTheme();
+ m_bIconThemeWasSetAutomatically = true;
+ }
+ else
+ m_bIconThemeWasSetAutomatically = false;
+
+ AllSettings aAllSettings = Application::GetSettings();
+ StyleSettings aStyleSettings = aAllSettings.GetStyleSettings();
+ aStyleSettings.SetIconTheme(aTheme);
+
+ aAllSettings.SetStyleSettings(aStyleSettings);
+ Application::MergeSystemSettings( aAllSettings );
+ Application::SetSettings(aAllSettings);
+
+ if (setModified == SetModifiedFlag::SET) {
+ SetModified();
+ }
+ CallListeners();
+}
+
+
+// public method
+
+void SvtMiscOptions_Impl::Notify( const Sequence< OUString >& rPropertyNames )
+{
+ Load( rPropertyNames );
+ CallListeners();
+}
+
+
+// public method
+
+void SvtMiscOptions_Impl::ImplCommit()
+{
+ // Get names of supported properties, create a list for values and copy current values to it.
+ Sequence< OUString > seqNames = GetPropertyNames ();
+ sal_Int32 nCount = seqNames.getLength();
+ Sequence< Any > seqValues ( nCount );
+ auto seqValuesRange = asNonConstRange(seqValues);
+ for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
+ {
+ switch( nProperty )
+ {
+ case PROPERTYHANDLE_SYMBOLSET :
+ {
+ if ( !m_bIsSymbolsSizeRO )
+ seqValuesRange[nProperty] <<= m_nSymbolsSize;
+ break;
+ }
+
+ case PROPERTYHANDLE_SYMBOLSTYLE :
+ {
+ if ( !m_bIsSymbolsStyleRO ) {
+ OUString value;
+ if (m_bIconThemeWasSetAutomatically) {
+ value = "auto";
+ }
+ else {
+ value = GetIconTheme();
+ }
+ seqValuesRange[nProperty] <<= value;
+ }
+ break;
+ }
+
+ }
+ }
+ // Set properties in configuration.
+ PutProperties( seqNames, seqValues );
+}
+
+
+// private method
+
+Sequence< OUString > SvtMiscOptions_Impl::GetPropertyNames()
+{
+ return Sequence<OUString>
+ {
+ PROPERTYNAME_SYMBOLSET,
+ PROPERTYNAME_ICONTHEME,
+ };
+}
+
+namespace {
+
+std::weak_ptr<SvtMiscOptions_Impl> g_pMiscOptions;
+
+}
+
+SvtMiscOptions::SvtMiscOptions()
+{
+ // Global access, must be guarded (multithreading!).
+ std::unique_lock aGuard( GetInitMutex() );
+
+ m_pImpl = g_pMiscOptions.lock();
+ if( !m_pImpl )
+ {
+ m_pImpl = std::make_shared<SvtMiscOptions_Impl>();
+ g_pMiscOptions = m_pImpl;
+ aGuard.unlock(); // because holdConfigItem will call this constructor
+ svtools::ItemHolder2::holdConfigItem(EItem::MiscOptions);
+ }
+}
+
+SvtMiscOptions::~SvtMiscOptions()
+{
+ // Global access, must be guarded (multithreading!)
+ std::unique_lock aGuard( GetInitMutex() );
+
+ m_pImpl.reset();
+}
+
+
+sal_Int16 SvtMiscOptions::GetSymbolsSize() const
+{
+ return m_pImpl->GetSymbolsSize();
+}
+
+void SvtMiscOptions::SetSymbolsSize( sal_Int16 nSet )
+{
+ m_pImpl->SetSymbolsSize( nSet );
+}
+
+sal_Int16 SvtMiscOptions::GetCurrentSymbolsSize() const
+{
+ sal_Int16 eOptSymbolsSize = m_pImpl->GetSymbolsSize();
+
+ if ( eOptSymbolsSize == SFX_SYMBOLS_SIZE_AUTO )
+ {
+ // Use system settings, we have to retrieve the toolbar icon size from the
+ // Application class
+ ToolbarIconSize nStyleIconSize = Application::GetSettings().GetStyleSettings().GetToolbarIconSize();
+ if (nStyleIconSize == ToolbarIconSize::Size32)
+ eOptSymbolsSize = SFX_SYMBOLS_SIZE_32;
+ else if (nStyleIconSize == ToolbarIconSize::Large)
+ eOptSymbolsSize = SFX_SYMBOLS_SIZE_LARGE;
+ else
+ eOptSymbolsSize = SFX_SYMBOLS_SIZE_SMALL;
+ }
+
+ return eOptSymbolsSize;
+}
+
+bool SvtMiscOptions::AreCurrentSymbolsLarge() const
+{
+ return ( GetCurrentSymbolsSize() == SFX_SYMBOLS_SIZE_LARGE || GetCurrentSymbolsSize() == SFX_SYMBOLS_SIZE_32);
+}
+
+OUString SvtMiscOptions::GetIconTheme() const
+{
+ return SvtMiscOptions_Impl::GetIconTheme();
+}
+
+void SvtMiscOptions::SetIconTheme(const OUString& iconTheme)
+{
+ m_pImpl->SetIconTheme(iconTheme, SvtMiscOptions_Impl::SetModifiedFlag::SET);
+}
+
+void SvtMiscOptions::AddListenerLink( const Link<LinkParamNone*,void>& rLink )
+{
+ m_pImpl->AddListenerLink( rLink );
+}
+
+void SvtMiscOptions::RemoveListenerLink( const Link<LinkParamNone*,void>& rLink )
+{
+ m_pImpl->RemoveListenerLink( rLink );
+}
+
+bool
+SvtMiscOptions::IconThemeWasSetAutomatically() const
+{
+ return m_pImpl->IconThemeWasSetAutomatically();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/config/optionsdrawinglayer.cxx b/svtools/source/config/optionsdrawinglayer.cxx
new file mode 100644
index 000000000..54efe4a66
--- /dev/null
+++ b/svtools/source/config/optionsdrawinglayer.cxx
@@ -0,0 +1,263 @@
+/* -*- 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 <svtools/optionsdrawinglayer.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/settings.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <mutex>
+
+// #i73602#
+// #i74769#, #i75172#
+// #i4219#
+
+namespace SvtOptionsDrawinglayer
+{
+
+bool IsOverlayBuffer()
+{
+ return officecfg::Office::Common::Drawinglayer::OverlayBuffer::get();
+}
+
+bool IsPaintBuffer()
+{
+ return officecfg::Office::Common::Drawinglayer::PaintBuffer::get();
+}
+
+Color GetStripeColorA()
+{
+ return Color(ColorTransparency, officecfg::Office::Common::Drawinglayer::StripeColorA::get());
+}
+
+Color GetStripeColorB()
+{
+ return Color(ColorTransparency, officecfg::Office::Common::Drawinglayer::StripeColorB::get());
+}
+
+sal_uInt16 GetStripeLength()
+{
+ return officecfg::Office::Common::Drawinglayer::StripeLength::get();
+}
+
+bool IsOverlayBuffer_Calc()
+{
+ return officecfg::Office::Common::Drawinglayer::OverlayBuffer_Calc::get();
+}
+
+bool IsOverlayBuffer_Writer()
+{
+ return officecfg::Office::Common::Drawinglayer::OverlayBuffer_Writer::get();
+}
+
+bool IsOverlayBuffer_DrawImpress()
+{
+ return officecfg::Office::Common::Drawinglayer::OverlayBuffer_DrawImpress::get();
+}
+
+// #i74769#, #i75172#
+bool IsPaintBuffer_Calc()
+{
+ return officecfg::Office::Common::Drawinglayer::PaintBuffer_Calc::get();
+}
+
+bool IsPaintBuffer_Writer()
+{
+ return officecfg::Office::Common::Drawinglayer::PaintBuffer_Writer::get();
+}
+
+bool IsPaintBuffer_DrawImpress()
+{
+ return officecfg::Office::Common::Drawinglayer::PaintBuffer_DrawImpress::get();
+}
+
+// #i4219#
+sal_uInt32 GetMaximumPaperWidth()
+{
+ return officecfg::Office::Common::Drawinglayer::MaximumPaperWidth::get();
+}
+
+sal_uInt32 GetMaximumPaperHeight()
+{
+ return officecfg::Office::Common::Drawinglayer::MaximumPaperHeight::get();
+}
+
+sal_uInt32 GetMaximumPaperLeftMargin()
+{
+ return officecfg::Office::Common::Drawinglayer::MaximumPaperLeftMargin::get();
+}
+
+sal_uInt32 GetMaximumPaperRightMargin()
+{
+ return officecfg::Office::Common::Drawinglayer::MaximumPaperRightMargin::get();
+}
+
+sal_uInt32 GetMaximumPaperTopMargin()
+{
+ return officecfg::Office::Common::Drawinglayer::MaximumPaperTopMargin::get();
+}
+
+sal_uInt32 GetMaximumPaperBottomMargin()
+{
+ return officecfg::Office::Common::Drawinglayer::MaximumPaperBottomMargin::get();
+}
+
+static std::mutex gaAntiAliasMutex;
+static bool gbAntiAliasingInit = false;
+static bool gbAntiAliasing = false;
+static bool gbAllowAAInit = false;
+static bool gbAllowAA = false;
+
+bool IsAAPossibleOnThisSystem()
+{
+ std::scoped_lock aGuard(gaAntiAliasMutex);
+ if (!gbAllowAAInit)
+ {
+ gbAllowAAInit = true;
+ gbAllowAA = Application::GetDefaultDevice()->SupportsOperation( OutDevSupportType::TransparentRect );
+ }
+ return gbAllowAA;
+}
+
+
+bool IsAntiAliasing()
+{
+ bool bAntiAliasing;
+ {
+ std::scoped_lock aGuard(gaAntiAliasMutex);
+ if (!gbAntiAliasingInit)
+ {
+ gbAntiAliasingInit = true;
+ gbAntiAliasing = officecfg::Office::Common::Drawinglayer::AntiAliasing::get();
+ }
+ bAntiAliasing = gbAntiAliasing;
+ }
+ return bAntiAliasing && IsAAPossibleOnThisSystem();
+}
+
+/**
+ * Some code like to turn this stuff on and off during a drawing operation
+ * so it can "tunnel" information down through several layers,
+ * so we don't want to actually do a config write all the time.
+ */
+void SetAntiAliasing( bool bOn, bool bTemporary )
+{
+ std::scoped_lock aGuard(gaAntiAliasMutex);
+ if (!bTemporary)
+ {
+ std::shared_ptr<comphelper::ConfigurationChanges> batch =
+ comphelper::ConfigurationChanges::create();
+ officecfg::Office::Common::Drawinglayer::AntiAliasing::set(bOn, batch);
+ batch->commit();
+ }
+ gbAntiAliasing = bOn;
+}
+
+
+bool IsSnapHorVerLinesToDiscrete()
+{
+ return IsAntiAliasing() && officecfg::Office::Common::Drawinglayer::SnapHorVerLinesToDiscrete::get();
+}
+
+bool IsSolidDragCreate()
+{
+ return officecfg::Office::Common::Drawinglayer::SolidDragCreate::get();
+}
+
+bool IsRenderDecoratedTextDirect()
+{
+ return officecfg::Office::Common::Drawinglayer::RenderDecoratedTextDirect::get();
+}
+
+bool IsRenderSimpleTextDirect()
+{
+ return officecfg::Office::Common::Drawinglayer::RenderSimpleTextDirect::get();
+}
+
+sal_uInt32 GetQuadratic3DRenderLimit()
+{
+ return officecfg::Office::Common::Drawinglayer::Quadratic3DRenderLimit::get();
+}
+
+sal_uInt32 GetQuadraticFormControlRenderLimit()
+{
+ return officecfg::Office::Common::Drawinglayer::QuadraticFormControlRenderLimit::get();
+}
+
+// #i97672# selection settings
+bool IsTransparentSelection()
+{
+ return officecfg::Office::Common::Drawinglayer::TransparentSelection::get();
+}
+
+sal_uInt16 GetTransparentSelectionPercent()
+{
+ sal_uInt16 aRetval = officecfg::Office::Common::Drawinglayer::TransparentSelectionPercent::get();
+
+ // crop to range [10% .. 90%]
+ if(aRetval < 10)
+ {
+ aRetval = 10;
+ }
+
+ if(aRetval > 90)
+ {
+ aRetval = 90;
+ }
+
+ return aRetval;
+}
+
+sal_uInt16 GetSelectionMaximumLuminancePercent()
+{
+ sal_uInt16 aRetval = officecfg::Office::Common::Drawinglayer::SelectionMaximumLuminancePercent::get();
+
+ // crop to range [0% .. 100%]
+ if(aRetval > 90)
+ {
+ aRetval = 90;
+ }
+
+ return aRetval;
+}
+
+Color getHilightColor()
+{
+ Color aRetval(Application::GetSettings().GetStyleSettings().GetHighlightColor());
+ const basegfx::BColor aSelection(aRetval.getBColor());
+ const double fLuminance(aSelection.luminance());
+ const double fMaxLum(GetSelectionMaximumLuminancePercent() / 100.0);
+
+ if(fLuminance > fMaxLum)
+ {
+ const double fFactor(fMaxLum / fLuminance);
+ const basegfx::BColor aNewSelection(
+ aSelection.getRed() * fFactor,
+ aSelection.getGreen() * fFactor,
+ aSelection.getBlue() * fFactor);
+
+ aRetval = Color(aNewSelection);
+ }
+
+ return aRetval;
+}
+
+} // namespace SvtOptionsDrawinglayer
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/config/printoptions.cxx b/svtools/source/config/printoptions.cxx
new file mode 100644
index 000000000..ca9484356
--- /dev/null
+++ b/svtools/source/config/printoptions.cxx
@@ -0,0 +1,171 @@
+/* -*- 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 <svtools/printoptions.hxx>
+#include <vcl/printer/Options.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <sal/macros.h>
+#include <tools/long.hxx>
+
+const sal_uInt16 aDPIArray[] = { 72, 96, 150, 200, 300, 600 };
+
+#define DPI_COUNT (SAL_N_ELEMENTS(aDPIArray))
+
+using namespace ::osl;
+using namespace ::com::sun::star::uno;
+
+namespace svtools
+{
+
+void GetPrinterOptions( vcl::printer::Options& rOptions, bool bFile )
+{
+ if (bFile)
+ {
+ rOptions.SetReduceTransparency( officecfg::Office::Common::Print::Option::File::ReduceTransparency::get() );
+ rOptions.SetReducedTransparencyMode( static_cast<vcl::printer::TransparencyMode>(
+ officecfg::Office::Common::Print::Option::File::ReducedTransparencyMode::get() ) );
+ rOptions.SetReduceGradients( officecfg::Office::Common::Print::Option::File::ReduceGradients::get() );
+ rOptions.SetReducedGradientMode( static_cast<vcl::printer::GradientMode>(
+ officecfg::Office::Common::Print::Option::File::ReducedGradientMode::get()) );
+ rOptions.SetReducedGradientStepCount( officecfg::Office::Common::Print::Option::File::ReducedGradientStepCount::get() );
+ rOptions.SetReduceBitmaps( officecfg::Office::Common::Print::Option::File::ReduceBitmaps::get() );
+ rOptions.SetReducedBitmapMode( static_cast<vcl::printer::BitmapMode>(
+ officecfg::Office::Common::Print::Option::File::ReducedBitmapMode::get()) );
+ rOptions.SetReducedBitmapResolution( aDPIArray[ std::min( static_cast<sal_uInt16>(
+ officecfg::Office::Common::Print::Option::File::ReducedBitmapResolution::get()), sal_uInt16( DPI_COUNT - 1 ) ) ] );
+ rOptions.SetReducedBitmapIncludesTransparency(
+ officecfg::Office::Common::Print::Option::File::ReducedBitmapIncludesTransparency::get() );
+ rOptions.SetConvertToGreyscales( officecfg::Office::Common::Print::Option::File::ConvertToGreyscales::get() );
+ rOptions.SetPDFAsStandardPrintJobFormat( officecfg::Office::Common::Print::Option::File::PDFAsStandardPrintJobFormat::get() );
+ }
+ else
+ {
+ rOptions.SetReduceTransparency( officecfg::Office::Common::Print::Option::Printer::ReduceTransparency::get() );
+ rOptions.SetReducedTransparencyMode( static_cast<vcl::printer::TransparencyMode>(
+ officecfg::Office::Common::Print::Option::Printer::ReducedTransparencyMode::get() ) );
+ rOptions.SetReduceGradients( officecfg::Office::Common::Print::Option::Printer::ReduceGradients::get() );
+ rOptions.SetReducedGradientMode( static_cast<vcl::printer::GradientMode>(
+ officecfg::Office::Common::Print::Option::Printer::ReducedGradientMode::get()) );
+ rOptions.SetReducedGradientStepCount( officecfg::Office::Common::Print::Option::Printer::ReducedGradientStepCount::get() );
+ rOptions.SetReduceBitmaps( officecfg::Office::Common::Print::Option::Printer::ReduceBitmaps::get() );
+ rOptions.SetReducedBitmapMode( static_cast<vcl::printer::BitmapMode>(
+ officecfg::Office::Common::Print::Option::Printer::ReducedBitmapMode::get()) );
+ rOptions.SetReducedBitmapResolution( aDPIArray[ std::min( static_cast<sal_uInt16>(
+ officecfg::Office::Common::Print::Option::Printer::ReducedBitmapResolution::get()), sal_uInt16( DPI_COUNT - 1 ) ) ] );
+ rOptions.SetReducedBitmapIncludesTransparency(
+ officecfg::Office::Common::Print::Option::Printer::ReducedBitmapIncludesTransparency::get() );
+ rOptions.SetConvertToGreyscales( officecfg::Office::Common::Print::Option::Printer::ConvertToGreyscales::get() );
+ rOptions.SetPDFAsStandardPrintJobFormat( officecfg::Office::Common::Print::Option::Printer::PDFAsStandardPrintJobFormat::get() );
+ }
+}
+
+void SetPrinterOptions( const vcl::printer::Options& rOptions, bool bFile )
+{
+ std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
+ if (bFile)
+ {
+ officecfg::Office::Common::Print::Option::File::ReduceTransparency::set(
+ rOptions.IsReduceTransparency(), batch );
+ officecfg::Office::Common::Print::Option::File::ReducedTransparencyMode::set(
+ static_cast<sal_Int16>(rOptions.GetReducedTransparencyMode()), batch );
+ officecfg::Office::Common::Print::Option::File::ReduceGradients::set(
+ rOptions.IsReduceGradients(), batch );
+ officecfg::Office::Common::Print::Option::File::ReducedGradientMode::set(
+ static_cast<sal_Int16>(rOptions.GetReducedGradientMode()), batch );
+ officecfg::Office::Common::Print::Option::File::ReducedGradientStepCount::set(
+ rOptions.GetReducedGradientStepCount(), batch );
+ officecfg::Office::Common::Print::Option::File::ReduceBitmaps::set(
+ rOptions.IsReduceBitmaps(), batch );
+ officecfg::Office::Common::Print::Option::File::ReducedBitmapMode::set(
+ static_cast<sal_Int16>(rOptions.GetReducedBitmapMode()), batch );
+ officecfg::Office::Common::Print::Option::File::ReducedBitmapIncludesTransparency::set(
+ rOptions.IsReducedBitmapIncludesTransparency(), batch );
+ officecfg::Office::Common::Print::Option::File::ConvertToGreyscales::set(
+ rOptions.IsConvertToGreyscales(), batch );
+ officecfg::Office::Common::Print::Option::File::PDFAsStandardPrintJobFormat::set(
+ rOptions.IsPDFAsStandardPrintJobFormat(), batch );
+
+ const sal_uInt16 nDPI = rOptions.GetReducedBitmapResolution();
+
+ if( nDPI < aDPIArray[ 0 ] )
+ officecfg::Office::Common::Print::Option::File::ReducedBitmapResolution::set( 0, batch );
+ else
+ {
+ for( tools::Long i = DPI_COUNT - 1; i >= 0; i-- )
+ {
+ if( nDPI >= aDPIArray[ i ] )
+ {
+ officecfg::Office::Common::Print::Option::File::ReducedBitmapResolution::set(
+ static_cast<sal_Int16>(i), batch );
+ i = -1;
+ }
+ }
+ }
+ }
+ else
+ {
+ officecfg::Office::Common::Print::Option::Printer::ReduceTransparency::set(
+ rOptions.IsReduceTransparency(), batch );
+ officecfg::Office::Common::Print::Option::Printer::ReducedTransparencyMode::set(
+ static_cast<sal_Int16>(rOptions.GetReducedTransparencyMode()), batch );
+ officecfg::Office::Common::Print::Option::Printer::ReduceGradients::set(
+ rOptions.IsReduceGradients(), batch );
+ officecfg::Office::Common::Print::Option::Printer::ReducedGradientMode::set(
+ static_cast<sal_Int16>(rOptions.GetReducedGradientMode()), batch );
+ officecfg::Office::Common::Print::Option::Printer::ReducedGradientStepCount::set(
+ rOptions.GetReducedGradientStepCount(), batch );
+ officecfg::Office::Common::Print::Option::Printer::ReduceBitmaps::set(
+ rOptions.IsReduceBitmaps(), batch );
+ officecfg::Office::Common::Print::Option::Printer::ReducedBitmapMode::set(
+ static_cast<sal_Int16>(rOptions.GetReducedBitmapMode()), batch );
+ officecfg::Office::Common::Print::Option::Printer::ReducedBitmapIncludesTransparency::set(
+ rOptions.IsReducedBitmapIncludesTransparency(), batch );
+ officecfg::Office::Common::Print::Option::Printer::ConvertToGreyscales::set(
+ rOptions.IsConvertToGreyscales(), batch );
+ officecfg::Office::Common::Print::Option::Printer::PDFAsStandardPrintJobFormat::set(
+ rOptions.IsPDFAsStandardPrintJobFormat(), batch );
+
+ const sal_uInt16 nDPI = rOptions.GetReducedBitmapResolution();
+
+ if( nDPI < aDPIArray[ 0 ] )
+ officecfg::Office::Common::Print::Option::Printer::ReducedBitmapResolution::set( 0, batch );
+ else
+ {
+ for( tools::Long i = DPI_COUNT - 1; i >= 0; i-- )
+ {
+ if( nDPI >= aDPIArray[ i ] )
+ {
+ officecfg::Office::Common::Print::Option::Printer::ReducedBitmapResolution::set(
+ static_cast<sal_Int16>(i), batch );
+ i = -1;
+ }
+ }
+ }
+ }
+ batch->commit();
+}
+
+} // namespace svtools
+
+
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/config/slidesorterbaropt.cxx b/svtools/source/config/slidesorterbaropt.cxx
new file mode 100644
index 000000000..784e0894e
--- /dev/null
+++ b/svtools/source/config/slidesorterbaropt.cxx
@@ -0,0 +1,425 @@
+/* -*- 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 <svtools/slidesorterbaropt.hxx>
+#include <unotools/configitem.hxx>
+#include <tools/debug.hxx>
+#include <osl/diagnose.h>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <comphelper/lok.hxx>
+#include <comphelper/sequence.hxx>
+#include <mutex>
+
+using namespace ::utl;
+using namespace ::osl;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+
+constexpr OUStringLiteral ROOTNODE_SLIDESORTERBAR = u"Office.Impress/MultiPaneGUI/SlideSorterBar/Visible";
+
+constexpr OUStringLiteral PROPERTYNAME_VISIBLE_IMPRESSVIEW = u"ImpressView";
+#define PROPERTYHANDLE_VISIBLE_IMPRESSVIEW 0
+constexpr OUStringLiteral PROPERTYNAME_VISIBLE_OUTLINEVIEW = u"OutlineView";
+#define PROPERTYHANDLE_VISIBLE_OUTLINEVIEW 1
+constexpr OUStringLiteral PROPERTYNAME_VISIBLE_NOTESVIEW = u"NotesView";
+#define PROPERTYHANDLE_VISIBLE_NOTESVIEW 2
+constexpr OUStringLiteral PROPERTYNAME_VISIBLE_HANDOUTVIEW = u"HandoutView";
+#define PROPERTYHANDLE_VISIBLE_HANDOUTVIEW 3
+constexpr OUStringLiteral PROPERTYNAME_VISIBLE_SLIDESORTERVIEW = u"SlideSorterView";
+#define PROPERTYHANDLE_VISIBLE_SLIDESORTERVIEW 4
+constexpr OUStringLiteral PROPERTYNAME_VISIBLE_DRAWVIEW = u"DrawView";
+#define PROPERTYHANDLE_VISIBLE_DRAWVIEW 5
+
+static std::mutex & GetInitMutex()
+{
+ static std::mutex theSvtSlideSorterBarOptionsMutex;
+ return theSvtSlideSorterBarOptionsMutex;
+}
+
+
+class SvtSlideSorterBarOptions_Impl : public ConfigItem
+{
+ Sequence< OUString > m_seqPropertyNames;
+
+ public:
+
+ SvtSlideSorterBarOptions_Impl();
+ ~SvtSlideSorterBarOptions_Impl() override;
+
+ /** called for notify of configmanager
+
+ This method is called from the ConfigManager before the application ends or from the
+ PropertyChangeListener if the sub tree broadcasts changes. You must update your
+ internal values.
+
+ \sa baseclass ConfigItem
+ \param[in,out] seqPropertyNames is the list of properties which should be updated.
+ */
+ virtual void Notify( const Sequence< OUString >& seqPropertyNames ) override;
+
+ /**
+ loads required data from the configuration. It's called in the constructor to
+ read all entries and form ::Notify to re-read changed setting
+ */
+ void Load( const Sequence< OUString >& rPropertyNames );
+
+ // public interface
+ bool m_bVisibleImpressView;
+ bool m_bVisibleOutlineView;
+ bool m_bVisibleNotesView;
+ bool m_bVisibleHandoutView;
+ bool m_bVisibleSlideSorterView;
+ bool m_bVisibleDrawView;
+
+ private:
+ virtual void ImplCommit() final override;
+
+ /** return list of key names of our configuration management which represent our module tree
+
+ This method returns a static const list of key names. We need it to get needed values from
+ configuration management.
+
+ \return A list of needed configuration keys is returned.
+ */
+ static Sequence< OUString > GetPropertyNames();
+
+ void SetVisibleViewImpl( bool& bVisibleView, bool bVisible );
+
+ public:
+ void SetVisibleImpressView( bool bVisible)
+ { SetVisibleViewImpl( m_bVisibleImpressView, bVisible ); }
+
+ void SetVisibleOutlineView( bool bVisible)
+ { SetVisibleViewImpl( m_bVisibleOutlineView, bVisible ); }
+
+ void SetVisibleNotesView( bool bVisible)
+ { SetVisibleViewImpl( m_bVisibleNotesView, bVisible ); }
+
+ void SetVisibleHandoutView( bool bVisible)
+ { SetVisibleViewImpl( m_bVisibleHandoutView, bVisible ); }
+
+ void SetVisibleSlideSorterView( bool bVisible)
+ { SetVisibleViewImpl( m_bVisibleSlideSorterView, bVisible ); }
+
+ void SetVisibleDrawView( bool bVisible)
+ { SetVisibleViewImpl( m_bVisibleDrawView, bVisible ); }
+
+};
+
+SvtSlideSorterBarOptions_Impl::SvtSlideSorterBarOptions_Impl()
+ // Init baseclasses first
+ : ConfigItem( ROOTNODE_SLIDESORTERBAR )
+ , m_seqPropertyNames(GetPropertyNames())
+ , m_bVisibleImpressView( false )
+ , m_bVisibleOutlineView( false )
+ , m_bVisibleNotesView( false )
+ , m_bVisibleHandoutView( false )
+ , m_bVisibleSlideSorterView( false )
+ , m_bVisibleDrawView( false )
+
+{
+ // Use our static list of configuration keys to get his values.
+ Sequence< Any > seqValues = GetProperties( m_seqPropertyNames );
+
+ // Safe impossible cases.
+ // We need values from ALL configuration keys.
+ // Follow assignment use order of values in relation to our list of key names!
+ DBG_ASSERT( !(m_seqPropertyNames.getLength()!=seqValues.getLength()),
+ "SvtSlideSorterBarOptions_Impl::SvtSlideSorterBarOptions_Impl()\nI miss some values of configuration keys!\n" );
+
+ // Copy values from list in right order to our internal member.
+ for( sal_Int32 nProperty=0; nProperty<seqValues.getLength(); ++nProperty )
+ {
+ if (!seqValues[nProperty].hasValue())
+ continue;
+ switch( nProperty )
+ {
+ case PROPERTYHANDLE_VISIBLE_IMPRESSVIEW :
+ {
+ if( !(seqValues[nProperty] >>= m_bVisibleImpressView) )
+ OSL_FAIL("Wrong type of \"SlideSorterBar\\VisibleImpressView\"!" );
+ break;
+ }
+ case PROPERTYHANDLE_VISIBLE_OUTLINEVIEW :
+ {
+ if( !(seqValues[nProperty] >>= m_bVisibleOutlineView) )
+ OSL_FAIL("Wrong type of \"SlideSorterBar\\VisibleOutlineView\"!" );
+ break;
+ }
+ case PROPERTYHANDLE_VISIBLE_NOTESVIEW :
+ {
+ if( !(seqValues[nProperty] >>= m_bVisibleNotesView) )
+ OSL_FAIL("Wrong type of \"SlideSorterBar\\VisibleNotesView\"!" );
+ break;
+ }
+ case PROPERTYHANDLE_VISIBLE_HANDOUTVIEW :
+ {
+ if( !(seqValues[nProperty] >>= m_bVisibleHandoutView) )
+ OSL_FAIL("Wrong type of \"SlideSorterBar\\VisibleHandoutView\"!" );
+ break;
+ }
+ case PROPERTYHANDLE_VISIBLE_SLIDESORTERVIEW :
+ {
+ if( !(seqValues[nProperty] >>= m_bVisibleSlideSorterView) )
+ OSL_FAIL("Wrong type of \"SlideSorterBar\\VisibleSlideSorterView\"!" );
+ break;
+ }
+ case PROPERTYHANDLE_VISIBLE_DRAWVIEW :
+ {
+ if( !(seqValues[nProperty] >>= m_bVisibleDrawView) )
+ OSL_FAIL("Wrong type of \"SlideSorterBar\\VisibleDrawView\"!" );
+ break;
+ }
+ }
+ }
+
+ // Enable notification mechanism of our baseclass.
+ // We need it to get information about changes outside these class on our used configuration keys!
+ EnableNotification( m_seqPropertyNames );
+}
+
+SvtSlideSorterBarOptions_Impl::~SvtSlideSorterBarOptions_Impl()
+{
+ if (IsModified())
+ Commit();
+}
+
+void SvtSlideSorterBarOptions_Impl::Load( const Sequence< OUString >& rPropertyNames )
+{
+ const uno::Sequence< OUString> aInternalPropertyNames( GetPropertyNames());
+ Sequence< Any > seqValues = GetProperties( rPropertyNames );
+
+ // Safe impossible cases.
+ // We need values from ALL configuration keys.
+ // Follow assignment use order of values in relation to our list of key names!
+ DBG_ASSERT( !(rPropertyNames.getLength()!=seqValues.getLength()),
+ "SvtSlideSorterBarOptions_Impl::SvtSlideSorterBarOptions_Impl()\nI miss some values of configuration keys!\n" );
+
+ // Copy values from list in right order to our internal member.
+ for( sal_Int32 nProperty=0; nProperty<seqValues.getLength(); ++nProperty )
+ {
+ if (!seqValues[nProperty].hasValue())
+ continue;
+ switch( comphelper::findValue(aInternalPropertyNames, rPropertyNames[nProperty]) )
+ {
+ case PROPERTYHANDLE_VISIBLE_IMPRESSVIEW:
+ {
+ if( !(seqValues[nProperty] >>= m_bVisibleImpressView) )
+ OSL_FAIL("Wrong type of \"SlideSorterBar\\VisibleImpressView\"!" );
+ }
+ break;
+ case PROPERTYHANDLE_VISIBLE_OUTLINEVIEW :
+ {
+ if( !(seqValues[nProperty] >>= m_bVisibleOutlineView) )
+ OSL_FAIL("Wrong type of \"SlideSorterBar\\VisibleOutlineView\"!" );
+ }
+ break;
+ case PROPERTYHANDLE_VISIBLE_NOTESVIEW :
+ {
+ if( !(seqValues[nProperty] >>= m_bVisibleNotesView) )
+ OSL_FAIL("Wrong type of \"SlideSorterBar\\VisibleNotesView\"!" );
+ }
+ break;
+ case PROPERTYHANDLE_VISIBLE_HANDOUTVIEW :
+ {
+ if( !(seqValues[nProperty] >>= m_bVisibleHandoutView) )
+ OSL_FAIL("Wrong type of \"SlideSorterBar\\VisibleHandoutView\"!" );
+ }
+ break;
+ case PROPERTYHANDLE_VISIBLE_SLIDESORTERVIEW :
+ {
+ if( !(seqValues[nProperty] >>= m_bVisibleSlideSorterView) )
+ OSL_FAIL("Wrong type of \"SlideSorterBar\\VisibleSlideSorterView\"!" );
+ }
+ break;
+
+ case PROPERTYHANDLE_VISIBLE_DRAWVIEW :
+ {
+ if( !(seqValues[nProperty] >>= m_bVisibleDrawView) )
+ OSL_FAIL("Wrong type of \"SlideSorterBar\\VisibleDrawView\"!" );
+ }
+ break;
+ }
+ }
+}
+
+void SvtSlideSorterBarOptions_Impl::Notify( const Sequence< OUString >& rPropertyNames )
+{
+ Load( rPropertyNames );
+}
+
+void SvtSlideSorterBarOptions_Impl::ImplCommit()
+{
+ // Get names of supported properties, create a list for values and copy current values to it.
+ sal_Int32 nCount = m_seqPropertyNames.getLength();
+ Sequence< Any > seqValues ( nCount );
+ auto seqValuesRange = asNonConstRange(seqValues);
+ for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
+ {
+ switch( nProperty )
+ {
+ case PROPERTYHANDLE_VISIBLE_IMPRESSVIEW:
+ {
+ seqValuesRange[nProperty] <<= m_bVisibleImpressView;
+ break;
+ }
+ case PROPERTYHANDLE_VISIBLE_OUTLINEVIEW:
+ {
+ seqValuesRange[nProperty] <<= m_bVisibleOutlineView;
+ break;
+ }
+ case PROPERTYHANDLE_VISIBLE_NOTESVIEW:
+ {
+ seqValuesRange[nProperty] <<= m_bVisibleNotesView;
+ break;
+ }
+ case PROPERTYHANDLE_VISIBLE_HANDOUTVIEW:
+ {
+ seqValuesRange[nProperty] <<= m_bVisibleHandoutView;
+ break;
+ }
+ case PROPERTYHANDLE_VISIBLE_SLIDESORTERVIEW:
+ {
+ seqValuesRange[nProperty] <<= m_bVisibleSlideSorterView;
+ break;
+ }
+ case PROPERTYHANDLE_VISIBLE_DRAWVIEW:
+ {
+ seqValuesRange[nProperty] <<= m_bVisibleDrawView;
+ break;
+ }
+
+ }
+ }
+ // Set properties in configuration.
+ PutProperties( m_seqPropertyNames, seqValues );
+}
+
+Sequence< OUString > SvtSlideSorterBarOptions_Impl::GetPropertyNames()
+{
+ // Build list of configuration key names.
+ return
+ {
+ PROPERTYNAME_VISIBLE_IMPRESSVIEW,
+ PROPERTYNAME_VISIBLE_OUTLINEVIEW,
+ PROPERTYNAME_VISIBLE_NOTESVIEW,
+ PROPERTYNAME_VISIBLE_HANDOUTVIEW,
+ PROPERTYNAME_VISIBLE_SLIDESORTERVIEW,
+ PROPERTYNAME_VISIBLE_DRAWVIEW,
+ };
+}
+
+void SvtSlideSorterBarOptions_Impl::SetVisibleViewImpl( bool& bVisibleView, bool bVisible )
+{
+ if( bVisibleView != bVisible )
+ {
+ bVisibleView = bVisible;
+ SetModified();
+ }
+}
+
+namespace {
+ std::weak_ptr<SvtSlideSorterBarOptions_Impl> g_pSlideSorterBarOptions;
+}
+
+SvtSlideSorterBarOptions::SvtSlideSorterBarOptions()
+{
+ // Global access, must be guarded (multithreading!).
+ std::unique_lock aGuard( GetInitMutex() );
+
+ m_pImpl = g_pSlideSorterBarOptions.lock();
+ if( !m_pImpl )
+ {
+ m_pImpl = std::make_shared<SvtSlideSorterBarOptions_Impl>();
+ g_pSlideSorterBarOptions = m_pImpl;
+ }
+}
+
+SvtSlideSorterBarOptions::~SvtSlideSorterBarOptions()
+{
+ // Global access, must be guarded (multithreading!)
+ std::unique_lock aGuard( GetInitMutex() );
+
+ m_pImpl.reset();
+}
+
+bool SvtSlideSorterBarOptions::GetVisibleImpressView() const
+{
+ static const bool bRunningUnitTest = getenv("LO_TESTNAME");
+ return m_pImpl->m_bVisibleImpressView && (!bRunningUnitTest || !comphelper::LibreOfficeKit::isActive());
+}
+
+void SvtSlideSorterBarOptions::SetVisibleImpressView(bool bVisible)
+{
+ m_pImpl->SetVisibleImpressView( bVisible );
+}
+
+bool SvtSlideSorterBarOptions::GetVisibleOutlineView() const
+{
+ return m_pImpl->m_bVisibleOutlineView;
+}
+
+void SvtSlideSorterBarOptions::SetVisibleOutlineView(bool bVisible)
+{
+ m_pImpl->SetVisibleOutlineView( bVisible );
+}
+
+bool SvtSlideSorterBarOptions::GetVisibleNotesView() const
+{
+ return m_pImpl->m_bVisibleNotesView;
+}
+
+void SvtSlideSorterBarOptions::SetVisibleNotesView(bool bVisible)
+{
+ m_pImpl->SetVisibleNotesView( bVisible );
+}
+
+bool SvtSlideSorterBarOptions::GetVisibleHandoutView() const
+{
+ return m_pImpl->m_bVisibleHandoutView;
+}
+
+void SvtSlideSorterBarOptions::SetVisibleHandoutView(bool bVisible)
+{
+ m_pImpl->SetVisibleHandoutView( bVisible );
+}
+
+bool SvtSlideSorterBarOptions::GetVisibleSlideSorterView() const
+{
+ return m_pImpl->m_bVisibleSlideSorterView && !comphelper::LibreOfficeKit::isActive();
+}
+
+void SvtSlideSorterBarOptions::SetVisibleSlideSorterView(bool bVisible)
+{
+ m_pImpl->SetVisibleSlideSorterView( bVisible );
+}
+
+bool SvtSlideSorterBarOptions::GetVisibleDrawView() const
+{
+ return m_pImpl->m_bVisibleDrawView;
+}
+
+void SvtSlideSorterBarOptions::SetVisibleDrawView(bool bVisible)
+{
+ m_pImpl->SetVisibleDrawView( bVisible );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/config/test/test.cxx b/svtools/source/config/test/test.cxx
new file mode 100644
index 000000000..c84d2ca9f
--- /dev/null
+++ b/svtools/source/config/test/test.cxx
@@ -0,0 +1,215 @@
+/* -*- 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 .
+ */
+
+
+// switches
+// use it to enable test scenarios
+
+
+#define TEST_DYNAMICMENUOPTIONS
+
+#include <unotools/dynamicmenuoptions.hxx>
+
+#include <cppuhelper/bootstrap.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/registry/XSimpleRegistry.hpp>
+
+#include <cppuhelper/servicefactory.hxx>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Sequence.h>
+
+#include <rtl/ustring>
+#include <rtl/ustrbuf.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+
+#include <vcl/event.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace ::osl ;
+using namespace ::comphelper ;
+using namespace ::com::sun::star::uno ;
+using namespace ::com::sun::star::lang ;
+using namespace ::com::sun::star::beans ;
+using namespace ::com::sun::star::registry ;
+
+class TestApplication : public Application
+{
+
+ // interface
+
+ public:
+ void Main();
+
+
+ // test methods
+
+ private:
+ void impl_testDynamicMenuOptions();
+
+
+ // helper methods
+
+ private:
+ static Reference< XMultiServiceFactory > getUNOServiceManager();
+
+
+ // member
+
+ private:
+
+}; // class TestApplication
+
+
+// global variables
+
+
+TestApplication aTestApplication ;
+
+
+// main
+
+
+void TestApplication::Main()
+{
+ /**-***********************************************************************************************************
+ initialize program
+ **************************************************************************************************************/
+
+ // Init global servicemanager and set it for external services.
+ ::comphelper::setProcessServiceFactory( TestApplication::getUNOServiceManager() );
+ // Control success of operation.
+ OSL_ENSURE( !(::comphelper::getProcessServiceFactory()!=TestApplication::getUNOServiceManager()), "TestApplication::Main() Global servicemanager not right initialized." );
+
+ /**-***********************************************************************************************************
+ test area
+ **************************************************************************************************************/
+
+ #ifdef TEST_DYNAMICMENUOPTIONS
+ impl_testDynamicMenuOptions();
+ #endif
+
+// Execute();
+ OSL_FAIL( "Test was successful!" );
+}
+
+
+// test configuration of dynamic menus "New" and "Wizard"
+
+void TestApplication::impl_testDynamicMenuOptions()
+{
+ SvtDynamicMenuOptions aCFG;
+
+ // Test:
+ // read menus
+ // if( menus == empty )
+ // {
+ // fill it with samples
+ // read it again
+ // }
+ // output content
+
+ Sequence< Sequence< PropertyValue > > lNewMenu = aCFG.GetMenu( EDynamicMenuType::NewMenu );
+ Sequence< Sequence< PropertyValue > > lWizardMenu = aCFG.GetMenu( EDynamicMenuType::WizardMenu );
+
+ if( lNewMenu.getLength() < 1 )
+ {
+ aCFG.AppendItem( EDynamicMenuType::NewMenu, "private:factory/swriter", "new writer", "icon_writer", "_blank");
+ aCFG.AppendItem( EDynamicMenuType::NewMenu, "private:factory/scalc", "new calc", "icon_calc", "_blank");
+ aCFG.AppendItem( EDynamicMenuType::NewMenu, "private:factory/sdraw", "new draw", "icon_draw", "_blank");
+
+ lNewMenu = aCFG.GetMenu( EDynamicMenuType::NewMenu );
+ }
+
+ if( lWizardMenu.getLength() < 1 )
+ {
+ aCFG.AppendItem( EDynamicMenuType::WizardMenu, "file://a", "system file", "icon_file", "_self");
+ aCFG.AppendItem( EDynamicMenuType::WizardMenu, "ftp://b", "ftp host", "icon_ftp", "_self");
+ aCFG.AppendItem( EDynamicMenuType::WizardMenu, "http://c", "www", "icon_www", "_self");
+
+ lWizardMenu = aCFG.GetMenu( EDynamicMenuType::WizardMenu );
+ }
+
+ sal_uInt32 nItemCount ;
+ sal_uInt32 nItem ;
+ sal_uInt32 nPropertyCount;
+ sal_uInt32 nProperty ;
+ OUString sPropertyValue;
+ OUStringBuffer sOut( 5000 ) ;
+
+ nItemCount = lNewMenu.getLength();
+ for( nItem=0; nItem<nItemCount; ++nItem )
+ {
+ nPropertyCount = lNewMenu[nItem].getLength();
+ for( nProperty=0; nProperty<nPropertyCount; ++nProperty )
+ {
+ lNewMenu[nItem][nProperty].Value >>= sPropertyValue;
+
+ sOut.appendAscii ( "New/" );
+ sOut.append ( (sal_Int32)nItem );
+ sOut.appendAscii ( "/" );
+ sOut.append ( lNewMenu[nItem][nProperty].Name );
+ sOut.appendAscii ( " = " );
+ sOut.append ( sPropertyValue );
+ sOut.appendAscii ( "\n" );
+ }
+ }
+
+ sOut.appendAscii("\n--------------------------------------\n");
+
+ nItemCount = lWizardMenu.getLength();
+ for( nItem=0; nItem<nItemCount; ++nItem )
+ {
+ nPropertyCount = lNewMenu[nItem].getLength();
+ for( nProperty=0; nProperty<nPropertyCount; ++nProperty )
+ {
+ lWizardMenu[nItem][nProperty].Value >>= sPropertyValue;
+
+ sOut.appendAscii ( "Wizard/" );
+ sOut.append ( (sal_Int32)nItem );
+ sOut.appendAscii ( "/" );
+ sOut.append ( lNewMenu[nItem][nProperty].Name );
+ sOut.appendAscii ( " = " );
+ sOut.append ( sPropertyValue );
+ sOut.appendAscii ( "\n" );
+ }
+ }
+
+ SAL_WARN( "svtools", sOut );
+}
+
+
+// create new uno servicemanager by using normal applicat.rdb and user.rdb of an office installation!
+// Don't use this application at the same time like the office!
+
+Reference< XMultiServiceFactory > TestApplication::getUNOServiceManager()
+{
+ static Reference< XMultiServiceFactory > smgr;
+ if( ! smgr.is() )
+ {
+ Reference< XComponentContext > rCtx =
+ cppu::defaultBootstrap_InitialComponentContext();
+ smgr.set( rCtx->getServiceManager() , UNO_QUERY );
+ }
+ return smgr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */