Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sd / source / core / stlsheet.cxx
blob28013eaa72632c911bf3bbfc119036f069cc8364
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/beans/PropertyAttribute.hpp>
21 #include <com/sun/star/beans/XPropertySet.hpp>
22 #include <com/sun/star/lang/DisposedException.hpp>
23 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
24 #include <com/sun/star/style/XStyle.hpp>
25 #include <com/sun/star/table/BorderLine.hpp>
26 #include <com/sun/star/text/XTextColumns.hpp>
28 #include <o3tl/string_view.hxx>
29 #include <osl/mutex.hxx>
30 #include <vcl/svapp.hxx>
31 #include <cppuhelper/exc_hlp.hxx>
32 #include <cppuhelper/supportsservice.hxx>
34 #include <editeng/eeitem.hxx>
35 #include <editeng/fhgtitem.hxx>
36 #include <editeng/ulspitem.hxx>
37 #include <svl/hint.hxx>
38 #include <svl/intitem.hxx>
39 #include <svl/itemset.hxx>
41 #include <svx/xflbmtit.hxx>
42 #include <svx/xflbstit.hxx>
43 #include <svx/xlnclit.hxx>
44 #include <editeng/bulletitem.hxx>
45 #include <editeng/lrspitem.hxx>
46 #include <svx/unoshprp.hxx>
47 #include <svx/unoshape.hxx>
48 #include <svx/svdpool.hxx>
49 #include <svx/sdmetitm.hxx>
50 #include <svx/sdtaaitm.hxx>
51 #include <svx/sdtacitm.hxx>
52 #include <svx/sdtayitm.hxx>
53 #include <svx/sdtaiitm.hxx>
54 #include <svx/SvxXTextColumns.hxx>
55 #include <svx/xit.hxx>
56 #include <svx/xflclit.hxx>
57 #include <comphelper/diagnose_ex.hxx>
58 #include <stlsheet.hxx>
59 #include <sdresid.hxx>
60 #include <sdpage.hxx>
61 #include <drawdoc.hxx>
62 #include <stlpool.hxx>
63 #include <strings.hrc>
64 #include <app.hrc>
65 #include <strings.hxx>
66 #include <glob.hxx>
67 #include <DrawViewShell.hxx>
68 #include <ViewShellBase.hxx>
70 #include <cstddef>
71 #include <memory>
72 #include <string_view>
74 using ::osl::MutexGuard;
75 using ::com::sun::star::table::BorderLine;
76 using namespace ::com::sun::star::uno;
77 using namespace ::com::sun::star::util;
78 using namespace ::com::sun::star::lang;
79 using namespace ::com::sun::star::style;
80 using namespace ::com::sun::star::beans;
81 using namespace ::com::sun::star::container;
82 using namespace ::com::sun::star::drawing;
84 #define WID_STYLE_HIDDEN 7997
85 #define WID_STYLE_DISPNAME 7998
86 #define WID_STYLE_FAMILY 7999
88 static SvxItemPropertySet& GetStylePropertySet()
90 static const SfxItemPropertyMapEntry aFullPropertyMap_Impl[] =
92 { u"Family", WID_STYLE_FAMILY, ::cppu::UnoType<OUString>::get(), PropertyAttribute::READONLY, 0},
93 { u"UserDefinedAttributes", SDRATTR_XMLATTRIBUTES, cppu::UnoType<XNameContainer>::get(), 0, 0},
94 { u"DisplayName", WID_STYLE_DISPNAME, ::cppu::UnoType<OUString>::get(), PropertyAttribute::READONLY, 0},
95 { u"Hidden", WID_STYLE_HIDDEN, cppu::UnoType<bool>::get(), 0, 0},
97 SVX_UNOEDIT_NUMBERING_PROPERTY,
98 SHADOW_PROPERTIES
99 LINE_PROPERTIES
100 LINE_PROPERTIES_START_END
101 FILL_PROPERTIES
102 EDGERADIUS_PROPERTIES
103 TEXT_PROPERTIES_DEFAULTS
104 CONNECTOR_PROPERTIES
105 SPECIAL_DIMENSIONING_PROPERTIES_DEFAULTS
106 { u"TopBorder", SDRATTR_TABLE_BORDER, ::cppu::UnoType<BorderLine>::get(), 0, TOP_BORDER },
107 { u"BottomBorder", SDRATTR_TABLE_BORDER, ::cppu::UnoType<BorderLine>::get(), 0, BOTTOM_BORDER },
108 { u"LeftBorder", SDRATTR_TABLE_BORDER, ::cppu::UnoType<BorderLine>::get(), 0, LEFT_BORDER },
109 { u"RightBorder", SDRATTR_TABLE_BORDER, ::cppu::UnoType<BorderLine>::get(), 0, RIGHT_BORDER },
112 static SvxItemPropertySet aPropSet( aFullPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool() );
113 return aPropSet;
116 class ModifyListenerForwarder : public SfxListener
118 public:
119 explicit ModifyListenerForwarder( SdStyleSheet* pStyleSheet );
121 virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override;
123 private:
124 SdStyleSheet* mpStyleSheet;
127 ModifyListenerForwarder::ModifyListenerForwarder( SdStyleSheet* pStyleSheet )
128 : mpStyleSheet( pStyleSheet )
130 if( pStyleSheet )
132 SfxBroadcaster& rBC = static_cast< SfxBroadcaster& >( *pStyleSheet );
133 StartListening( rBC );
137 void ModifyListenerForwarder::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& /*rHint*/)
139 if( mpStyleSheet )
140 mpStyleSheet->notifyModifyListener();
143 SdStyleSheet::SdStyleSheet(const OUString& rDisplayName, SfxStyleSheetBasePool& _rPool, SfxStyleFamily eFamily, SfxStyleSearchBits _nMask)
144 : SdStyleSheetBase( rDisplayName, _rPool, eFamily, _nMask)
145 , msApiName( rDisplayName )
146 , mxPool( &_rPool )
150 SdStyleSheet::~SdStyleSheet()
152 delete pSet;
153 pSet = nullptr; // that following destructors also get a change
156 void SdStyleSheet::SetApiName( const OUString& rApiName )
158 msApiName = rApiName;
161 OUString const & SdStyleSheet::GetApiName() const
163 if( !msApiName.isEmpty() )
164 return msApiName;
165 else
166 return GetName();
169 bool SdStyleSheet::SetParent(const OUString& rParentName)
171 bool bResult = false;
173 if (SfxStyleSheet::SetParent(rParentName))
175 // PseudoStyleSheets do not have their own ItemSets
176 if (nFamily != SfxStyleFamily::Pseudo)
178 if( !rParentName.isEmpty() )
180 SfxStyleSheetBase* pStyle = m_pPool->Find(rParentName, nFamily);
181 if (pStyle)
183 bResult = true;
184 SfxItemSet& rParentSet = pStyle->GetItemSet();
185 GetItemSet().SetParent(&rParentSet);
186 Broadcast( SfxHint( SfxHintId::DataChanged ) );
189 else
191 bResult = true;
192 GetItemSet().SetParent(nullptr);
193 Broadcast( SfxHint( SfxHintId::DataChanged ) );
196 else
198 bResult = true;
201 return bResult;
205 * create if necessary and return ItemSets
207 SfxItemSet& SdStyleSheet::GetItemSet()
209 if (nFamily == SfxStyleFamily::Para || nFamily == SfxStyleFamily::Page)
211 // we create the ItemSet 'on demand' if necessary
212 if (!pSet)
214 pSet = new SfxItemSetFixed<
215 XATTR_LINE_FIRST, XATTR_LINE_LAST,
216 XATTR_FILL_FIRST, XATTR_FILL_LAST,
217 SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST,
218 SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_WORDWRAP,
219 SDRATTR_EDGE_FIRST, SDRATTR_MEASURE_LAST,
220 SDRATTR_3D_FIRST, SDRATTR_3D_LAST,
221 EE_PARA_START, EE_CHAR_END>(GetPool()->GetPool());
222 bMySet = true;
225 return *pSet;
228 else if( nFamily == SfxStyleFamily::Frame )
230 if (!pSet)
232 pSet = new SfxItemSetFixed<
233 XATTR_LINE_FIRST, XATTR_LINE_LAST,
234 XATTR_FILL_FIRST, XATTR_FILL_LAST,
235 SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST,
236 SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_XMLATTRIBUTES,
237 SDRATTR_TEXT_WORDWRAP, SDRATTR_TEXT_WORDWRAP,
238 SDRATTR_TABLE_FIRST, SDRATTR_TABLE_LAST,
239 EE_PARA_START, EE_CHAR_END>(GetPool()->GetPool());
241 bMySet = true;
244 return *pSet;
247 // this is a dummy template for the internal template of the
248 // current presentation layout; return the ItemSet of that template
249 else
252 SdStyleSheet* pSdSheet = GetRealStyleSheet();
254 if (pSdSheet)
256 return pSdSheet->GetItemSet();
258 else
260 if (!pSet)
262 pSet = new SfxItemSetFixed<
263 XATTR_LINE_FIRST, XATTR_LINE_LAST,
264 XATTR_FILL_FIRST, XATTR_FILL_LAST,
265 SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST,
266 SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_WORDWRAP,
267 SDRATTR_EDGE_FIRST, SDRATTR_MEASURE_LAST,
268 SDRATTR_3D_FIRST, SDRATTR_3D_LAST,
269 EE_PARA_START, EE_CHAR_END>(GetPool()->GetPool());
270 bMySet = true;
273 return(*pSet);
279 * A template is used when it is referenced by inserted object or by a used
280 * template.
282 bool SdStyleSheet::IsUsed() const
284 bool bResult = false;
286 const size_t nListenerCount = GetSizeOfVector();
287 for (size_t n = 0; n < nListenerCount; ++n)
289 SfxListener* pListener = GetListener(n);
290 if( pListener == this )
291 continue;
293 const svl::StyleSheetUser* const pUser(dynamic_cast<svl::StyleSheetUser*>(pListener));
294 if (pUser)
295 bResult = pUser->isUsedByModel();
296 if (bResult)
297 break;
300 if( !bResult )
302 std::unique_lock aGuard( m_aMutex );
304 if( maModifyListeners.getLength(aGuard) )
306 std::vector<css::uno::Reference<XModifyListener>> aModifyListeners( maModifyListeners.getElements(aGuard) );
307 bResult = std::any_of(aModifyListeners.begin(), aModifyListeners.end(),
308 [](const Reference<XInterface>& rListener) {
309 Reference< XStyle > xStyle( rListener, UNO_QUERY );
312 Reference<XPropertySet> xPropertySet(xStyle, UNO_QUERY_THROW);
313 if (xPropertySet->getPropertyValue("IsPhysical").get<bool>())
314 return true;
316 catch (const Exception&)
319 return xStyle.is() && xStyle->isInUse();
323 return bResult;
327 * Checks if a cell style is used in two places at once.
328 * Typically we modify the formatting of a single place,
329 * so such style shouldn't be edited directly.
331 bool SdStyleSheet::IsEditable()
333 if (GetFamily() != SfxStyleFamily::Frame)
334 return true;
336 if (!IsUserDefined())
337 return false;
339 const size_t nListenerCount = GetSizeOfVector();
340 for (size_t n = 0; n < nListenerCount; ++n)
342 SfxListener* pListener = GetListener(n);
343 if (pListener == this)
344 continue;
345 if (dynamic_cast<SdStyleSheet*>(pListener))
346 return false;
349 std::unique_lock aGuard(m_aMutex);
350 return maModifyListeners.getLength(aGuard) <= 1;
354 * Determine the style sheet for which this dummy is for.
356 SdStyleSheet* SdStyleSheet::GetRealStyleSheet() const
358 OUString aRealStyle;
359 OUString aSep( SD_LT_SEPARATOR );
360 SdStyleSheet* pRealStyle = nullptr;
361 SdDrawDocument* pDoc = static_cast<SdStyleSheetPool*>(m_pPool)->GetDoc();
363 ::sd::DrawViewShell* pDrawViewShell = nullptr;
365 ::sd::ViewShellBase* pBase = dynamic_cast< ::sd::ViewShellBase* >( SfxViewShell::Current() );
366 if( pBase )
367 pDrawViewShell = dynamic_cast< ::sd::DrawViewShell* >( pBase->GetMainViewShell().get() );
369 if (pDrawViewShell && pDrawViewShell->GetDoc() == pDoc)
371 SdPage* pPage = pDrawViewShell->getCurrentPage();
372 if( pPage )
374 aRealStyle = pPage->GetLayoutName();
375 // cut after separator string
377 if( aRealStyle.indexOf(aSep) >= 0)
379 aRealStyle = aRealStyle.copy(0,(aRealStyle.indexOf(aSep) + aSep.getLength()));
383 if (aRealStyle.isEmpty())
385 SdPage* pPage = pDoc->GetSdPage(0, PageKind::Standard);
387 if (pPage)
389 aRealStyle = pDoc->GetSdPage(0, PageKind::Standard)->GetLayoutName();
391 else
393 /* no page available yet. This can happen when actualizing the
394 document templates. */
395 SfxStyleSheetIterator aIter(m_pPool, SfxStyleFamily::Page);
396 SfxStyleSheetBase* pSheet = aIter.First();
397 if( pSheet )
398 aRealStyle = pSheet->GetName();
401 if( aRealStyle.indexOf(aSep) >= 0)
403 aRealStyle = aRealStyle.copy(0,(aRealStyle.indexOf(aSep) + aSep.getLength()));
407 /* now map from the name (specified for country language) to the internal
408 name (independent of the country language) */
409 OUString aInternalName;
410 OUString aStyleName(aName);
412 if (aStyleName == SdResId(STR_PSEUDOSHEET_TITLE))
414 aInternalName = STR_LAYOUT_TITLE;
416 else if (aStyleName == SdResId(STR_PSEUDOSHEET_SUBTITLE))
418 aInternalName = STR_LAYOUT_SUBTITLE;
420 else if (aStyleName == SdResId(STR_PSEUDOSHEET_BACKGROUND))
422 aInternalName = STR_LAYOUT_BACKGROUND;
424 else if (aStyleName == SdResId(STR_PSEUDOSHEET_BACKGROUNDOBJECTS))
426 aInternalName = STR_LAYOUT_BACKGROUNDOBJECTS;
428 else if (aStyleName == SdResId(STR_PSEUDOSHEET_NOTES))
430 aInternalName = STR_LAYOUT_NOTES;
432 else
434 OUString aOutlineStr(SdResId(STR_PSEUDOSHEET_OUTLINE));
435 sal_Int32 nPos = aStyleName.indexOf(aOutlineStr);
436 if (nPos >= 0)
438 std::u16string_view aNumStr(aStyleName.subView(aOutlineStr.getLength()));
439 aInternalName = STR_LAYOUT_OUTLINE + aNumStr;
443 aRealStyle += aInternalName;
444 pRealStyle = static_cast< SdStyleSheet* >( m_pPool->Find(aRealStyle, SfxStyleFamily::Page) );
446 #ifdef DBG_UTIL
447 if( !pRealStyle )
449 SfxStyleSheetIterator aIter(m_pPool, SfxStyleFamily::Page);
450 if( aIter.Count() > 0 )
451 // StyleSheet not found, but pool already loaded
452 DBG_ASSERT(pRealStyle, "Internal StyleSheet not found");
454 #endif
456 return pRealStyle;
460 * Determine pseudo style sheet which stands for this style sheet.
462 SdStyleSheet* SdStyleSheet::GetPseudoStyleSheet() const
464 SdStyleSheet* pPseudoStyle = nullptr;
465 OUString aSep( SD_LT_SEPARATOR );
466 OUString aStyleName(aName);
467 // without layout name and separator
469 if( aStyleName.indexOf(aSep) >=0 )
471 aStyleName = aStyleName.copy (aStyleName.indexOf(aSep) + aSep.getLength());
474 if (aStyleName == STR_LAYOUT_TITLE)
476 aStyleName = SdResId(STR_PSEUDOSHEET_TITLE);
478 else if (aStyleName == STR_LAYOUT_SUBTITLE)
480 aStyleName = SdResId(STR_PSEUDOSHEET_SUBTITLE);
482 else if (aStyleName == STR_LAYOUT_BACKGROUND)
484 aStyleName = SdResId(STR_PSEUDOSHEET_BACKGROUND);
486 else if (aStyleName == STR_LAYOUT_BACKGROUNDOBJECTS)
488 aStyleName = SdResId(STR_PSEUDOSHEET_BACKGROUNDOBJECTS);
490 else if (aStyleName == STR_LAYOUT_NOTES)
492 aStyleName = SdResId(STR_PSEUDOSHEET_NOTES);
494 else
496 OUString aOutlineStr(STR_LAYOUT_OUTLINE);
497 sal_Int32 nPos = aStyleName.indexOf(aOutlineStr);
498 if (nPos != -1)
500 std::u16string_view aNumStr(aStyleName.subView(aOutlineStr.getLength()));
501 aStyleName = SdResId(STR_PSEUDOSHEET_OUTLINE) + aNumStr;
505 pPseudoStyle = static_cast<SdStyleSheet*>(m_pPool->Find(aStyleName, SfxStyleFamily::Pseudo));
506 DBG_ASSERT(pPseudoStyle, "PseudoStyleSheet missing");
508 return pPseudoStyle;
511 void SdStyleSheet::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
513 // first, base class functionality
514 SfxStyleSheet::Notify(rBC, rHint);
516 if (nFamily != SfxStyleFamily::Pseudo)
517 return;
519 /* if the dummy gets a notify about a changed attribute, he takes care that
520 the actual meant style sheet sends broadcasts. */
521 if (rHint.GetId() == SfxHintId::DataChanged)
523 SdStyleSheet* pRealStyle = GetRealStyleSheet();
524 if (pRealStyle)
525 pRealStyle->Broadcast(rHint);
530 * Adjust the bullet width and the left text indent of the provided ItemSets to
531 * their font height. The new values are calculated that the ratio to the font
532 * height is as in the style sheet.
534 * @param bOnlyMissingItems If sal_True, only not set items are completed. With
535 * sal_False, are items are overwritten.
537 void SdStyleSheet::AdjustToFontHeight(SfxItemSet& rSet, bool bOnlyMissingItems)
539 /* If not explicit set, adjust bullet width and text indent to new font
540 height. */
541 SfxStyleFamily eFamily = nFamily;
542 OUString aStyleName(aName);
543 if (eFamily == SfxStyleFamily::Pseudo)
545 SfxStyleSheet* pRealStyle = GetRealStyleSheet();
546 eFamily = pRealStyle->GetFamily();
547 aStyleName = pRealStyle->GetName();
550 if (!(eFamily == SfxStyleFamily::Page &&
551 aStyleName.indexOf(STR_LAYOUT_OUTLINE) != -1 &&
552 rSet.GetItemState(EE_CHAR_FONTHEIGHT) == SfxItemState::SET))
553 return;
555 const SfxItemSet* pCurSet = &GetItemSet();
556 sal_uInt32 nNewHeight = rSet.Get(EE_CHAR_FONTHEIGHT).GetHeight();
557 sal_uInt32 nOldHeight = pCurSet->Get(EE_CHAR_FONTHEIGHT).GetHeight();
559 if (rSet.GetItemState(EE_PARA_BULLET) != SfxItemState::SET || !bOnlyMissingItems)
561 const SvxBulletItem& rBItem = pCurSet->Get(EE_PARA_BULLET);
562 double fBulletFraction = double(rBItem.GetWidth()) / nOldHeight;
563 SvxBulletItem aNewBItem(rBItem);
564 aNewBItem.SetWidth(static_cast<sal_uInt32>(fBulletFraction * nNewHeight));
565 rSet.Put(aNewBItem);
568 if (rSet.GetItemState(EE_PARA_LRSPACE) != SfxItemState::SET || !bOnlyMissingItems)
570 const SvxLRSpaceItem& rLRItem = pCurSet->Get(EE_PARA_LRSPACE);
571 double fIndentFraction = double(rLRItem.GetTextLeft()) / nOldHeight;
572 SvxLRSpaceItem aNewLRItem(rLRItem);
573 aNewLRItem.SetTextLeft(fIndentFraction * nNewHeight);
574 double fFirstIndentFraction = double(rLRItem.GetTextFirstLineOffset()) / nOldHeight;
575 aNewLRItem.SetTextFirstLineOffset(static_cast<short>(fFirstIndentFraction * nNewHeight));
576 rSet.Put(aNewLRItem);
579 if (rSet.GetItemState(EE_PARA_ULSPACE) != SfxItemState::SET || !bOnlyMissingItems)
581 const SvxULSpaceItem& rULItem = pCurSet->Get(EE_PARA_ULSPACE);
582 SvxULSpaceItem aNewULItem(rULItem);
583 double fLowerFraction = double(rULItem.GetLower()) / nOldHeight;
584 aNewULItem.SetLower(static_cast<sal_uInt16>(fLowerFraction * nNewHeight));
585 double fUpperFraction = double(rULItem.GetUpper()) / nOldHeight;
586 aNewULItem.SetUpper(static_cast<sal_uInt16>(fUpperFraction * nNewHeight));
587 rSet.Put(aNewULItem);
591 bool SdStyleSheet::HasFollowSupport() const
593 return false;
596 bool SdStyleSheet::HasParentSupport() const
598 return true;
601 bool SdStyleSheet::HasClearParentSupport() const
603 return true;
606 namespace
608 struct ApiNameMap
610 std::u16string_view mpApiName;
611 sal_uInt32 mnHelpId;
612 } const pApiNameMap[]
613 = { { std::u16string_view(u"title"), HID_PSEUDOSHEET_TITLE },
614 { std::u16string_view(u"subtitle"), HID_PSEUDOSHEET_SUBTITLE },
615 { std::u16string_view(u"background"), HID_PSEUDOSHEET_BACKGROUND },
616 { std::u16string_view(u"backgroundobjects"), HID_PSEUDOSHEET_BACKGROUNDOBJECTS },
617 { std::u16string_view(u"notes"), HID_PSEUDOSHEET_NOTES },
618 { std::u16string_view(u"standard"), HID_STANDARD_STYLESHEET_NAME },
619 { std::u16string_view(u"objectwithoutfill"), HID_POOLSHEET_OBJWITHOUTFILL },
621 { std::u16string_view(u"Text"), HID_POOLSHEET_TEXT },
622 { std::u16string_view(u"A4"), HID_POOLSHEET_A4 },
623 { std::u16string_view(u"Title A4"), HID_POOLSHEET_A4_TITLE },
624 { std::u16string_view(u"Heading A4"), HID_POOLSHEET_A4_HEADLINE },
625 { std::u16string_view(u"Text A4"), HID_POOLSHEET_A4_TEXT },
626 { std::u16string_view(u"A0"), HID_POOLSHEET_A0 },
627 { std::u16string_view(u"Title A0"), HID_POOLSHEET_A0_TITLE },
628 { std::u16string_view(u"Heading A0"), HID_POOLSHEET_A0_HEADLINE },
629 { std::u16string_view(u"Text A0"), HID_POOLSHEET_A0_TEXT },
631 { std::u16string_view(u"Graphic"), HID_POOLSHEET_GRAPHIC },
632 { std::u16string_view(u"Shapes"), HID_POOLSHEET_SHAPES },
633 { std::u16string_view(u"Filled"), HID_POOLSHEET_FILLED },
634 { std::u16string_view(u"Filled Blue"), HID_POOLSHEET_FILLED_BLUE },
635 { std::u16string_view(u"Filled Green"), HID_POOLSHEET_FILLED_GREEN },
636 { std::u16string_view(u"Filled Red"), HID_POOLSHEET_FILLED_RED },
637 { std::u16string_view(u"Filled Yellow"), HID_POOLSHEET_FILLED_YELLOW },
638 { std::u16string_view(u"Outlined"), HID_POOLSHEET_OUTLINE },
639 { std::u16string_view(u"Outlined Blue"), HID_POOLSHEET_OUTLINE_BLUE },
640 { std::u16string_view(u"Outlined Green"), HID_POOLSHEET_OUTLINE_GREEN },
641 { std::u16string_view(u"Outlined Red"), HID_POOLSHEET_OUTLINE_RED },
642 { std::u16string_view(u"Outlined Yellow"), HID_POOLSHEET_OUTLINE_YELLOW },
643 { std::u16string_view(u"Lines"), HID_POOLSHEET_LINES },
644 { std::u16string_view(u"Arrow Line"), HID_POOLSHEET_MEASURE },
645 { std::u16string_view(u"Arrow Dashed"), HID_POOLSHEET_LINES_DASHED }
648 OUString GetApiNameForHelpId(sal_uLong nId)
650 if ((nId >= HID_PSEUDOSHEET_OUTLINE1) && (nId <= HID_PSEUDOSHEET_OUTLINE9))
651 return "outline" + OUStringChar(sal_Unicode('1' + (nId - HID_PSEUDOSHEET_OUTLINE1)));
653 for (const auto& i : pApiNameMap)
654 if (nId == i.mnHelpId)
655 return OUString(i.mpApiName);
657 return OUString();
660 sal_uInt32 GetHelpIdForApiName(std::u16string_view sName)
662 std::u16string_view sRest;
663 if (o3tl::starts_with(sName, u"outline", &sRest))
665 if (sRest.length() == 1)
667 sal_Unicode ch = sRest.front();
668 if ('1' <= ch && ch <= '9')
669 return HID_PSEUDOSHEET_OUTLINE1 + ch - '1';
671 // No other pre-defined names start with "outline"
672 return 0;
675 for (const auto& i : pApiNameMap)
676 if (sName == i.mpApiName)
677 return i.mnHelpId;
679 return 0;
683 void SdStyleSheet::SetHelpId( const OUString& r, sal_uLong nId )
685 SfxStyleSheet::SetHelpId( r, nId );
687 const OUString sNewApiName = GetApiNameForHelpId(nId);
688 if (!sNewApiName.isEmpty())
689 msApiName = sNewApiName;
692 OUString SdStyleSheet::GetFamilyString( SfxStyleFamily eFamily )
694 switch( eFamily )
696 case SfxStyleFamily::Frame:
697 return "cell";
698 default:
699 OSL_FAIL( "SdStyleSheet::GetFamilyString(), illegal family!" );
700 [[fallthrough]];
701 case SfxStyleFamily::Para:
702 return "graphics";
706 void SdStyleSheet::throwIfDisposed()
708 if( !mxPool.is() )
709 throw DisposedException();
712 rtl::Reference<SdStyleSheet> SdStyleSheet::CreateEmptyUserStyle( SfxStyleSheetBasePool& rPool, SfxStyleFamily eFamily )
714 OUString aName;
715 sal_Int32 nIndex = 1;
718 aName = "user" + OUString::number( nIndex++ );
720 while( rPool.Find( aName, eFamily ) != nullptr );
722 return new SdStyleSheet(aName, rPool, eFamily, SfxStyleSearchBits::UserDefined);
725 // XInterface
727 void SAL_CALL SdStyleSheet::release( ) noexcept
729 if (osl_atomic_decrement( &m_refCount ) != 0)
730 return;
732 // restore reference count:
733 osl_atomic_increment( &m_refCount );
734 if (! m_bDisposed) try
736 dispose();
738 catch (RuntimeException const&)
740 // don't break throw ()
741 TOOLS_WARN_EXCEPTION( "sd", "" );
743 OSL_ASSERT( m_bDisposed );
744 SdStyleSheetBase::release();
747 // XComponent
749 void SAL_CALL SdStyleSheet::dispose( )
752 std::unique_lock aGuard(m_aMutex);
753 if (m_bDisposed || m_bInDispose)
754 return;
756 m_bInDispose = true;
760 std::unique_lock aGuard(m_aMutex);
761 // side effect: keeping a reference to this
762 EventObject aEvt( static_cast< OWeakObject * >( this ) );
765 maModifyListeners.disposeAndClear( aGuard, aEvt );
766 maEventListeners.disposeAndClear( aGuard, aEvt );
767 disposing();
769 catch (...)
771 // bDisposed and bInDispose must be set in this order:
772 m_bDisposed = true;
773 m_bInDispose = false;
774 throw;
776 // bDisposed and bInDispose must be set in this order:
777 m_bDisposed = true;
778 m_bInDispose = false;
780 catch (RuntimeException &)
782 throw;
784 catch (const Exception & exc)
786 css::uno::Any anyEx = cppu::getCaughtException();
787 throw css::lang::WrappedTargetRuntimeException(
788 "unexpected UNO exception caught: " + exc.Message ,
789 nullptr, anyEx );
793 void SdStyleSheet::disposing()
795 SolarMutexGuard aGuard;
796 if (bMySet)
798 delete pSet;
800 pSet = nullptr;
801 m_pPool = nullptr;
802 mxPool.clear();
805 void SAL_CALL SdStyleSheet::addEventListener( const Reference< XEventListener >& xListener )
807 std::unique_lock aGuard( m_aMutex );
808 if (m_bDisposed || m_bInDispose)
810 aGuard.unlock();
811 EventObject aEvt( static_cast< OWeakObject * >( this ) );
812 xListener->disposing( aEvt );
814 else
816 maEventListeners.addInterface( aGuard, xListener );
820 void SAL_CALL SdStyleSheet::removeEventListener( const Reference< XEventListener >& xListener )
822 std::unique_lock aGuard( m_aMutex );
823 maEventListeners.removeInterface( aGuard, xListener );
826 // XModifyBroadcaster
828 void SAL_CALL SdStyleSheet::addModifyListener( const Reference< XModifyListener >& xListener )
830 std::unique_lock aGuard( m_aMutex );
831 if (m_bDisposed || m_bInDispose)
833 aGuard.unlock();
834 EventObject aEvt( static_cast< OWeakObject * >( this ) );
835 xListener->disposing( aEvt );
837 else
839 if (!mpModifyListenerForwarder)
840 mpModifyListenerForwarder.reset( new ModifyListenerForwarder( this ) );
841 maModifyListeners.addInterface( aGuard, xListener );
845 void SAL_CALL SdStyleSheet::removeModifyListener( const Reference< XModifyListener >& xListener )
847 std::unique_lock aGuard( m_aMutex );
848 maModifyListeners.removeInterface( aGuard, xListener );
851 void SdStyleSheet::notifyModifyListener()
853 std::unique_lock aGuard( m_aMutex );
855 if( maModifyListeners.getLength(aGuard) )
857 EventObject aEvt( static_cast< OWeakObject * >( this ) );
858 maModifyListeners.notifyEach(aGuard, &XModifyListener::modified, aEvt);
862 // XServiceInfo
863 OUString SAL_CALL SdStyleSheet::getImplementationName()
865 return "SdStyleSheet";
868 sal_Bool SAL_CALL SdStyleSheet::supportsService( const OUString& ServiceName )
870 return cppu::supportsService( this, ServiceName );
873 Sequence< OUString > SAL_CALL SdStyleSheet::getSupportedServiceNames()
875 return { "com.sun.star.style.Style",
876 "com.sun.star.drawing.FillProperties",
877 "com.sun.star.drawing.LineProperties",
878 "com.sun.star.drawing.ShadowProperties",
879 "com.sun.star.drawing.ConnectorProperties",
880 "com.sun.star.drawing.MeasureProperties",
881 "com.sun.star.style.ParagraphProperties",
882 "com.sun.star.style.CharacterProperties",
883 "com.sun.star.drawing.TextProperties",
884 "com.sun.star.drawing.Text" };
887 bool SdStyleSheet::SetName(const OUString& rNewName, bool bReindexNow)
889 const bool bResult = SfxUnoStyleSheet::SetName(rNewName, bReindexNow);
890 // Don't overwrite predefined API names
891 if (bResult && GetHelpIdForApiName(msApiName) == 0)
893 msApiName = rNewName;
894 Broadcast(SfxHint(SfxHintId::DataChanged));
896 return bResult;
899 // XNamed
900 OUString SAL_CALL SdStyleSheet::getName()
902 SolarMutexGuard aGuard;
903 throwIfDisposed();
904 return GetApiName();
907 void SAL_CALL SdStyleSheet::setName( const OUString& rName )
909 SolarMutexGuard aGuard;
910 throwIfDisposed();
911 SetName(rName);
914 // XStyle
916 sal_Bool SAL_CALL SdStyleSheet::isUserDefined()
918 SolarMutexGuard aGuard;
919 throwIfDisposed();
920 return IsUserDefined();
923 sal_Bool SAL_CALL SdStyleSheet::isInUse()
925 SolarMutexGuard aGuard;
926 throwIfDisposed();
927 return IsUsed();
930 OUString SAL_CALL SdStyleSheet::getParentStyle()
932 SolarMutexGuard aGuard;
933 throwIfDisposed();
935 if( !GetParent().isEmpty() )
937 SdStyleSheet* pParentStyle = static_cast< SdStyleSheet* >( mxPool->Find( GetParent(), nFamily ) );
938 if( pParentStyle )
939 return pParentStyle->GetApiName();
941 return OUString();
944 void SAL_CALL SdStyleSheet::setParentStyle( const OUString& rParentName )
946 SolarMutexGuard aGuard;
947 throwIfDisposed();
949 if( !rParentName.isEmpty() )
951 OUString const name(GetName());
952 sal_Int32 const sep(name.indexOf(SD_LT_SEPARATOR));
953 OUString const master((sep == -1) ? OUString() : name.copy(0, sep));
954 std::shared_ptr<SfxStyleSheetIterator> aSSSI = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), nFamily);
955 for (SfxStyleSheetBase *pStyle = aSSSI->First(); pStyle; pStyle = aSSSI->Next())
957 // we hope that we have only sd style sheets
958 SdStyleSheet* pSdStyleSheet = static_cast<SdStyleSheet*>(pStyle);
959 OUString const curName(pStyle->GetName());
960 sal_Int32 const curSep(curName.indexOf(SD_LT_SEPARATOR));
961 OUString const curMaster((curSep == -1)
962 ? OUString() : curName.copy(0, curSep));
963 // check that the master matches, as msApiName exists once per
964 // master page
965 if (pSdStyleSheet->msApiName == rParentName && master == curMaster)
967 if( pStyle != this )
969 SetParent(curName);
971 return;
974 throw NoSuchElementException();
976 else
978 SetParent( rParentName );
982 // XPropertySet/XMultiPropertySet utility functions
984 // Does not broadcast
985 // Must be guarded by solar mutex; must not be disposed
986 void SdStyleSheet::setPropertyValue_Impl(const OUString& aPropertyName, const css::uno::Any& aValue)
988 const SfxItemPropertyMapEntry* pEntry = getPropertyMapEntry( aPropertyName );
989 if( pEntry == nullptr )
991 throw UnknownPropertyException( aPropertyName, static_cast<cppu::OWeakObject*>(this));
994 if( pEntry->nWID == WID_STYLE_HIDDEN )
996 bool bValue = false;
997 if ( aValue >>= bValue )
998 SetHidden( bValue );
999 return;
1001 if( pEntry->nWID == SDRATTR_TEXTDIRECTION )
1002 return; // not yet implemented for styles
1004 if( pEntry->nWID == WID_STYLE_FAMILY )
1005 throw PropertyVetoException();
1007 if( (pEntry->nWID == EE_PARA_NUMBULLET) && (GetFamily() == SfxStyleFamily::Page) )
1009 OUString aStr;
1010 const sal_uInt32 nTempHelpId = GetHelpId( aStr );
1012 if( (nTempHelpId >= HID_PSEUDOSHEET_OUTLINE2) && (nTempHelpId <= HID_PSEUDOSHEET_OUTLINE9) )
1013 return;
1016 SfxItemSet &rStyleSet = GetItemSet();
1018 if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
1020 BitmapMode eMode;
1021 if( aValue >>= eMode )
1023 rStyleSet.Put( XFillBmpStretchItem( eMode == BitmapMode_STRETCH ) );
1024 rStyleSet.Put( XFillBmpTileItem( eMode == BitmapMode_REPEAT ) );
1025 return;
1027 throw IllegalArgumentException();
1030 if (pEntry->nWID == OWN_ATTR_TEXTCOLUMNS)
1032 if (css::uno::Reference<css::text::XTextColumns> xColumns; aValue >>= xColumns)
1034 rStyleSet.Put(SfxInt16Item(SDRATTR_TEXTCOLUMNS_NUMBER, xColumns->getColumnCount()));
1035 if (css::uno::Reference<css::beans::XPropertySet> xPropSet{ xColumns,
1036 css::uno::UNO_QUERY })
1038 auto aVal = xPropSet->getPropertyValue("AutomaticDistance");
1039 if (sal_Int32 nSpacing; aVal >>= nSpacing)
1040 rStyleSet.Put(SdrMetricItem(SDRATTR_TEXTCOLUMNS_SPACING, nSpacing));
1042 return;
1044 throw IllegalArgumentException();
1047 SfxItemSet aSet( GetPool()->GetPool(), pEntry->nWID, pEntry->nWID);
1048 aSet.Put( rStyleSet );
1050 if( !aSet.Count() )
1052 if( EE_PARA_NUMBULLET == pEntry->nWID )
1054 vcl::Font aBulletFont;
1055 SdStyleSheetPool::PutNumBulletItem( this, aBulletFont );
1056 aSet.Put( rStyleSet );
1058 else
1060 aSet.Put( GetPool()->GetPool().GetDefaultItem( pEntry->nWID ) );
1064 if( pEntry->nMemberId == MID_NAME &&
1065 ( pEntry->nWID == XATTR_FILLBITMAP || pEntry->nWID == XATTR_FILLGRADIENT ||
1066 pEntry->nWID == XATTR_FILLHATCH || pEntry->nWID == XATTR_FILLFLOATTRANSPARENCE ||
1067 pEntry->nWID == XATTR_LINESTART || pEntry->nWID == XATTR_LINEEND || pEntry->nWID == XATTR_LINEDASH) )
1069 OUString aTempName;
1070 if(!(aValue >>= aTempName ))
1071 throw IllegalArgumentException();
1073 SvxShape::SetFillAttribute( pEntry->nWID, aTempName, aSet );
1075 else if(!SvxUnoTextRangeBase::SetPropertyValueHelper( pEntry, aValue, aSet ))
1077 SvxItemPropertySet_setPropertyValue( pEntry, aValue, aSet );
1080 rStyleSet.Put( aSet );
1083 // Must be guarded by solar mutex; must not be disposed
1084 css::uno::Any SdStyleSheet::getPropertyValue_Impl(const OUString& PropertyName)
1086 const SfxItemPropertyMapEntry* pEntry = getPropertyMapEntry( PropertyName );
1087 if( pEntry == nullptr )
1089 throw UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this));
1092 Any aAny;
1094 if( pEntry->nWID == WID_STYLE_FAMILY )
1096 if( nFamily == SfxStyleFamily::Page )
1098 const OUString aLayoutName( GetName() );
1099 aAny <<= aLayoutName.copy( 0, aLayoutName.indexOf( SD_LT_SEPARATOR) );
1101 else
1103 aAny <<= GetFamilyString(nFamily);
1106 else if( pEntry->nWID == WID_STYLE_DISPNAME )
1108 OUString aDisplayName;
1109 if ( nFamily == SfxStyleFamily::Page )
1111 const SdStyleSheet* pStyleSheet = GetPseudoStyleSheet();
1112 if (pStyleSheet != nullptr)
1113 aDisplayName = pStyleSheet->GetName();
1116 if (aDisplayName.isEmpty())
1117 aDisplayName = GetName();
1119 aAny <<= aDisplayName;
1121 else if( pEntry->nWID == SDRATTR_TEXTDIRECTION )
1123 aAny <<= false;
1125 else if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
1127 SfxItemSet &rStyleSet = GetItemSet();
1129 const XFillBmpStretchItem* pStretchItem = rStyleSet.GetItem<XFillBmpStretchItem>(XATTR_FILLBMP_STRETCH);
1130 const XFillBmpTileItem* pTileItem = rStyleSet.GetItem<XFillBmpTileItem>(XATTR_FILLBMP_TILE);
1132 if( pStretchItem && pTileItem )
1134 if( pTileItem->GetValue() )
1135 aAny <<= BitmapMode_REPEAT;
1136 else if( pStretchItem->GetValue() )
1137 aAny <<= BitmapMode_STRETCH;
1138 else
1139 aAny <<= BitmapMode_NO_REPEAT;
1142 else if( pEntry->nWID == WID_STYLE_HIDDEN )
1144 aAny <<= IsHidden( );
1146 else if (pEntry->nWID == OWN_ATTR_TEXTCOLUMNS)
1148 const SfxItemSet& rStyleSet = GetItemSet();
1150 auto xIf = SvxXTextColumns_createInstance();
1151 css::uno::Reference<css::text::XTextColumns> xCols(xIf, css::uno::UNO_QUERY_THROW);
1152 xCols->setColumnCount(rStyleSet.Get(SDRATTR_TEXTCOLUMNS_NUMBER).GetValue());
1153 css::uno::Reference<css::beans::XPropertySet> xProp(xIf, css::uno::UNO_QUERY_THROW);
1154 xProp->setPropertyValue(
1155 "AutomaticDistance",
1156 css::uno::Any(rStyleSet.Get(SDRATTR_TEXTCOLUMNS_SPACING).GetValue()));
1157 aAny <<= xIf;
1159 else
1161 SfxItemSet aSet( GetPool()->GetPool(), pEntry->nWID, pEntry->nWID);
1163 const SfxPoolItem* pItem;
1164 SfxItemSet& rStyleSet = GetItemSet();
1166 if( rStyleSet.GetItemState( pEntry->nWID, true, &pItem ) == SfxItemState::SET )
1167 aSet.Put( *pItem );
1169 if( !aSet.Count() )
1170 aSet.Put( GetPool()->GetPool().GetDefaultItem( pEntry->nWID ) );
1172 if(SvxUnoTextRangeBase::GetPropertyValueHelper( aSet, pEntry, aAny ))
1173 return aAny;
1175 // Get value of ItemSet
1176 aAny = SvxItemPropertySet_getPropertyValue( pEntry, aSet );
1179 if( pEntry->aType != aAny.getValueType() )
1181 // since the sfx uint16 item now exports a sal_Int32, we may have to fix this here
1182 if( ( pEntry->aType == ::cppu::UnoType<sal_Int16>::get()) && aAny.getValueType() == ::cppu::UnoType<sal_Int32>::get() )
1184 sal_Int32 nValue = 0;
1185 aAny >>= nValue;
1186 aAny <<= static_cast<sal_Int16>(nValue);
1188 else
1190 OSL_FAIL("SvxShape::GetAnyForItem() Returnvalue has wrong Type!" );
1194 return aAny;
1197 // XPropertySet
1199 Reference< XPropertySetInfo > SdStyleSheet::getPropertySetInfo()
1201 throwIfDisposed();
1202 static Reference< XPropertySetInfo > xInfo = GetStylePropertySet().getPropertySetInfo();
1203 return xInfo;
1206 void SAL_CALL SdStyleSheet::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
1208 SolarMutexGuard aGuard;
1209 throwIfDisposed();
1211 setPropertyValue_Impl(aPropertyName, aValue);
1212 Broadcast(SfxHint(SfxHintId::DataChanged));
1215 Any SAL_CALL SdStyleSheet::getPropertyValue( const OUString& PropertyName )
1217 SolarMutexGuard aGuard;
1218 throwIfDisposed();
1220 return getPropertyValue_Impl(PropertyName);
1223 void SAL_CALL SdStyleSheet::addPropertyChangeListener( const OUString& , const Reference< XPropertyChangeListener >& ) {}
1224 void SAL_CALL SdStyleSheet::removePropertyChangeListener( const OUString& , const Reference< XPropertyChangeListener >& ) {}
1225 void SAL_CALL SdStyleSheet::addVetoableChangeListener( const OUString& , const Reference< XVetoableChangeListener >& ) {}
1226 void SAL_CALL SdStyleSheet::removeVetoableChangeListener( const OUString& , const Reference< XVetoableChangeListener >& ) {}
1228 // XMultiPropertySet
1230 void SAL_CALL SdStyleSheet::setPropertyValues(const css::uno::Sequence<OUString>& aPropertyNames,
1231 const css::uno::Sequence<css::uno::Any>& aValues)
1233 const sal_Int32 nCount = aPropertyNames.getLength();
1235 if (nCount != aValues.getLength())
1236 throw css::lang::IllegalArgumentException();
1238 if (!nCount)
1239 return;
1241 SolarMutexGuard aGuard;
1242 throwIfDisposed();
1244 for (sal_Int32 i = 0; i < nCount; ++i)
1248 setPropertyValue_Impl(aPropertyNames[i], aValues[i]);
1250 catch (const css::beans::UnknownPropertyException&)
1252 DBG_UNHANDLED_EXCEPTION("sd");
1256 Broadcast(SfxHint(SfxHintId::DataChanged));
1259 css::uno::Sequence<css::uno::Any>
1260 SAL_CALL SdStyleSheet::getPropertyValues(const css::uno::Sequence<OUString>& aPropertyNames)
1262 SolarMutexGuard aGuard;
1263 throwIfDisposed();
1265 const sal_Int32 nCount = aPropertyNames.getLength();
1266 css::uno::Sequence<css::uno::Any> aValues(nCount);
1267 Any* pAny = aValues.getArray();
1269 for (sal_Int32 i = 0; i < nCount; ++i)
1270 pAny[i] = getPropertyValue_Impl(aPropertyNames[i]);
1272 return aValues;
1275 void SAL_CALL SdStyleSheet::addPropertiesChangeListener(const css::uno::Sequence<OUString>&, const css::uno::Reference<css::beans::XPropertiesChangeListener>&) {}
1276 void SAL_CALL SdStyleSheet::removePropertiesChangeListener(const css::uno::Reference<css::beans::XPropertiesChangeListener>&) {}
1277 void SAL_CALL SdStyleSheet::firePropertiesChangeEvent(const css::uno::Sequence<OUString>&, const css::uno::Reference<css::beans::XPropertiesChangeListener>&) {}
1279 // XPropertyState
1281 PropertyState SAL_CALL SdStyleSheet::getPropertyState( const OUString& PropertyName )
1283 SolarMutexGuard aGuard;
1285 throwIfDisposed();
1287 const SfxItemPropertyMapEntry* pEntry = getPropertyMapEntry( PropertyName );
1289 if( pEntry == nullptr )
1290 throw UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this));
1292 if( pEntry->nWID == WID_STYLE_FAMILY )
1294 return PropertyState_DIRECT_VALUE;
1296 else if( pEntry->nWID == SDRATTR_TEXTDIRECTION )
1298 return PropertyState_DEFAULT_VALUE;
1300 else if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
1302 const SfxItemSet& rSet = GetItemSet();
1304 if( rSet.GetItemState( XATTR_FILLBMP_STRETCH, false ) == SfxItemState::SET ||
1305 rSet.GetItemState( XATTR_FILLBMP_TILE, false ) == SfxItemState::SET )
1307 return PropertyState_DIRECT_VALUE;
1309 else
1311 return PropertyState_AMBIGUOUS_VALUE;
1314 else if (pEntry->nWID == OWN_ATTR_TEXTCOLUMNS)
1316 const SfxItemSet& rSet = GetItemSet();
1318 const auto eState1 = rSet.GetItemState(SDRATTR_TEXTCOLUMNS_NUMBER, false);
1319 const auto eState2 = rSet.GetItemState(SDRATTR_TEXTCOLUMNS_SPACING, false);
1320 if (eState1 == SfxItemState::SET || eState2 == SfxItemState::SET)
1321 return PropertyState_DIRECT_VALUE;
1322 else if (eState1 == SfxItemState::DEFAULT && eState2 == SfxItemState::DEFAULT)
1323 return PropertyState_DEFAULT_VALUE;
1324 else
1325 return PropertyState_AMBIGUOUS_VALUE;
1327 else
1329 SfxItemSet &rStyleSet = GetItemSet();
1331 PropertyState eState;
1333 switch( rStyleSet.GetItemState( pEntry->nWID, false ) )
1335 case SfxItemState::SET:
1336 eState = PropertyState_DIRECT_VALUE;
1337 break;
1338 case SfxItemState::DEFAULT:
1339 eState = PropertyState_DEFAULT_VALUE;
1340 break;
1341 default:
1342 eState = PropertyState_AMBIGUOUS_VALUE;
1343 break;
1346 // if an item is set, this doesn't mean we want it :)
1347 if( PropertyState_DIRECT_VALUE == eState )
1349 switch( pEntry->nWID )
1351 case XATTR_FILLBITMAP:
1352 case XATTR_FILLGRADIENT:
1353 case XATTR_FILLHATCH:
1354 case XATTR_FILLFLOATTRANSPARENCE:
1355 case XATTR_LINEEND:
1356 case XATTR_LINESTART:
1357 case XATTR_LINEDASH:
1359 const NameOrIndex* pItem = rStyleSet.GetItem<NameOrIndex>(pEntry->nWID);
1360 if( ( pItem == nullptr ) || pItem->GetName().isEmpty() )
1361 eState = PropertyState_DEFAULT_VALUE;
1363 break;
1364 case XATTR_FILLCOLOR:
1365 if (pEntry->nMemberId == MID_COLOR_THEME_INDEX)
1367 const XFillColorItem* pColor = rStyleSet.GetItem<XFillColorItem>(pEntry->nWID);
1368 if (pColor->getComplexColor().getSchemeType() == model::ThemeColorType::Unknown)
1370 eState = PropertyState_DEFAULT_VALUE;
1373 else if (pEntry->nMemberId == MID_COLOR_LUM_MOD)
1375 const XFillColorItem* pColor = rStyleSet.GetItem<XFillColorItem>(pEntry->nWID);
1376 sal_Int16 nLumMod = 10000;
1377 for (auto const& rTransform : pColor->getComplexColor().getTransformations())
1379 if (rTransform.meType == model::TransformationType::LumMod)
1380 nLumMod = rTransform.mnValue;
1382 if (nLumMod == 10000)
1384 eState = PropertyState_DEFAULT_VALUE;
1387 else if (pEntry->nMemberId == MID_COLOR_LUM_OFF)
1389 const XFillColorItem* pColor = rStyleSet.GetItem<XFillColorItem>(pEntry->nWID);
1390 sal_Int16 nLumOff = 0;
1391 for (auto const& rTransform : pColor->getComplexColor().getTransformations())
1393 if (rTransform.meType == model::TransformationType::LumOff)
1394 nLumOff = rTransform.mnValue;
1396 if (nLumOff == 0)
1398 eState = PropertyState_DEFAULT_VALUE;
1401 else if (pEntry->nMemberId == MID_COMPLEX_COLOR)
1403 auto const* pColor = rStyleSet.GetItem<XFillColorItem>(pEntry->nWID);
1404 if (pColor->getComplexColor().getType() == model::ColorType::Unused)
1406 eState = PropertyState_DEFAULT_VALUE;
1409 break;
1410 case XATTR_LINECOLOR:
1411 if (pEntry->nMemberId == MID_COMPLEX_COLOR)
1413 auto const* pColor = rStyleSet.GetItem<XLineColorItem>(pEntry->nWID);
1414 if (pColor->getComplexColor().getType() == model::ColorType::Unused)
1416 eState = PropertyState_DEFAULT_VALUE;
1419 break;
1423 return eState;
1427 Sequence< PropertyState > SAL_CALL SdStyleSheet::getPropertyStates( const Sequence< OUString >& aPropertyName )
1429 SolarMutexGuard aGuard;
1431 throwIfDisposed();
1433 sal_Int32 nCount = aPropertyName.getLength();
1435 Sequence< PropertyState > aPropertyStateSequence( nCount );
1437 std::transform(aPropertyName.begin(), aPropertyName.end(), aPropertyStateSequence.getArray(),
1438 [this](const OUString& rName) -> PropertyState { return getPropertyState(rName); });
1440 return aPropertyStateSequence;
1443 void SAL_CALL SdStyleSheet::setPropertyToDefault( const OUString& PropertyName )
1445 SolarMutexGuard aGuard;
1447 throwIfDisposed();
1449 const SfxItemPropertyMapEntry* pEntry = getPropertyMapEntry( PropertyName );
1450 if( pEntry == nullptr )
1451 throw UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this));
1453 SfxItemSet &rStyleSet = GetItemSet();
1455 if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
1457 rStyleSet.ClearItem( XATTR_FILLBMP_STRETCH );
1458 rStyleSet.ClearItem( XATTR_FILLBMP_TILE );
1460 else
1462 rStyleSet.ClearItem( pEntry->nWID );
1464 Broadcast(SfxHint(SfxHintId::DataChanged));
1467 Any SAL_CALL SdStyleSheet::getPropertyDefault( const OUString& aPropertyName )
1469 SolarMutexGuard aGuard;
1471 throwIfDisposed();
1473 const SfxItemPropertyMapEntry* pEntry = getPropertyMapEntry( aPropertyName );
1474 if( pEntry == nullptr )
1475 throw UnknownPropertyException( aPropertyName, static_cast<cppu::OWeakObject*>(this));
1476 Any aRet;
1477 if( pEntry->nWID == WID_STYLE_FAMILY )
1479 aRet <<= GetFamilyString(nFamily);
1481 else if( pEntry->nWID == SDRATTR_TEXTDIRECTION )
1483 aRet <<= false;
1485 else if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
1487 aRet <<= BitmapMode_REPEAT;
1489 else
1491 SfxItemPool& rMyPool = GetPool()->GetPool();
1492 SfxItemSet aSet( rMyPool, pEntry->nWID, pEntry->nWID);
1493 aSet.Put( rMyPool.GetDefaultItem( pEntry->nWID ) );
1494 aRet = SvxItemPropertySet_getPropertyValue( pEntry, aSet );
1496 return aRet;
1499 /** this is used because our property map is not sorted yet */
1500 const SfxItemPropertyMapEntry* SdStyleSheet::getPropertyMapEntry( std::u16string_view rPropertyName )
1502 return GetStylePropertySet().getPropertyMapEntry(rPropertyName);
1505 //Broadcast that a SdStyleSheet has changed, taking into account outline sublevels
1506 //which need to be explicitly broadcast as changing if their parent style was
1507 //the one that changed
1508 void SdStyleSheet::BroadcastSdStyleSheetChange(SfxStyleSheetBase const * pStyleSheet,
1509 PresentationObjects ePO, SfxStyleSheetBasePool* pSSPool)
1511 SdStyleSheet* pRealSheet = static_cast<SdStyleSheet const *>(pStyleSheet)->GetRealStyleSheet();
1512 pRealSheet->Broadcast(SfxHint(SfxHintId::DataChanged));
1514 if( (ePO < PresentationObjects::Outline_1) || (ePO > PresentationObjects::Outline_8) )
1515 return;
1517 OUString sStyleName(SdResId(STR_PSEUDOSHEET_OUTLINE) + " ");
1519 for( sal_uInt16 n = static_cast<sal_uInt16>(ePO) - static_cast<sal_uInt16>(PresentationObjects::Outline_1) + 2; n < 10; n++ )
1521 OUString aName( sStyleName + OUString::number(n) );
1523 SfxStyleSheetBase* pSheet = pSSPool->Find( aName, SfxStyleFamily::Pseudo);
1525 if(pSheet)
1527 SdStyleSheet* pRealStyleSheet = static_cast<SdStyleSheet*>(pSheet)->GetRealStyleSheet();
1528 pRealStyleSheet->Broadcast(SfxHint(SfxHintId::DataChanged));
1533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */