Bump version to 24.04.3.4
[LibreOffice.git] / svx / source / sidebar / nbdtmg.cxx
blobb572d49f8adf42916b36de6ea028cab1ab8d25c4
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 .
19 #include <svx/nbdtmg.hxx>
20 #include <svx/svxids.hrc>
21 #include <vcl/svapp.hxx>
22 #include <svl/itemset.hxx>
23 #include <sfx2/request.hxx>
24 #include <svl/stritem.hxx>
25 #include <svtools/ctrltool.hxx>
26 #include <sfx2/objsh.hxx>
27 #include <editeng/flstitem.hxx>
28 #include <svl/itempool.hxx>
29 #include <vcl/outdev.hxx>
30 #include <editeng/brushitem.hxx>
31 #include <svx/dialmgr.hxx>
32 #include <svx/strings.hrc>
33 #include <vcl/graph.hxx>
34 #include <vcl/settings.hxx>
36 #include <i18nlangtag/languagetag.hxx>
37 #include <o3tl/temporary.hxx>
38 #include <tools/debug.hxx>
39 #include <tools/urlobj.hxx>
40 #include <unotools/ucbstreamhelper.hxx>
41 #include <unotools/pathoptions.hxx>
42 #include <editeng/eeitem.hxx>
44 #include <com/sun/star/text/VertOrientation.hpp>
45 #include <com/sun/star/style/NumberingType.hpp>
46 #include <com/sun/star/container/XIndexAccess.hpp>
47 #include <com/sun/star/text/DefaultNumberingProvider.hpp>
48 #include <com/sun/star/beans/PropertyValue.hpp>
49 #include <comphelper/processfactory.hxx>
50 #include <memory>
52 using namespace com::sun::star;
53 using namespace com::sun::star::uno;
54 using namespace com::sun::star::beans;
55 using namespace com::sun::star::lang;
56 using namespace com::sun::star::text;
57 using namespace com::sun::star::container;
58 using namespace com::sun::star::style;
60 namespace svx::sidebar {
62 namespace {
64 const vcl::Font& lcl_GetDefaultBulletFont()
66 static vcl::Font aDefBulletFont = []()
68 static vcl::Font tmp("OpenSymbol", "", Size(0, 14));
69 tmp.SetCharSet( RTL_TEXTENCODING_SYMBOL );
70 tmp.SetFamily( FAMILY_DONTKNOW );
71 tmp.SetPitch( PITCH_DONTKNOW );
72 tmp.SetWeight( WEIGHT_DONTKNOW );
73 tmp.SetTransparent( true );
74 return tmp;
75 }();
76 return aDefBulletFont;
79 const sal_Unicode aDefaultBulletTypes[] =
81 0x2022,
82 0x25cf,
83 0xe00c,
84 0xe00a,
85 0x2794,
86 0x27a2,
87 0x2717,
88 0x2714
91 NumSettings_Impl* lcl_CreateNumberingSettingsPtr(const Sequence<PropertyValue>& rLevelProps)
93 NumSettings_Impl* pNew = new NumSettings_Impl;
94 for(const PropertyValue& rValue : rLevelProps)
96 if(rValue.Name == "NumberingType")
98 sal_Int16 nTmp;
99 if (rValue.Value >>= nTmp)
100 pNew->nNumberType = static_cast<SvxNumType>(nTmp);
102 else if(rValue.Name == "Prefix")
103 rValue.Value >>= pNew->sPrefix;
104 else if(rValue.Name == "Suffix")
105 rValue.Value >>= pNew->sSuffix;
106 else if (rValue.Name == "Adjust")
108 sal_Int16 nTmp;
109 if (rValue.Value >>= nTmp)
110 pNew->eNumAlign = static_cast<SvxAdjust>(nTmp);
112 else if(rValue.Name == "ParentNumbering")
113 rValue.Value >>= pNew->nParentNumbering;
114 else if(rValue.Name == "BulletChar")
115 rValue.Value >>= pNew->sBulletChar;
116 else if(rValue.Name == "BulletFontName")
117 rValue.Value >>= pNew->sBulletFont;
119 const sal_Unicode cLocalPrefix = pNew->sPrefix.getLength() ? pNew->sPrefix[0] : 0;
120 const sal_Unicode cLocalSuffix = pNew->sSuffix.getLength() ? pNew->sSuffix[0] : 0;
121 if( cLocalPrefix == ' ') pNew->sPrefix.clear();
122 if( cLocalSuffix == ' ') pNew->sSuffix.clear();
123 return pNew;
128 sal_uInt16 NBOTypeMgrBase:: IsSingleLevel(sal_uInt16 nCurLevel)
130 sal_uInt16 nLv = sal_uInt16(0xFFFF);
131 sal_uInt16 nCount = 0;
132 sal_uInt16 nMask = 1;
133 for( sal_uInt16 i = 0; i < SVX_MAX_NUM; i++ )
135 if(nCurLevel & nMask)
137 nCount++;
138 nLv=i;
140 nMask <<= 1 ;
143 if ( nCount == 1)
144 return nLv;
145 else
146 return sal_uInt16(0xFFFF);
149 void NBOTypeMgrBase::SetItems(const SfxItemSet* pArg) {
150 pSet = pArg;
151 if ( !pSet )
152 return;
154 SfxAllItemSet aSet(*pSet);
156 const SfxStringItem* pBulletCharFmt = aSet.GetItem<SfxStringItem>(SID_BULLET_CHAR_FMT, false);
157 if (pBulletCharFmt)
158 aBulletCharFmtName = pBulletCharFmt->GetValue();
160 const SfxStringItem* pNumCharFmt = aSet.GetItem<SfxStringItem>(SID_NUM_CHAR_FMT, false);
161 if (pNumCharFmt)
162 aNumCharFmtName = pNumCharFmt->GetValue();
164 const SfxPoolItem* pItem;
165 SfxItemState eState = pSet->GetItemState(SID_ATTR_NUMBERING_RULE, false, &pItem);
166 if(eState == SfxItemState::SET)
168 eCoreUnit = pSet->GetPool()->GetMetric(pSet->GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE));
169 } else {
170 //sd use different sid for numbering rule
171 eState = pSet->GetItemState(EE_PARA_NUMBULLET, false, &pItem);
172 if(eState == SfxItemState::SET)
174 eCoreUnit = pSet->GetPool()->GetMetric(pSet->GetPool()->GetWhich(EE_PARA_NUMBULLET));
179 void NBOTypeMgrBase::ImplLoad(std::u16string_view filename)
181 bIsLoading = true;
182 MapUnit eOldCoreUnit=eCoreUnit;
183 eCoreUnit = MapUnit::Map100thMM;
184 INetURLObject aFile( SvtPathOptions().GetUserConfigPath() );
185 aFile.Append( filename);
186 std::unique_ptr<SvStream> xIStm(::utl::UcbStreamHelper::CreateStream( aFile.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ ));
187 if( xIStm ) {
188 sal_uInt32 nVersion = 0;
189 sal_Int32 nNumIndex = 0;
190 xIStm->ReadUInt32( nVersion );
191 if (nVersion==DEFAULT_NUMBERING_CACHE_FORMAT_VERSION) //first version
193 xIStm->ReadInt32( nNumIndex );
194 while (nNumIndex>=0 && nNumIndex<DEFAULT_NUM_VALUSET_COUNT) {
195 SvxNumRule aNum(*xIStm);
196 //bullet color in font properties is not stored correctly. Need set transparency bits manually
197 for(sal_uInt16 i = 0; i < aNum.GetLevelCount(); i++)
199 SvxNumberFormat aFmt(aNum.GetLevel(i));
200 if (aFmt.GetBulletFont()) {
201 vcl::Font aFont(*aFmt.GetBulletFont());
202 Color c=aFont.GetColor();
203 c.SetAlpha(0);
204 aFont.SetColor(c);
205 aFmt.SetBulletFont(&aFont);
206 aNum.SetLevel(i, aFmt);
209 ReplaceNumRule(aNum,nNumIndex,0x1/*nLevel*/);
210 xIStm->ReadInt32( nNumIndex );
214 eCoreUnit = eOldCoreUnit;
215 bIsLoading = false;
217 void NBOTypeMgrBase::ImplStore(std::u16string_view filename)
219 if (bIsLoading) return;
220 MapUnit eOldCoreUnit=eCoreUnit;
221 eCoreUnit = MapUnit::Map100thMM;
222 INetURLObject aFile( SvtPathOptions().GetUserConfigPath() );
223 aFile.Append( filename);
224 std::unique_ptr<SvStream> xOStm(::utl::UcbStreamHelper::CreateStream( aFile.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::WRITE ));
225 if( xOStm ) {
226 sal_uInt32 nVersion;
227 sal_Int32 nNumIndex;
228 nVersion = DEFAULT_NUMBERING_CACHE_FORMAT_VERSION;
229 xOStm->WriteUInt32( nVersion );
230 for(sal_Int32 nItem = 0; nItem < DEFAULT_NUM_VALUSET_COUNT; nItem++ ) {
231 if (IsCustomized(nItem)) {
232 SvxNumRule aDefNumRule( SvxNumRuleFlags::BULLET_REL_SIZE | SvxNumRuleFlags::CONTINUOUS | SvxNumRuleFlags::BULLET_COLOR,
233 10, false,
234 SvxNumRuleType::NUMBERING, SvxNumberFormat::LABEL_ALIGNMENT);
235 xOStm->WriteInt32( nItem );
236 ApplyNumRule(aDefNumRule,nItem,0x1/*nLevel*/,false,true);
237 aDefNumRule.Store(*xOStm);
240 nNumIndex = -1;
241 xOStm->WriteInt32( nNumIndex ); //write end flag
243 eCoreUnit = eOldCoreUnit;
246 // Character Bullet Type lib
247 BulletsSettings* BulletsTypeMgr::pActualBullets[] ={nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr};
248 sal_Unicode BulletsTypeMgr::aDynamicBulletTypes[]={' ',' ',' ',' ',' ',' ',' ',' '};
249 sal_Unicode BulletsTypeMgr::aDynamicRTLBulletTypes[]={' ',' ',' ',' ',' ',' ',' ',' '};
251 BulletsTypeMgr::BulletsTypeMgr()
253 Init();
256 BulletsTypeMgr& BulletsTypeMgr::GetInstance()
258 static BulletsTypeMgr theBulletsTypeMgr;
259 return theBulletsTypeMgr;
262 void BulletsTypeMgr::Init()
264 const vcl::Font& rActBulletFont = lcl_GetDefaultBulletFont();
266 for (sal_uInt16 i=0;i<DEFAULT_BULLET_TYPES;i++)
268 pActualBullets[i] = new BulletsSettings;
269 pActualBullets[i]->cBulletChar = aDefaultBulletTypes[i];
270 pActualBullets[i]->aFont = rActBulletFont;
271 OString id = OString::Concat(RID_SVXSTR_BULLET_DESCRIPTION_0.getId()) + OString::number(i);
272 pActualBullets[i]->sDescription = SvxResId( TranslateId(RID_SVXSTR_BULLET_DESCRIPTION_0.mpContext, id.getStr()) );
275 sal_uInt16 BulletsTypeMgr::GetNBOIndexForNumRule(SvxNumRule& aNum,sal_uInt16 mLevel,sal_uInt16 nFromIndex)
277 if ( mLevel == sal_uInt16(0xFFFF) || mLevel == 0)
278 return sal_uInt16(0xFFFF);
279 //if ( !lcl_IsNumFmtSet(pNR, mLevel) ) return (sal_uInt16)0xFFFF;
281 sal_uInt16 nActLv = IsSingleLevel(mLevel);
283 if ( nActLv == sal_uInt16(0xFFFF) )
284 return sal_uInt16(0xFFFF);
286 const SvxNumberFormat& aFmt(aNum.GetLevel(nActLv));
287 sal_UCS4 cChar = aFmt.GetBulletChar();
288 for(sal_uInt16 i = nFromIndex; i < DEFAULT_BULLET_TYPES; i++)
290 if ( (cChar == pActualBullets[i]->cBulletChar) ||
291 (cChar == 9830 && 57356 == pActualBullets[i]->cBulletChar) ||
292 (cChar == 9632 && 57354 == pActualBullets[i]->cBulletChar) )
294 return i+1;
298 return sal_uInt16(0xFFFF);
301 void BulletsTypeMgr::ReplaceNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel)
303 if ( nIndex >= DEFAULT_BULLET_TYPES )
304 return;
306 if ( mLevel == sal_uInt16(0xFFFF) || mLevel == 0)
307 return;
309 if ( GetNBOIndexForNumRule(aNum,mLevel) != sal_uInt16(0xFFFF) )
310 return;
312 sal_uInt16 nActLv = IsSingleLevel(mLevel);
314 if ( nActLv == sal_uInt16(0xFFFF) )
315 return;
317 SvxNumberFormat aFmt(aNum.GetLevel(nActLv));
318 sal_UCS4 cChar = aFmt.GetBulletChar();
319 std::optional<vcl::Font> pFont = aFmt.GetBulletFont();
321 pActualBullets[nIndex]->cBulletChar = cChar;
322 if ( pFont )
323 pActualBullets[nIndex]->aFont = *pFont;
324 pActualBullets[nIndex]->bIsCustomized = true;
327 void BulletsTypeMgr::ApplyNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel, bool /*isDefault*/, bool isResetSize)
329 if ( nIndex >= DEFAULT_BULLET_TYPES )
330 return;
331 sal_UCS4 cChar = pActualBullets[nIndex]->cBulletChar;
332 const vcl::Font& rActBulletFont = pActualBullets[nIndex]->aFont;
334 sal_uInt16 nMask = 1;
335 OUString sBulletCharFormatName = GetBulletCharFmtName();
336 for(sal_uInt16 i = 0; i < aNum.GetLevelCount(); i++)
338 if(mLevel & nMask)
340 SvxNumberFormat aFmt(aNum.GetLevel(i));
341 aFmt.SetNumberingType( SVX_NUM_CHAR_SPECIAL );
342 aFmt.SetBulletFont(&rActBulletFont);
343 aFmt.SetBulletChar(cChar);
344 aFmt.SetCharFormatName(sBulletCharFormatName);
345 aFmt.SetListFormat( "" );
346 if (isResetSize) aFmt.SetBulletRelSize(45);
347 aNum.SetLevel(i, aFmt);
349 nMask <<= 1;
353 OUString BulletsTypeMgr::GetDescription(sal_uInt16 nIndex, bool /*isDefault*/)
355 OUString sRet;
357 if ( nIndex >= DEFAULT_BULLET_TYPES )
358 return sRet;
359 else
360 sRet = pActualBullets[nIndex]->sDescription;
362 return sRet;
365 bool BulletsTypeMgr::IsCustomized(sal_uInt16 nIndex)
367 bool bRet = false;
369 if ( nIndex >= DEFAULT_BULLET_TYPES )
370 bRet = false;
371 else
372 bRet = pActualBullets[nIndex]->bIsCustomized;
374 return bRet;
377 // Numbering Type lib
378 NumberingTypeMgr::NumberingTypeMgr()
380 Init();
381 maDefaultNumberSettingsArr = maNumberSettingsArr;
382 ImplLoad(u"standard.syb");
385 NumberingTypeMgr::~NumberingTypeMgr()
389 const TranslateId RID_SVXSTR_SINGLENUM_DESCRIPTIONS[] =
391 RID_SVXSTR_SINGLENUM_DESCRIPTION_0,
392 RID_SVXSTR_SINGLENUM_DESCRIPTION_1,
393 RID_SVXSTR_SINGLENUM_DESCRIPTION_2,
394 RID_SVXSTR_SINGLENUM_DESCRIPTION_3,
395 RID_SVXSTR_SINGLENUM_DESCRIPTION_4,
396 RID_SVXSTR_SINGLENUM_DESCRIPTION_5,
397 RID_SVXSTR_SINGLENUM_DESCRIPTION_6,
398 RID_SVXSTR_SINGLENUM_DESCRIPTION_7
401 NumberingTypeMgr& NumberingTypeMgr::GetInstance()
403 static NumberingTypeMgr theNumberingTypeMgr;
404 return theNumberingTypeMgr;
407 void NumberingTypeMgr::Init()
409 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
410 Reference<XDefaultNumberingProvider> xDefNum = DefaultNumberingProvider::create( xContext );
412 Sequence< Sequence< PropertyValue > > aNumberings;
413 Locale aLocale(Application::GetSettings().GetLanguageTag().getLocale());
416 aNumberings = xDefNum->getDefaultContinuousNumberingLevels( aLocale );
418 sal_Int32 nLength = aNumberings.getLength();
420 const Sequence<PropertyValue>* pValuesArr = aNumberings.getConstArray();
421 for(sal_Int32 i = 0; i < nLength; i++)
423 NumSettings_Impl* pNew = lcl_CreateNumberingSettingsPtr(pValuesArr[i]);
424 std::shared_ptr<NumberSettings_Impl> pNumEntry = std::make_shared<NumberSettings_Impl>();
425 pNumEntry->pNumSetting = pNew;
426 if ( i < 8 )
427 pNumEntry->sDescription = SvxResId(RID_SVXSTR_SINGLENUM_DESCRIPTIONS[i]);
428 maNumberSettingsArr.push_back(pNumEntry);
431 catch(Exception&)
436 sal_uInt16 NumberingTypeMgr::GetNBOIndexForNumRule(SvxNumRule& aNum,sal_uInt16 mLevel,sal_uInt16 nFromIndex)
438 if ( mLevel == sal_uInt16(0xFFFF) || mLevel > aNum.GetLevelCount() || mLevel == 0)
439 return sal_uInt16(0xFFFF);
441 sal_uInt16 nActLv = IsSingleLevel(mLevel);
443 if ( nActLv == sal_uInt16(0xFFFF) )
444 return sal_uInt16(0xFFFF);
446 const SvxNumberFormat& aFmt(aNum.GetLevel(nActLv));
447 //sal_Unicode cPrefix = OUString(aFmt.GetPrefix())[0];
448 //sal_Unicode cSuffix = :OUString(aFmt.GetSuffix())[0];
449 const OUString& sPrefix = aFmt.GetPrefix();
450 const OUString& sLclSuffix = aFmt.GetSuffix();
451 sal_Int16 eNumType = aFmt.GetNumberingType();
453 sal_uInt16 nCount = maNumberSettingsArr.size();
454 for(sal_uInt16 i = nFromIndex; i < nCount; ++i)
456 NumberSettings_Impl* _pSet = maNumberSettingsArr[i].get();
457 sal_Int16 eNType = _pSet->pNumSetting->nNumberType;
458 OUString sLocalPrefix = _pSet->pNumSetting->sPrefix;
459 OUString sLocalSuffix = _pSet->pNumSetting->sSuffix;
460 if (sPrefix == sLocalPrefix &&
461 sLclSuffix == sLocalSuffix &&
462 eNumType == eNType )
464 return i+1;
469 return sal_uInt16(0xFFFF);
472 void NumberingTypeMgr::ReplaceNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel)
474 sal_uInt16 nActLv = IsSingleLevel(mLevel);
476 if ( nActLv == sal_uInt16(0xFFFF) )
477 return;
479 const SvxNumberFormat& aFmt(aNum.GetLevel(nActLv));
480 SvxNumType eNumType = aFmt.GetNumberingType();
482 sal_uInt16 nCount = maNumberSettingsArr.size();
483 if ( nIndex >= nCount )
484 return;
486 NumberSettings_Impl* _pSet = maNumberSettingsArr[nIndex].get();
488 _pSet->pNumSetting->sPrefix = aFmt.GetPrefix();
489 _pSet->pNumSetting->sSuffix = aFmt.GetSuffix();
490 _pSet->pNumSetting->nNumberType = eNumType;
491 _pSet->bIsCustomized = true;
493 SvxNumRule aTmpRule1(aNum);
494 SvxNumRule aTmpRule2(aNum);
495 ApplyNumRule(aTmpRule1,nIndex,mLevel,true);
496 ApplyNumRule(aTmpRule2,nIndex,mLevel);
497 if (aTmpRule1==aTmpRule2) _pSet->bIsCustomized=false;
498 if (!_pSet->bIsCustomized) {
499 _pSet->sDescription = GetDescription(nIndex,true);
501 ImplStore(u"standard.syb");
504 void NumberingTypeMgr::ApplyNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel, bool isDefault, bool isResetSize)
506 if(maNumberSettingsArr.size() <= nIndex)
507 return;
508 NumberSettingsArr_Impl* pCurrentNumberSettingsArr = &maNumberSettingsArr;
509 if (isDefault) pCurrentNumberSettingsArr = &maDefaultNumberSettingsArr;
510 NumberSettings_Impl* _pSet = (*pCurrentNumberSettingsArr)[nIndex].get();
511 SvxNumType eNewType = _pSet->pNumSetting->nNumberType;
513 sal_uInt16 nMask = 1;
514 OUString sNumCharFmtName = GetNumCharFmtName();
515 for(sal_uInt16 i = 0; i < aNum.GetLevelCount(); i++)
517 if(mLevel & nMask)
519 SvxNumberFormat aFmt(aNum.GetLevel(i));
520 if (eNewType!=aFmt.GetNumberingType()) isResetSize=true;
521 aFmt.SetNumberingType(eNewType);
522 aFmt.SetListFormat(_pSet->pNumSetting->sPrefix, _pSet->pNumSetting->sSuffix, i);
523 aFmt.SetCharFormatName(sNumCharFmtName);
524 if (isResetSize) aFmt.SetBulletRelSize(100);
525 aNum.SetLevel(i, aFmt);
527 nMask <<= 1 ;
531 OUString NumberingTypeMgr::GetDescription(sal_uInt16 nIndex, bool isDefault)
533 OUString sRet;
534 sal_uInt16 nLength = maNumberSettingsArr.size();
536 if ( nIndex >= nLength )
537 return sRet;
538 else
539 sRet = maNumberSettingsArr[nIndex]->sDescription;
540 if (isDefault) sRet = maDefaultNumberSettingsArr[nIndex]->sDescription;
542 return sRet;
545 bool NumberingTypeMgr::IsCustomized(sal_uInt16 nIndex)
547 bool bRet = false;
548 sal_uInt16 nLength = maNumberSettingsArr.size();
550 if ( nIndex >= nLength )
551 bRet = false;
552 else
553 bRet = maNumberSettingsArr[nIndex]->bIsCustomized;
555 return bRet;
557 // Multi-level /Outline Type lib
558 OutlineTypeMgr::OutlineTypeMgr()
560 Init();
561 for(sal_Int32 nItem = 0; nItem < DEFAULT_NUM_VALUSET_COUNT; nItem++ )
563 pDefaultOutlineSettingsArrs[nItem] = pOutlineSettingsArrs[nItem];
565 //Initial the first time to store the default value. Then do it again for customized value
566 Init();
567 ImplLoad(u"standard.syc");
570 OutlineTypeMgr& OutlineTypeMgr::GetInstance()
572 static OutlineTypeMgr theOutlineTypeMgr;
573 return theOutlineTypeMgr;
576 void OutlineTypeMgr::Init()
578 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
579 Reference<XDefaultNumberingProvider> xDefNum = DefaultNumberingProvider::create( xContext );
581 Sequence<Reference<XIndexAccess> > aOutlineAccess;
582 Locale aLocale(Application::GetSettings().GetLanguageTag().getLocale());
585 aOutlineAccess = xDefNum->getDefaultOutlineNumberings( aLocale );
587 SvxNumRule aDefNumRule( SvxNumRuleFlags::BULLET_REL_SIZE | SvxNumRuleFlags::CONTINUOUS | SvxNumRuleFlags::BULLET_COLOR,
588 10, false,
589 SvxNumRuleType::NUMBERING, SvxNumberFormat::LABEL_ALIGNMENT);
591 auto nSize = std::min<sal_Int32>(aOutlineAccess.getLength(), DEFAULT_NUM_VALUSET_COUNT);
592 for(sal_Int32 nItem = 0; nItem < nSize; nItem++ )
594 pOutlineSettingsArrs[ nItem ] = new OutlineSettings_Impl;
595 OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[ nItem ];
596 OString id = OString::Concat(RID_SVXSTR_OUTLINENUM_DESCRIPTION_0.getId()) + OString::number(nItem);
597 pItemArr->sDescription = SvxResId( TranslateId(RID_SVXSTR_OUTLINENUM_DESCRIPTION_0.mpContext, id.getStr()) );
598 pItemArr->pNumSettingsArr = new NumSettingsArr_Impl;
599 Reference<XIndexAccess> xLevel = aOutlineAccess.getConstArray()[nItem];
600 for(sal_Int32 nLevel = 0; nLevel < SVX_MAX_NUM; nLevel++)
602 // use the last locale-defined level for all remaining levels.
603 sal_Int32 nLocaleLevel = std::min(nLevel, xLevel->getCount() - 1);
604 Sequence<PropertyValue> aLevelProps;
605 if (nLocaleLevel >= 0)
606 xLevel->getByIndex(nLocaleLevel) >>= aLevelProps;
608 NumSettings_Impl* pNew = lcl_CreateNumberingSettingsPtr(aLevelProps);
609 const SvxNumberFormat& aNumFmt( aDefNumRule.GetLevel( nLevel) );
610 assert(aNumFmt.GetNumAdjust() == SvxAdjust::Left && "new entry was previously defined by default, now defaults to Left");
611 pNew->eLabelFollowedBy = aNumFmt.GetLabelFollowedBy();
612 pNew->nTabValue = aNumFmt.GetListtabPos();
613 if (pNew->eNumAlign == SvxAdjust::Right)
614 pNew->nNumAlignAt = -174; // number borrowed from RES_POOLNUMRULE_NUM4
615 else
616 pNew->nNumAlignAt = aNumFmt.GetFirstLineIndent();
617 pNew->nNumIndentAt = aNumFmt.GetIndentAt();
618 pItemArr->pNumSettingsArr->push_back(std::shared_ptr<NumSettings_Impl>(pNew));
622 catch(Exception&)
627 sal_uInt16 OutlineTypeMgr::GetNBOIndexForNumRule(SvxNumRule& aNum,sal_uInt16 /*mLevel*/,sal_uInt16 nFromIndex)
629 sal_uInt16 const nLength = SAL_N_ELEMENTS(pOutlineSettingsArrs);
630 for(sal_uInt16 iDex = nFromIndex; iDex < nLength; iDex++)
632 bool bNotMatch = false;
633 OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[iDex];
634 sal_uInt16 nCount = pItemArr ? pItemArr->pNumSettingsArr->size() : 0;
635 for (sal_uInt16 iLevel=0;iLevel < nCount;iLevel++)
637 NumSettings_Impl* _pSet = (*pItemArr->pNumSettingsArr)[iLevel].get();
638 sal_Int16 eNType = _pSet->nNumberType;
640 const SvxNumberFormat& aFmt(aNum.GetLevel(iLevel));
641 const OUString& sPrefix = aFmt.GetPrefix();
642 const OUString& sLclSuffix = aFmt.GetSuffix();
643 sal_Int16 eNumType = aFmt.GetNumberingType();
644 if( eNumType == SVX_NUM_CHAR_SPECIAL)
646 sal_UCS4 cChar = aFmt.GetBulletChar();
648 sal_UCS4 ccChar
649 = _pSet->sBulletChar.isEmpty()
651 : _pSet->sBulletChar.iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
653 if ( !((cChar == ccChar) &&
654 _pSet->eLabelFollowedBy == aFmt.GetLabelFollowedBy() &&
655 _pSet->nTabValue == aFmt.GetListtabPos() &&
656 _pSet->eNumAlign == aFmt.GetNumAdjust() &&
657 _pSet->nNumAlignAt == aFmt.GetFirstLineIndent() &&
658 _pSet->nNumIndentAt == aFmt.GetIndentAt()))
660 bNotMatch = true;
661 break;
664 else if ((eNumType&(~LINK_TOKEN)) == SVX_NUM_BITMAP )
666 const SvxBrushItem* pBrsh1 = aFmt.GetBrush();
667 const SvxBrushItem* pBrsh2 = _pSet->pBrushItem;
668 bool bIsMatch = false;
669 if (SfxPoolItem::areSame(pBrsh1,pBrsh2)) bIsMatch = true;
670 if (pBrsh1 && pBrsh2) {
671 const Graphic* pGrf1 = pBrsh1->GetGraphic();
672 const Graphic* pGrf2 = pBrsh2->GetGraphic();
673 if (pGrf1==pGrf2) bIsMatch = true;
674 if (pGrf1 && pGrf2) {
675 if ( pGrf1->GetBitmapEx() == pGrf2->GetBitmapEx() &&
676 _pSet->aSize == aFmt.GetGraphicSize())
677 bIsMatch = true;
680 if (!bIsMatch) {
681 bNotMatch = true;
682 break;
685 else
687 if (!(sPrefix == _pSet->sPrefix &&
688 sLclSuffix == _pSet->sSuffix &&
689 eNumType == eNType &&
690 _pSet->eLabelFollowedBy == aFmt.GetLabelFollowedBy() &&
691 _pSet->nTabValue == aFmt.GetListtabPos() &&
692 _pSet->eNumAlign == aFmt.GetNumAdjust() &&
693 _pSet->nNumAlignAt == aFmt.GetFirstLineIndent() &&
694 _pSet->nNumIndentAt == aFmt.GetIndentAt()))
696 bNotMatch = true;
697 break;
701 if ( !bNotMatch )
702 return iDex+1;
706 return sal_uInt16(0xFFFF);
709 void OutlineTypeMgr::ReplaceNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel)
711 sal_uInt16 const nLength = SAL_N_ELEMENTS(pOutlineSettingsArrs);
712 if ( nIndex >= nLength )
713 return;
715 OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[nIndex];
716 sal_uInt16 nCount = pItemArr->pNumSettingsArr->size();
717 for (sal_uInt16 iLevel=0;iLevel < nCount;iLevel++)
719 const SvxNumberFormat& aFmt(aNum.GetLevel(iLevel));
720 SvxNumType eNumType = aFmt.GetNumberingType();
722 NumSettings_Impl* _pSet = (*pItemArr->pNumSettingsArr)[iLevel].get();
724 _pSet->eLabelFollowedBy = aFmt.GetLabelFollowedBy();
725 _pSet->nTabValue = aFmt.GetListtabPos();
726 _pSet->eNumAlign = aFmt.GetNumAdjust();
727 _pSet->nNumAlignAt = aFmt.GetFirstLineIndent();
728 _pSet->nNumIndentAt = aFmt.GetIndentAt();
730 if( eNumType == SVX_NUM_CHAR_SPECIAL)
732 sal_UCS4 cChar = aFmt.GetBulletChar();
733 OUString sChar(&cChar, 1);
734 _pSet->sBulletChar = sChar;
735 if ( aFmt.GetBulletFont() )
736 _pSet->sBulletFont = aFmt.GetBulletFont()->GetFamilyName();
737 _pSet->nNumberType = eNumType;
738 pItemArr->bIsCustomized = true;
739 }else if ((eNumType&(~LINK_TOKEN)) == SVX_NUM_BITMAP ) {
740 if (_pSet->pBrushItem) {
741 delete _pSet->pBrushItem;
742 _pSet->pBrushItem=nullptr;
744 if (aFmt.GetBrush())
745 _pSet->pBrushItem = new SvxBrushItem(*aFmt.GetBrush());
746 _pSet->aSize = aFmt.GetGraphicSize();
747 _pSet->nNumberType = eNumType;
748 } else
750 _pSet->sPrefix = aFmt.GetPrefix();
751 _pSet->sSuffix = aFmt.GetSuffix();
752 _pSet->nNumberType = eNumType;
753 if ( aFmt.GetBulletFont() )
754 _pSet->sBulletFont = aFmt.GetBulletFont()->GetFamilyName();
755 pItemArr->bIsCustomized = true;
758 SvxNumRule aTmpRule1(aNum);
759 SvxNumRule aTmpRule2(aNum);
760 ApplyNumRule(aTmpRule1,nIndex,mLevel,true);
761 ApplyNumRule(aTmpRule2,nIndex,mLevel);
762 if (aTmpRule1==aTmpRule2) pItemArr->bIsCustomized=false;
763 if (!pItemArr->bIsCustomized) {
764 pItemArr->sDescription = GetDescription(nIndex,true);
766 ImplStore(u"standard.syc");
769 void OutlineTypeMgr::ApplyNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 /*mLevel*/, bool isDefault, bool isResetSize)
771 DBG_ASSERT(DEFAULT_NUM_VALUSET_COUNT > nIndex, "wrong index");
772 if(DEFAULT_NUM_VALUSET_COUNT <= nIndex)
773 return;
775 const FontList* pList = nullptr;
777 OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[nIndex];
778 if (isDefault) pItemArr=pDefaultOutlineSettingsArrs[nIndex];
780 NumSettingsArr_Impl *pNumSettingsArr=pItemArr->pNumSettingsArr;
782 NumSettings_Impl* pLevelSettings = nullptr;
783 for(sal_uInt16 i = 0; i < aNum.GetLevelCount(); i++)
785 if(pNumSettingsArr->size() > i)
786 pLevelSettings = (*pNumSettingsArr)[i].get();
788 if(!pLevelSettings)
789 break;
791 SvxNumberFormat aFmt(aNum.GetLevel(i));
792 const vcl::Font& rActBulletFont = lcl_GetDefaultBulletFont();
793 if (pLevelSettings->nNumberType !=aFmt.GetNumberingType()) isResetSize=true;
794 aFmt.SetNumberingType( pLevelSettings->nNumberType );
795 sal_uInt16 nUpperLevelOrChar = static_cast<sal_uInt16>(pLevelSettings->nParentNumbering);
796 if(aFmt.GetNumberingType() == SVX_NUM_CHAR_SPECIAL)
798 if( pLevelSettings->sBulletFont.getLength() &&
799 pLevelSettings->sBulletFont != rActBulletFont.GetFamilyName() )
801 //search for the font
802 if(!pList)
804 if (SfxObjectShell* pCurDocShell = SfxObjectShell::Current())
806 const SvxFontListItem* pFontListItem = static_cast<const SvxFontListItem*>(pCurDocShell->GetItem(SID_ATTR_CHAR_FONTLIST));
807 pList = pFontListItem ? pFontListItem->GetFontList() : nullptr;
810 if(pList && pList->IsAvailable( pLevelSettings->sBulletFont ) )
812 FontMetric aFontMetric = pList->Get(pLevelSettings->sBulletFont,WEIGHT_NORMAL, ITALIC_NONE);
813 vcl::Font aFont(aFontMetric);
814 aFmt.SetBulletFont(&aFont);
816 else
818 //if it cannot be found then create a new one
819 vcl::Font aCreateFont( pLevelSettings->sBulletFont, OUString(), Size( 0, 14 ) );
820 aCreateFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW );
821 aCreateFont.SetFamily( FAMILY_DONTKNOW );
822 aCreateFont.SetPitch( PITCH_DONTKNOW );
823 aCreateFont.SetWeight( WEIGHT_DONTKNOW );
824 aCreateFont.SetTransparent( true );
825 aFmt.SetBulletFont( &aCreateFont );
827 }else
828 aFmt.SetBulletFont( &rActBulletFont );
830 sal_UCS4 cChar = 0;
831 if( !pLevelSettings->sBulletChar.isEmpty() )
833 cChar
834 = pLevelSettings->sBulletChar.iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
836 if( AllSettings::GetLayoutRTL() )
838 if( 0 == i && cChar == BulletsTypeMgr::aDynamicBulletTypes[5] )
839 cChar = BulletsTypeMgr::aDynamicRTLBulletTypes[5];
840 else if( 1 == i )
842 const SvxNumberFormat& numberFmt = aNum.GetLevel(0);
843 if( numberFmt.GetBulletChar() == BulletsTypeMgr::aDynamicRTLBulletTypes[5] )
844 cChar = BulletsTypeMgr::aDynamicRTLBulletTypes[4];
848 aFmt.SetBulletChar(cChar);
849 aFmt.SetCharFormatName( GetBulletCharFmtName() );
850 if (isResetSize) aFmt.SetBulletRelSize(45);
851 }else if ((aFmt.GetNumberingType()&(~LINK_TOKEN)) == SVX_NUM_BITMAP ) {
852 if (pLevelSettings->pBrushItem) {
853 const Graphic* pGrf = pLevelSettings->pBrushItem->GetGraphic();
854 Size aSize = pLevelSettings->aSize;
855 sal_Int16 eOrient = text::VertOrientation::LINE_CENTER;
856 if (!isResetSize && aFmt.GetGraphicSize()!=Size(0,0))
857 aSize = aFmt.GetGraphicSize();
858 else if (aSize.IsEmpty() && pGrf)
859 aSize = SvxNumberFormat::GetGraphicSizeMM100( pGrf );
860 aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(GetMapUnit()));
861 aFmt.SetGraphicBrush( pLevelSettings->pBrushItem, &aSize, &eOrient );
863 } else
865 aFmt.SetIncludeUpperLevels(sal::static_int_cast< sal_uInt8 >(0 != nUpperLevelOrChar ? aNum.GetLevelCount() : 1));
866 aFmt.SetCharFormatName(GetNumCharFmtName());
867 if (isResetSize) aFmt.SetBulletRelSize(100);
869 if(pNumSettingsArr->size() > i) {
870 aFmt.SetLabelFollowedBy(pLevelSettings->eLabelFollowedBy);
871 aFmt.SetListtabPos(pLevelSettings->nTabValue);
872 aFmt.SetNumAdjust(pLevelSettings->eNumAlign);
873 aFmt.SetFirstLineIndent(pLevelSettings->nNumAlignAt);
874 aFmt.SetIndentAt(pLevelSettings->nNumIndentAt);
876 aFmt.SetListFormat(pLevelSettings->sPrefix, pLevelSettings->sSuffix, i);
877 aNum.SetLevel(i, aFmt);
881 OUString OutlineTypeMgr::GetDescription(sal_uInt16 nIndex, bool isDefault)
883 OUString sRet;
885 if ( nIndex >= SAL_N_ELEMENTS(pOutlineSettingsArrs) )
886 return sRet;
887 else
889 OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[nIndex];
890 if (isDefault) pItemArr = pDefaultOutlineSettingsArrs[nIndex];
891 if ( pItemArr )
893 sRet = pItemArr->sDescription;
896 return sRet;
899 bool OutlineTypeMgr::IsCustomized(sal_uInt16 nIndex)
901 bool bRet = false;
903 if ( nIndex >= SAL_N_ELEMENTS(pOutlineSettingsArrs) )
904 return bRet;
905 else
907 OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[nIndex];
908 if ( pItemArr )
910 bRet = pItemArr->bIsCustomized;
914 return bRet;
920 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */