1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
28 using namespace css::uno
;
30 namespace sfx2::sidebar
{
32 Theme
& Theme::GetCurrentTheme()
34 OSL_ASSERT(SfxGetpApp());
35 return SfxGetpApp()->GetSidebarTheme();
39 : mbIsHighContrastMode(Application::GetSettings().GetStyleSettings().GetHighContrastMode()),
40 mbIsHighContrastModeSetManually(false)
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
];
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()
93 maPropertyIdToNameMap
[Bool_UseSystemColors
],
97 void Theme::UpdateTheme()
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);
110 maPropertyIdToNameMap
[Color_DeckBackground
],
111 Any(sal_Int32(aBaseBackgroundColor
.GetRGBColor())));
114 maPropertyIdToNameMap
[Color_DeckTitleBarBackground
],
115 Any(sal_Int32(aBaseBackgroundColor
.GetRGBColor())));
117 maPropertyIdToNameMap
[Int_DeckSeparatorHeight
],
120 maPropertyIdToNameMap
[Color_PanelBackground
],
121 Any(sal_Int32(aBaseBackgroundColor
.GetRGBColor())));
124 maPropertyIdToNameMap
[Color_PanelTitleBarBackground
],
125 Any(sal_Int32(aSecondColor
.GetRGBColor())));
127 maPropertyIdToNameMap
[Color_TabBarBackground
],
128 Any(sal_Int32(aBaseBackgroundColor
.GetRGBColor())));
131 maPropertyIdToNameMap
[Color_Highlight
],
132 Any(sal_Int32(rStyle
.GetHighlightColor().GetRGBColor())));
134 maPropertyIdToNameMap
[Color_HighlightText
],
135 Any(sal_Int32(rStyle
.GetHighlightTextColor().GetRGBColor())));
137 catch(beans::UnknownPropertyException
const &)
139 DBG_UNHANDLED_EXCEPTION("sfx", "unknown property");
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()
171 return Reference
<beans::XPropertySet
>(&GetCurrentTheme());
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.
204 const Any
aOldValue (maRawValues
[eItem
]);
206 const beans::PropertyChangeEvent
aEvent(
214 if (DoVetoableListenersVeto(GetVetoableListeners(AnyItem_
, false), aEvent
))
216 if (DoVetoableListenersVeto(GetVetoableListeners(eItem
, false), aEvent
))
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
);
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
);
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
);
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
);
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
)
373 const beans::Property
aProperty(
374 maPropertyIdToNameMap
[eItem
],
378 aProperties
.push_back(aProperty
);
381 return css::uno::Sequence
<css::beans::Property
>(
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(
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())
415 const PropertyType
eType (GetPropertyType(iId
->second
));
416 if (eType
== PT_Invalid
)
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
)
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
:
493 case Int_DeckBorderSize
:
494 case Int_DeckSeparatorHeight
:
495 case Int_DeckLeftPadding
:
496 case Int_DeckTopPadding
:
497 case Int_DeckRightPadding
:
498 case Int_DeckBottomPadding
:
501 case Bool_UseSystemColors
:
502 case Bool_IsHighContrastModeActive
:
510 css::uno::Type
const & Theme::GetCppuType (const PropertyType eType
)
515 return cppu::UnoType
<sal_uInt32
>::get();
518 return cppu::UnoType
<sal_Int32
>::get();
521 return cppu::UnoType
<sal_Bool
>::get();
525 return cppu::UnoType
<void>::get();
529 sal_Int32
Theme::GetIndex (const ThemeItem eItem
, const PropertyType eType
)
534 return eItem
- Pre_Color_
-1;
536 return eItem
- Color_Int_
-1;
538 return eItem
- Int_Bool_
-1;
545 Theme::VetoableListenerContainer
* Theme::GetVetoableListeners (
546 const ThemeItem eItem
,
549 VetoableListeners::iterator
iContainer (maVetoableListeners
.find(eItem
));
550 if (iContainer
!= maVetoableListeners
.end())
551 return &iContainer
->second
;
554 maVetoableListeners
[eItem
] = VetoableListenerContainer();
555 return &maVetoableListeners
[eItem
];
561 Theme::ChangeListenerContainer
* Theme::GetChangeListeners (
562 const ThemeItem eItem
,
565 ChangeListeners::iterator
iContainer (maChangeListeners
.find(eItem
));
566 if (iContainer
!= maChangeListeners
.end())
567 return &iContainer
->second
;
570 maChangeListeners
[eItem
] = ChangeListenerContainer();
571 return &maChangeListeners
[eItem
];
577 bool Theme::DoVetoableListenersVeto (
578 const VetoableListenerContainer
* pListeners
,
579 const beans::PropertyChangeEvent
& rEvent
)
581 if (pListeners
== nullptr)
584 VetoableListenerContainer
aListeners (*pListeners
);
587 for (const auto& rxListener
: aListeners
)
589 rxListener
->vetoableChange(rEvent
);
592 catch(const beans::PropertyVetoException
&)
596 catch(const Exception
&)
598 // Ignore any other errors (such as disposed listeners).
603 void Theme::BroadcastPropertyChange (
604 const ChangeListenerContainer
* pListeners
,
605 const beans::PropertyChangeEvent
& rEvent
)
607 if (pListeners
== nullptr)
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 (
626 const ThemeItem eItem
,
627 const PropertyType eType
)
629 const sal_Int32
nIndex (GetIndex (eItem
, eType
));
635 if (rValue
>>= nColorValue
)
636 maColors
[nIndex
] = nColorValue
;
641 sal_Int32
nValue (0);
642 if (rValue
>>= nValue
)
644 maIntegers
[nIndex
] = nValue
;
651 if (rValue
>>= bValue
)
653 maBooleans
[nIndex
] = bValue
;
654 if (eItem
== Bool_IsHighContrastModeActive
)
656 mbIsHighContrastModeSetManually
= true;
657 mbIsHighContrastMode
= maBooleans
[nIndex
];
660 else if (eItem
== Bool_UseSystemColors
)
668 OSL_ASSERT(eType
!= PT_Invalid
);
669 throw RuntimeException();
673 } // end of namespace sfx2::sidebar
675 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */