nss: upgrade to release 3.73
[LibreOffice.git] / svtools / source / config / extcolorcfg.cxx
blob707047f8b535f07667aef7f92d749d2397fc6878
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <map>
24 #include <svtools/extcolorcfg.hxx>
25 #include <com/sun/star/uno/Any.hxx>
26 #include <com/sun/star/uno/Sequence.hxx>
27 #include <com/sun/star/beans/PropertyValue.hpp>
28 #include <tools/color.hxx>
29 #include <unotools/configitem.hxx>
30 #include <com/sun/star/uno/Sequence.h>
31 #include <comphelper/sequence.hxx>
32 #include <svl/hint.hxx>
33 #include <osl/mutex.hxx>
34 #include <sal/log.hxx>
35 #include <osl/diagnose.h>
37 #include <vcl/svapp.hxx>
38 #include <vcl/settings.hxx>
39 #include <vcl/event.hxx>
40 #include <rtl/instance.hxx>
43 using namespace utl;
44 using namespace com::sun::star;
47 namespace svtools
50 static sal_Int32 nExtendedColorRefCount_Impl = 0;
51 namespace
53 struct ColorMutex_Impl
54 : public rtl::Static< ::osl::Mutex, ColorMutex_Impl > {};
57 ExtendedColorConfig_Impl* ExtendedColorConfig::m_pImpl = nullptr;
59 class ExtendedColorConfig_Impl : public utl::ConfigItem, public SfxBroadcaster
61 typedef std::map<OUString, OUString> TDisplayNames;
62 typedef std::map<OUString, ExtendedColorConfigValue> TConfigValues;
63 typedef ::std::vector<TConfigValues::iterator> TMapPos;
64 typedef ::std::pair< TConfigValues, TMapPos > TComponentMapping;
65 typedef std::map<OUString, TComponentMapping> TComponents;
66 TComponents m_aConfigValues;
67 TDisplayNames m_aComponentDisplayNames;
68 ::std::vector<TComponents::iterator> m_aConfigValuesPos;
70 OUString m_sLoadedScheme;
71 bool m_bIsBroadcastEnabled;
72 static bool m_bLockBroadcast;
73 static bool m_bBroadcastWhenUnlocked;
75 uno::Sequence< OUString> GetPropertyNames(const OUString& rScheme);
76 void FillComponentColors(const uno::Sequence < OUString >& _rComponents,const TDisplayNames& _rDisplayNames);
78 virtual void ImplCommit() override;
80 public:
81 explicit ExtendedColorConfig_Impl();
82 virtual ~ExtendedColorConfig_Impl() override;
84 void Load(const OUString& rScheme);
85 void CommitCurrentSchemeName();
86 //changes the name of the current scheme but doesn't load it!
87 void SetCurrentSchemeName(const OUString& rSchemeName) {m_sLoadedScheme = rSchemeName;}
88 bool ExistsScheme(const OUString& _sSchemeName);
89 virtual void Notify( const uno::Sequence<OUString>& aPropertyNames) override;
91 sal_Int32 GetComponentCount() const;
92 OUString GetComponentName(sal_uInt32 _nPos) const;
93 OUString GetComponentDisplayName(const OUString& _sComponentName) const;
94 sal_Int32 GetComponentColorCount(const OUString& _sName) const;
95 ExtendedColorConfigValue GetComponentColorConfigValue(const OUString& _sName,sal_uInt32 _nPos) const;
97 ExtendedColorConfigValue GetColorConfigValue(const OUString& _sComponentName,const OUString& _sName)
99 TComponents::iterator aFind = m_aConfigValues.find(_sComponentName);
100 if ( aFind != m_aConfigValues.end() )
102 TConfigValues::iterator aFind2 = aFind->second.first.find(_sName);
103 if ( aFind2 != aFind->second.first.end() )
104 return aFind2->second;
106 #if OSL_DEBUG_LEVEL > 0
107 SAL_WARN( "svtools", "Could find the required config:\n"
108 "component: " << _sComponentName
109 << "\nname: " << _sName );
110 #endif
111 return ExtendedColorConfigValue();
113 void SetColorConfigValue(const OUString& _sName,
114 const ExtendedColorConfigValue& rValue );
116 void AddScheme(const OUString& rNode);
117 void RemoveScheme(const OUString& rNode);
118 using ConfigItem::SetModified;
119 using ConfigItem::ClearModified;
120 void SettingsChanged();
122 static void DisableBroadcast();
123 static void EnableBroadcast();
125 static void LockBroadcast();
126 static void UnlockBroadcast();
128 DECL_LINK( DataChangedEventListener, VclSimpleEvent&, void );
131 uno::Sequence< OUString> ExtendedColorConfig_Impl::GetPropertyNames(const OUString& rScheme)
133 uno::Sequence< OUString> aNames(GetNodeNames(rScheme));
134 for(OUString & i : aNames)
136 i = rScheme + "/" + i;
138 return aNames;
141 sal_Int32 ExtendedColorConfig_Impl::GetComponentCount() const
143 return m_aConfigValues.size();
146 sal_Int32 ExtendedColorConfig_Impl::GetComponentColorCount(const OUString& _sName) const
148 sal_Int32 nSize = 0;
149 TComponents::const_iterator aFind = m_aConfigValues.find(_sName);
150 if ( aFind != m_aConfigValues.end() )
152 nSize = aFind->second.first.size();
154 return nSize;
157 ExtendedColorConfigValue ExtendedColorConfig_Impl::GetComponentColorConfigValue(const OUString& _sName,sal_uInt32 _nPos) const
159 TComponents::const_iterator aFind = m_aConfigValues.find(_sName);
160 if ( aFind != m_aConfigValues.end() )
162 if ( _nPos < aFind->second.second.size() )
164 return aFind->second.second[_nPos]->second;
167 return ExtendedColorConfigValue();
170 OUString ExtendedColorConfig_Impl::GetComponentDisplayName(const OUString& _sComponentName) const
172 OUString sRet;
173 TDisplayNames::const_iterator aFind = m_aComponentDisplayNames.find(_sComponentName);
174 if ( aFind != m_aComponentDisplayNames.end() )
175 sRet = aFind->second;
176 return sRet;
179 OUString ExtendedColorConfig_Impl::GetComponentName(sal_uInt32 _nPos) const
181 OUString sRet;
182 if ( _nPos < m_aConfigValuesPos.size() )
183 sRet = m_aConfigValuesPos[_nPos]->first;
184 return sRet;
187 bool ExtendedColorConfig_Impl::m_bLockBroadcast = false;
188 bool ExtendedColorConfig_Impl::m_bBroadcastWhenUnlocked = false;
189 ExtendedColorConfig_Impl::ExtendedColorConfig_Impl() :
190 ConfigItem("Office.ExtendedColorScheme"),
191 m_bIsBroadcastEnabled(true)
193 //try to register on the root node - if possible
194 uno::Sequence < OUString > aNames(1);
195 EnableNotification( aNames );
196 Load(OUString());
198 ::Application::AddEventListener( LINK(this, ExtendedColorConfig_Impl, DataChangedEventListener) );
202 ExtendedColorConfig_Impl::~ExtendedColorConfig_Impl()
204 ::Application::RemoveEventListener( LINK(this, ExtendedColorConfig_Impl, DataChangedEventListener) );
207 void ExtendedColorConfig_Impl::DisableBroadcast()
209 if ( ExtendedColorConfig::m_pImpl )
210 ExtendedColorConfig::m_pImpl->m_bIsBroadcastEnabled = false;
213 void ExtendedColorConfig_Impl::EnableBroadcast()
215 if ( ExtendedColorConfig::m_pImpl )
216 ExtendedColorConfig::m_pImpl->m_bIsBroadcastEnabled = true;
219 static void lcl_addString(uno::Sequence < OUString >& _rSeq,const OUString& _sAdd)
221 for(OUString & i : _rSeq)
222 i += _sAdd;
225 void ExtendedColorConfig_Impl::Load(const OUString& rScheme)
227 m_aComponentDisplayNames.clear();
228 m_aConfigValuesPos.clear();
229 m_aConfigValues.clear();
231 // fill display names
232 TDisplayNames aDisplayNameMap;
233 uno::Sequence < OUString > aComponentNames = GetPropertyNames("EntryNames");
234 OUString sDisplayName("/DisplayName");
235 for(OUString & componentName : aComponentNames)
237 uno::Sequence < OUString > aComponentDisplayNames(1);
238 aComponentDisplayNames[0] = componentName + sDisplayName;
239 uno::Sequence< uno::Any > aComponentDisplayNamesValue = GetProperties( aComponentDisplayNames );
240 OUString sComponentDisplayName;
241 if ( aComponentDisplayNamesValue.hasElements() && (aComponentDisplayNamesValue[0] >>= sComponentDisplayName) )
243 m_aComponentDisplayNames.emplace(componentName.getToken(1, '/'),sComponentDisplayName);
246 componentName += "/Entries";
247 uno::Sequence < OUString > aDisplayNames = GetPropertyNames(componentName);
248 lcl_addString(aDisplayNames,sDisplayName);
250 uno::Sequence< uno::Any > aDisplayNamesValue = GetProperties( aDisplayNames );
252 const OUString* pDispIter = aDisplayNames.getConstArray();
253 const OUString* pDispEnd = pDispIter + aDisplayNames.getLength();
254 for(sal_Int32 j = 0;pDispIter != pDispEnd;++pDispIter,++j)
256 sal_Int32 nIndex = 0;
257 pDispIter->getToken(0,'/',nIndex);
258 OUString sName = pDispIter->copy(nIndex);
259 sName = sName.copy(0,sName.lastIndexOf(sDisplayName));
260 OUString sCurrentDisplayName;
261 aDisplayNamesValue[j] >>= sCurrentDisplayName;
262 aDisplayNameMap.emplace(sName,sCurrentDisplayName);
266 // load color settings
267 OUString sScheme(rScheme);
269 if(sScheme.isEmpty())
271 //detect current scheme name
272 uno::Sequence < OUString > aCurrent { "ExtendedColorScheme/CurrentColorScheme" };
273 uno::Sequence< uno::Any > aCurrentVal = GetProperties( aCurrent );
274 aCurrentVal.getConstArray()[0] >>= sScheme;
275 } // if(!sScheme.getLength())
277 m_sLoadedScheme = sScheme;
278 OUString sBase = "ExtendedColorScheme/ColorSchemes/"
279 + sScheme;
281 bool bFound = ExistsScheme(sScheme);
282 if ( bFound )
284 aComponentNames = GetPropertyNames(sBase);
285 FillComponentColors(aComponentNames,aDisplayNameMap);
288 if ( m_sLoadedScheme.isEmpty() )
289 m_sLoadedScheme = "default";
291 if ( sScheme != "default" )
293 if ( ExistsScheme("default") )
295 aComponentNames = GetPropertyNames("ExtendedColorScheme/ColorSchemes/default");
296 FillComponentColors(aComponentNames,aDisplayNameMap);
299 if ( !bFound && !sScheme.isEmpty() )
301 AddScheme(sScheme);
302 CommitCurrentSchemeName();
306 void ExtendedColorConfig_Impl::FillComponentColors(const uno::Sequence < OUString >& _rComponents,const TDisplayNames& _rDisplayNames)
308 const OUString sColorEntries("/Entries");
309 for(OUString const & component : _rComponents)
311 OUString sComponentName = component.copy(component.lastIndexOf('/')+1);
312 if ( m_aConfigValues.find(sComponentName) == m_aConfigValues.end() )
314 OUString sEntry = component + sColorEntries;
316 uno::Sequence < OUString > aColorNames = GetPropertyNames(sEntry);
317 uno::Sequence < OUString > aDefaultColorNames = aColorNames;
319 const OUString sColor("/Color");
320 lcl_addString(aColorNames,sColor);
321 lcl_addString(aDefaultColorNames,"/DefaultColor");
322 uno::Sequence< uno::Any > aColors = GetProperties( aColorNames );
323 const uno::Any* pColors = aColors.getConstArray();
325 uno::Sequence< uno::Any > aDefaultColors = GetProperties( aDefaultColorNames );
326 bool bDefaultColorFound = aDefaultColors.hasElements();
327 const uno::Any* pDefaultColors = aDefaultColors.getConstArray();
329 OUString* pColorIter = aColorNames.getArray();
330 OUString* pColorEnd = pColorIter + aColorNames.getLength();
332 m_aConfigValuesPos.push_back(m_aConfigValues.emplace(sComponentName,TComponentMapping(TConfigValues(),TMapPos())).first);
333 TConfigValues& aConfigValues = (*m_aConfigValuesPos.rbegin())->second.first;
334 TMapPos& aConfigValuesPos = (*m_aConfigValuesPos.rbegin())->second.second;
335 for(int i = 0; pColorIter != pColorEnd; ++pColorIter ,++i)
337 if ( aConfigValues.find(*pColorIter) == aConfigValues.end() )
339 sal_Int32 nIndex = 0;
340 pColorIter->getToken(2,'/',nIndex);
341 OUString sName(pColorIter->copy(nIndex)),sDisplayName;
342 OUString sTemp = sName.copy(0,sName.lastIndexOf(sColor));
344 TDisplayNames::const_iterator aFind = _rDisplayNames.find(sTemp);
345 sName = sName.getToken(2, '/');
346 OSL_ENSURE(aFind != _rDisplayNames.end(),"DisplayName is not in EntryNames config list!");
347 if ( aFind != _rDisplayNames.end() )
348 sDisplayName = aFind->second;
350 OSL_ENSURE(pColors[i].hasValue(),"Color config entry has NIL as color value set!");
351 OSL_ENSURE(pDefaultColors[i].hasValue(),"Color config entry has NIL as color value set!");
352 Color nColor, nDefaultColor;
353 pColors[i] >>= nColor;
354 if ( bDefaultColorFound )
355 pDefaultColors[i] >>= nDefaultColor;
356 else
357 nDefaultColor = nColor;
358 ExtendedColorConfigValue aValue(sName,sDisplayName,nColor,nDefaultColor);
359 aConfigValuesPos.push_back(aConfigValues.emplace(sName,aValue).first);
361 } // for(int i = 0; pColorIter != pColorEnd; ++pColorIter ,++i)
366 void ExtendedColorConfig_Impl::Notify( const uno::Sequence<OUString>& /*rPropertyNames*/)
368 //loading via notification always uses the default setting
369 Load(OUString());
371 SolarMutexGuard aVclGuard;
373 if(m_bLockBroadcast)
375 m_bBroadcastWhenUnlocked = true;
377 else
378 Broadcast(SfxHint(SfxHintId::ColorsChanged));
381 void ExtendedColorConfig_Impl::ImplCommit()
383 if ( m_sLoadedScheme.isEmpty() )
384 return;
385 const OUString sColorEntries("Entries");
386 const OUString sColor("/Color");
387 OUString sBase = "ExtendedColorScheme/ColorSchemes/"
388 + m_sLoadedScheme;
389 const OUString s_sSep("/");
391 for (auto const& configValue : m_aConfigValues)
393 if ( ConfigItem::AddNode(sBase, configValue.first) )
395 OUString sNode = sBase
396 + s_sSep
397 + configValue.first
398 //ConfigItem::AddNode(sNode, sColorEntries);
399 + s_sSep
400 + sColorEntries;
402 uno::Sequence < beans::PropertyValue > aPropValues(configValue.second.first.size());
403 beans::PropertyValue* pPropValues = aPropValues.getArray();
404 for (auto const& elem : configValue.second.first)
406 pPropValues->Name = sNode + s_sSep + elem.first;
407 ConfigItem::AddNode(sNode, elem.first);
408 pPropValues->Name += sColor;
409 pPropValues->Value <<= elem.second.getColor();
410 // the default color will never be changed
411 ++pPropValues;
413 SetSetProperties("ExtendedColorScheme/ColorSchemes", aPropValues);
417 CommitCurrentSchemeName();
420 void ExtendedColorConfig_Impl::CommitCurrentSchemeName()
422 //save current scheme name
423 uno::Sequence < OUString > aCurrent { "ExtendedColorScheme/CurrentColorScheme" };
424 uno::Sequence< uno::Any > aCurrentVal(1);
425 aCurrentVal.getArray()[0] <<= m_sLoadedScheme;
426 PutProperties(aCurrent, aCurrentVal);
429 bool ExtendedColorConfig_Impl::ExistsScheme(const OUString& _sSchemeName)
431 OUString sBase("ExtendedColorScheme/ColorSchemes");
433 uno::Sequence < OUString > aComponentNames = GetPropertyNames(sBase);
434 sBase += "/" + _sSchemeName;
435 return comphelper::findValue(aComponentNames, sBase) != -1;
438 void ExtendedColorConfig_Impl::SetColorConfigValue(const OUString& _sName, const ExtendedColorConfigValue& rValue )
440 TComponents::iterator aFind = m_aConfigValues.find(_sName);
441 if ( aFind != m_aConfigValues.end() )
443 TConfigValues::iterator aFind2 = aFind->second.first.find(rValue.getName());
444 if ( aFind2 != aFind->second.first.end() )
445 aFind2->second = rValue;
446 SetModified();
450 void ExtendedColorConfig_Impl::AddScheme(const OUString& rScheme)
452 if(ConfigItem::AddNode("ExtendedColorScheme/ColorSchemes", rScheme))
454 m_sLoadedScheme = rScheme;
455 Commit();
459 void ExtendedColorConfig_Impl::RemoveScheme(const OUString& rScheme)
461 uno::Sequence< OUString > aElements { rScheme };
462 ClearNodeElements("ExtendedColorScheme/ColorSchemes", aElements);
465 void ExtendedColorConfig_Impl::SettingsChanged()
467 SolarMutexGuard aVclGuard;
469 Broadcast( SfxHint( SfxHintId::ColorsChanged ) );
472 void ExtendedColorConfig_Impl::LockBroadcast()
474 m_bLockBroadcast = true;
477 void ExtendedColorConfig_Impl::UnlockBroadcast()
479 if ( m_bBroadcastWhenUnlocked )
481 m_bBroadcastWhenUnlocked = ExtendedColorConfig::m_pImpl != nullptr;
482 if ( m_bBroadcastWhenUnlocked )
484 if (ExtendedColorConfig::m_pImpl->m_bIsBroadcastEnabled)
486 m_bBroadcastWhenUnlocked = false;
487 ExtendedColorConfig::m_pImpl->Broadcast(SfxHint(SfxHintId::ColorsChanged));
491 m_bLockBroadcast = false;
494 IMPL_LINK( ExtendedColorConfig_Impl, DataChangedEventListener, VclSimpleEvent&, rEvent, void )
496 if ( rEvent.GetId() == VclEventId::ApplicationDataChanged )
498 DataChangedEvent* pData = static_cast<DataChangedEvent*>(static_cast<VclWindowEvent&>(rEvent).GetData());
499 if ( (pData->GetType() == DataChangedEventType::SETTINGS) &&
500 (pData->GetFlags() & AllSettingsFlags::STYLE) )
502 SettingsChanged();
508 ExtendedColorConfig::ExtendedColorConfig()
510 ::osl::MutexGuard aGuard( ColorMutex_Impl::get() );
511 if ( !m_pImpl )
512 m_pImpl = new ExtendedColorConfig_Impl;
513 ++nExtendedColorRefCount_Impl;
514 StartListening( *m_pImpl);
517 ExtendedColorConfig::~ExtendedColorConfig()
519 ::osl::MutexGuard aGuard( ColorMutex_Impl::get() );
520 EndListening( *m_pImpl);
521 if(!--nExtendedColorRefCount_Impl)
523 delete m_pImpl;
524 m_pImpl = nullptr;
528 ExtendedColorConfigValue ExtendedColorConfig::GetColorValue(const OUString& _sComponentName,const OUString& _sName)const
530 return m_pImpl->GetColorConfigValue(_sComponentName,_sName);
533 sal_Int32 ExtendedColorConfig::GetComponentCount() const
535 return m_pImpl->GetComponentCount();
538 sal_Int32 ExtendedColorConfig::GetComponentColorCount(const OUString& _sName) const
540 return m_pImpl->GetComponentColorCount(_sName);
543 ExtendedColorConfigValue ExtendedColorConfig::GetComponentColorConfigValue(const OUString& _sName,sal_uInt32 _nPos) const
545 return m_pImpl->GetComponentColorConfigValue(_sName,_nPos);
548 OUString ExtendedColorConfig::GetComponentName(sal_uInt32 _nPos) const
550 return m_pImpl->GetComponentName(_nPos);
553 OUString ExtendedColorConfig::GetComponentDisplayName(const OUString& _sComponentName) const
555 return m_pImpl->GetComponentDisplayName(_sComponentName);
558 void ExtendedColorConfig::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
560 SolarMutexGuard aVclGuard;
562 Broadcast( rHint );
565 EditableExtendedColorConfig::EditableExtendedColorConfig() :
566 m_pImpl(new ExtendedColorConfig_Impl),
567 m_bModified(false)
569 ExtendedColorConfig_Impl::LockBroadcast();
572 EditableExtendedColorConfig::~EditableExtendedColorConfig()
574 ExtendedColorConfig_Impl::UnlockBroadcast();
575 if(m_bModified)
576 m_pImpl->SetModified();
577 if(m_pImpl->IsModified())
578 m_pImpl->Commit();
581 void EditableExtendedColorConfig::DeleteScheme(const OUString& rScheme )
583 m_pImpl->RemoveScheme(rScheme);
586 void EditableExtendedColorConfig::AddScheme(const OUString& rScheme )
588 m_pImpl->AddScheme(rScheme);
591 void EditableExtendedColorConfig::LoadScheme(const OUString& rScheme )
593 if(m_bModified)
594 m_pImpl->SetModified();
595 if(m_pImpl->IsModified())
596 m_pImpl->Commit();
597 m_bModified = false;
598 m_pImpl->Load(rScheme);
599 //the name of the loaded scheme has to be committed separately
600 m_pImpl->CommitCurrentSchemeName();
603 // Changes the name of the current scheme but doesn't load it!
604 void EditableExtendedColorConfig::SetCurrentSchemeName(const OUString& rScheme)
606 m_pImpl->SetCurrentSchemeName(rScheme);
607 m_pImpl->CommitCurrentSchemeName();
610 void EditableExtendedColorConfig::SetColorValue(
611 const OUString& _sName, const ExtendedColorConfigValue& rValue)
613 m_pImpl->SetColorConfigValue(_sName, rValue);
614 m_pImpl->ClearModified();
615 m_bModified = true;
618 void EditableExtendedColorConfig::SetModified()
620 m_bModified = true;
623 void EditableExtendedColorConfig::Commit()
625 if(m_bModified)
626 m_pImpl->SetModified();
627 if(m_pImpl->IsModified())
628 m_pImpl->Commit();
629 m_bModified = false;
632 void EditableExtendedColorConfig::DisableBroadcast()
634 ExtendedColorConfig_Impl::DisableBroadcast();
637 void EditableExtendedColorConfig::EnableBroadcast()
639 ExtendedColorConfig_Impl::EnableBroadcast();
642 sal_Int32 EditableExtendedColorConfig::GetComponentCount() const
644 return m_pImpl->GetComponentCount();
647 sal_Int32 EditableExtendedColorConfig::GetComponentColorCount(const OUString& _sName) const
649 return m_pImpl->GetComponentColorCount(_sName);
652 ExtendedColorConfigValue EditableExtendedColorConfig::GetComponentColorConfigValue(const OUString& _sName,sal_uInt32 _nPos) const
654 return m_pImpl->GetComponentColorConfigValue(_sName,_nPos);
657 OUString EditableExtendedColorConfig::GetComponentName(sal_uInt32 _nPos) const
659 return m_pImpl->GetComponentName(_nPos);
661 }//namespace svtools
663 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */