Update git submodules
[LibreOffice.git] / sfx2 / source / sidebar / Theme.cxx
blobda2308915999755a02af449c23e881b410eae3d3
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 <sfx2/sidebar/Theme.hxx>
21 #include <sfx2/app.hxx>
23 #include <vcl/svapp.hxx>
24 #include <vcl/settings.hxx>
25 #include <comphelper/diagnose_ex.hxx>
27 using namespace css;
28 using namespace css::uno;
30 namespace sfx2::sidebar {
32 Theme& Theme::GetCurrentTheme()
34 OSL_ASSERT(SfxGetpApp());
35 return SfxGetpApp()->GetSidebarTheme();
38 Theme::Theme()
39 : mbIsHighContrastMode(Application::GetSettings().GetStyleSettings().GetHighContrastMode()),
40 mbIsHighContrastModeSetManually(false)
42 SetupPropertyMaps();
45 Theme::~Theme()
49 Color Theme::GetColor (const ThemeItem eItem)
51 const PropertyType eType (GetPropertyType(eItem));
52 OSL_ASSERT(eType==PT_Color);
53 const sal_Int32 nIndex (GetIndex(eItem, eType));
54 const Theme& rTheme (GetCurrentTheme());
55 if (eType == PT_Color)
56 return rTheme.maColors[nIndex];
57 else
58 return COL_WHITE;
61 sal_Int32 Theme::GetInteger (const ThemeItem eItem)
63 const PropertyType eType (GetPropertyType(eItem));
64 OSL_ASSERT(eType==PT_Integer);
65 const sal_Int32 nIndex (GetIndex(eItem, eType));
66 const Theme& rTheme (GetCurrentTheme());
67 return rTheme.maIntegers[nIndex];
70 bool Theme::IsHighContrastMode()
72 const Theme& rTheme (GetCurrentTheme());
73 return rTheme.mbIsHighContrastMode;
76 void Theme::HandleDataChange()
78 Theme& rTheme (GetCurrentTheme());
80 if ( ! rTheme.mbIsHighContrastModeSetManually)
82 // Do not modify mbIsHighContrastMode when it was manually set.
83 GetCurrentTheme().mbIsHighContrastMode = Application::GetSettings().GetStyleSettings().GetHighContrastMode();
84 rTheme.maRawValues[Bool_IsHighContrastModeActive] <<= GetCurrentTheme().mbIsHighContrastMode;
87 GetCurrentTheme().UpdateTheme();
90 void Theme::InitializeTheme()
92 setPropertyValue(
93 maPropertyIdToNameMap[Bool_UseSystemColors],
94 Any(false));
97 void Theme::UpdateTheme()
99 try
101 const StyleSettings& rStyle (Application::GetSettings().GetStyleSettings());
103 Color aBaseBackgroundColor (rStyle.GetDialogColor());
104 // UX says this should be a little brighter, but that looks off when compared to the other windows.
105 //aBaseBackgroundColor.IncreaseLuminance(7);
106 Color aSecondColor (aBaseBackgroundColor);
107 aSecondColor.DecreaseLuminance(15);
109 setPropertyValue(
110 maPropertyIdToNameMap[Color_DeckBackground],
111 Any(sal_Int32(aBaseBackgroundColor.GetRGBColor())));
113 setPropertyValue(
114 maPropertyIdToNameMap[Color_DeckTitleBarBackground],
115 Any(sal_Int32(aBaseBackgroundColor.GetRGBColor())));
116 setPropertyValue(
117 maPropertyIdToNameMap[Int_DeckSeparatorHeight],
118 Any(sal_Int32(1)));
119 setPropertyValue(
120 maPropertyIdToNameMap[Color_PanelBackground],
121 Any(sal_Int32(aBaseBackgroundColor.GetRGBColor())));
123 setPropertyValue(
124 maPropertyIdToNameMap[Color_PanelTitleBarBackground],
125 Any(sal_Int32(aSecondColor.GetRGBColor())));
126 setPropertyValue(
127 maPropertyIdToNameMap[Color_TabBarBackground],
128 Any(sal_Int32(aBaseBackgroundColor.GetRGBColor())));
130 setPropertyValue(
131 maPropertyIdToNameMap[Color_Highlight],
132 Any(sal_Int32(rStyle.GetHighlightColor().GetRGBColor())));
133 setPropertyValue(
134 maPropertyIdToNameMap[Color_HighlightText],
135 Any(sal_Int32(rStyle.GetHighlightTextColor().GetRGBColor())));
137 catch(beans::UnknownPropertyException const &)
139 DBG_UNHANDLED_EXCEPTION("sfx", "unknown property");
140 OSL_ASSERT(false);
144 void Theme::disposing(std::unique_lock<std::mutex>&)
146 SolarMutexGuard aGuard;
148 ChangeListeners aListeners;
149 aListeners.swap(maChangeListeners);
151 const lang::EventObject aEvent (getXWeak());
153 for (const auto& rContainer : aListeners)
155 for (const auto& rxListener : rContainer.second)
159 rxListener->disposing(aEvent);
161 catch(const Exception&)
168 Reference<beans::XPropertySet> Theme::GetPropertySet()
170 if (SfxGetpApp())
171 return Reference<beans::XPropertySet>(&GetCurrentTheme());
172 else
173 return Reference<beans::XPropertySet>();
176 Reference<beans::XPropertySetInfo> SAL_CALL Theme::getPropertySetInfo()
178 return Reference<beans::XPropertySetInfo>(this);
181 void SAL_CALL Theme::setPropertyValue (
182 const OUString& rsPropertyName,
183 const css::uno::Any& rValue)
185 SolarMutexGuard aGuard;
187 PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName));
188 if (iId == maPropertyNameToIdMap.end())
189 throw beans::UnknownPropertyException(rsPropertyName);
191 const PropertyType eType (GetPropertyType(iId->second));
192 if (eType == PT_Invalid)
193 throw beans::UnknownPropertyException(rsPropertyName);
195 const ThemeItem eItem (iId->second);
197 if (rValue == maRawValues[eItem])
199 // Value is not different from the one in the property
200 // set => nothing to do.
201 return;
204 const Any aOldValue (maRawValues[eItem]);
206 const beans::PropertyChangeEvent aEvent(
207 getXWeak(),
208 rsPropertyName,
209 false,
210 eItem,
211 aOldValue,
212 rValue);
214 if (DoVetoableListenersVeto(GetVetoableListeners(AnyItem_, false), aEvent))
215 return;
216 if (DoVetoableListenersVeto(GetVetoableListeners(eItem, false), aEvent))
217 return;
219 maRawValues[eItem] = rValue;
220 ProcessNewValue(rValue, eItem, eType);
222 BroadcastPropertyChange(GetChangeListeners(AnyItem_, false), aEvent);
223 BroadcastPropertyChange(GetChangeListeners(eItem, false), aEvent);
226 Any SAL_CALL Theme::getPropertyValue (
227 const OUString& rsPropertyName)
229 SolarMutexGuard aGuard;
231 PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName));
232 if (iId == maPropertyNameToIdMap.end())
233 throw beans::UnknownPropertyException(rsPropertyName);
235 const PropertyType eType (GetPropertyType(iId->second));
236 if (eType == PT_Invalid)
237 throw beans::UnknownPropertyException(rsPropertyName);
239 const ThemeItem eItem (iId->second);
241 return maRawValues[eItem];
244 void SAL_CALL Theme::addPropertyChangeListener(
245 const OUString& rsPropertyName,
246 const css::uno::Reference<css::beans::XPropertyChangeListener>& rxListener)
248 SolarMutexGuard aGuard;
250 ThemeItem eItem (AnyItem_);
251 if (rsPropertyName.getLength() > 0)
253 PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName));
254 if (iId == maPropertyNameToIdMap.end())
255 throw beans::UnknownPropertyException(rsPropertyName);
257 const PropertyType eType (GetPropertyType(iId->second));
258 if (eType == PT_Invalid)
259 throw beans::UnknownPropertyException(rsPropertyName);
261 eItem = iId->second;
263 ChangeListenerContainer* pListeners = GetChangeListeners(eItem, true);
264 if (pListeners != nullptr)
265 pListeners->push_back(rxListener);
268 void SAL_CALL Theme::removePropertyChangeListener(
269 const OUString& rsPropertyName,
270 const css::uno::Reference<css::beans::XPropertyChangeListener>& rxListener)
272 SolarMutexGuard aGuard;
274 ThemeItem eItem (AnyItem_);
275 if (rsPropertyName.getLength() > 0)
277 PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName));
278 if (iId == maPropertyNameToIdMap.end())
279 throw beans::UnknownPropertyException(rsPropertyName);
281 const PropertyType eType (GetPropertyType(iId->second));
282 if (eType == PT_Invalid)
283 throw beans::UnknownPropertyException(rsPropertyName);
285 eItem = iId->second;
287 ChangeListenerContainer* pContainer = GetChangeListeners(eItem, false);
288 if (pContainer != nullptr)
290 ChangeListenerContainer::iterator iListener (::std::find(pContainer->begin(), pContainer->end(), rxListener));
291 if (iListener != pContainer->end())
293 pContainer->erase(iListener);
295 // Remove the listener container when empty.
296 if (pContainer->empty())
297 maChangeListeners.erase(eItem);
302 void SAL_CALL Theme::addVetoableChangeListener(
303 const OUString& rsPropertyName,
304 const css::uno::Reference<css::beans::XVetoableChangeListener>& rxListener)
306 SolarMutexGuard aGuard;
308 ThemeItem eItem (AnyItem_);
309 if (rsPropertyName.getLength() > 0)
311 PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName));
312 if (iId == maPropertyNameToIdMap.end())
313 throw beans::UnknownPropertyException(rsPropertyName);
315 const PropertyType eType (GetPropertyType(iId->second));
316 if (eType == PT_Invalid)
317 throw beans::UnknownPropertyException(rsPropertyName);
319 eItem = iId->second;
321 VetoableListenerContainer* pListeners = GetVetoableListeners(eItem, true);
322 if (pListeners != nullptr)
323 pListeners->push_back(rxListener);
326 void SAL_CALL Theme::removeVetoableChangeListener(
327 const OUString& rsPropertyName,
328 const css::uno::Reference<css::beans::XVetoableChangeListener>& rxListener)
330 SolarMutexGuard aGuard;
332 ThemeItem eItem (AnyItem_);
333 if (rsPropertyName.getLength() > 0)
335 PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName));
336 if (iId == maPropertyNameToIdMap.end())
337 throw beans::UnknownPropertyException(rsPropertyName);
339 const PropertyType eType (GetPropertyType(iId->second));
340 if (eType == PT_Invalid)
341 throw beans::UnknownPropertyException(rsPropertyName);
343 eItem = iId->second;
345 VetoableListenerContainer* pContainer = GetVetoableListeners(eItem, false);
346 if (pContainer != nullptr)
348 VetoableListenerContainer::iterator iListener (::std::find(pContainer->begin(), pContainer->end(), rxListener));
349 if (iListener != pContainer->end())
351 pContainer->erase(iListener);
352 // Remove container when empty.
353 if (pContainer->empty())
354 maVetoableListeners.erase(eItem);
359 css::uno::Sequence<css::beans::Property> SAL_CALL Theme::getProperties()
361 SolarMutexGuard aGuard;
363 ::std::vector<beans::Property> aProperties;
365 sal_Int32 const nEnd(End_);
366 for (sal_Int32 nItem(Begin_); nItem!=nEnd; ++nItem)
368 const ThemeItem eItem (static_cast<ThemeItem>(nItem));
369 const PropertyType eType (GetPropertyType(eItem));
370 if (eType == PT_Invalid)
371 continue;
373 const beans::Property aProperty(
374 maPropertyIdToNameMap[eItem],
375 eItem,
376 GetCppuType(eType),
378 aProperties.push_back(aProperty);
381 return css::uno::Sequence<css::beans::Property>(
382 aProperties.data(),
383 aProperties.size());
386 beans::Property SAL_CALL Theme::getPropertyByName (const OUString& rsPropertyName)
388 SolarMutexGuard aGuard;
390 PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName));
391 if (iId == maPropertyNameToIdMap.end())
392 throw beans::UnknownPropertyException(rsPropertyName);
394 const PropertyType eType (GetPropertyType(iId->second));
395 if (eType == PT_Invalid)
396 throw beans::UnknownPropertyException(rsPropertyName);
398 const ThemeItem eItem (iId->second);
400 return beans::Property(
401 rsPropertyName,
402 eItem,
403 GetCppuType(eType),
407 sal_Bool SAL_CALL Theme::hasPropertyByName (const OUString& rsPropertyName)
409 SolarMutexGuard aGuard;
411 PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName));
412 if (iId == maPropertyNameToIdMap.end())
413 return false;
415 const PropertyType eType (GetPropertyType(iId->second));
416 if (eType == PT_Invalid)
417 return false;
419 return true;
422 void Theme::SetupPropertyMaps()
424 maPropertyIdToNameMap.resize(Post_Bool_);
425 maColors.resize(Color_Int_ - Pre_Color_ - 1);
426 maIntegers.resize(Int_Bool_ - Color_Int_ - 1);
427 maBooleans.resize(Post_Bool_ - Int_Bool_ - 1);
429 maPropertyNameToIdMap[u"Color_Highlight"_ustr]=Color_Highlight;
430 maPropertyIdToNameMap[Color_Highlight]="Color_Highlight";
432 maPropertyNameToIdMap[u"Color_HighlightText"_ustr]=Color_HighlightText;
433 maPropertyIdToNameMap[Color_HighlightText]="Color_HighlightText";
436 maPropertyNameToIdMap[u"Color_DeckBackground"_ustr]=Color_DeckBackground;
437 maPropertyIdToNameMap[Color_DeckBackground]="Color_DeckBackground";
439 maPropertyNameToIdMap[u"Color_DeckTitleBarBackground"_ustr]=Color_DeckTitleBarBackground;
440 maPropertyIdToNameMap[Color_DeckTitleBarBackground]="Color_DeckTitleBarBackground";
442 maPropertyNameToIdMap[u"Color_PanelBackground"_ustr]=Color_PanelBackground;
443 maPropertyIdToNameMap[Color_PanelBackground]="Color_PanelBackground";
445 maPropertyNameToIdMap[u"Color_PanelTitleBarBackground"_ustr]=Color_PanelTitleBarBackground;
446 maPropertyIdToNameMap[Color_PanelTitleBarBackground]="Color_PanelTitleBarBackground";
448 maPropertyNameToIdMap[u"Color_TabBarBackground"_ustr]=Color_TabBarBackground;
449 maPropertyIdToNameMap[Color_TabBarBackground]="Color_TabBarBackground";
452 maPropertyNameToIdMap[u"Int_DeckBorderSize"_ustr]=Int_DeckBorderSize;
453 maPropertyIdToNameMap[Int_DeckBorderSize]="Int_DeckBorderSize";
455 maPropertyNameToIdMap[u"Int_DeckSeparatorHeight"_ustr]=Int_DeckSeparatorHeight;
456 maPropertyIdToNameMap[Int_DeckSeparatorHeight]="Int_DeckSeparatorHeight";
458 maPropertyNameToIdMap[u"Int_DeckLeftPadding"_ustr]=Int_DeckLeftPadding;
459 maPropertyIdToNameMap[Int_DeckLeftPadding]="Int_DeckLeftPadding";
461 maPropertyNameToIdMap[u"Int_DeckTopPadding"_ustr]=Int_DeckTopPadding;
462 maPropertyIdToNameMap[Int_DeckTopPadding]="Int_DeckTopPadding";
464 maPropertyNameToIdMap[u"Int_DeckRightPadding"_ustr]=Int_DeckRightPadding;
465 maPropertyIdToNameMap[Int_DeckRightPadding]="Int_DeckRightPadding";
467 maPropertyNameToIdMap[u"Int_DeckBottomPadding"_ustr]=Int_DeckBottomPadding;
468 maPropertyIdToNameMap[Int_DeckBottomPadding]="Int_DeckBottomPadding";
471 maPropertyNameToIdMap[u"Bool_UseSystemColors"_ustr]=Bool_UseSystemColors;
472 maPropertyIdToNameMap[Bool_UseSystemColors]="Bool_UseSystemColors";
474 maPropertyNameToIdMap[u"Bool_IsHighContrastModeActive"_ustr]=Bool_IsHighContrastModeActive;
475 maPropertyIdToNameMap[Bool_IsHighContrastModeActive]="Bool_IsHighContrastModeActive";
477 maRawValues.resize(maPropertyIdToNameMap.size());
480 Theme::PropertyType Theme::GetPropertyType (const ThemeItem eItem)
482 switch(eItem)
484 case Color_Highlight:
485 case Color_HighlightText:
486 case Color_DeckBackground:
487 case Color_DeckTitleBarBackground:
488 case Color_PanelBackground:
489 case Color_PanelTitleBarBackground:
490 case Color_TabBarBackground:
491 return PT_Color;
493 case Int_DeckBorderSize:
494 case Int_DeckSeparatorHeight:
495 case Int_DeckLeftPadding:
496 case Int_DeckTopPadding:
497 case Int_DeckRightPadding:
498 case Int_DeckBottomPadding:
499 return PT_Integer;
501 case Bool_UseSystemColors:
502 case Bool_IsHighContrastModeActive:
503 return PT_Boolean;
505 default:
506 return PT_Invalid;
510 css::uno::Type const & Theme::GetCppuType (const PropertyType eType)
512 switch(eType)
514 case PT_Color:
515 return cppu::UnoType<sal_uInt32>::get();
517 case PT_Integer:
518 return cppu::UnoType<sal_Int32>::get();
520 case PT_Boolean:
521 return cppu::UnoType<sal_Bool>::get();
523 case PT_Invalid:
524 default:
525 return cppu::UnoType<void>::get();
529 sal_Int32 Theme::GetIndex (const ThemeItem eItem, const PropertyType eType)
531 switch(eType)
533 case PT_Color:
534 return eItem - Pre_Color_-1;
535 case PT_Integer:
536 return eItem - Color_Int_-1;
537 case PT_Boolean:
538 return eItem - Int_Bool_-1;
539 default:
540 OSL_ASSERT(false);
541 return 0;
545 Theme::VetoableListenerContainer* Theme::GetVetoableListeners (
546 const ThemeItem eItem,
547 const bool bCreate)
549 VetoableListeners::iterator iContainer (maVetoableListeners.find(eItem));
550 if (iContainer != maVetoableListeners.end())
551 return &iContainer->second;
552 else if (bCreate)
554 maVetoableListeners[eItem] = VetoableListenerContainer();
555 return &maVetoableListeners[eItem];
557 else
558 return nullptr;
561 Theme::ChangeListenerContainer* Theme::GetChangeListeners (
562 const ThemeItem eItem,
563 const bool bCreate)
565 ChangeListeners::iterator iContainer (maChangeListeners.find(eItem));
566 if (iContainer != maChangeListeners.end())
567 return &iContainer->second;
568 else if (bCreate)
570 maChangeListeners[eItem] = ChangeListenerContainer();
571 return &maChangeListeners[eItem];
573 else
574 return nullptr;
577 bool Theme::DoVetoableListenersVeto (
578 const VetoableListenerContainer* pListeners,
579 const beans::PropertyChangeEvent& rEvent)
581 if (pListeners == nullptr)
582 return false;
584 VetoableListenerContainer aListeners (*pListeners);
587 for (const auto& rxListener : aListeners)
589 rxListener->vetoableChange(rEvent);
592 catch(const beans::PropertyVetoException&)
594 return true;
596 catch(const Exception&)
598 // Ignore any other errors (such as disposed listeners).
600 return false;
603 void Theme::BroadcastPropertyChange (
604 const ChangeListenerContainer* pListeners,
605 const beans::PropertyChangeEvent& rEvent)
607 if (pListeners == nullptr)
608 return;
610 const ChangeListenerContainer aListeners (*pListeners);
613 for (const auto& rxListener : aListeners)
615 rxListener->propertyChange(rEvent);
618 catch(const Exception&)
620 // Ignore any errors (such as disposed listeners).
624 void Theme::ProcessNewValue (
625 const Any& rValue,
626 const ThemeItem eItem,
627 const PropertyType eType)
629 const sal_Int32 nIndex (GetIndex (eItem, eType));
630 switch (eType)
632 case PT_Color:
634 Color nColorValue;
635 if (rValue >>= nColorValue)
636 maColors[nIndex] = nColorValue;
637 break;
639 case PT_Integer:
641 sal_Int32 nValue (0);
642 if (rValue >>= nValue)
644 maIntegers[nIndex] = nValue;
646 break;
648 case PT_Boolean:
650 bool bValue (false);
651 if (rValue >>= bValue)
653 maBooleans[nIndex] = bValue;
654 if (eItem == Bool_IsHighContrastModeActive)
656 mbIsHighContrastModeSetManually = true;
657 mbIsHighContrastMode = maBooleans[nIndex];
658 HandleDataChange();
660 else if (eItem == Bool_UseSystemColors)
662 HandleDataChange();
665 break;
667 case PT_Invalid:
668 OSL_ASSERT(eType != PT_Invalid);
669 throw RuntimeException();
673 } // end of namespace sfx2::sidebar
675 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */