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 <sidebar/Tools.hxx>
22 #include <sfx2/app.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/settings.hxx>
26 #include <tools/diagnose_ex.h>
29 using namespace css::uno
;
31 namespace sfx2::sidebar
{
33 Theme
& Theme::GetCurrentTheme()
35 OSL_ASSERT(SfxGetpApp());
36 return SfxGetpApp()->GetSidebarTheme();
40 : ThemeInterfaceBase(m_aMutex
),
41 mbIsHighContrastMode(Application::GetSettings().GetStyleSettings().GetHighContrastMode()),
42 mbIsHighContrastModeSetManually(false)
51 Color
Theme::GetColor (const ThemeItem eItem
)
53 const PropertyType
eType (GetPropertyType(eItem
));
54 OSL_ASSERT(eType
==PT_Color
);
55 const sal_Int32
nIndex (GetIndex(eItem
, eType
));
56 const Theme
& rTheme (GetCurrentTheme());
57 if (eType
== PT_Color
)
58 return rTheme
.maColors
[nIndex
];
63 sal_Int32
Theme::GetInteger (const ThemeItem eItem
)
65 const PropertyType
eType (GetPropertyType(eItem
));
66 OSL_ASSERT(eType
==PT_Integer
);
67 const sal_Int32
nIndex (GetIndex(eItem
, eType
));
68 const Theme
& rTheme (GetCurrentTheme());
69 return rTheme
.maIntegers
[nIndex
];
72 bool Theme::IsHighContrastMode()
74 const Theme
& rTheme (GetCurrentTheme());
75 return rTheme
.mbIsHighContrastMode
;
78 void Theme::HandleDataChange()
80 Theme
& rTheme (GetCurrentTheme());
82 if ( ! rTheme
.mbIsHighContrastModeSetManually
)
84 // Do not modify mbIsHighContrastMode when it was manually set.
85 GetCurrentTheme().mbIsHighContrastMode
= Application::GetSettings().GetStyleSettings().GetHighContrastMode();
86 rTheme
.maRawValues
[Bool_IsHighContrastModeActive
] <<= GetCurrentTheme().mbIsHighContrastMode
;
89 GetCurrentTheme().UpdateTheme();
92 void Theme::InitializeTheme()
95 maPropertyIdToNameMap
[Bool_UseSystemColors
],
99 void Theme::UpdateTheme()
103 const StyleSettings
& rStyle (Application::GetSettings().GetStyleSettings());
105 Color
aBaseBackgroundColor (rStyle
.GetDialogColor());
106 // UX says this should be a little brighter, but that looks off when compared to the other windows.
107 //aBaseBackgroundColor.IncreaseLuminance(7);
108 Color
aSecondColor (aBaseBackgroundColor
);
109 aSecondColor
.DecreaseLuminance(15);
112 maPropertyIdToNameMap
[Color_DeckBackground
],
113 Any(sal_Int32(aBaseBackgroundColor
.GetRGBColor())));
116 maPropertyIdToNameMap
[Color_DeckTitleBarBackground
],
117 Any(sal_Int32(aBaseBackgroundColor
.GetRGBColor())));
119 maPropertyIdToNameMap
[Int_DeckSeparatorHeight
],
122 maPropertyIdToNameMap
[Color_PanelBackground
],
123 Any(sal_Int32(aBaseBackgroundColor
.GetRGBColor())));
126 maPropertyIdToNameMap
[Color_PanelTitleBarBackground
],
127 Any(sal_Int32(aSecondColor
.GetRGBColor())));
129 maPropertyIdToNameMap
[Color_TabBarBackground
],
130 Any(sal_Int32(aBaseBackgroundColor
.GetRGBColor())));
133 maPropertyIdToNameMap
[Color_Highlight
],
134 Any(sal_Int32(rStyle
.GetHighlightColor().GetRGBColor())));
136 maPropertyIdToNameMap
[Color_HighlightText
],
137 Any(sal_Int32(rStyle
.GetHighlightTextColor().GetRGBColor())));
139 catch(beans::UnknownPropertyException
const &)
141 DBG_UNHANDLED_EXCEPTION("sfx", "unknown property");
146 void SAL_CALL
Theme::disposing()
148 SolarMutexGuard aGuard
;
150 ChangeListeners aListeners
;
151 aListeners
.swap(maChangeListeners
);
153 const lang::EventObject
aEvent (static_cast<XWeak
*>(this));
155 for (const auto& rContainer
: aListeners
)
157 for (const auto& rxListener
: rContainer
.second
)
161 rxListener
->disposing(aEvent
);
163 catch(const Exception
&)
170 Reference
<beans::XPropertySet
> Theme::GetPropertySet()
173 return Reference
<beans::XPropertySet
>(&GetCurrentTheme());
175 return Reference
<beans::XPropertySet
>();
178 Reference
<beans::XPropertySetInfo
> SAL_CALL
Theme::getPropertySetInfo()
180 return Reference
<beans::XPropertySetInfo
>(this);
183 void SAL_CALL
Theme::setPropertyValue (
184 const OUString
& rsPropertyName
,
185 const css::uno::Any
& rValue
)
187 SolarMutexGuard aGuard
;
189 PropertyNameToIdMap::const_iterator
iId (maPropertyNameToIdMap
.find(rsPropertyName
));
190 if (iId
== maPropertyNameToIdMap
.end())
191 throw beans::UnknownPropertyException(rsPropertyName
);
193 const PropertyType
eType (GetPropertyType(iId
->second
));
194 if (eType
== PT_Invalid
)
195 throw beans::UnknownPropertyException(rsPropertyName
);
197 const ThemeItem
eItem (iId
->second
);
199 if (rValue
== maRawValues
[eItem
])
201 // Value is not different from the one in the property
202 // set => nothing to do.
206 const Any
aOldValue (maRawValues
[eItem
]);
208 const beans::PropertyChangeEvent
aEvent(
209 static_cast<XWeak
*>(this),
216 if (DoVetoableListenersVeto(GetVetoableListeners(AnyItem_
, false), aEvent
))
218 if (DoVetoableListenersVeto(GetVetoableListeners(eItem
, false), aEvent
))
221 maRawValues
[eItem
] = rValue
;
222 ProcessNewValue(rValue
, eItem
, eType
);
224 BroadcastPropertyChange(GetChangeListeners(AnyItem_
, false), aEvent
);
225 BroadcastPropertyChange(GetChangeListeners(eItem
, false), aEvent
);
228 Any SAL_CALL
Theme::getPropertyValue (
229 const OUString
& rsPropertyName
)
231 SolarMutexGuard aGuard
;
233 PropertyNameToIdMap::const_iterator
iId (maPropertyNameToIdMap
.find(rsPropertyName
));
234 if (iId
== maPropertyNameToIdMap
.end())
235 throw beans::UnknownPropertyException(rsPropertyName
);
237 const PropertyType
eType (GetPropertyType(iId
->second
));
238 if (eType
== PT_Invalid
)
239 throw beans::UnknownPropertyException(rsPropertyName
);
241 const ThemeItem
eItem (iId
->second
);
243 return maRawValues
[eItem
];
246 void SAL_CALL
Theme::addPropertyChangeListener(
247 const OUString
& rsPropertyName
,
248 const css::uno::Reference
<css::beans::XPropertyChangeListener
>& rxListener
)
250 SolarMutexGuard aGuard
;
252 ThemeItem
eItem (AnyItem_
);
253 if (rsPropertyName
.getLength() > 0)
255 PropertyNameToIdMap::const_iterator
iId (maPropertyNameToIdMap
.find(rsPropertyName
));
256 if (iId
== maPropertyNameToIdMap
.end())
257 throw beans::UnknownPropertyException(rsPropertyName
);
259 const PropertyType
eType (GetPropertyType(iId
->second
));
260 if (eType
== PT_Invalid
)
261 throw beans::UnknownPropertyException(rsPropertyName
);
265 ChangeListenerContainer
* pListeners
= GetChangeListeners(eItem
, true);
266 if (pListeners
!= nullptr)
267 pListeners
->push_back(rxListener
);
270 void SAL_CALL
Theme::removePropertyChangeListener(
271 const OUString
& rsPropertyName
,
272 const css::uno::Reference
<css::beans::XPropertyChangeListener
>& rxListener
)
274 SolarMutexGuard aGuard
;
276 ThemeItem
eItem (AnyItem_
);
277 if (rsPropertyName
.getLength() > 0)
279 PropertyNameToIdMap::const_iterator
iId (maPropertyNameToIdMap
.find(rsPropertyName
));
280 if (iId
== maPropertyNameToIdMap
.end())
281 throw beans::UnknownPropertyException(rsPropertyName
);
283 const PropertyType
eType (GetPropertyType(iId
->second
));
284 if (eType
== PT_Invalid
)
285 throw beans::UnknownPropertyException(rsPropertyName
);
289 ChangeListenerContainer
* pContainer
= GetChangeListeners(eItem
, false);
290 if (pContainer
!= nullptr)
292 ChangeListenerContainer::iterator
iListener (::std::find(pContainer
->begin(), pContainer
->end(), rxListener
));
293 if (iListener
!= pContainer
->end())
295 pContainer
->erase(iListener
);
297 // Remove the listener container when empty.
298 if (pContainer
->empty())
299 maChangeListeners
.erase(eItem
);
304 void SAL_CALL
Theme::addVetoableChangeListener(
305 const OUString
& rsPropertyName
,
306 const css::uno::Reference
<css::beans::XVetoableChangeListener
>& rxListener
)
308 SolarMutexGuard aGuard
;
310 ThemeItem
eItem (AnyItem_
);
311 if (rsPropertyName
.getLength() > 0)
313 PropertyNameToIdMap::const_iterator
iId (maPropertyNameToIdMap
.find(rsPropertyName
));
314 if (iId
== maPropertyNameToIdMap
.end())
315 throw beans::UnknownPropertyException(rsPropertyName
);
317 const PropertyType
eType (GetPropertyType(iId
->second
));
318 if (eType
== PT_Invalid
)
319 throw beans::UnknownPropertyException(rsPropertyName
);
323 VetoableListenerContainer
* pListeners
= GetVetoableListeners(eItem
, true);
324 if (pListeners
!= nullptr)
325 pListeners
->push_back(rxListener
);
328 void SAL_CALL
Theme::removeVetoableChangeListener(
329 const OUString
& rsPropertyName
,
330 const css::uno::Reference
<css::beans::XVetoableChangeListener
>& rxListener
)
332 SolarMutexGuard aGuard
;
334 ThemeItem
eItem (AnyItem_
);
335 if (rsPropertyName
.getLength() > 0)
337 PropertyNameToIdMap::const_iterator
iId (maPropertyNameToIdMap
.find(rsPropertyName
));
338 if (iId
== maPropertyNameToIdMap
.end())
339 throw beans::UnknownPropertyException(rsPropertyName
);
341 const PropertyType
eType (GetPropertyType(iId
->second
));
342 if (eType
== PT_Invalid
)
343 throw beans::UnknownPropertyException(rsPropertyName
);
347 VetoableListenerContainer
* pContainer
= GetVetoableListeners(eItem
, false);
348 if (pContainer
!= nullptr)
350 VetoableListenerContainer::iterator
iListener (::std::find(pContainer
->begin(), pContainer
->end(), rxListener
));
351 if (iListener
!= pContainer
->end())
353 pContainer
->erase(iListener
);
354 // Remove container when empty.
355 if (pContainer
->empty())
356 maVetoableListeners
.erase(eItem
);
361 css::uno::Sequence
<css::beans::Property
> SAL_CALL
Theme::getProperties()
363 SolarMutexGuard aGuard
;
365 ::std::vector
<beans::Property
> aProperties
;
367 sal_Int32
const nEnd(End_
);
368 for (sal_Int32
nItem(Begin_
); nItem
!=nEnd
; ++nItem
)
370 const ThemeItem
eItem (static_cast<ThemeItem
>(nItem
));
371 const PropertyType
eType (GetPropertyType(eItem
));
372 if (eType
== PT_Invalid
)
375 const beans::Property
aProperty(
376 maPropertyIdToNameMap
[eItem
],
380 aProperties
.push_back(aProperty
);
383 return css::uno::Sequence
<css::beans::Property
>(
388 beans::Property SAL_CALL
Theme::getPropertyByName (const OUString
& rsPropertyName
)
390 SolarMutexGuard aGuard
;
392 PropertyNameToIdMap::const_iterator
iId (maPropertyNameToIdMap
.find(rsPropertyName
));
393 if (iId
== maPropertyNameToIdMap
.end())
394 throw beans::UnknownPropertyException(rsPropertyName
);
396 const PropertyType
eType (GetPropertyType(iId
->second
));
397 if (eType
== PT_Invalid
)
398 throw beans::UnknownPropertyException(rsPropertyName
);
400 const ThemeItem
eItem (iId
->second
);
402 return beans::Property(
409 sal_Bool SAL_CALL
Theme::hasPropertyByName (const OUString
& rsPropertyName
)
411 SolarMutexGuard aGuard
;
413 PropertyNameToIdMap::const_iterator
iId (maPropertyNameToIdMap
.find(rsPropertyName
));
414 if (iId
== maPropertyNameToIdMap
.end())
417 const PropertyType
eType (GetPropertyType(iId
->second
));
418 if (eType
== PT_Invalid
)
424 void Theme::SetupPropertyMaps()
426 maPropertyIdToNameMap
.resize(Post_Bool_
);
427 maColors
.resize(Color_Int_
- Pre_Color_
- 1);
428 maIntegers
.resize(Int_Bool_
- Color_Int_
- 1);
429 maBooleans
.resize(Post_Bool_
- Int_Bool_
- 1);
431 maPropertyNameToIdMap
["Color_Highlight"]=Color_Highlight
;
432 maPropertyIdToNameMap
[Color_Highlight
]="Color_Highlight";
434 maPropertyNameToIdMap
["Color_HighlightText"]=Color_HighlightText
;
435 maPropertyIdToNameMap
[Color_HighlightText
]="Color_HighlightText";
438 maPropertyNameToIdMap
["Color_DeckBackground"]=Color_DeckBackground
;
439 maPropertyIdToNameMap
[Color_DeckBackground
]="Color_DeckBackground";
441 maPropertyNameToIdMap
["Color_DeckTitleBarBackground"]=Color_DeckTitleBarBackground
;
442 maPropertyIdToNameMap
[Color_DeckTitleBarBackground
]="Color_DeckTitleBarBackground";
444 maPropertyNameToIdMap
["Color_PanelBackground"]=Color_PanelBackground
;
445 maPropertyIdToNameMap
[Color_PanelBackground
]="Color_PanelBackground";
447 maPropertyNameToIdMap
["Color_PanelTitleBarBackground"]=Color_PanelTitleBarBackground
;
448 maPropertyIdToNameMap
[Color_PanelTitleBarBackground
]="Color_PanelTitleBarBackground";
450 maPropertyNameToIdMap
["Color_TabBarBackground"]=Color_TabBarBackground
;
451 maPropertyIdToNameMap
[Color_TabBarBackground
]="Color_TabBarBackground";
454 maPropertyNameToIdMap
["Int_DeckBorderSize"]=Int_DeckBorderSize
;
455 maPropertyIdToNameMap
[Int_DeckBorderSize
]="Int_DeckBorderSize";
457 maPropertyNameToIdMap
["Int_DeckSeparatorHeight"]=Int_DeckSeparatorHeight
;
458 maPropertyIdToNameMap
[Int_DeckSeparatorHeight
]="Int_DeckSeparatorHeight";
460 maPropertyNameToIdMap
["Int_DeckLeftPadding"]=Int_DeckLeftPadding
;
461 maPropertyIdToNameMap
[Int_DeckLeftPadding
]="Int_DeckLeftPadding";
463 maPropertyNameToIdMap
["Int_DeckTopPadding"]=Int_DeckTopPadding
;
464 maPropertyIdToNameMap
[Int_DeckTopPadding
]="Int_DeckTopPadding";
466 maPropertyNameToIdMap
["Int_DeckRightPadding"]=Int_DeckRightPadding
;
467 maPropertyIdToNameMap
[Int_DeckRightPadding
]="Int_DeckRightPadding";
469 maPropertyNameToIdMap
["Int_DeckBottomPadding"]=Int_DeckBottomPadding
;
470 maPropertyIdToNameMap
[Int_DeckBottomPadding
]="Int_DeckBottomPadding";
473 maPropertyNameToIdMap
["Bool_UseSystemColors"]=Bool_UseSystemColors
;
474 maPropertyIdToNameMap
[Bool_UseSystemColors
]="Bool_UseSystemColors";
476 maPropertyNameToIdMap
["Bool_IsHighContrastModeActive"]=Bool_IsHighContrastModeActive
;
477 maPropertyIdToNameMap
[Bool_IsHighContrastModeActive
]="Bool_IsHighContrastModeActive";
479 maRawValues
.resize(maPropertyIdToNameMap
.size());
482 Theme::PropertyType
Theme::GetPropertyType (const ThemeItem eItem
)
486 case Color_Highlight
:
487 case Color_HighlightText
:
488 case Color_DeckBackground
:
489 case Color_DeckTitleBarBackground
:
490 case Color_PanelBackground
:
491 case Color_PanelTitleBarBackground
:
492 case Color_TabBarBackground
:
495 case Int_DeckBorderSize
:
496 case Int_DeckSeparatorHeight
:
497 case Int_DeckLeftPadding
:
498 case Int_DeckTopPadding
:
499 case Int_DeckRightPadding
:
500 case Int_DeckBottomPadding
:
503 case Bool_UseSystemColors
:
504 case Bool_IsHighContrastModeActive
:
512 css::uno::Type
const & Theme::GetCppuType (const PropertyType eType
)
517 return cppu::UnoType
<sal_uInt32
>::get();
520 return cppu::UnoType
<sal_Int32
>::get();
523 return cppu::UnoType
<sal_Bool
>::get();
527 return cppu::UnoType
<void>::get();
531 sal_Int32
Theme::GetIndex (const ThemeItem eItem
, const PropertyType eType
)
536 return eItem
- Pre_Color_
-1;
538 return eItem
- Color_Int_
-1;
540 return eItem
- Int_Bool_
-1;
547 Theme::VetoableListenerContainer
* Theme::GetVetoableListeners (
548 const ThemeItem eItem
,
551 VetoableListeners::iterator
iContainer (maVetoableListeners
.find(eItem
));
552 if (iContainer
!= maVetoableListeners
.end())
553 return &iContainer
->second
;
556 maVetoableListeners
[eItem
] = VetoableListenerContainer();
557 return &maVetoableListeners
[eItem
];
563 Theme::ChangeListenerContainer
* Theme::GetChangeListeners (
564 const ThemeItem eItem
,
567 ChangeListeners::iterator
iContainer (maChangeListeners
.find(eItem
));
568 if (iContainer
!= maChangeListeners
.end())
569 return &iContainer
->second
;
572 maChangeListeners
[eItem
] = ChangeListenerContainer();
573 return &maChangeListeners
[eItem
];
579 bool Theme::DoVetoableListenersVeto (
580 const VetoableListenerContainer
* pListeners
,
581 const beans::PropertyChangeEvent
& rEvent
)
583 if (pListeners
== nullptr)
586 VetoableListenerContainer
aListeners (*pListeners
);
589 for (const auto& rxListener
: aListeners
)
591 rxListener
->vetoableChange(rEvent
);
594 catch(const beans::PropertyVetoException
&)
598 catch(const Exception
&)
600 // Ignore any other errors (such as disposed listeners).
605 void Theme::BroadcastPropertyChange (
606 const ChangeListenerContainer
* pListeners
,
607 const beans::PropertyChangeEvent
& rEvent
)
609 if (pListeners
== nullptr)
612 const ChangeListenerContainer
aListeners (*pListeners
);
615 for (const auto& rxListener
: aListeners
)
617 rxListener
->propertyChange(rEvent
);
620 catch(const Exception
&)
622 // Ignore any errors (such as disposed listeners).
626 void Theme::ProcessNewValue (
628 const ThemeItem eItem
,
629 const PropertyType eType
)
631 const sal_Int32
nIndex (GetIndex (eItem
, eType
));
637 if (rValue
>>= nColorValue
)
638 maColors
[nIndex
] = nColorValue
;
643 sal_Int32
nValue (0);
644 if (rValue
>>= nValue
)
646 maIntegers
[nIndex
] = nValue
;
653 if (rValue
>>= bValue
)
655 maBooleans
[nIndex
] = bValue
;
656 if (eItem
== Bool_IsHighContrastModeActive
)
658 mbIsHighContrastModeSetManually
= true;
659 mbIsHighContrastMode
= maBooleans
[nIndex
];
662 else if (eItem
== Bool_UseSystemColors
)
670 OSL_ASSERT(eType
!= PT_Invalid
);
671 throw RuntimeException();
675 } // end of namespace sfx2::sidebar
677 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */