diff options
Diffstat (limited to '')
-rw-r--r-- | sfx2/source/sidebar/Theme.cxx | 675 |
1 files changed, 675 insertions, 0 deletions
diff --git a/sfx2/source/sidebar/Theme.cxx b/sfx2/source/sidebar/Theme.cxx new file mode 100644 index 000000000..b97587767 --- /dev/null +++ b/sfx2/source/sidebar/Theme.cxx @@ -0,0 +1,675 @@ +/* -*- 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 <sfx2/sidebar/Theme.hxx> +#include <sfx2/app.hxx> + +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <tools/diagnose_ex.h> + +using namespace css; +using namespace css::uno; + +namespace sfx2::sidebar { + +Theme& Theme::GetCurrentTheme() +{ + OSL_ASSERT(SfxGetpApp()); + return SfxGetpApp()->GetSidebarTheme(); +} + +Theme::Theme() + : mbIsHighContrastMode(Application::GetSettings().GetStyleSettings().GetHighContrastMode()), + mbIsHighContrastModeSetManually(false) +{ + SetupPropertyMaps(); +} + +Theme::~Theme() +{ +} + +Color Theme::GetColor (const ThemeItem eItem) +{ + const PropertyType eType (GetPropertyType(eItem)); + OSL_ASSERT(eType==PT_Color); + const sal_Int32 nIndex (GetIndex(eItem, eType)); + const Theme& rTheme (GetCurrentTheme()); + if (eType == PT_Color) + return rTheme.maColors[nIndex]; + else + return COL_WHITE; +} + +sal_Int32 Theme::GetInteger (const ThemeItem eItem) +{ + const PropertyType eType (GetPropertyType(eItem)); + OSL_ASSERT(eType==PT_Integer); + const sal_Int32 nIndex (GetIndex(eItem, eType)); + const Theme& rTheme (GetCurrentTheme()); + return rTheme.maIntegers[nIndex]; +} + +bool Theme::IsHighContrastMode() +{ + const Theme& rTheme (GetCurrentTheme()); + return rTheme.mbIsHighContrastMode; +} + +void Theme::HandleDataChange() +{ + Theme& rTheme (GetCurrentTheme()); + + if ( ! rTheme.mbIsHighContrastModeSetManually) + { + // Do not modify mbIsHighContrastMode when it was manually set. + GetCurrentTheme().mbIsHighContrastMode = Application::GetSettings().GetStyleSettings().GetHighContrastMode(); + rTheme.maRawValues[Bool_IsHighContrastModeActive] <<= GetCurrentTheme().mbIsHighContrastMode; + } + + GetCurrentTheme().UpdateTheme(); +} + +void Theme::InitializeTheme() +{ + setPropertyValue( + maPropertyIdToNameMap[Bool_UseSystemColors], + Any(false)); +} + +void Theme::UpdateTheme() +{ + try + { + const StyleSettings& rStyle (Application::GetSettings().GetStyleSettings()); + + Color aBaseBackgroundColor (rStyle.GetDialogColor()); + // UX says this should be a little brighter, but that looks off when compared to the other windows. + //aBaseBackgroundColor.IncreaseLuminance(7); + Color aSecondColor (aBaseBackgroundColor); + aSecondColor.DecreaseLuminance(15); + + setPropertyValue( + maPropertyIdToNameMap[Color_DeckBackground], + Any(sal_Int32(aBaseBackgroundColor.GetRGBColor()))); + + setPropertyValue( + maPropertyIdToNameMap[Color_DeckTitleBarBackground], + Any(sal_Int32(aBaseBackgroundColor.GetRGBColor()))); + setPropertyValue( + maPropertyIdToNameMap[Int_DeckSeparatorHeight], + Any(sal_Int32(1))); + setPropertyValue( + maPropertyIdToNameMap[Color_PanelBackground], + Any(sal_Int32(aBaseBackgroundColor.GetRGBColor()))); + + setPropertyValue( + maPropertyIdToNameMap[Color_PanelTitleBarBackground], + Any(sal_Int32(aSecondColor.GetRGBColor()))); + setPropertyValue( + maPropertyIdToNameMap[Color_TabBarBackground], + Any(sal_Int32(aBaseBackgroundColor.GetRGBColor()))); + + setPropertyValue( + maPropertyIdToNameMap[Color_Highlight], + Any(sal_Int32(rStyle.GetHighlightColor().GetRGBColor()))); + setPropertyValue( + maPropertyIdToNameMap[Color_HighlightText], + Any(sal_Int32(rStyle.GetHighlightTextColor().GetRGBColor()))); + } + catch(beans::UnknownPropertyException const &) + { + DBG_UNHANDLED_EXCEPTION("sfx", "unknown property"); + OSL_ASSERT(false); + } +} + +void Theme::disposing(std::unique_lock<std::mutex>&) +{ + SolarMutexGuard aGuard; + + ChangeListeners aListeners; + aListeners.swap(maChangeListeners); + + const lang::EventObject aEvent (static_cast<XWeak*>(this)); + + for (const auto& rContainer : aListeners) + { + for (const auto& rxListener : rContainer.second) + { + try + { + rxListener->disposing(aEvent); + } + catch(const Exception&) + { + } + } + } +} + +Reference<beans::XPropertySet> Theme::GetPropertySet() +{ + if (SfxGetpApp()) + return Reference<beans::XPropertySet>(&GetCurrentTheme()); + else + return Reference<beans::XPropertySet>(); +} + +Reference<beans::XPropertySetInfo> SAL_CALL Theme::getPropertySetInfo() +{ + return Reference<beans::XPropertySetInfo>(this); +} + +void SAL_CALL Theme::setPropertyValue ( + const OUString& rsPropertyName, + const css::uno::Any& rValue) +{ + SolarMutexGuard aGuard; + + PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName)); + if (iId == maPropertyNameToIdMap.end()) + throw beans::UnknownPropertyException(rsPropertyName); + + const PropertyType eType (GetPropertyType(iId->second)); + if (eType == PT_Invalid) + throw beans::UnknownPropertyException(rsPropertyName); + + const ThemeItem eItem (iId->second); + + if (rValue == maRawValues[eItem]) + { + // Value is not different from the one in the property + // set => nothing to do. + return; + } + + const Any aOldValue (maRawValues[eItem]); + + const beans::PropertyChangeEvent aEvent( + static_cast<XWeak*>(this), + rsPropertyName, + false, + eItem, + aOldValue, + rValue); + + if (DoVetoableListenersVeto(GetVetoableListeners(AnyItem_, false), aEvent)) + return; + if (DoVetoableListenersVeto(GetVetoableListeners(eItem, false), aEvent)) + return; + + maRawValues[eItem] = rValue; + ProcessNewValue(rValue, eItem, eType); + + BroadcastPropertyChange(GetChangeListeners(AnyItem_, false), aEvent); + BroadcastPropertyChange(GetChangeListeners(eItem, false), aEvent); +} + +Any SAL_CALL Theme::getPropertyValue ( + const OUString& rsPropertyName) +{ + SolarMutexGuard aGuard; + + PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName)); + if (iId == maPropertyNameToIdMap.end()) + throw beans::UnknownPropertyException(rsPropertyName); + + const PropertyType eType (GetPropertyType(iId->second)); + if (eType == PT_Invalid) + throw beans::UnknownPropertyException(rsPropertyName); + + const ThemeItem eItem (iId->second); + + return maRawValues[eItem]; +} + +void SAL_CALL Theme::addPropertyChangeListener( + const OUString& rsPropertyName, + const css::uno::Reference<css::beans::XPropertyChangeListener>& rxListener) +{ + SolarMutexGuard aGuard; + + ThemeItem eItem (AnyItem_); + if (rsPropertyName.getLength() > 0) + { + PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName)); + if (iId == maPropertyNameToIdMap.end()) + throw beans::UnknownPropertyException(rsPropertyName); + + const PropertyType eType (GetPropertyType(iId->second)); + if (eType == PT_Invalid) + throw beans::UnknownPropertyException(rsPropertyName); + + eItem = iId->second; + } + ChangeListenerContainer* pListeners = GetChangeListeners(eItem, true); + if (pListeners != nullptr) + pListeners->push_back(rxListener); +} + +void SAL_CALL Theme::removePropertyChangeListener( + const OUString& rsPropertyName, + const css::uno::Reference<css::beans::XPropertyChangeListener>& rxListener) +{ + SolarMutexGuard aGuard; + + ThemeItem eItem (AnyItem_); + if (rsPropertyName.getLength() > 0) + { + PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName)); + if (iId == maPropertyNameToIdMap.end()) + throw beans::UnknownPropertyException(rsPropertyName); + + const PropertyType eType (GetPropertyType(iId->second)); + if (eType == PT_Invalid) + throw beans::UnknownPropertyException(rsPropertyName); + + eItem = iId->second; + } + ChangeListenerContainer* pContainer = GetChangeListeners(eItem, false); + if (pContainer != nullptr) + { + ChangeListenerContainer::iterator iListener (::std::find(pContainer->begin(), pContainer->end(), rxListener)); + if (iListener != pContainer->end()) + { + pContainer->erase(iListener); + + // Remove the listener container when empty. + if (pContainer->empty()) + maChangeListeners.erase(eItem); + } + } +} + +void SAL_CALL Theme::addVetoableChangeListener( + const OUString& rsPropertyName, + const css::uno::Reference<css::beans::XVetoableChangeListener>& rxListener) +{ + SolarMutexGuard aGuard; + + ThemeItem eItem (AnyItem_); + if (rsPropertyName.getLength() > 0) + { + PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName)); + if (iId == maPropertyNameToIdMap.end()) + throw beans::UnknownPropertyException(rsPropertyName); + + const PropertyType eType (GetPropertyType(iId->second)); + if (eType == PT_Invalid) + throw beans::UnknownPropertyException(rsPropertyName); + + eItem = iId->second; + } + VetoableListenerContainer* pListeners = GetVetoableListeners(eItem, true); + if (pListeners != nullptr) + pListeners->push_back(rxListener); +} + +void SAL_CALL Theme::removeVetoableChangeListener( + const OUString& rsPropertyName, + const css::uno::Reference<css::beans::XVetoableChangeListener>& rxListener) +{ + SolarMutexGuard aGuard; + + ThemeItem eItem (AnyItem_); + if (rsPropertyName.getLength() > 0) + { + PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName)); + if (iId == maPropertyNameToIdMap.end()) + throw beans::UnknownPropertyException(rsPropertyName); + + const PropertyType eType (GetPropertyType(iId->second)); + if (eType == PT_Invalid) + throw beans::UnknownPropertyException(rsPropertyName); + + eItem = iId->second; + } + VetoableListenerContainer* pContainer = GetVetoableListeners(eItem, false); + if (pContainer != nullptr) + { + VetoableListenerContainer::iterator iListener (::std::find(pContainer->begin(), pContainer->end(), rxListener)); + if (iListener != pContainer->end()) + { + pContainer->erase(iListener); + // Remove container when empty. + if (pContainer->empty()) + maVetoableListeners.erase(eItem); + } + } +} + +css::uno::Sequence<css::beans::Property> SAL_CALL Theme::getProperties() +{ + SolarMutexGuard aGuard; + + ::std::vector<beans::Property> aProperties; + + sal_Int32 const nEnd(End_); + for (sal_Int32 nItem(Begin_); nItem!=nEnd; ++nItem) + { + const ThemeItem eItem (static_cast<ThemeItem>(nItem)); + const PropertyType eType (GetPropertyType(eItem)); + if (eType == PT_Invalid) + continue; + + const beans::Property aProperty( + maPropertyIdToNameMap[eItem], + eItem, + GetCppuType(eType), + 0); + aProperties.push_back(aProperty); + } + + return css::uno::Sequence<css::beans::Property>( + aProperties.data(), + aProperties.size()); +} + +beans::Property SAL_CALL Theme::getPropertyByName (const OUString& rsPropertyName) +{ + SolarMutexGuard aGuard; + + PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName)); + if (iId == maPropertyNameToIdMap.end()) + throw beans::UnknownPropertyException(rsPropertyName); + + const PropertyType eType (GetPropertyType(iId->second)); + if (eType == PT_Invalid) + throw beans::UnknownPropertyException(rsPropertyName); + + const ThemeItem eItem (iId->second); + + return beans::Property( + rsPropertyName, + eItem, + GetCppuType(eType), + 0); +} + +sal_Bool SAL_CALL Theme::hasPropertyByName (const OUString& rsPropertyName) +{ + SolarMutexGuard aGuard; + + PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName)); + if (iId == maPropertyNameToIdMap.end()) + return false; + + const PropertyType eType (GetPropertyType(iId->second)); + if (eType == PT_Invalid) + return false; + + return true; +} + +void Theme::SetupPropertyMaps() +{ + maPropertyIdToNameMap.resize(Post_Bool_); + maColors.resize(Color_Int_ - Pre_Color_ - 1); + maIntegers.resize(Int_Bool_ - Color_Int_ - 1); + maBooleans.resize(Post_Bool_ - Int_Bool_ - 1); + + maPropertyNameToIdMap["Color_Highlight"]=Color_Highlight; + maPropertyIdToNameMap[Color_Highlight]="Color_Highlight"; + + maPropertyNameToIdMap["Color_HighlightText"]=Color_HighlightText; + maPropertyIdToNameMap[Color_HighlightText]="Color_HighlightText"; + + + maPropertyNameToIdMap["Color_DeckBackground"]=Color_DeckBackground; + maPropertyIdToNameMap[Color_DeckBackground]="Color_DeckBackground"; + + maPropertyNameToIdMap["Color_DeckTitleBarBackground"]=Color_DeckTitleBarBackground; + maPropertyIdToNameMap[Color_DeckTitleBarBackground]="Color_DeckTitleBarBackground"; + + maPropertyNameToIdMap["Color_PanelBackground"]=Color_PanelBackground; + maPropertyIdToNameMap[Color_PanelBackground]="Color_PanelBackground"; + + maPropertyNameToIdMap["Color_PanelTitleBarBackground"]=Color_PanelTitleBarBackground; + maPropertyIdToNameMap[Color_PanelTitleBarBackground]="Color_PanelTitleBarBackground"; + + maPropertyNameToIdMap["Color_TabBarBackground"]=Color_TabBarBackground; + maPropertyIdToNameMap[Color_TabBarBackground]="Color_TabBarBackground"; + + + maPropertyNameToIdMap["Int_DeckBorderSize"]=Int_DeckBorderSize; + maPropertyIdToNameMap[Int_DeckBorderSize]="Int_DeckBorderSize"; + + maPropertyNameToIdMap["Int_DeckSeparatorHeight"]=Int_DeckSeparatorHeight; + maPropertyIdToNameMap[Int_DeckSeparatorHeight]="Int_DeckSeparatorHeight"; + + maPropertyNameToIdMap["Int_DeckLeftPadding"]=Int_DeckLeftPadding; + maPropertyIdToNameMap[Int_DeckLeftPadding]="Int_DeckLeftPadding"; + + maPropertyNameToIdMap["Int_DeckTopPadding"]=Int_DeckTopPadding; + maPropertyIdToNameMap[Int_DeckTopPadding]="Int_DeckTopPadding"; + + maPropertyNameToIdMap["Int_DeckRightPadding"]=Int_DeckRightPadding; + maPropertyIdToNameMap[Int_DeckRightPadding]="Int_DeckRightPadding"; + + maPropertyNameToIdMap["Int_DeckBottomPadding"]=Int_DeckBottomPadding; + maPropertyIdToNameMap[Int_DeckBottomPadding]="Int_DeckBottomPadding"; + + + maPropertyNameToIdMap["Bool_UseSystemColors"]=Bool_UseSystemColors; + maPropertyIdToNameMap[Bool_UseSystemColors]="Bool_UseSystemColors"; + + maPropertyNameToIdMap["Bool_IsHighContrastModeActive"]=Bool_IsHighContrastModeActive; + maPropertyIdToNameMap[Bool_IsHighContrastModeActive]="Bool_IsHighContrastModeActive"; + + maRawValues.resize(maPropertyIdToNameMap.size()); +} + +Theme::PropertyType Theme::GetPropertyType (const ThemeItem eItem) +{ + switch(eItem) + { + case Color_Highlight: + case Color_HighlightText: + case Color_DeckBackground: + case Color_DeckTitleBarBackground: + case Color_PanelBackground: + case Color_PanelTitleBarBackground: + case Color_TabBarBackground: + return PT_Color; + + case Int_DeckBorderSize: + case Int_DeckSeparatorHeight: + case Int_DeckLeftPadding: + case Int_DeckTopPadding: + case Int_DeckRightPadding: + case Int_DeckBottomPadding: + return PT_Integer; + + case Bool_UseSystemColors: + case Bool_IsHighContrastModeActive: + return PT_Boolean; + + default: + return PT_Invalid; + } +} + +css::uno::Type const & Theme::GetCppuType (const PropertyType eType) +{ + switch(eType) + { + case PT_Color: + return cppu::UnoType<sal_uInt32>::get(); + + case PT_Integer: + return cppu::UnoType<sal_Int32>::get(); + + case PT_Boolean: + return cppu::UnoType<sal_Bool>::get(); + + case PT_Invalid: + default: + return cppu::UnoType<void>::get(); + } +} + +sal_Int32 Theme::GetIndex (const ThemeItem eItem, const PropertyType eType) +{ + switch(eType) + { + case PT_Color: + return eItem - Pre_Color_-1; + case PT_Integer: + return eItem - Color_Int_-1; + case PT_Boolean: + return eItem - Int_Bool_-1; + default: + OSL_ASSERT(false); + return 0; + } +} + +Theme::VetoableListenerContainer* Theme::GetVetoableListeners ( + const ThemeItem eItem, + const bool bCreate) +{ + VetoableListeners::iterator iContainer (maVetoableListeners.find(eItem)); + if (iContainer != maVetoableListeners.end()) + return &iContainer->second; + else if (bCreate) + { + maVetoableListeners[eItem] = VetoableListenerContainer(); + return &maVetoableListeners[eItem]; + } + else + return nullptr; +} + +Theme::ChangeListenerContainer* Theme::GetChangeListeners ( + const ThemeItem eItem, + const bool bCreate) +{ + ChangeListeners::iterator iContainer (maChangeListeners.find(eItem)); + if (iContainer != maChangeListeners.end()) + return &iContainer->second; + else if (bCreate) + { + maChangeListeners[eItem] = ChangeListenerContainer(); + return &maChangeListeners[eItem]; + } + else + return nullptr; +} + +bool Theme::DoVetoableListenersVeto ( + const VetoableListenerContainer* pListeners, + const beans::PropertyChangeEvent& rEvent) +{ + if (pListeners == nullptr) + return false; + + VetoableListenerContainer aListeners (*pListeners); + try + { + for (const auto& rxListener : aListeners) + { + rxListener->vetoableChange(rEvent); + } + } + catch(const beans::PropertyVetoException&) + { + return true; + } + catch(const Exception&) + { + // Ignore any other errors (such as disposed listeners). + } + return false; +} + +void Theme::BroadcastPropertyChange ( + const ChangeListenerContainer* pListeners, + const beans::PropertyChangeEvent& rEvent) +{ + if (pListeners == nullptr) + return; + + const ChangeListenerContainer aListeners (*pListeners); + try + { + for (const auto& rxListener : aListeners) + { + rxListener->propertyChange(rEvent); + } + } + catch(const Exception&) + { + // Ignore any errors (such as disposed listeners). + } +} + +void Theme::ProcessNewValue ( + const Any& rValue, + const ThemeItem eItem, + const PropertyType eType) +{ + const sal_Int32 nIndex (GetIndex (eItem, eType)); + switch (eType) + { + case PT_Color: + { + Color nColorValue; + if (rValue >>= nColorValue) + maColors[nIndex] = nColorValue; + break; + } + case PT_Integer: + { + sal_Int32 nValue (0); + if (rValue >>= nValue) + { + maIntegers[nIndex] = nValue; + } + break; + } + case PT_Boolean: + { + bool bValue (false); + if (rValue >>= bValue) + { + maBooleans[nIndex] = bValue; + if (eItem == Bool_IsHighContrastModeActive) + { + mbIsHighContrastModeSetManually = true; + mbIsHighContrastMode = maBooleans[nIndex]; + HandleDataChange(); + } + else if (eItem == Bool_UseSystemColors) + { + HandleDataChange(); + } + } + break; + } + case PT_Invalid: + OSL_ASSERT(eType != PT_Invalid); + throw RuntimeException(); + } +} + +} // end of namespace sfx2::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |