pyuno: call target only with internal python
[LibreOffice.git] / sd / source / core / stlsheet.cxx
blobc4b5dfe92046c942c1c66e4274a91654df7d332e
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"_ustr, WID_STYLE_FAMILY, ::cppu::UnoType<OUString>::get(), PropertyAttribute::READONLY, 0},
93 { u"UserDefinedAttributes"_ustr, SDRATTR_XMLATTRIBUTES, cppu::UnoType<XNameContainer>::get(), 0, 0},
94 { u"DisplayName"_ustr, WID_STYLE_DISPNAME, ::cppu::UnoType<OUString>::get(), PropertyAttribute::READONLY, 0},
95 { u"Hidden"_ustr, 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"_ustr, SDRATTR_TABLE_BORDER, ::cppu::UnoType<BorderLine>::get(), 0, TOP_BORDER },
107 { u"BottomBorder"_ustr, SDRATTR_TABLE_BORDER, ::cppu::UnoType<BorderLine>::get(), 0, BOTTOM_BORDER },
108 { u"LeftBorder"_ustr, SDRATTR_TABLE_BORDER, ::cppu::UnoType<BorderLine>::get(), 0, LEFT_BORDER },
109 { u"RightBorder"_ustr, 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,
144 SfxStyleFamily eFamily,
145 SfxStyleSearchBits _nMask,
146 const OUString& rParentStyleSheetName)
147 : SdStyleSheetBase( rDisplayName, _rPool, eFamily, _nMask, rParentStyleSheetName)
148 , msApiName( rDisplayName )
149 , mxPool( &_rPool )
153 SdStyleSheet::~SdStyleSheet()
155 // restore reference count, prevent double-delete from calling dispose
156 osl_atomic_increment( &m_refCount );
157 dispose();
159 delete pSet;
160 pSet = nullptr; // that following destructors also get a change
163 void SdStyleSheet::SetApiName( const OUString& rApiName )
165 msApiName = rApiName;
168 OUString const & SdStyleSheet::GetApiName() const
170 if( !msApiName.isEmpty() )
171 return msApiName;
172 else
173 return GetName();
176 bool SdStyleSheet::SetParent(const OUString& rParentName)
178 bool bResult = false;
180 if (SfxStyleSheet::SetParent(rParentName))
182 // PseudoStyleSheets do not have their own ItemSets
183 if (nFamily != SfxStyleFamily::Pseudo)
185 if( !rParentName.isEmpty() )
187 SfxStyleSheetBase* pStyle = m_pPool->Find(rParentName, nFamily);
188 if (pStyle)
190 bResult = true;
191 SfxItemSet& rParentSet = pStyle->GetItemSet();
192 GetItemSet().SetParent(&rParentSet);
193 Broadcast( SfxHint( SfxHintId::DataChanged ) );
196 else
198 bResult = true;
199 GetItemSet().SetParent(nullptr);
200 Broadcast( SfxHint( SfxHintId::DataChanged ) );
203 else
205 bResult = true;
208 return bResult;
212 * create if necessary and return ItemSets
214 SfxItemSet& SdStyleSheet::GetItemSet()
216 if (nFamily == SfxStyleFamily::Para || nFamily == SfxStyleFamily::Page)
218 // we create the ItemSet 'on demand' if necessary
219 if (!pSet)
221 pSet = new SfxItemSet(GetPool()->GetPool(), WhichRangesContainer(svl::Items<
222 XATTR_LINE_FIRST, XATTR_LINE_LAST,
223 XATTR_FILL_FIRST, XATTR_FILL_LAST,
224 SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST,
225 SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_WORDWRAP,
226 SDRATTR_EDGE_FIRST, SDRATTR_MEASURE_LAST,
227 SDRATTR_3D_FIRST, SDRATTR_3D_LAST,
228 EE_PARA_START, EE_CHAR_END>));
229 bMySet = true;
232 return *pSet;
235 else if( nFamily == SfxStyleFamily::Frame )
237 if (!pSet)
239 pSet = new SfxItemSet(GetPool()->GetPool(), WhichRangesContainer(svl::Items<
240 XATTR_LINE_FIRST, XATTR_LINE_LAST,
241 XATTR_FILL_FIRST, XATTR_FILL_LAST,
242 SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST,
243 SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_XMLATTRIBUTES,
244 SDRATTR_TEXT_WORDWRAP, SDRATTR_TEXT_WORDWRAP,
245 SDRATTR_TABLE_FIRST, SDRATTR_TABLE_LAST,
246 EE_PARA_START, EE_CHAR_END>));
247 bMySet = true;
250 return *pSet;
253 // this is a dummy template for the internal template of the
254 // current presentation layout; return the ItemSet of that template
255 else
258 SdStyleSheet* pSdSheet = GetRealStyleSheet();
260 if (pSdSheet)
262 return pSdSheet->GetItemSet();
264 else
266 if (!pSet)
268 pSet = new SfxItemSet(GetPool()->GetPool(), WhichRangesContainer(svl::Items<
269 XATTR_LINE_FIRST, XATTR_LINE_LAST,
270 XATTR_FILL_FIRST, XATTR_FILL_LAST,
271 SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST,
272 SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_WORDWRAP,
273 SDRATTR_EDGE_FIRST, SDRATTR_MEASURE_LAST,
274 SDRATTR_3D_FIRST, SDRATTR_3D_LAST,
275 EE_PARA_START, EE_CHAR_END>));
276 bMySet = true;
279 return(*pSet);
285 * A template is used when it is referenced by inserted object or by a used
286 * template.
288 bool SdStyleSheet::IsUsed() const
290 bool bResult = false;
292 ForAllListeners(
293 [this, &bResult] (SfxListener* pListener)
295 if( pListener == this )
296 return false; // continue
298 const svl::StyleSheetUser* const pUser(dynamic_cast<svl::StyleSheetUser*>(pListener));
299 if (pUser)
300 bResult = pUser->isUsedByModel();
301 if (bResult)
302 return true; // break loop
303 return false;
306 if( !bResult )
308 std::unique_lock aGuard( m_aMutex );
310 if( maModifyListeners.getLength(aGuard) )
312 std::vector<css::uno::Reference<XModifyListener>> aModifyListeners( maModifyListeners.getElements(aGuard) );
313 bResult = std::any_of(aModifyListeners.begin(), aModifyListeners.end(),
314 [](const Reference<XInterface>& rListener) {
315 Reference< XStyle > xStyle( rListener, UNO_QUERY );
318 Reference<XPropertySet> xPropertySet(xStyle, UNO_QUERY_THROW);
319 if (xPropertySet->getPropertyValue(u"IsPhysical"_ustr).get<bool>())
320 return true;
322 catch (const Exception&)
325 return xStyle.is() && xStyle->isInUse();
329 return bResult;
333 * Checks if a cell style is used in two places at once.
334 * Typically we modify the formatting of a single place,
335 * so such style shouldn't be edited directly.
337 bool SdStyleSheet::IsEditable()
339 if (GetFamily() != SfxStyleFamily::Frame)
340 return true;
342 if (!IsUserDefined())
343 return false;
345 bool bFoundOne = false;
346 ForAllListeners(
347 [this, &bFoundOne] (SfxListener* pListener)
349 if (pListener != this && dynamic_cast<SdStyleSheet*>(pListener))
351 bFoundOne = true;
352 return true; // break loop
354 return false;
356 if (bFoundOne)
357 return false;
359 std::unique_lock aGuard(m_aMutex);
360 return maModifyListeners.getLength(aGuard) <= 1;
364 * Determine the style sheet for which this dummy is for.
366 SdStyleSheet* SdStyleSheet::GetRealStyleSheet() const
368 OUString aRealStyle;
369 OUString aSep( SD_LT_SEPARATOR );
370 SdStyleSheet* pRealStyle = nullptr;
371 SdDrawDocument* pDoc = static_cast<SdStyleSheetPool*>(m_pPool)->GetDoc();
373 ::sd::DrawViewShell* pDrawViewShell = nullptr;
375 ::sd::ViewShellBase* pBase = dynamic_cast< ::sd::ViewShellBase* >( SfxViewShell::Current() );
376 if( pBase )
377 pDrawViewShell = dynamic_cast< ::sd::DrawViewShell* >( pBase->GetMainViewShell().get() );
379 if (pDrawViewShell && pDrawViewShell->GetDoc() == pDoc)
381 SdPage* pPage = pDrawViewShell->getCurrentPage();
382 if( pPage )
384 aRealStyle = pPage->GetLayoutName();
385 // cut after separator string
387 if( aRealStyle.indexOf(aSep) >= 0)
389 aRealStyle = aRealStyle.copy(0,(aRealStyle.indexOf(aSep) + aSep.getLength()));
393 if (aRealStyle.isEmpty())
395 SdPage* pPage = pDoc->GetSdPage(0, PageKind::Standard);
397 if (pPage)
399 aRealStyle = pDoc->GetSdPage(0, PageKind::Standard)->GetLayoutName();
401 else
403 /* no page available yet. This can happen when actualizing the
404 document templates. */
405 SfxStyleSheetIterator aIter(m_pPool, SfxStyleFamily::Page);
406 SfxStyleSheetBase* pSheet = aIter.First();
407 if( pSheet )
408 aRealStyle = pSheet->GetName();
411 if( aRealStyle.indexOf(aSep) >= 0)
413 aRealStyle = aRealStyle.copy(0,(aRealStyle.indexOf(aSep) + aSep.getLength()));
417 /* now map from the name (specified for country language) to the internal
418 name (independent of the country language) */
419 OUString aInternalName;
420 OUString aStyleName(aName);
422 if (aStyleName == SdResId(STR_PSEUDOSHEET_TITLE))
424 aInternalName = STR_LAYOUT_TITLE;
426 else if (aStyleName == SdResId(STR_PSEUDOSHEET_SUBTITLE))
428 aInternalName = STR_LAYOUT_SUBTITLE;
430 else if (aStyleName == SdResId(STR_PSEUDOSHEET_BACKGROUND))
432 aInternalName = STR_LAYOUT_BACKGROUND;
434 else if (aStyleName == SdResId(STR_PSEUDOSHEET_BACKGROUNDOBJECTS))
436 aInternalName = STR_LAYOUT_BACKGROUNDOBJECTS;
438 else if (aStyleName == SdResId(STR_PSEUDOSHEET_NOTES))
440 aInternalName = STR_LAYOUT_NOTES;
442 else
444 OUString aOutlineStr(SdResId(STR_PSEUDOSHEET_OUTLINE));
445 sal_Int32 nPos = aStyleName.indexOf(aOutlineStr);
446 if (nPos >= 0)
448 std::u16string_view aNumStr(aStyleName.subView(aOutlineStr.getLength()));
449 aInternalName = STR_LAYOUT_OUTLINE + aNumStr;
453 aRealStyle += aInternalName;
454 pRealStyle = static_cast< SdStyleSheet* >( m_pPool->Find(aRealStyle, SfxStyleFamily::Page) );
456 #ifdef DBG_UTIL
457 if( !pRealStyle )
459 SfxStyleSheetIterator aIter(m_pPool, SfxStyleFamily::Page);
460 if( aIter.Count() > 0 )
461 // StyleSheet not found, but pool already loaded
462 DBG_ASSERT(pRealStyle, "Internal StyleSheet not found");
464 #endif
466 return pRealStyle;
470 * Determine pseudo style sheet which stands for this style sheet.
472 SdStyleSheet* SdStyleSheet::GetPseudoStyleSheet() const
474 SdStyleSheet* pPseudoStyle = nullptr;
475 OUString aSep( SD_LT_SEPARATOR );
476 OUString aStyleName(aName);
477 // without layout name and separator
479 if( aStyleName.indexOf(aSep) >=0 )
481 aStyleName = aStyleName.copy (aStyleName.indexOf(aSep) + aSep.getLength());
484 if (aStyleName == STR_LAYOUT_TITLE)
486 aStyleName = SdResId(STR_PSEUDOSHEET_TITLE);
488 else if (aStyleName == STR_LAYOUT_SUBTITLE)
490 aStyleName = SdResId(STR_PSEUDOSHEET_SUBTITLE);
492 else if (aStyleName == STR_LAYOUT_BACKGROUND)
494 aStyleName = SdResId(STR_PSEUDOSHEET_BACKGROUND);
496 else if (aStyleName == STR_LAYOUT_BACKGROUNDOBJECTS)
498 aStyleName = SdResId(STR_PSEUDOSHEET_BACKGROUNDOBJECTS);
500 else if (aStyleName == STR_LAYOUT_NOTES)
502 aStyleName = SdResId(STR_PSEUDOSHEET_NOTES);
504 else
506 OUString aOutlineStr(STR_LAYOUT_OUTLINE);
507 sal_Int32 nPos = aStyleName.indexOf(aOutlineStr);
508 if (nPos != -1)
510 std::u16string_view aNumStr(aStyleName.subView(aOutlineStr.getLength()));
511 aStyleName = SdResId(STR_PSEUDOSHEET_OUTLINE) + aNumStr;
515 pPseudoStyle = static_cast<SdStyleSheet*>(m_pPool->Find(aStyleName, SfxStyleFamily::Pseudo));
516 DBG_ASSERT(pPseudoStyle, "PseudoStyleSheet missing");
518 return pPseudoStyle;
521 void SdStyleSheet::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
523 // first, base class functionality
524 SfxStyleSheet::Notify(rBC, rHint);
526 if (nFamily != SfxStyleFamily::Pseudo)
527 return;
529 /* if the dummy gets a notify about a changed attribute, he takes care that
530 the actual meant style sheet sends broadcasts. */
531 if (rHint.GetId() == SfxHintId::DataChanged)
533 SdStyleSheet* pRealStyle = GetRealStyleSheet();
534 if (pRealStyle)
535 pRealStyle->Broadcast(rHint);
540 * Adjust the bullet width and the left text indent of the provided ItemSets to
541 * their font height. The new values are calculated that the ratio to the font
542 * height is as in the style sheet.
544 * @param bOnlyMissingItems If sal_True, only not set items are completed. With
545 * sal_False, are items are overwritten.
547 void SdStyleSheet::AdjustToFontHeight(SfxItemSet& rSet, bool bOnlyMissingItems)
549 /* If not explicit set, adjust bullet width and text indent to new font
550 height. */
551 SfxStyleFamily eFamily = nFamily;
552 OUString aStyleName(aName);
553 if (eFamily == SfxStyleFamily::Pseudo)
555 SfxStyleSheet* pRealStyle = GetRealStyleSheet();
556 eFamily = pRealStyle->GetFamily();
557 aStyleName = pRealStyle->GetName();
560 if (!(eFamily == SfxStyleFamily::Page &&
561 aStyleName.indexOf(STR_LAYOUT_OUTLINE) != -1 &&
562 rSet.GetItemState(EE_CHAR_FONTHEIGHT) == SfxItemState::SET))
563 return;
565 const SfxItemSet* pCurSet = &GetItemSet();
566 sal_uInt32 nNewHeight = rSet.Get(EE_CHAR_FONTHEIGHT).GetHeight();
567 sal_uInt32 nOldHeight = pCurSet->Get(EE_CHAR_FONTHEIGHT).GetHeight();
569 if (rSet.GetItemState(EE_PARA_BULLET) != SfxItemState::SET || !bOnlyMissingItems)
571 const SvxBulletItem& rBItem = pCurSet->Get(EE_PARA_BULLET);
572 double fBulletFraction = double(rBItem.GetWidth()) / nOldHeight;
573 SvxBulletItem aNewBItem(rBItem);
574 aNewBItem.SetWidth(static_cast<sal_uInt32>(fBulletFraction * nNewHeight));
575 rSet.Put(aNewBItem);
578 if (rSet.GetItemState(EE_PARA_LRSPACE) != SfxItemState::SET || !bOnlyMissingItems)
580 const SvxLRSpaceItem& rLRItem = pCurSet->Get(EE_PARA_LRSPACE);
581 double fIndentFraction = double(rLRItem.ResolveTextLeft({})) / nOldHeight;
582 SvxLRSpaceItem aNewLRItem(rLRItem);
583 aNewLRItem.SetTextLeft(SvxIndentValue::twips(fIndentFraction * nNewHeight));
584 double fFirstIndentFraction = rLRItem.GetTextFirstLineOffset().m_dValue / nOldHeight;
585 aNewLRItem.SetTextFirstLineOffset(SvxIndentValue{ fFirstIndentFraction * nNewHeight,
586 rLRItem.GetTextFirstLineOffset().m_nUnit });
587 rSet.Put(aNewLRItem);
590 if (rSet.GetItemState(EE_PARA_ULSPACE) != SfxItemState::SET || !bOnlyMissingItems)
592 const SvxULSpaceItem& rULItem = pCurSet->Get(EE_PARA_ULSPACE);
593 SvxULSpaceItem aNewULItem(rULItem);
594 double fLowerFraction = double(rULItem.GetLower()) / nOldHeight;
595 aNewULItem.SetLower(static_cast<sal_uInt16>(fLowerFraction * nNewHeight));
596 double fUpperFraction = double(rULItem.GetUpper()) / nOldHeight;
597 aNewULItem.SetUpper(static_cast<sal_uInt16>(fUpperFraction * nNewHeight));
598 rSet.Put(aNewULItem);
602 bool SdStyleSheet::HasFollowSupport() const
604 return false;
607 bool SdStyleSheet::HasParentSupport() const
609 return true;
612 bool SdStyleSheet::HasClearParentSupport() const
614 return true;
617 namespace
619 struct ApiNameMap
621 std::u16string_view mpApiName;
622 sal_uInt32 mnHelpId;
623 } const pApiNameMap[]
624 = { { std::u16string_view(u"title"), HID_PSEUDOSHEET_TITLE },
625 { std::u16string_view(u"subtitle"), HID_PSEUDOSHEET_SUBTITLE },
626 { std::u16string_view(u"background"), HID_PSEUDOSHEET_BACKGROUND },
627 { std::u16string_view(u"backgroundobjects"), HID_PSEUDOSHEET_BACKGROUNDOBJECTS },
628 { std::u16string_view(u"notes"), HID_PSEUDOSHEET_NOTES },
629 { std::u16string_view(u"standard"), HID_STANDARD_STYLESHEET_NAME },
630 { std::u16string_view(u"objectwithoutfill"), HID_POOLSHEET_OBJWITHOUTFILL },
631 { std::u16string_view(u"Object with no fill and no line"), HID_POOLSHEET_OBJNOLINENOFILL },
633 { std::u16string_view(u"Text"), HID_POOLSHEET_TEXT },
634 { std::u16string_view(u"A4"), HID_POOLSHEET_A4 },
635 { std::u16string_view(u"Title A4"), HID_POOLSHEET_A4_TITLE },
636 { std::u16string_view(u"Heading A4"), HID_POOLSHEET_A4_HEADLINE },
637 { std::u16string_view(u"Text A4"), HID_POOLSHEET_A4_TEXT },
638 { std::u16string_view(u"A0"), HID_POOLSHEET_A0 },
639 { std::u16string_view(u"Title A0"), HID_POOLSHEET_A0_TITLE },
640 { std::u16string_view(u"Heading A0"), HID_POOLSHEET_A0_HEADLINE },
641 { std::u16string_view(u"Text A0"), HID_POOLSHEET_A0_TEXT },
643 { std::u16string_view(u"Graphic"), HID_POOLSHEET_GRAPHIC },
644 { std::u16string_view(u"Shapes"), HID_POOLSHEET_SHAPES },
645 { std::u16string_view(u"Filled"), HID_POOLSHEET_FILLED },
646 { std::u16string_view(u"Filled Blue"), HID_POOLSHEET_FILLED_BLUE },
647 { std::u16string_view(u"Filled Green"), HID_POOLSHEET_FILLED_GREEN },
648 { std::u16string_view(u"Filled Red"), HID_POOLSHEET_FILLED_RED },
649 { std::u16string_view(u"Filled Yellow"), HID_POOLSHEET_FILLED_YELLOW },
650 { std::u16string_view(u"Outlined"), HID_POOLSHEET_OUTLINE },
651 { std::u16string_view(u"Outlined Blue"), HID_POOLSHEET_OUTLINE_BLUE },
652 { std::u16string_view(u"Outlined Green"), HID_POOLSHEET_OUTLINE_GREEN },
653 { std::u16string_view(u"Outlined Red"), HID_POOLSHEET_OUTLINE_RED },
654 { std::u16string_view(u"Outlined Yellow"), HID_POOLSHEET_OUTLINE_YELLOW },
655 { std::u16string_view(u"Lines"), HID_POOLSHEET_LINES },
656 { std::u16string_view(u"Arrow Line"), HID_POOLSHEET_MEASURE },
657 { std::u16string_view(u"Arrow Dashed"), HID_POOLSHEET_LINES_DASHED }
660 OUString GetApiNameForHelpId(sal_uInt32 nId)
662 if ((nId >= HID_PSEUDOSHEET_OUTLINE1) && (nId <= HID_PSEUDOSHEET_OUTLINE9))
663 return "outline" + OUStringChar(sal_Unicode('1' + (nId - HID_PSEUDOSHEET_OUTLINE1)));
665 for (const auto& i : pApiNameMap)
666 if (nId == i.mnHelpId)
667 return OUString(i.mpApiName);
669 return OUString();
672 sal_uInt32 GetHelpIdForApiName(std::u16string_view sName)
674 std::u16string_view sRest;
675 if (o3tl::starts_with(sName, u"outline", &sRest))
677 if (sRest.length() == 1)
679 sal_Unicode ch = sRest.front();
680 if ('1' <= ch && ch <= '9')
681 return HID_PSEUDOSHEET_OUTLINE1 + ch - '1';
683 // No other pre-defined names start with "outline"
684 return 0;
687 for (const auto& i : pApiNameMap)
688 if (sName == i.mpApiName)
689 return i.mnHelpId;
691 return 0;
695 void SdStyleSheet::SetHelpId( const OUString& r, sal_uInt32 nId )
697 SfxStyleSheet::SetHelpId( r, nId );
699 const OUString sNewApiName = GetApiNameForHelpId(nId);
700 if (!sNewApiName.isEmpty())
701 msApiName = sNewApiName;
704 OUString SdStyleSheet::GetFamilyString( SfxStyleFamily eFamily )
706 switch( eFamily )
708 case SfxStyleFamily::Frame:
709 return u"cell"_ustr;
710 default:
711 OSL_FAIL( "SdStyleSheet::GetFamilyString(), illegal family!" );
712 [[fallthrough]];
713 case SfxStyleFamily::Para:
714 return u"graphics"_ustr;
718 void SdStyleSheet::throwIfDisposed()
720 if( !mxPool.is() )
721 throw DisposedException();
724 rtl::Reference<SdStyleSheet> SdStyleSheet::CreateEmptyUserStyle( SfxStyleSheetBasePool& rPool, SfxStyleFamily eFamily )
726 OUString aName;
727 sal_Int32 nIndex = 1;
730 aName = "user" + OUString::number( nIndex++ );
732 while( rPool.Find( aName, eFamily ) != nullptr );
734 return new SdStyleSheet(aName, rPool, eFamily, SfxStyleSearchBits::UserDefined);
737 // XComponent
739 void SAL_CALL SdStyleSheet::dispose( )
742 std::unique_lock aGuard(m_aMutex);
743 if (m_bDisposed || m_bInDispose)
744 return;
746 m_bInDispose = true;
750 std::unique_lock aGuard(m_aMutex);
751 // side effect: keeping a reference to this
752 EventObject aEvt( static_cast< OWeakObject * >( this ) );
755 maModifyListeners.disposeAndClear( aGuard, aEvt );
756 maEventListeners.disposeAndClear( aGuard, aEvt );
757 disposing();
759 catch (...)
761 // bDisposed and bInDispose must be set in this order:
762 m_bDisposed = true;
763 m_bInDispose = false;
764 throw;
766 // bDisposed and bInDispose must be set in this order:
767 m_bDisposed = true;
768 m_bInDispose = false;
770 catch (RuntimeException &)
772 throw;
774 catch (const Exception & exc)
776 css::uno::Any anyEx = cppu::getCaughtException();
777 throw css::lang::WrappedTargetRuntimeException(
778 "unexpected UNO exception caught: " + exc.Message ,
779 nullptr, anyEx );
783 void SdStyleSheet::disposing()
785 SolarMutexGuard aGuard;
786 if (bMySet)
788 delete pSet;
790 pSet = nullptr;
791 m_pPool = nullptr;
792 mxPool.clear();
795 void SAL_CALL SdStyleSheet::addEventListener( const Reference< XEventListener >& xListener )
797 std::unique_lock aGuard( m_aMutex );
798 if (m_bDisposed || m_bInDispose)
800 aGuard.unlock();
801 EventObject aEvt( static_cast< OWeakObject * >( this ) );
802 xListener->disposing( aEvt );
804 else
806 maEventListeners.addInterface( aGuard, xListener );
810 void SAL_CALL SdStyleSheet::removeEventListener( const Reference< XEventListener >& xListener )
812 std::unique_lock aGuard( m_aMutex );
813 maEventListeners.removeInterface( aGuard, xListener );
816 // XModifyBroadcaster
818 void SAL_CALL SdStyleSheet::addModifyListener( const Reference< XModifyListener >& xListener )
820 std::unique_lock aGuard( m_aMutex );
821 if (m_bDisposed || m_bInDispose)
823 aGuard.unlock();
824 EventObject aEvt( static_cast< OWeakObject * >( this ) );
825 xListener->disposing( aEvt );
827 else
829 if (!mpModifyListenerForwarder)
830 mpModifyListenerForwarder.reset( new ModifyListenerForwarder( this ) );
831 maModifyListeners.addInterface( aGuard, xListener );
835 void SAL_CALL SdStyleSheet::removeModifyListener( const Reference< XModifyListener >& xListener )
837 std::unique_lock aGuard( m_aMutex );
838 maModifyListeners.removeInterface( aGuard, xListener );
841 void SdStyleSheet::notifyModifyListener()
843 std::unique_lock aGuard( m_aMutex );
845 if( maModifyListeners.getLength(aGuard) )
847 EventObject aEvt( static_cast< OWeakObject * >( this ) );
848 maModifyListeners.notifyEach(aGuard, &XModifyListener::modified, aEvt);
852 // XServiceInfo
853 OUString SAL_CALL SdStyleSheet::getImplementationName()
855 return u"SdStyleSheet"_ustr;
858 sal_Bool SAL_CALL SdStyleSheet::supportsService( const OUString& ServiceName )
860 return cppu::supportsService( this, ServiceName );
863 Sequence< OUString > SAL_CALL SdStyleSheet::getSupportedServiceNames()
865 return { u"com.sun.star.style.Style"_ustr,
866 u"com.sun.star.drawing.FillProperties"_ustr,
867 u"com.sun.star.drawing.LineProperties"_ustr,
868 u"com.sun.star.drawing.ShadowProperties"_ustr,
869 u"com.sun.star.drawing.ConnectorProperties"_ustr,
870 u"com.sun.star.drawing.MeasureProperties"_ustr,
871 u"com.sun.star.style.ParagraphProperties"_ustr,
872 u"com.sun.star.style.CharacterProperties"_ustr,
873 u"com.sun.star.drawing.TextProperties"_ustr,
874 u"com.sun.star.drawing.Text"_ustr };
877 bool SdStyleSheet::SetName(const OUString& rNewName, bool bReindexNow)
879 const bool bResult = SfxUnoStyleSheet::SetName(rNewName, bReindexNow);
880 // Don't overwrite predefined API names
881 if (bResult && GetHelpIdForApiName(msApiName) == 0)
883 msApiName = rNewName;
884 Broadcast(SfxHint(SfxHintId::DataChanged));
886 return bResult;
889 // XNamed
890 OUString SAL_CALL SdStyleSheet::getName()
892 SolarMutexGuard aGuard;
893 throwIfDisposed();
894 return GetApiName();
897 void SAL_CALL SdStyleSheet::setName( const OUString& rName )
899 SolarMutexGuard aGuard;
900 throwIfDisposed();
901 SetName(rName);
904 // XStyle
906 sal_Bool SAL_CALL SdStyleSheet::isUserDefined()
908 SolarMutexGuard aGuard;
909 throwIfDisposed();
910 return IsUserDefined();
913 sal_Bool SAL_CALL SdStyleSheet::isInUse()
915 SolarMutexGuard aGuard;
916 throwIfDisposed();
917 return IsUsed();
920 OUString SAL_CALL SdStyleSheet::getParentStyle()
922 SolarMutexGuard aGuard;
923 throwIfDisposed();
925 if( !GetParent().isEmpty() )
927 SdStyleSheet* pParentStyle = static_cast< SdStyleSheet* >( mxPool->Find( GetParent(), nFamily ) );
928 if( pParentStyle )
929 return pParentStyle->GetApiName();
931 return OUString();
934 void SAL_CALL SdStyleSheet::setParentStyle( const OUString& rParentName )
936 SolarMutexGuard aGuard;
937 throwIfDisposed();
939 if( !rParentName.isEmpty() )
941 OUString const& name(GetName());
942 sal_Int32 const sep(name.indexOf(SD_LT_SEPARATOR));
943 OUString const master((sep == -1) ? OUString() : name.copy(0, sep));
944 std::shared_ptr<SfxStyleSheetIterator> aSSSI = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), nFamily);
945 for (SfxStyleSheetBase *pStyle = aSSSI->First(); pStyle; pStyle = aSSSI->Next())
947 // we hope that we have only sd style sheets
948 SdStyleSheet* pSdStyleSheet = static_cast<SdStyleSheet*>(pStyle);
950 // check that the master msApiName matches, as msApiName exists once per
951 // master page
952 if (pSdStyleSheet->msApiName != rParentName)
953 continue;
955 OUString const& curName(pStyle->GetName());
956 sal_Int32 const curSep(curName.indexOf(SD_LT_SEPARATOR));
957 OUString const curMaster((curSep == -1)
958 ? OUString() : curName.copy(0, curSep));
959 // check that the master matches
960 if (master == curMaster)
962 if( pStyle != this )
964 SetParent(curName);
966 return;
969 throw NoSuchElementException();
971 else
973 SetParent( rParentName );
977 // XPropertySet/XMultiPropertySet utility functions
979 // Does not broadcast
980 // Must be guarded by solar mutex; must not be disposed
981 void SdStyleSheet::setPropertyValue_Impl(const OUString& aPropertyName, const css::uno::Any& aValue)
983 const SfxItemPropertyMapEntry* pEntry = getPropertyMapEntry( aPropertyName );
984 if( pEntry == nullptr )
986 throw UnknownPropertyException( aPropertyName, static_cast<cppu::OWeakObject*>(this));
989 if( pEntry->nWID == WID_STYLE_HIDDEN )
991 bool bValue = false;
992 if ( aValue >>= bValue )
993 SetHidden( bValue );
994 return;
996 if( pEntry->nWID == SDRATTR_TEXTDIRECTION )
997 return; // not yet implemented for styles
999 if( pEntry->nWID == WID_STYLE_FAMILY )
1000 throw PropertyVetoException();
1002 if( (pEntry->nWID == EE_PARA_NUMBULLET) && (GetFamily() == SfxStyleFamily::Page) )
1004 OUString aStr;
1005 const sal_uInt32 nTempHelpId = GetHelpId( aStr );
1007 if( (nTempHelpId >= HID_PSEUDOSHEET_OUTLINE2) && (nTempHelpId <= HID_PSEUDOSHEET_OUTLINE9) )
1008 return;
1011 SfxItemSet &rStyleSet = GetItemSet();
1013 if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
1015 BitmapMode eMode;
1016 if( aValue >>= eMode )
1018 rStyleSet.Put( XFillBmpStretchItem( eMode == BitmapMode_STRETCH ) );
1019 rStyleSet.Put( XFillBmpTileItem( eMode == BitmapMode_REPEAT ) );
1020 return;
1022 throw IllegalArgumentException();
1025 if (pEntry->nWID == OWN_ATTR_TEXTCOLUMNS)
1027 if (css::uno::Reference<css::text::XTextColumns> xColumns; aValue >>= xColumns)
1029 rStyleSet.Put(SfxInt16Item(SDRATTR_TEXTCOLUMNS_NUMBER, xColumns->getColumnCount()));
1030 if (css::uno::Reference<css::beans::XPropertySet> xPropSet{ xColumns,
1031 css::uno::UNO_QUERY })
1033 auto aVal = xPropSet->getPropertyValue(u"AutomaticDistance"_ustr);
1034 if (sal_Int32 nSpacing; aVal >>= nSpacing)
1035 rStyleSet.Put(SdrMetricItem(SDRATTR_TEXTCOLUMNS_SPACING, nSpacing));
1037 return;
1039 throw IllegalArgumentException();
1042 SfxItemSet aSet( GetPool()->GetPool(), pEntry->nWID, pEntry->nWID);
1043 aSet.Put( rStyleSet );
1045 if( !aSet.Count() )
1047 if( EE_PARA_NUMBULLET == pEntry->nWID )
1049 vcl::Font aBulletFont;
1050 SdStyleSheetPool::PutNumBulletItem( this, aBulletFont );
1051 aSet.Put( rStyleSet );
1053 else
1055 aSet.Put( GetPool()->GetPool().GetUserOrPoolDefaultItem( pEntry->nWID ) );
1059 if( pEntry->nMemberId == MID_NAME &&
1060 ( pEntry->nWID == XATTR_FILLBITMAP || pEntry->nWID == XATTR_FILLGRADIENT ||
1061 pEntry->nWID == XATTR_FILLHATCH || pEntry->nWID == XATTR_FILLFLOATTRANSPARENCE ||
1062 pEntry->nWID == XATTR_LINESTART || pEntry->nWID == XATTR_LINEEND || pEntry->nWID == XATTR_LINEDASH) )
1064 OUString aTempName;
1065 if(!(aValue >>= aTempName ))
1066 throw IllegalArgumentException();
1068 SvxShape::SetFillAttribute( pEntry->nWID, aTempName, aSet );
1070 else if(!SvxUnoTextRangeBase::SetPropertyValueHelper( pEntry, aValue, aSet ))
1072 SvxItemPropertySet_setPropertyValue( pEntry, aValue, aSet );
1075 rStyleSet.Put( aSet );
1078 // Must be guarded by solar mutex; must not be disposed
1079 css::uno::Any SdStyleSheet::getPropertyValue_Impl(const OUString& PropertyName)
1081 const SfxItemPropertyMapEntry* pEntry = getPropertyMapEntry( PropertyName );
1082 if( pEntry == nullptr )
1084 throw UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this));
1087 Any aAny;
1089 if( pEntry->nWID == WID_STYLE_FAMILY )
1091 if( nFamily == SfxStyleFamily::Page )
1093 const OUString aLayoutName( GetName() );
1094 aAny <<= aLayoutName.copy( 0, aLayoutName.indexOf( SD_LT_SEPARATOR) );
1096 else
1098 aAny <<= GetFamilyString(nFamily);
1101 else if( pEntry->nWID == WID_STYLE_DISPNAME )
1103 OUString aDisplayName;
1104 if ( nFamily == SfxStyleFamily::Page )
1106 const SdStyleSheet* pStyleSheet = GetPseudoStyleSheet();
1107 if (pStyleSheet != nullptr)
1108 aDisplayName = pStyleSheet->GetName();
1111 if (aDisplayName.isEmpty())
1112 aDisplayName = GetName();
1114 aAny <<= aDisplayName;
1116 else if( pEntry->nWID == SDRATTR_TEXTDIRECTION )
1118 aAny <<= false;
1120 else if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
1122 SfxItemSet &rStyleSet = GetItemSet();
1124 const XFillBmpStretchItem* pStretchItem = rStyleSet.GetItem<XFillBmpStretchItem>(XATTR_FILLBMP_STRETCH);
1125 const XFillBmpTileItem* pTileItem = rStyleSet.GetItem<XFillBmpTileItem>(XATTR_FILLBMP_TILE);
1127 if( pStretchItem && pTileItem )
1129 if( pTileItem->GetValue() )
1130 aAny <<= BitmapMode_REPEAT;
1131 else if( pStretchItem->GetValue() )
1132 aAny <<= BitmapMode_STRETCH;
1133 else
1134 aAny <<= BitmapMode_NO_REPEAT;
1137 else if( pEntry->nWID == WID_STYLE_HIDDEN )
1139 aAny <<= IsHidden( );
1141 else if (pEntry->nWID == OWN_ATTR_TEXTCOLUMNS)
1143 const SfxItemSet& rStyleSet = GetItemSet();
1145 auto xIf = SvxXTextColumns_createInstance();
1146 css::uno::Reference<css::text::XTextColumns> xCols(xIf, css::uno::UNO_QUERY_THROW);
1147 xCols->setColumnCount(rStyleSet.Get(SDRATTR_TEXTCOLUMNS_NUMBER).GetValue());
1148 css::uno::Reference<css::beans::XPropertySet> xProp(xIf, css::uno::UNO_QUERY_THROW);
1149 xProp->setPropertyValue(
1150 u"AutomaticDistance"_ustr,
1151 css::uno::Any(rStyleSet.Get(SDRATTR_TEXTCOLUMNS_SPACING).GetValue()));
1152 aAny <<= xIf;
1154 else
1156 SfxItemSet aSet( GetPool()->GetPool(), pEntry->nWID, pEntry->nWID);
1158 const SfxPoolItem* pItem;
1159 SfxItemSet& rStyleSet = GetItemSet();
1161 if( rStyleSet.GetItemState( pEntry->nWID, true, &pItem ) == SfxItemState::SET )
1162 aSet.Put( *pItem );
1164 if( !aSet.Count() )
1165 aSet.Put( GetPool()->GetPool().GetUserOrPoolDefaultItem( pEntry->nWID ) );
1167 if(SvxUnoTextRangeBase::GetPropertyValueHelper( aSet, pEntry, aAny ))
1168 return aAny;
1170 // Get value of ItemSet
1171 aAny = SvxItemPropertySet_getPropertyValue( pEntry, aSet );
1174 if( pEntry->aType != aAny.getValueType() )
1176 // since the sfx uint16 item now exports a sal_Int32, we may have to fix this here
1177 if( ( pEntry->aType == ::cppu::UnoType<sal_Int16>::get()) && aAny.getValueType() == ::cppu::UnoType<sal_Int32>::get() )
1179 sal_Int32 nValue = 0;
1180 aAny >>= nValue;
1181 aAny <<= static_cast<sal_Int16>(nValue);
1183 else
1185 OSL_FAIL("SvxShape::GetAnyForItem() Returnvalue has wrong Type!" );
1189 return aAny;
1192 // XPropertySet
1194 Reference< XPropertySetInfo > SdStyleSheet::getPropertySetInfo()
1196 throwIfDisposed();
1197 static Reference< XPropertySetInfo > xInfo = GetStylePropertySet().getPropertySetInfo();
1198 return xInfo;
1201 void SAL_CALL SdStyleSheet::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
1203 SolarMutexGuard aGuard;
1204 throwIfDisposed();
1206 setPropertyValue_Impl(aPropertyName, aValue);
1207 Broadcast(SfxHint(SfxHintId::DataChanged));
1210 Any SAL_CALL SdStyleSheet::getPropertyValue( const OUString& PropertyName )
1212 SolarMutexGuard aGuard;
1213 throwIfDisposed();
1215 return getPropertyValue_Impl(PropertyName);
1218 void SAL_CALL SdStyleSheet::addPropertyChangeListener( const OUString& , const Reference< XPropertyChangeListener >& ) {}
1219 void SAL_CALL SdStyleSheet::removePropertyChangeListener( const OUString& , const Reference< XPropertyChangeListener >& ) {}
1220 void SAL_CALL SdStyleSheet::addVetoableChangeListener( const OUString& , const Reference< XVetoableChangeListener >& ) {}
1221 void SAL_CALL SdStyleSheet::removeVetoableChangeListener( const OUString& , const Reference< XVetoableChangeListener >& ) {}
1223 // XMultiPropertySet
1225 void SAL_CALL SdStyleSheet::setPropertyValues(const css::uno::Sequence<OUString>& aPropertyNames,
1226 const css::uno::Sequence<css::uno::Any>& aValues)
1228 const sal_Int32 nCount = aPropertyNames.getLength();
1230 if (nCount != aValues.getLength())
1231 throw css::lang::IllegalArgumentException();
1233 if (!nCount)
1234 return;
1236 SolarMutexGuard aGuard;
1237 throwIfDisposed();
1239 for (sal_Int32 i = 0; i < nCount; ++i)
1243 setPropertyValue_Impl(aPropertyNames[i], aValues[i]);
1245 catch (const css::beans::UnknownPropertyException&)
1247 // ignore this, some code likes to liberally sprinkle properties all over stuff that doesn't support those properties
1251 Broadcast(SfxHint(SfxHintId::DataChanged));
1254 css::uno::Sequence<css::uno::Any>
1255 SAL_CALL SdStyleSheet::getPropertyValues(const css::uno::Sequence<OUString>& aPropertyNames)
1257 SolarMutexGuard aGuard;
1258 throwIfDisposed();
1260 const sal_Int32 nCount = aPropertyNames.getLength();
1261 css::uno::Sequence<css::uno::Any> aValues(nCount);
1262 Any* pAny = aValues.getArray();
1264 for (sal_Int32 i = 0; i < nCount; ++i)
1265 pAny[i] = getPropertyValue_Impl(aPropertyNames[i]);
1267 return aValues;
1270 void SAL_CALL SdStyleSheet::addPropertiesChangeListener(const css::uno::Sequence<OUString>&, const css::uno::Reference<css::beans::XPropertiesChangeListener>&) {}
1271 void SAL_CALL SdStyleSheet::removePropertiesChangeListener(const css::uno::Reference<css::beans::XPropertiesChangeListener>&) {}
1272 void SAL_CALL SdStyleSheet::firePropertiesChangeEvent(const css::uno::Sequence<OUString>&, const css::uno::Reference<css::beans::XPropertiesChangeListener>&) {}
1274 // XPropertyState
1276 PropertyState SAL_CALL SdStyleSheet::getPropertyState( const OUString& PropertyName )
1278 SolarMutexGuard aGuard;
1280 throwIfDisposed();
1282 const SfxItemPropertyMapEntry* pEntry = getPropertyMapEntry( PropertyName );
1284 if( pEntry == nullptr )
1285 throw UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this));
1287 if( pEntry->nWID == WID_STYLE_FAMILY )
1289 return PropertyState_DIRECT_VALUE;
1291 else if( pEntry->nWID == SDRATTR_TEXTDIRECTION )
1293 return PropertyState_DEFAULT_VALUE;
1295 else if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
1297 const SfxItemSet& rSet = GetItemSet();
1299 if( rSet.GetItemState( XATTR_FILLBMP_STRETCH, false ) == SfxItemState::SET ||
1300 rSet.GetItemState( XATTR_FILLBMP_TILE, false ) == SfxItemState::SET )
1302 return PropertyState_DIRECT_VALUE;
1304 else
1306 return PropertyState_AMBIGUOUS_VALUE;
1309 else if (pEntry->nWID == OWN_ATTR_TEXTCOLUMNS)
1311 const SfxItemSet& rSet = GetItemSet();
1313 const auto eState1 = rSet.GetItemState(SDRATTR_TEXTCOLUMNS_NUMBER, false);
1314 const auto eState2 = rSet.GetItemState(SDRATTR_TEXTCOLUMNS_SPACING, false);
1315 if (eState1 == SfxItemState::SET || eState2 == SfxItemState::SET)
1316 return PropertyState_DIRECT_VALUE;
1317 else if (eState1 == SfxItemState::DEFAULT && eState2 == SfxItemState::DEFAULT)
1318 return PropertyState_DEFAULT_VALUE;
1319 else
1320 return PropertyState_AMBIGUOUS_VALUE;
1322 else
1324 SfxItemSet &rStyleSet = GetItemSet();
1326 PropertyState eState;
1328 switch( rStyleSet.GetItemState( pEntry->nWID, false ) )
1330 case SfxItemState::SET:
1331 eState = PropertyState_DIRECT_VALUE;
1332 break;
1333 case SfxItemState::DEFAULT:
1334 eState = PropertyState_DEFAULT_VALUE;
1335 break;
1336 default:
1337 eState = PropertyState_AMBIGUOUS_VALUE;
1338 break;
1341 // if an item is set, this doesn't mean we want it :)
1342 if( PropertyState_DIRECT_VALUE == eState )
1344 switch( pEntry->nWID )
1346 case XATTR_FILLBITMAP:
1347 case XATTR_FILLGRADIENT:
1348 case XATTR_FILLHATCH:
1349 case XATTR_FILLFLOATTRANSPARENCE:
1350 case XATTR_LINEEND:
1351 case XATTR_LINESTART:
1352 case XATTR_LINEDASH:
1354 const NameOrIndex* pItem = rStyleSet.GetItem<NameOrIndex>(pEntry->nWID);
1355 if( ( pItem == nullptr ) || pItem->GetName().isEmpty() )
1356 eState = PropertyState_DEFAULT_VALUE;
1358 break;
1359 case XATTR_FILLCOLOR:
1360 if (pEntry->nMemberId == MID_COLOR_THEME_INDEX)
1362 const XFillColorItem* pColor = rStyleSet.GetItem<XFillColorItem>(pEntry->nWID);
1363 if (pColor->getComplexColor().getThemeColorType() == model::ThemeColorType::Unknown)
1365 eState = PropertyState_DEFAULT_VALUE;
1368 else if (pEntry->nMemberId == MID_COLOR_LUM_MOD)
1370 const XFillColorItem* pColor = rStyleSet.GetItem<XFillColorItem>(pEntry->nWID);
1371 sal_Int16 nLumMod = 10000;
1372 for (auto const& rTransform : pColor->getComplexColor().getTransformations())
1374 if (rTransform.meType == model::TransformationType::LumMod)
1375 nLumMod = rTransform.mnValue;
1377 if (nLumMod == 10000)
1379 eState = PropertyState_DEFAULT_VALUE;
1382 else if (pEntry->nMemberId == MID_COLOR_LUM_OFF)
1384 const XFillColorItem* pColor = rStyleSet.GetItem<XFillColorItem>(pEntry->nWID);
1385 sal_Int16 nLumOff = 0;
1386 for (auto const& rTransform : pColor->getComplexColor().getTransformations())
1388 if (rTransform.meType == model::TransformationType::LumOff)
1389 nLumOff = rTransform.mnValue;
1391 if (nLumOff == 0)
1393 eState = PropertyState_DEFAULT_VALUE;
1396 else if (pEntry->nMemberId == MID_COMPLEX_COLOR)
1398 auto const* pColor = rStyleSet.GetItem<XFillColorItem>(pEntry->nWID);
1399 if (pColor->getComplexColor().getType() == model::ColorType::Unused)
1401 eState = PropertyState_DEFAULT_VALUE;
1404 break;
1405 case XATTR_LINECOLOR:
1406 if (pEntry->nMemberId == MID_COMPLEX_COLOR)
1408 auto const* pColor = rStyleSet.GetItem<XLineColorItem>(pEntry->nWID);
1409 if (pColor->getComplexColor().getType() == model::ColorType::Unused)
1411 eState = PropertyState_DEFAULT_VALUE;
1414 break;
1418 return eState;
1422 Sequence< PropertyState > SAL_CALL SdStyleSheet::getPropertyStates( const Sequence< OUString >& aPropertyName )
1424 SolarMutexGuard aGuard;
1426 throwIfDisposed();
1428 sal_Int32 nCount = aPropertyName.getLength();
1430 Sequence< PropertyState > aPropertyStateSequence( nCount );
1432 std::transform(aPropertyName.begin(), aPropertyName.end(), aPropertyStateSequence.getArray(),
1433 [this](const OUString& rName) -> PropertyState { return getPropertyState(rName); });
1435 return aPropertyStateSequence;
1438 void SAL_CALL SdStyleSheet::setPropertyToDefault( const OUString& PropertyName )
1440 SolarMutexGuard aGuard;
1442 throwIfDisposed();
1444 const SfxItemPropertyMapEntry* pEntry = getPropertyMapEntry( PropertyName );
1445 if( pEntry == nullptr )
1446 throw UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this));
1448 SfxItemSet &rStyleSet = GetItemSet();
1450 if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
1452 rStyleSet.ClearItem( XATTR_FILLBMP_STRETCH );
1453 rStyleSet.ClearItem( XATTR_FILLBMP_TILE );
1455 else
1457 rStyleSet.ClearItem( pEntry->nWID );
1459 Broadcast(SfxHint(SfxHintId::DataChanged));
1462 Any SAL_CALL SdStyleSheet::getPropertyDefault( const OUString& aPropertyName )
1464 SolarMutexGuard aGuard;
1466 throwIfDisposed();
1468 const SfxItemPropertyMapEntry* pEntry = getPropertyMapEntry( aPropertyName );
1469 if( pEntry == nullptr )
1470 throw UnknownPropertyException( aPropertyName, static_cast<cppu::OWeakObject*>(this));
1471 Any aRet;
1472 if( pEntry->nWID == WID_STYLE_FAMILY )
1474 aRet <<= GetFamilyString(nFamily);
1476 else if( pEntry->nWID == SDRATTR_TEXTDIRECTION )
1478 aRet <<= false;
1480 else if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE )
1482 aRet <<= BitmapMode_REPEAT;
1484 else
1486 SfxItemPool& rMyPool = GetPool()->GetPool();
1487 SfxItemSet aSet( rMyPool, pEntry->nWID, pEntry->nWID);
1488 aSet.Put( rMyPool.GetUserOrPoolDefaultItem( pEntry->nWID ) );
1489 aRet = SvxItemPropertySet_getPropertyValue( pEntry, aSet );
1491 return aRet;
1494 /** this is used because our property map is not sorted yet */
1495 const SfxItemPropertyMapEntry* SdStyleSheet::getPropertyMapEntry( const OUString& rPropertyName )
1497 return GetStylePropertySet().getPropertyMapEntry(rPropertyName);
1500 //Broadcast that a SdStyleSheet has changed, taking into account outline sublevels
1501 //which need to be explicitly broadcast as changing if their parent style was
1502 //the one that changed
1503 void SdStyleSheet::BroadcastSdStyleSheetChange(SfxStyleSheetBase const * pStyleSheet,
1504 PresentationObjects ePO, SfxStyleSheetBasePool* pSSPool)
1506 SdStyleSheet* pRealSheet = static_cast<SdStyleSheet const *>(pStyleSheet)->GetRealStyleSheet();
1507 pRealSheet->Broadcast(SfxHint(SfxHintId::DataChanged));
1509 if( (ePO < PresentationObjects::Outline_1) || (ePO > PresentationObjects::Outline_8) )
1510 return;
1512 OUString sStyleName(SdResId(STR_PSEUDOSHEET_OUTLINE) + " ");
1514 for( sal_uInt16 n = static_cast<sal_uInt16>(ePO) - static_cast<sal_uInt16>(PresentationObjects::Outline_1) + 2; n < 10; n++ )
1516 OUString aName( sStyleName + OUString::number(n) );
1518 SfxStyleSheetBase* pSheet = pSSPool->Find( aName, SfxStyleFamily::Pseudo);
1520 if(pSheet)
1522 SdStyleSheet* pRealStyleSheet = static_cast<SdStyleSheet*>(pSheet)->GetRealStyleSheet();
1523 pRealStyleSheet->Broadcast(SfxHint(SfxHintId::DataChanged));
1528 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */