/* -*- 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 <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
#include <com/sun/star/style/XStyle.hpp>
#include <com/sun/star/table/BorderLine.hpp>
#include <com/sun/star/text/XTextColumns.hpp>
#include <o3tl/string_view.hxx>
#include <osl/mutex.hxx>
#include <vcl/svapp.hxx>
#include <cppuhelper/exc_hlp.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <editeng/eeitem.hxx>
#include <editeng/fhgtitem.hxx>
#include <editeng/ulspitem.hxx>
#include <svl/hint.hxx>
#include <svl/intitem.hxx>
#include <svl/itemset.hxx>
#include <svx/xflbmtit.hxx>
#include <svx/xflbstit.hxx>
#include <svx/xlnclit.hxx>
#include <editeng/bulletitem.hxx>
#include <editeng/lrspitem.hxx>
#include <svx/unoshprp.hxx>
#include <svx/unoshape.hxx>
#include <svx/svdpool.hxx>
#include <svx/sdmetitm.hxx>
#include <svx/sdtaaitm.hxx>
#include <svx/sdtacitm.hxx>
#include <svx/sdtayitm.hxx>
#include <svx/sdtaiitm.hxx>
#include <svx/SvxXTextColumns.hxx>
#include <svx/xit.hxx>
#include <svx/xflclit.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <stlsheet.hxx>
#include <sdresid.hxx>
#include <sdpage.hxx>
#include <drawdoc.hxx>
#include <stlpool.hxx>
#include <strings.hrc>
#include <app.hrc>
#include <strings.hxx>
#include <glob.hxx>
#include <DrawViewShell.hxx>
#include <ViewShellBase.hxx>
#include <cstddef>
#include <memory>
#include <string_view>
using ::osl::MutexGuard;
using ::com::sun::star::table::BorderLine;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::style;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::drawing;
#define WID_STYLE_HIDDEN 7997
#define WID_STYLE_DISPNAME 7998
#define WID_STYLE_FAMILY 7999
static SvxItemPropertySet& GetStylePropertySet()
{
static const SfxItemPropertyMapEntry aFullPropertyMap_Impl[] =
{
{ u"Family"_ustr, WID_STYLE_FAMILY, ::cppu::UnoType<OUString>::get(), PropertyAttribute::READONLY, 0},
{ u"UserDefinedAttributes"_ustr, SDRATTR_XMLATTRIBUTES, cppu::UnoType<XNameContainer>::get(), 0, 0},
{ u"DisplayName"_ustr, WID_STYLE_DISPNAME, ::cppu::UnoType<OUString>::get(), PropertyAttribute::READONLY, 0},
{ u"Hidden"_ustr, WID_STYLE_HIDDEN, cppu::UnoType<bool>::get(), 0, 0},
SVX_UNOEDIT_NUMBERING_PROPERTY,
SHADOW_PROPERTIES
LINE_PROPERTIES
LINE_PROPERTIES_START_END
FILL_PROPERTIES
EDGERADIUS_PROPERTIES
TEXT_PROPERTIES_DEFAULTS
CONNECTOR_PROPERTIES
SPECIAL_DIMENSIONING_PROPERTIES_DEFAULTS
{ u"TopBorder"_ustr, SDRATTR_TABLE_BORDER, ::cppu::UnoType<BorderLine>::get(), 0, TOP_BORDER },
{ u"BottomBorder"_ustr, SDRATTR_TABLE_BORDER, ::cppu::UnoType<BorderLine>::get(), 0, BOTTOM_BORDER },
{ u"LeftBorder"_ustr, SDRATTR_TABLE_BORDER, ::cppu::UnoType<BorderLine>::get(), 0, LEFT_BORDER },
{ u"RightBorder"_ustr, SDRATTR_TABLE_BORDER, ::cppu::UnoType<BorderLine>::get(), 0, RIGHT_BORDER },
};
static SvxItemPropertySet aPropSet( aFullPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool() );
return aPropSet;
}
class ModifyListenerForwarder : public SfxListener
{
public:
explicit ModifyListenerForwarder( SdStyleSheet* pStyleSheet );
virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override;
private:
SdStyleSheet* mpStyleSheet;
};
ModifyListenerForwarder::ModifyListenerForwarder( SdStyleSheet* pStyleSheet )
: mpStyleSheet( pStyleSheet )
{
if( pStyleSheet )
{
SfxBroadcaster& rBC = static_cast< SfxBroadcaster& >( *pStyleSheet );
StartListening( rBC );
}
}
void ModifyListenerForwarder::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& /*rHint*/)
{
if( mpStyleSheet )
mpStyleSheet->notifyModifyListener();
}
SdStyleSheet::SdStyleSheet(const OUString& rDisplayName, SfxStyleSheetBasePool& _rPool,
SfxStyleFamily eFamily,
SfxStyleSearchBits _nMask,
const OUString& rParentStyleSheetName)
: SdStyleSheetBase( rDisplayName, _rPool, eFamily, _nMask, rParentStyleSheetName)
, msApiName( rDisplayName )
, mxPool( &_rPool )
{
}
SdStyleSheet::~SdStyleSheet()
{
// restore reference count, prevent double-delete from calling dispose
osl_atomic_increment( &m_refCount );
dispose();
delete pSet;
pSet = nullptr; // that following destructors also get a change
}
void SdStyleSheet::SetApiName( const OUString& rApiName )
{
msApiName = rApiName;
}
OUString const & SdStyleSheet::GetApiName() const
{
if( !msApiName.isEmpty() )
return msApiName;
else
return GetName();
}
bool SdStyleSheet::SetParent(const OUString& rParentName)
{
bool bResult = false;
if (SfxStyleSheet::SetParent(rParentName))
{
// PseudoStyleSheets do not have their own ItemSets
if (nFamily != SfxStyleFamily::Pseudo)
{
if( !rParentName.isEmpty() )
{
SfxStyleSheetBase* pStyle = m_pPool->Find(rParentName, nFamily);
if (pStyle)
{
bResult = true;
SfxItemSet& rParentSet = pStyle->GetItemSet();
GetItemSet().SetParent(&rParentSet);
Broadcast( SfxHint( SfxHintId::DataChanged ) );
}
}
else
{
bResult = true;
GetItemSet().SetParent(nullptr);
Broadcast( SfxHint( SfxHintId::DataChanged ) );
}
}
else
{
bResult = true;
}
}
return bResult;
}
/**
* create if necessary and return ItemSets
*/
SfxItemSet& SdStyleSheet::GetItemSet()
{
if (nFamily == SfxStyleFamily::Para || nFamily == SfxStyleFamily::Page)
{
// we create the ItemSet 'on demand' if necessary
if (!pSet)
{
pSet = new SfxItemSetFixed<
XATTR_LINE_FIRST, XATTR_LINE_LAST,
XATTR_FILL_FIRST, XATTR_FILL_LAST,
SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST,
SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_WORDWRAP,
SDRATTR_EDGE_FIRST, SDRATTR_MEASURE_LAST,
SDRATTR_3D_FIRST, SDRATTR_3D_LAST,
EE_PARA_START, EE_CHAR_END>(GetPool()->GetPool());
bMySet = true;
}
return *pSet;
}
else if( nFamily == SfxStyleFamily::Frame )
{
if (!pSet)
{
pSet = new SfxItemSetFixed<
XATTR_LINE_FIRST, XATTR_LINE_LAST,
XATTR_FILL_FIRST, XATTR_FILL_LAST,
SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST,
SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_XMLATTRIBUTES,
SDRATTR_TEXT_WORDWRAP, SDRATTR_TEXT_WORDWRAP,
SDRATTR_TABLE_FIRST, SDRATTR_TABLE_LAST,
EE_PARA_START, EE_CHAR_END>(GetPool()->GetPool());
bMySet = true;
}
return *pSet;
}
// this is a dummy template for the internal template of the
// current presentation layout; return the ItemSet of that template
else
{
SdStyleSheet* pSdSheet = GetRealStyleSheet();
if (pSdSheet)
{
return pSdSheet->GetItemSet();
}
else
{
if (!pSet)
{
pSet = new SfxItemSetFixed<
XATTR_LINE_FIRST, XATTR_LINE_LAST,
XATTR_FILL_FIRST, XATTR_FILL_LAST,
SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST,
SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_WORDWRAP,
SDRATTR_EDGE_FIRST, SDRATTR_MEASURE_LAST,
SDRATTR_3D_FIRST, SDRATTR_3D_LAST,
EE_PARA_START, EE_CHAR_END>(GetPool()->GetPool());
bMySet = true;
}
return(*pSet);
}
}
}
/**
* A template is used when it is referenced by inserted object or by a used
* template.
*/
bool SdStyleSheet::IsUsed() const
{
bool bResult = false;
ForAllListeners(
[this, &bResult] (SfxListener* pListener)
{
if( pListener == this )
return false; // continue
const svl::StyleSheetUser* const pUser(dynamic_cast<svl::StyleSheetUser*>(pListener));
if (pUser)
bResult = pUser->isUsedByModel();
if (bResult)
return true; // break loop
return false;
});
if( !bResult )
{
std::unique_lock aGuard( m_aMutex );
if( maModifyListeners.getLength(aGuard) )
{
std::vector<css::uno::Reference<XModifyListener>> aModifyListeners( maModifyListeners.getElements(aGuard) );
bResult = std::any_of(aModifyListeners.begin(), aModifyListeners.end(),
[](const Reference<XInterface>& rListener) {
Reference< XStyle > xStyle( rListener, UNO_QUERY );
try
{
Reference<XPropertySet> xPropertySet(xStyle, UNO_QUERY_THROW);
if (xPropertySet->getPropertyValue(u"IsPhysical"_ustr).get<bool>())
return true;
}
catch (const Exception&)
{
}
return xStyle.is() && xStyle->isInUse();
});
}
}
return bResult;
}
/**
* Checks if a cell style is used in two places at once.
* Typically we modify the formatting of a single place,
* so such style shouldn't be edited directly.
*/
bool SdStyleSheet::IsEditable()
{
if (GetFamily() != SfxStyleFamily::Frame)
return true;
if (!IsUserDefined())
return false;
bool bFoundOne = false;
ForAllListeners(
[this, &bFoundOne] (SfxListener* pListener)
{
if (pListener != this && dynamic_cast<SdStyleSheet*>(pListener))
{
bFoundOne = true;
return true; // break loop
}
return false;
});
if (bFoundOne)
return false;
std::unique_lock aGuard(m_aMutex);
return maModifyListeners.getLength(aGuard) <= 1;
}
/**
* Determine the style sheet for which this dummy is for.
*/
SdStyleSheet* SdStyleSheet::GetRealStyleSheet() const
{
OUString aRealStyle;
OUString aSep( SD_LT_SEPARATOR );
SdStyleSheet* pRealStyle = nullptr;
SdDrawDocument* pDoc = static_cast<SdStyleSheetPool*>(m_pPool)->GetDoc();
::sd::DrawViewShell* pDrawViewShell = nullptr;
::sd::ViewShellBase* pBase = dynamic_cast< ::sd::ViewShellBase* >( SfxViewShell::Current() );
if( pBase )
pDrawViewShell = dynamic_cast< ::sd::DrawViewShell* >( pBase->GetMainViewShell().get() );
if (pDrawViewShell && pDrawViewShell->GetDoc() == pDoc)
{
SdPage* pPage = pDrawViewShell->getCurrentPage();
if( pPage )
{
aRealStyle = pPage->GetLayoutName();
// cut after separator string
if( aRealStyle.indexOf(aSep) >= 0)
{
aRealStyle = aRealStyle.copy(0,(aRealStyle.indexOf(aSep) + aSep.getLength()));
}
}
}
if (aRealStyle.isEmpty())
{
SdPage* pPage = pDoc->GetSdPage(0, PageKind::Standard);
if (pPage)
{
aRealStyle = pDoc->GetSdPage(0, PageKind::Standard)->GetLayoutName();
}
else
{
/* no page available yet. This can happen when actualizing the
document templates. */
SfxStyleSheetIterator aIter(m_pPool, SfxStyleFamily::Page);
SfxStyleSheetBase* pSheet = aIter.First();
if( pSheet )
aRealStyle = pSheet->GetName();
}
if( aRealStyle.indexOf(aSep) >= 0)
{
aRealStyle = aRealStyle.copy(0,(aRealStyle.indexOf(aSep) + aSep.getLength()));
}
}
/* now map from the name (specified for country language) to the internal
name (independent of the country language) */
OUString aInternalName;
OUString aStyleName(aName);
if (aStyleName == SdResId(STR_PSEUDOSHEET_TITLE))
{
aInternalName = STR_LAYOUT_TITLE;
}
else if (aStyleName == SdResId(STR_PSEUDOSHEET_SUBTITLE))
{
aInternalName = STR_LAYOUT_SUBTITLE;
}
else if (aStyleName == SdResId(STR_PSEUDOSHEET_BACKGROUND))
{
aInternalName = STR_LAYOUT_BACKGROUND;
}
else if (aStyleName == SdResId(STR_PSEUDOSHEET_BACKGROUNDOBJECTS))
{
aInternalName = STR_LAYOUT_BACKGROUNDOBJECTS;
}
else if (aStyleName == SdResId(STR_PSEUDOSHEET_NOTES))
{
aInternalName = STR_LAYOUT_NOTES;
}
else
{
OUString aOutlineStr(SdResId(STR_PSEUDOSHEET_OUTLINE));
sal_Int32 nPos = aStyleName.indexOf(aOutlineStr);
if (nPos >= 0)
{
std::u16string_view aNumStr(aStyleName.subView(aOutlineStr.getLength()));
aInternalName = STR_LAYOUT_OUTLINE + aNumStr;
}
}
aRealStyle += aInternalName;
pRealStyle = static_cast< SdStyleSheet* >( m_pPool->Find(aRealStyle, SfxStyleFamily::Page) );
#ifdef DBG_UTIL
if( !pRealStyle )
{
SfxStyleSheetIterator aIter(m_pPool, SfxStyleFamily::Page);
if( aIter.Count() > 0 )
// StyleSheet not found, but pool already loaded
DBG_ASSERT(pRealStyle, "Internal StyleSheet not found");
}
#endif
return pRealStyle;
}
/**
* Determine pseudo style sheet which stands for this style sheet.
*/
SdStyleSheet* SdStyleSheet::GetPseudoStyleSheet() const
{
SdStyleSheet* pPseudoStyle = nullptr;
OUString aSep( SD_LT_SEPARATOR );
OUString aStyleName(aName);
// without layout name and separator
if( aStyleName.indexOf(aSep) >=0 )
{
aStyleName = aStyleName.copy (aStyleName.indexOf(aSep) + aSep.getLength());
}
if (aStyleName == STR_LAYOUT_TITLE)
{
aStyleName = SdResId(STR_PSEUDOSHEET_TITLE);
}
else if (aStyleName == STR_LAYOUT_SUBTITLE)
{
aStyleName = SdResId(STR_PSEUDOSHEET_SUBTITLE);
}
else if (aStyleName == STR_LAYOUT_BACKGROUND)
{
aStyleName = SdResId(STR_PSEUDOSHEET_BACKGROUND);
}
else if (aStyleName == STR_LAYOUT_BACKGROUNDOBJECTS)
{
aStyleName = SdResId(STR_PSEUDOSHEET_BACKGROUNDOBJECTS);
}
else if (aStyleName == STR_LAYOUT_NOTES)
{
aStyleName = SdResId(STR_PSEUDOSHEET_NOTES);
}
else
{
OUString aOutlineStr(STR_LAYOUT_OUTLINE);
sal_Int32 nPos = aStyleName.indexOf(aOutlineStr);
if (nPos != -1)
{
std::u16string_view aNumStr(aStyleName.subView(aOutlineStr.getLength()));
aStyleName = SdResId(STR_PSEUDOSHEET_OUTLINE) + aNumStr;
}
}
pPseudoStyle = static_cast<SdStyleSheet*>(m_pPool->Find(aStyleName, SfxStyleFamily::Pseudo));
DBG_ASSERT(pPseudoStyle, "PseudoStyleSheet missing");
return pPseudoStyle;
}
void SdStyleSheet::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
{
// first, base class functionality
SfxStyleSheet::Notify(rBC, rHint);
if (nFamily != SfxStyleFamily::Pseudo)
return;
/* if the dummy gets a notify about a changed attribute, he takes care that
the actual meant style sheet sends broadcasts. */
if (rHint.GetId() == SfxHintId::DataChanged)
{
SdStyleSheet* pRealStyle = GetRealStyleSheet();
if (pRealStyle)
pRealStyle->Broadcast(rHint);
}
}
/**
* Adjust the bullet width and the left text indent of the provided ItemSets to
* their font height. The new values are calculated that the ratio to the font
* height is as in the style sheet.
*
* @param bOnlyMissingItems If sal_True, only not set items are completed. With
* sal_False, are items are overwritten.
*/
void SdStyleSheet::AdjustToFontHeight(SfxItemSet& rSet, bool bOnlyMissingItems)
{
/* If not explicit set, adjust bullet width and text indent to new font
height. */
SfxStyleFamily eFamily = nFamily;
OUString aStyleName(aName);
if (eFamily == SfxStyleFamily::Pseudo)
{
SfxStyleSheet* pRealStyle = GetRealStyleSheet();
eFamily = pRealStyle->GetFamily();
aStyleName = pRealStyle->GetName();
}
if (!(eFamily == SfxStyleFamily::Page &&
aStyleName.indexOf(STR_LAYOUT_OUTLINE) != -1 &&
rSet.GetItemState(EE_CHAR_FONTHEIGHT) == SfxItemState::SET))
return;
const SfxItemSet* pCurSet = &GetItemSet();
sal_uInt32 nNewHeight = rSet.Get(EE_CHAR_FONTHEIGHT).GetHeight();
sal_uInt32 nOldHeight = pCurSet->Get(EE_CHAR_FONTHEIGHT).GetHeight();
if (rSet.GetItemState(EE_PARA_BULLET) != SfxItemState::SET || !bOnlyMissingItems)
{
const SvxBulletItem& rBItem = pCurSet->Get(EE_PARA_BULLET);
double fBulletFraction = double(rBItem.GetWidth()) / nOldHeight;
SvxBulletItem aNewBItem(rBItem);
aNewBItem.SetWidth(static_cast<sal_uInt32>(fBulletFraction * nNewHeight));
rSet.Put(aNewBItem);
}
if (rSet.GetItemState(EE_PARA_LRSPACE) != SfxItemState::SET || !bOnlyMissingItems)
{
const SvxLRSpaceItem& rLRItem = pCurSet->Get(EE_PARA_LRSPACE);
double fIndentFraction = double(rLRItem.GetTextLeft()) / nOldHeight;
SvxLRSpaceItem aNewLRItem(rLRItem);
aNewLRItem.SetTextLeft(fIndentFraction * nNewHeight);
double fFirstIndentFraction = double(rLRItem.GetTextFirstLineOffset()) / nOldHeight;
aNewLRItem.SetTextFirstLineOffset(static_cast<short>(fFirstIndentFraction * nNewHeight));
rSet.Put(aNewLRItem);
}
if (rSet.GetItemState(EE_PARA_ULSPACE) != SfxItemState::SET || !bOnlyMissingItems)
{
const SvxULSpaceItem& rULItem = pCurSet->Get(EE_PARA_ULSPACE);
SvxULSpaceItem aNewULItem(rULItem);
double fLowerFraction = double(rULItem.GetLower()) / nOldHeight;
aNewULItem.SetLower(static_cast<sal_uInt16>(fLowerFraction * nNewHeight));
double fUpperFraction = double(rULItem.GetUpper()) / nOldHeight;
aNewULItem.SetUpper(static_cast<sal_uInt16>(fUpperFraction * nNewHeight));
rSet.Put(aNewULItem);
}
}
bool SdStyleSheet::HasFollowSupport() const
{
return false;
}
bool SdStyleSheet::HasParentSupport() const
{
return true;
}
bool SdStyleSheet::HasClearParentSupport() const
{
return true;
}
namespace
{
struct ApiNameMap
{
std::u16string_view mpApiName;
sal_uInt32 mnHelpId;
} const pApiNameMap[]
= { { std::u16string_view(u"title"), HID_PSEUDOSHEET_TITLE },
{ std::u16string_view(u"subtitle"), HID_PSEUDOSHEET_SUBTITLE },
{ std::u16string_view(u"background"), HID_PSEUDOSHEET_BACKGROUND },
{ std::u16string_view(u"backgroundobjects"), HID_PSEUDOSHEET_BACKGROUNDOBJECTS },
{ std::u16string_view(u"notes"), HID_PSEUDOSHEET_NOTES },
{ std::u16string_view(u"standard"), HID_STANDARD_STYLESHEET_NAME },
{ std::u16string_view(u"objectwithoutfill"), HID_POOLSHEET_OBJWITHOUTFILL },
{ std::u16string_view(u"Object with no fill and no line"), HID_POOLSHEET_OBJNOLINENOFILL },
{ std::u16string_view(u"Text"), HID_POOLSHEET_TEXT },
{ std::u16string_view(u"A4"), HID_POOLSHEET_A4 },
{ std::u16string_view(u"Title A4"), HID_POOLSHEET_A4_TITLE },
{ std::u16string_view(u"Heading A4"), HID_POOLSHEET_A4_HEADLINE },
{ std::u16string_view(u"Text A4"), HID_POOLSHEET_A4_TEXT },
{ std::u16string_view(u"A0"), HID_POOLSHEET_A0 },
{ std::u16string_view(u"Title A0"), HID_POOLSHEET_A0_TITLE },
{ std::u16string_view(u"Heading A0"), HID_POOLSHEET_A0_HEADLINE },
{ std::u16string_view(u"Text A0"), HID_POOLSHEET_A0_TEXT },
{ std::u16string_view(u"Graphic"), HID_POOLSHEET_GRAPHIC },
{ std::u16string_view(u"Shapes"), HID_POOLSHEET_SHAPES },
{ std::u16string_view(u"Filled"), HID_POOLSHEET_FILLED },
{ std::u16string_view(u"Filled Blue"), HID_POOLSHEET_FILLED_BLUE },
{ std::u16string_view(u"Filled Green"), HID_POOLSHEET_FILLED_GREEN },
{ std::u16string_view(u"Filled Red"), HID_POOLSHEET_FILLED_RED },
{ std::u16string_view(u"Filled Yellow"), HID_POOLSHEET_FILLED_YELLOW },
{ std::u16string_view(u"Outlined"), HID_POOLSHEET_OUTLINE },
{ std::u16string_view(u"Outlined Blue"), HID_POOLSHEET_OUTLINE_BLUE },
{ std::u16string_view(u"Outlined Green"), HID_POOLSHEET_OUTLINE_GREEN },
{ std::u16string_view(u"Outlined Red"), HID_POOLSHEET_OUTLINE_RED },
{ std::u16string_view(u"Outlined Yellow"), HID_POOLSHEET_OUTLINE_YELLOW },
{ std::u16string_view(u"Lines"), HID_POOLSHEET_LINES },
{ std::u16string_view(u"Arrow Line"), HID_POOLSHEET_MEASURE },
{ std::u16string_view(u"Arrow Dashed"), HID_POOLSHEET_LINES_DASHED }
};
OUString GetApiNameForHelpId(sal_uInt32 nId)
{
if ((nId >= HID_PSEUDOSHEET_OUTLINE1) && (nId <= HID_PSEUDOSHEET_OUTLINE9))
return "outline" + OUStringChar(sal_Unicode('1' + (nId - HID_PSEUDOSHEET_OUTLINE1)));
for (const auto& i : pApiNameMap)
if (nId == i.mnHelpId)
return OUString(i.mpApiName);
return OUString();
}
sal_uInt32 GetHelpIdForApiName(std::u16string_view sName)
{
std::u16string_view sRest;
if (o3tl::starts_with(sName, u"outline", &sRest))
{
if (sRest.length() == 1)
{
sal_Unicode ch = sRest.front();
if ('1' <= ch && ch <= '9')
return HID_PSEUDOSHEET_OUTLINE1 + ch - '1';
}
// No other pre-defined names start with "outline"
return 0;
}
for (const auto& i : pApiNameMap)
if (sName == i.mpApiName)
return i.mnHelpId;
return 0;
}
}
void SdStyleSheet::SetHelpId( const OUString& r, sal_uInt32 nId )
{
SfxStyleSheet::SetHelpId( r, nId );
const OUString sNewApiName = GetApiNameForHelpId(nId);
if (!sNewApiName.isEmpty())
msApiName = sNewApiName;
}
OUString SdStyleSheet::GetFamilyString( SfxStyleFamily eFamily )
{
switch( eFamily )
{
case SfxStyleFamily::Frame:
return u"cell"_ustr;
default:
OSL_FAIL( "SdStyleSheet::GetFamilyString(), illegal family!" );
[[fallthrough]];
case SfxStyleFamily::Para:
return u"graphics"_ustr;
}
}
void SdStyleSheet::throwIfDisposed()
{
if( !mxPool.is() )
throw DisposedException();
}
rtl::Reference<SdStyleSheet> SdStyleSheet::CreateEmptyUserStyle( SfxStyleSheetBasePool& rPool, SfxStyleFamily eFamily )
{
OUString aName;
sal_Int32 nIndex = 1;
do
{
aName = "user" + OUString::number( nIndex++ );
}
while( rPool.Find( aName, eFamily ) != nullptr );
return new SdStyleSheet(aName, rPool, eFamily, SfxStyleSearchBits::UserDefined);
}
// XComponent
void SAL_CALL SdStyleSheet::dispose( )
{
{
std::unique_lock aGuard(m_aMutex);
if (m_bDisposed || m_bInDispose)
return;
m_bInDispose = true;
}
try
{
std::unique_lock aGuard(m_aMutex);
// side effect: keeping a reference to this
EventObject aEvt( static_cast< OWeakObject * >( this ) );
try
{
maModifyListeners.disposeAndClear( aGuard, aEvt );
maEventListeners.disposeAndClear( aGuard, aEvt );
disposing();
}
catch (...)
{
// bDisposed and bInDispose must be set in this order:
m_bDisposed = true;
m_bInDispose = false;
throw;
}
// bDisposed and bInDispose must be set in this order:
m_bDisposed = true;
m_bInDispose = false;
}
catch (RuntimeException &)
{
throw;
}
catch (const Exception & exc)
{
css::uno::Any anyEx = cppu::getCaughtException();
throw css::lang::WrappedTargetRuntimeException(
"unexpected UNO exception caught: " + exc.Message ,
nullptr, anyEx );
}
}
void SdStyleSheet::disposing()
{
SolarMutexGuard aGuard;
if (bMySet)
{
delete pSet;
}
pSet = nullptr;
m_pPool = nullptr;
mxPool.clear();
}
void SAL_CALL SdStyleSheet::addEventListener( const Reference< XEventListener >& xListener )
{
std::unique_lock aGuard( m_aMutex );
if (m_bDisposed || m_bInDispose)
{
aGuard.unlock();
EventObject aEvt( static_cast< OWeakObject * >( this ) );
xListener->disposing( aEvt );
}
else
{
maEventListeners.addInterface( aGuard, xListener );
}
}
void SAL_CALL SdStyleSheet::removeEventListener( const Reference< XEventListener >& xListener )
{
std::unique_lock aGuard( m_aMutex );
maEventListeners.removeInterface( aGuard, xListener );
}
// XModifyBroadcaster
void SAL_CALL SdStyleSheet::addModifyListener( const Reference< XModifyListener >& xListener )
{
std::unique_lock aGuard( m_aMutex );
if (m_bDisposed || m_bInDispose)
{
aGuard.unlock();
EventObject aEvt( static_cast< OWeakObject * >( this ) );
xListener->disposing( aEvt );
}
else
{
if (!mpModifyListenerForwarder)
mpModifyListenerForwarder.reset( new ModifyListenerForwarder( this ) );
maModifyListeners.addInterface( aGuard, xListener );
}
}
void SAL_CALL SdStyleSheet::removeModifyListener( const Reference< XModifyListener >& xListener )
{
std::unique_lock aGuard( m_aMutex );
maModifyListeners.removeInterface( aGuard, xListener );
}
void SdStyleSheet::notifyModifyListener()
{
std::unique_lock aGuard( m_aMutex );
if( maModifyListeners.getLength(aGuard) )
{
EventObject aEvt( static_cast< OWeakObject * >( this ) );
maModifyListeners.notifyEach(aGuard, &XModifyListener::modified, aEvt);
}
}
// XServiceInfo
OUString SAL_CALL SdStyleSheet::getImplementationName()
{
return u"SdStyleSheet"_ustr;
}
sal_Bool SAL_CALL SdStyleSheet::supportsService( const OUString& ServiceName )
{
return cppu::supportsService( this, ServiceName );
}
Sequence< OUString > SAL_CALL SdStyleSheet::getSupportedServiceNames()
{
return { u"com.sun.star.style.Style"_ustr,
u"com.sun.star.drawing.FillProperties"_ustr,
u"com.sun.star.drawing.LineProperties"_ustr,
u"com.sun.star.drawing.ShadowProperties"_ustr,
u"com.sun.star.drawing.ConnectorProperties"_ustr,
u"com.sun.star.drawing.MeasureProperties"_ustr,
u"com.sun.star.style.ParagraphProperties"_ustr,
u"com.sun.star.style.CharacterProperties"_ustr,
u"com.sun.star.drawing.TextProperties"_ustr,
u"com.sun.star.drawing.Text"_ustr };
}
bool SdStyleSheet::SetName(const OUString& rNewName, bool bReindexNow)
{
const bool bResult = SfxUnoStyleSheet::SetName(rNewName, bReindexNow);
// Don't overwrite predefined API names
if (bResult && GetHelpIdForApiName(msApiName) == 0)
{
msApiName = rNewName;
Broadcast(SfxHint(SfxHintId::DataChanged));
}
return bResult;
}
// XNamed
OUString SAL_CALL SdStyleSheet::getName()
{
SolarMutexGuard aGuard;
throwIfDisposed();
return GetApiName();
}
void SAL_CALL SdStyleSheet::setName( const OUString& rName )
{
SolarMutexGuard aGuard;
throwIfDisposed();
SetName(rName);
}
// XStyle
sal_Bool SAL_CALL SdStyleSheet::isUserDefined()
{
SolarMutexGuard aGuard;
throwIfDisposed();
return IsUserDefined();
}
sal_Bool SAL_CALL SdStyleSheet::isInUse()
{
SolarMutexGuard aGuard;
throwIfDisposed();
return IsUsed();
}
OUString SAL_CALL SdStyleSheet::getParentStyle()
{
SolarMutexGuard aGuard;
throwIfDisposed();
if( !GetParent().isEmpty() )
{
SdStyleSheet* pParentStyle = static_cast< SdStyleSheet* >( mxPool->Find( GetParent(), nFamily ) );
if( pParentStyle )
return pParentStyle->GetApiName();
}
return OUString();
}
void SAL_CALL SdStyleSheet::setParentStyle( const OUString& rParentName )
{
SolarMutexGuard aGuard;
throwIfDisposed();
if( !rParentName.isEmpty() )
{
OUString const& name(GetName());
sal_Int32 const sep(name.indexOf(SD_LT_SEPARATOR));
OUString const master((sep == -1) ? OUString() : name.copy(0, sep));
std::shared_ptr<SfxStyleSheetIterator> aSSSI = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), nFamily);
for (SfxStyleSheetBase *pStyle = aSSSI->First(); pStyle; pStyle = aSSSI->Next())
{
// we hope that we have only sd style sheets
SdStyleSheet* pSdStyleSheet = static_cast<SdStyleSheet*>(pStyle);
// check that the master msApiName matches, as msApiName exists once per
// master page
if (pSdStyleSheet->msApiName != rParentName)
continue;
OUString const& curName(pStyle->GetName());
sal_Int32 const curSep(curName.indexOf(SD_LT_SEPARATOR));
OUString const curMaster((curSep == -1)
? OUString() : curName.copy(0, curSep));
// check that the master matches
if (master == curMaster)
{
if( pStyle != this )
{
SetParent(curName);
}
return;
}
}
throw NoSuchElementException();
}
else
{
SetParent( rParentName );
}
}
// XPropertySet/XMultiPropertySet utility functions
// Does not broadcast
// Must be guarded by solar mutex; must not be disposed
void SdStyleSheet::setPropertyValue_Impl(const OUString& aPropertyName, const css::uno::Any& aValue)
{
const SfxItemPropertyMapEntry* pEntry = getPropertyMapEntry( aPropertyName );
if( pEntry == nullptr )
{
throw UnknownPropertyException( aPropertyName, static_cast<cppu::OWeakObject*>(this));
}
if( pEntry->nWID == WID_STYLE_HIDDEN )
{
bool bValue = false;
if ( aValue >>= bValue )
SetHidden( bValue );
return;
}
if( pEntry->nWID == SDRATTR_TEXTDIRECTION )
return; // not yet implemented for styles
if( pEntry->nWID == WID_STYLE_FAMILY )
throw PropertyVetoException();
if( (pEntry->nWID == EE_PARA_NUMBULLET) && (GetFamily() == SfxStyleFamily::Page) )
{
OUString aStr;
const sal_uInt32 nTempHelpId = GetHelpId( aStr );
if( (nTempHelpId >= HID_PSEUDOSHEET_OUTLINE2) && (nTempHelpId <= HID_PSEUDOSHEET_OUTLINE9) )
return;
}
SfxItemSet &rStyleSet = GetItemSet();
if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
{
BitmapMode eMode;
if( aValue >>= eMode )
{
rStyleSet.Put( XFillBmpStretchItem( eMode == BitmapMode_STRETCH ) );
rStyleSet.Put( XFillBmpTileItem( eMode == BitmapMode_REPEAT ) );
return;
}
throw IllegalArgumentException();
}
if (pEntry->nWID == OWN_ATTR_TEXTCOLUMNS)
{
if (css::uno::Reference<css::text::XTextColumns> xColumns; aValue >>= xColumns)
{
rStyleSet.Put(SfxInt16Item(SDRATTR_TEXTCOLUMNS_NUMBER, xColumns->getColumnCount()));
if (css::uno::Reference<css::beans::XPropertySet> xPropSet{ xColumns,
css::uno::UNO_QUERY })
{
auto aVal = xPropSet->getPropertyValue(u"AutomaticDistance"_ustr);
if (sal_Int32 nSpacing; aVal >>= nSpacing)
rStyleSet.Put(SdrMetricItem(SDRATTR_TEXTCOLUMNS_SPACING, nSpacing));
}
return;
}
throw IllegalArgumentException();
}
SfxItemSet aSet( GetPool()->GetPool(), pEntry->nWID, pEntry->nWID);
aSet.Put( rStyleSet );
if( !aSet.Count() )
{
if( EE_PARA_NUMBULLET == pEntry->nWID )
{
vcl::Font aBulletFont;
SdStyleSheetPool::PutNumBulletItem( this, aBulletFont );
aSet.Put( rStyleSet );
}
else
{
aSet.Put( GetPool()->GetPool().GetUserOrPoolDefaultItem( pEntry->nWID ) );
}
}
if( pEntry->nMemberId == MID_NAME &&
( pEntry->nWID == XATTR_FILLBITMAP || pEntry->nWID == XATTR_FILLGRADIENT ||
pEntry->nWID == XATTR_FILLHATCH || pEntry->nWID == XATTR_FILLFLOATTRANSPARENCE ||
pEntry->nWID == XATTR_LINESTART || pEntry->nWID == XATTR_LINEEND || pEntry->nWID == XATTR_LINEDASH) )
{
OUString aTempName;
if(!(aValue >>= aTempName ))
throw IllegalArgumentException();
SvxShape::SetFillAttribute( pEntry->nWID, aTempName, aSet );
}
else if(!SvxUnoTextRangeBase::SetPropertyValueHelper( pEntry, aValue, aSet ))
{
SvxItemPropertySet_setPropertyValue( pEntry, aValue, aSet );
}
rStyleSet.Put( aSet );
}
// Must be guarded by solar mutex; must not be disposed
css::uno::Any SdStyleSheet::getPropertyValue_Impl(const OUString& PropertyName)
{
const SfxItemPropertyMapEntry* pEntry = getPropertyMapEntry( PropertyName );
if( pEntry == nullptr )
{
throw UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this));
}
Any aAny;
if( pEntry->nWID == WID_STYLE_FAMILY )
{
if( nFamily == SfxStyleFamily::Page )
{
const OUString aLayoutName( GetName() );
aAny <<= aLayoutName.copy( 0, aLayoutName.indexOf( SD_LT_SEPARATOR) );
}
else
{
aAny <<= GetFamilyString(nFamily);
}
}
else if( pEntry->nWID == WID_STYLE_DISPNAME )
{
OUString aDisplayName;
if ( nFamily == SfxStyleFamily::Page )
{
const SdStyleSheet* pStyleSheet = GetPseudoStyleSheet();
if (pStyleSheet != nullptr)
aDisplayName = pStyleSheet->GetName();
}
if (aDisplayName.isEmpty())
aDisplayName = GetName();
aAny <<= aDisplayName;
}
else if( pEntry->nWID == SDRATTR_TEXTDIRECTION )
{
aAny <<= false;
}
else if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
{
SfxItemSet &rStyleSet = GetItemSet();
const XFillBmpStretchItem* pStretchItem = rStyleSet.GetItem<XFillBmpStretchItem>(XATTR_FILLBMP_STRETCH);
const XFillBmpTileItem* pTileItem = rStyleSet.GetItem<XFillBmpTileItem>(XATTR_FILLBMP_TILE);
if( pStretchItem && pTileItem )
{
if( pTileItem->GetValue() )
aAny <<= BitmapMode_REPEAT;
else if( pStretchItem->GetValue() )
aAny <<= BitmapMode_STRETCH;
else
aAny <<= BitmapMode_NO_REPEAT;
}
}
else if( pEntry->nWID == WID_STYLE_HIDDEN )
{
aAny <<= IsHidden( );
}
else if (pEntry->nWID == OWN_ATTR_TEXTCOLUMNS)
{
const SfxItemSet& rStyleSet = GetItemSet();
auto xIf = SvxXTextColumns_createInstance();
css::uno::Reference<css::text::XTextColumns> xCols(xIf, css::uno::UNO_QUERY_THROW);
xCols->setColumnCount(rStyleSet.Get(SDRATTR_TEXTCOLUMNS_NUMBER).GetValue());
css::uno::Reference<css::beans::XPropertySet> xProp(xIf, css::uno::UNO_QUERY_THROW);
xProp->setPropertyValue(
u"AutomaticDistance"_ustr,
css::uno::Any(rStyleSet.Get(SDRATTR_TEXTCOLUMNS_SPACING).GetValue()));
aAny <<= xIf;
}
else
{
SfxItemSet aSet( GetPool()->GetPool(), pEntry->nWID, pEntry->nWID);
const SfxPoolItem* pItem;
SfxItemSet& rStyleSet = GetItemSet();
if( rStyleSet.GetItemState( pEntry->nWID, true, &pItem ) == SfxItemState::SET )
aSet.Put( *pItem );
if( !aSet.Count() )
aSet.Put( GetPool()->GetPool().GetUserOrPoolDefaultItem( pEntry->nWID ) );
if(SvxUnoTextRangeBase::GetPropertyValueHelper( aSet, pEntry, aAny ))
return aAny;
// Get value of ItemSet
aAny = SvxItemPropertySet_getPropertyValue( pEntry, aSet );
}
if( pEntry->aType != aAny.getValueType() )
{
// since the sfx uint16 item now exports a sal_Int32, we may have to fix this here
if( ( pEntry->aType == ::cppu::UnoType<sal_Int16>::get()) && aAny.getValueType() == ::cppu::UnoType<sal_Int32>::get() )
{
sal_Int32 nValue = 0;
aAny >>= nValue;
aAny <<= static_cast<sal_Int16>(nValue);
}
else
{
OSL_FAIL("SvxShape::GetAnyForItem() Returnvalue has wrong Type!" );
}
}
return aAny;
}
// XPropertySet
Reference< XPropertySetInfo > SdStyleSheet::getPropertySetInfo()
{
throwIfDisposed();
static Reference< XPropertySetInfo > xInfo = GetStylePropertySet().getPropertySetInfo();
return xInfo;
}
void SAL_CALL SdStyleSheet::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
{
SolarMutexGuard aGuard;
throwIfDisposed();
setPropertyValue_Impl(aPropertyName, aValue);
Broadcast(SfxHint(SfxHintId::DataChanged));
}
Any SAL_CALL SdStyleSheet::getPropertyValue( const OUString& PropertyName )
{
SolarMutexGuard aGuard;
throwIfDisposed();
return getPropertyValue_Impl(PropertyName);
}
void SAL_CALL SdStyleSheet::addPropertyChangeListener( const OUString& , const Reference< XPropertyChangeListener >& ) {}
void SAL_CALL SdStyleSheet::removePropertyChangeListener( const OUString& , const Reference< XPropertyChangeListener >& ) {}
void SAL_CALL SdStyleSheet::addVetoableChangeListener( const OUString& , const Reference< XVetoableChangeListener >& ) {}
void SAL_CALL SdStyleSheet::removeVetoableChangeListener( const OUString& , const Reference< XVetoableChangeListener >& ) {}
// XMultiPropertySet
void SAL_CALL SdStyleSheet::setPropertyValues(const css::uno::Sequence<OUString>& aPropertyNames,
const css::uno::Sequence<css::uno::Any>& aValues)
{
const sal_Int32 nCount = aPropertyNames.getLength();
if (nCount != aValues.getLength())
throw css::lang::IllegalArgumentException();
if (!nCount)
return;
SolarMutexGuard aGuard;
throwIfDisposed();
for (sal_Int32 i = 0; i < nCount; ++i)
{
try
{
setPropertyValue_Impl(aPropertyNames[i], aValues[i]);
}
catch (const css::beans::UnknownPropertyException&)
{
// ignore this, some code likes to liberally sprinkle properties all over stuff that doesn't support those properties
}
}
Broadcast(SfxHint(SfxHintId::DataChanged));
}
css::uno::Sequence<css::uno::Any>
SAL_CALL SdStyleSheet::getPropertyValues(const css::uno::Sequence<OUString>& aPropertyNames)
{
SolarMutexGuard aGuard;
throwIfDisposed();
const sal_Int32 nCount = aPropertyNames.getLength();
css::uno::Sequence<css::uno::Any> aValues(nCount);
Any* pAny = aValues.getArray();
for (sal_Int32 i = 0; i < nCount; ++i)
pAny[i] = getPropertyValue_Impl(aPropertyNames[i]);
return aValues;
}
void SAL_CALL SdStyleSheet::addPropertiesChangeListener(const css::uno::Sequence<OUString>&, const css::uno::Reference<css::beans::XPropertiesChangeListener>&) {}
void SAL_CALL SdStyleSheet::removePropertiesChangeListener(const css::uno::Reference<css::beans::XPropertiesChangeListener>&) {}
void SAL_CALL SdStyleSheet::firePropertiesChangeEvent(const css::uno::Sequence<OUString>&, const css::uno::Reference<css::beans::XPropertiesChangeListener>&) {}
// XPropertyState
PropertyState SAL_CALL SdStyleSheet::getPropertyState( const OUString& PropertyName )
{
SolarMutexGuard aGuard;
throwIfDisposed();
const SfxItemPropertyMapEntry* pEntry = getPropertyMapEntry( PropertyName );
if( pEntry == nullptr )
throw UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this));
if( pEntry->nWID == WID_STYLE_FAMILY )
{
return PropertyState_DIRECT_VALUE;
}
else if( pEntry->nWID == SDRATTR_TEXTDIRECTION )
{
return PropertyState_DEFAULT_VALUE;
}
else if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
{
const SfxItemSet& rSet = GetItemSet();
if( rSet.GetItemState( XATTR_FILLBMP_STRETCH, false ) == SfxItemState::SET ||
rSet.GetItemState( XATTR_FILLBMP_TILE, false ) == SfxItemState::SET )
{
return PropertyState_DIRECT_VALUE;
}
else
{
return PropertyState_AMBIGUOUS_VALUE;
}
}
else if (pEntry->nWID == OWN_ATTR_TEXTCOLUMNS)
{
const SfxItemSet& rSet = GetItemSet();
const auto eState1 = rSet.GetItemState(SDRATTR_TEXTCOLUMNS_NUMBER, false);
const auto eState2 = rSet.GetItemState(SDRATTR_TEXTCOLUMNS_SPACING, false);
if (eState1 == SfxItemState::SET || eState2 == SfxItemState::SET)
return PropertyState_DIRECT_VALUE;
else if (eState1 == SfxItemState::DEFAULT && eState2 == SfxItemState::DEFAULT)
return PropertyState_DEFAULT_VALUE;
else
return PropertyState_AMBIGUOUS_VALUE;
}
else
{
SfxItemSet &rStyleSet = GetItemSet();
PropertyState eState;
switch( rStyleSet.GetItemState( pEntry->nWID, false ) )
{
case SfxItemState::SET:
eState = PropertyState_DIRECT_VALUE;
break;
case SfxItemState::DEFAULT:
eState = PropertyState_DEFAULT_VALUE;
break;
default:
eState = PropertyState_AMBIGUOUS_VALUE;
break;
}
// if an item is set, this doesn't mean we want it :)
if( PropertyState_DIRECT_VALUE == eState )
{
switch( pEntry->nWID )
{
case XATTR_FILLBITMAP:
case XATTR_FILLGRADIENT:
case XATTR_FILLHATCH:
case XATTR_FILLFLOATTRANSPARENCE:
case XATTR_LINEEND:
case XATTR_LINESTART:
case XATTR_LINEDASH:
{
const NameOrIndex* pItem = rStyleSet.GetItem<NameOrIndex>(pEntry->nWID);
if( ( pItem == nullptr ) || pItem->GetName().isEmpty() )
eState = PropertyState_DEFAULT_VALUE;
}
break;
case XATTR_FILLCOLOR:
if (pEntry->nMemberId == MID_COLOR_THEME_INDEX)
{
const XFillColorItem* pColor = rStyleSet.GetItem<XFillColorItem>(pEntry->nWID);
if (pColor->getComplexColor().getThemeColorType() == model::ThemeColorType::Unknown)
{
eState = PropertyState_DEFAULT_VALUE;
}
}
else if (pEntry->nMemberId == MID_COLOR_LUM_MOD)
{
const XFillColorItem* pColor = rStyleSet.GetItem<XFillColorItem>(pEntry->nWID);
sal_Int16 nLumMod = 10000;
for (auto const& rTransform : pColor->getComplexColor().getTransformations())
{
if (rTransform.meType == model::TransformationType::LumMod)
nLumMod = rTransform.mnValue;
}
if (nLumMod == 10000)
{
eState = PropertyState_DEFAULT_VALUE;
}
}
else if (pEntry->nMemberId == MID_COLOR_LUM_OFF)
{
const XFillColorItem* pColor = rStyleSet.GetItem<XFillColorItem>(pEntry->nWID);
sal_Int16 nLumOff = 0;
for (auto const& rTransform : pColor->getComplexColor().getTransformations())
{
if (rTransform.meType == model::TransformationType::LumOff)
nLumOff = rTransform.mnValue;
}
if (nLumOff == 0)
{
eState = PropertyState_DEFAULT_VALUE;
}
}
else if (pEntry->nMemberId == MID_COMPLEX_COLOR)
{
auto const* pColor = rStyleSet.GetItem<XFillColorItem>(pEntry->nWID);
if (pColor->getComplexColor().getType() == model::ColorType::Unused)
{
eState = PropertyState_DEFAULT_VALUE;
}
}
break;
case XATTR_LINECOLOR:
if (pEntry->nMemberId == MID_COMPLEX_COLOR)
{
auto const* pColor = rStyleSet.GetItem<XLineColorItem>(pEntry->nWID);
if (pColor->getComplexColor().getType() == model::ColorType::Unused)
{
eState = PropertyState_DEFAULT_VALUE;
}
}
break;
}
}
return eState;
}
}
Sequence< PropertyState > SAL_CALL SdStyleSheet::getPropertyStates( const Sequence< OUString >& aPropertyName )
{
SolarMutexGuard aGuard;
throwIfDisposed();
sal_Int32 nCount = aPropertyName.getLength();
Sequence< PropertyState > aPropertyStateSequence( nCount );
std::transform(aPropertyName.begin(), aPropertyName.end(), aPropertyStateSequence.getArray(),
[this](const OUString& rName) -> PropertyState { return getPropertyState(rName); });
return aPropertyStateSequence;
}
void SAL_CALL SdStyleSheet::setPropertyToDefault( const OUString& PropertyName )
{
SolarMutexGuard aGuard;
throwIfDisposed();
const SfxItemPropertyMapEntry* pEntry = getPropertyMapEntry( PropertyName );
if( pEntry == nullptr )
throw UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this));
SfxItemSet &rStyleSet = GetItemSet();
if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
{
rStyleSet.ClearItem( XATTR_FILLBMP_STRETCH );
rStyleSet.ClearItem( XATTR_FILLBMP_TILE );
}
else
{
rStyleSet.ClearItem( pEntry->nWID );
}
Broadcast(SfxHint(SfxHintId::DataChanged));
}
Any SAL_CALL SdStyleSheet::getPropertyDefault( const OUString& aPropertyName )
{
SolarMutexGuard aGuard;
throwIfDisposed();
const SfxItemPropertyMapEntry* pEntry = getPropertyMapEntry( aPropertyName );
if( pEntry == nullptr )
throw UnknownPropertyException( aPropertyName, static_cast<cppu::OWeakObject*>(this));
Any aRet;
if( pEntry->nWID == WID_STYLE_FAMILY )
{
aRet <<= GetFamilyString(nFamily);
}
else if( pEntry->nWID == SDRATTR_TEXTDIRECTION )
{
aRet <<= false;
}
else if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
{
aRet <<= BitmapMode_REPEAT;
}
else
{
SfxItemPool& rMyPool = GetPool()->GetPool();
SfxItemSet aSet( rMyPool, pEntry->nWID, pEntry->nWID);
aSet.Put( rMyPool.GetUserOrPoolDefaultItem( pEntry->nWID ) );
aRet = SvxItemPropertySet_getPropertyValue( pEntry, aSet );
}
return aRet;
}
/** this is used because our property map is not sorted yet */
const SfxItemPropertyMapEntry* SdStyleSheet::getPropertyMapEntry( const OUString& rPropertyName )
{
return GetStylePropertySet().getPropertyMapEntry(rPropertyName);
}
//Broadcast that a SdStyleSheet has changed, taking into account outline sublevels
//which need to be explicitly broadcast as changing if their parent style was
//the one that changed
void SdStyleSheet::BroadcastSdStyleSheetChange(SfxStyleSheetBase const * pStyleSheet,
PresentationObjects ePO, SfxStyleSheetBasePool* pSSPool)
{
SdStyleSheet* pRealSheet = static_cast<SdStyleSheet const *>(pStyleSheet)->GetRealStyleSheet();
pRealSheet->Broadcast(SfxHint(SfxHintId::DataChanged));
if( (ePO < PresentationObjects::Outline_1) || (ePO > PresentationObjects::Outline_8) )
return;
OUString sStyleName(SdResId(STR_PSEUDOSHEET_OUTLINE) + " ");
for( sal_uInt16 n = static_cast<sal_uInt16>(ePO) - static_cast<sal_uInt16>(PresentationObjects::Outline_1) + 2; n < 10; n++ )
{
OUString aName( sStyleName + OUString::number(n) );
SfxStyleSheetBase* pSheet = pSSPool->Find( aName, SfxStyleFamily::Pseudo);
if(pSheet)
{
SdStyleSheet* pRealStyleSheet = static_cast<SdStyleSheet*>(pSheet)->GetRealStyleSheet();
pRealStyleSheet->Broadcast(SfxHint(SfxHintId::DataChanged));
}
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V614 Uninitialized variable 'nSpacing' used. Consider checking the second actual argument of the 'SdrMetricItem' function.
↑ V1053 Calling the 'dispose' virtual function in the destructor may lead to unexpected result at runtime.