xref: /core/cui/source/tabpages/numpages.cxx (revision b8a89b33)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <com/sun/star/text/VertOrientation.hpp>
21 
22 #include <numpages.hxx>
23 #include <dialmgr.hxx>
24 #include <tools/mapunit.hxx>
25 #include <i18nlangtag/languagetag.hxx>
26 #include <i18nlangtag/mslangid.hxx>
27 #include <editeng/numitem.hxx>
28 #include <svl/eitem.hxx>
29 #include <vcl/svapp.hxx>
30 #include <svx/colorbox.hxx>
31 #include <svx/dlgutil.hxx>
32 #include <svx/strarray.hxx>
33 #include <svx/gallery.hxx>
34 #include <editeng/brushitem.hxx>
35 #include <svl/intitem.hxx>
36 #include <sfx2/objsh.hxx>
37 #include <vcl/graph.hxx>
38 #include <vcl/settings.hxx>
39 #include <svx/cuicharmap.hxx>
40 #include <editeng/flstitem.hxx>
41 #include <svx/numvset.hxx>
42 #include <sfx2/htmlmode.hxx>
43 #include <unotools/pathoptions.hxx>
44 #include <svtools/ctrltool.hxx>
45 #include <svtools/unitconv.hxx>
46 #include <svtools/colorcfg.hxx>
47 #include <com/sun/star/style/NumberingType.hpp>
48 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
49 #include <com/sun/star/container/XIndexAccess.hpp>
50 #include <com/sun/star/text/XDefaultNumberingProvider.hpp>
51 #include <com/sun/star/text/XNumberingFormatter.hpp>
52 #include <com/sun/star/beans/PropertyValue.hpp>
53 #include <comphelper/processfactory.hxx>
54 #include <comphelper/propertyvalue.hxx>
55 #include <comphelper/lok.hxx>
56 #include <svx/svxids.hrc>
57 #include <o3tl/string_view.hxx>
58 #include <officecfg/Office/Common.hxx>
59 
60 #include <algorithm>
61 #include <memory>
62 #include <vector>
63 #include <sfx2/opengrf.hxx>
64 
65 #include <strings.hrc>
66 #include <svl/stritem.hxx>
67 #include <svl/slstitm.hxx>
68 #include <sfx2/filedlghelper.hxx>
69 #include <unotools/ucbstreamhelper.hxx>
70 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
71 #include <sal/log.hxx>
72 #include <vcl/cvtgrf.hxx>
73 #include <vcl/graphicfilter.hxx>
74 #include <svx/SvxNumOptionsTabPageHelper.hxx>
75 #include <tools/urlobj.hxx>
76 #include <o3tl/temporary.hxx>
77 #include <osl/diagnose.h>
78 
79 #include <bitmaps.hlst>
80 
81 using namespace css;
82 using namespace css::uno;
83 using namespace css::beans;
84 using namespace css::lang;
85 using namespace css::text;
86 using namespace css::container;
87 
88 #define SHOW_NUMBERING              0
89 #define SHOW_BULLET                 1
90 #define SHOW_BITMAP                 2
91 
92 #define MAX_BMP_WIDTH               16
93 #define MAX_BMP_HEIGHT              16
94 #define SEARCHPATH_DELIMITER        u';'
95 #define SEARCHFILENAME_DELIMITER    u'/'
96 
97 static bool bLastRelative =         false;
98 
lcl_CreateNumSettingsPtr(const Sequence<PropertyValue> & rLevelProps)99 static SvxNumSettings_Impl* lcl_CreateNumSettingsPtr(const Sequence<PropertyValue>& rLevelProps)
100 {
101     SvxNumSettings_Impl* pNew = new SvxNumSettings_Impl;
102     for (auto& prop : rLevelProps)
103     {
104         if (prop.Name == "NumberingType")
105         {
106             sal_Int16 nTmp;
107             if (prop.Value >>= nTmp)
108                 pNew->nNumberType = static_cast<SvxNumType>(nTmp);
109         }
110         else if (prop.Name == "Prefix")
111             prop.Value >>= pNew->sPrefix;
112         else if (prop.Name == "Suffix")
113             prop.Value >>= pNew->sSuffix;
114         else if (prop.Name == "ParentNumbering")
115             prop.Value >>= pNew->nParentNumbering;
116         else if (prop.Name == "BulletChar")
117             prop.Value >>= pNew->sBulletChar;
118         else if (prop.Name == "BulletFontName")
119             prop.Value >>= pNew->sBulletFont;
120     }
121     return pNew;
122 }
123 
124 // Is one of the masked formats set?
lcl_IsNumFmtSet(SvxNumRule const * pNum,sal_uInt16 nLevelMask)125 static bool lcl_IsNumFmtSet(SvxNumRule const * pNum, sal_uInt16 nLevelMask)
126 {
127     bool bRet = false;
128     sal_uInt16 nMask = 1;
129     for( sal_uInt16 i = 0; i < SVX_MAX_NUM && !bRet; i++ )
130     {
131         if(nLevelMask & nMask)
132             bRet |= nullptr != pNum->Get( i );
133         nMask <<= 1 ;
134     }
135     return bRet;
136 }
137 
lcl_GetDefaultBulletFont()138 static vcl::Font& lcl_GetDefaultBulletFont()
139 {
140     static vcl::Font aDefBulletFont = []()
141     {
142         vcl::Font tmp(u"OpenSymbol"_ustr, u""_ustr, Size(0, 14));
143         tmp.SetCharSet( RTL_TEXTENCODING_SYMBOL );
144         tmp.SetFamily( FAMILY_DONTKNOW );
145         tmp.SetPitch( PITCH_DONTKNOW );
146         tmp.SetWeight( WEIGHT_DONTKNOW );
147         tmp.SetTransparent( true );
148         return tmp;
149     }();
150     return aDefBulletFont;
151 }
152 
SvxSingleNumPickTabPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)153 SvxSingleNumPickTabPage::SvxSingleNumPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
154     : SfxTabPage(pPage, pController, u"cui/ui/picknumberingpage.ui"_ustr, u"PickNumberingPage"_ustr, &rSet)
155     , nActNumLvl(SAL_MAX_UINT16)
156     , bModified(false)
157     , bPreset(false)
158     , nNumItemId(SID_ATTR_NUMBERING_RULE)
159     , m_xExamplesVS(new SvxNumValueSet(m_xBuilder->weld_scrolled_window(u"valuesetwin"_ustr, true)))
160     , m_xExamplesVSWin(new weld::CustomWeld(*m_xBuilder, u"valueset"_ustr, *m_xExamplesVS))
161 {
162     SetExchangeSupport();
163     m_xExamplesVS->init(NumberingPageType::SINGLENUM);
164     m_xExamplesVS->SetSelectHdl(LINK(this, SvxSingleNumPickTabPage, NumSelectHdl_Impl));
165     m_xExamplesVS->SetDoubleClickHdl(LINK(this, SvxSingleNumPickTabPage, DoubleClickHdl_Impl));
166 
167     Reference<XDefaultNumberingProvider> xDefNum = SvxNumOptionsTabPageHelper::GetNumberingProvider();
168     if(!xDefNum.is())
169         return;
170 
171     Sequence< Sequence< PropertyValue > > aNumberings;
172     const Locale& rLocale = Application::GetSettings().GetLanguageTag().getLocale();
173     try
174     {
175         aNumberings =
176             xDefNum->getDefaultContinuousNumberingLevels( rLocale );
177 
178         sal_Int32 nLength = std::min<sal_Int32>(aNumberings.getLength(), NUM_VALUSET_COUNT);
179         for(sal_Int32 i = 0; i < nLength; i++)
180         {
181             SvxNumSettings_Impl* pNew = lcl_CreateNumSettingsPtr(aNumberings[i]);
182             aNumSettingsArr.push_back(std::unique_ptr<SvxNumSettings_Impl>(pNew));
183         }
184     }
185     catch(const Exception&)
186     {
187     }
188     Reference<XNumberingFormatter> xFormat(xDefNum, UNO_QUERY);
189     m_xExamplesVS->SetNumberingSettings(aNumberings, xFormat, rLocale);
190 }
191 
~SvxSingleNumPickTabPage()192 SvxSingleNumPickTabPage::~SvxSingleNumPickTabPage()
193 {
194     m_xExamplesVSWin.reset();
195     m_xExamplesVS.reset();
196 }
197 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rAttrSet)198 std::unique_ptr<SfxTabPage> SvxSingleNumPickTabPage::Create(weld::Container* pPage, weld::DialogController* pController,
199                                                    const SfxItemSet* rAttrSet)
200 {
201     return std::make_unique<SvxSingleNumPickTabPage>(pPage, pController, *rAttrSet);
202 }
203 
FillItemSet(SfxItemSet * rSet)204 bool  SvxSingleNumPickTabPage::FillItemSet( SfxItemSet* rSet )
205 {
206     if( (bPreset || bModified) && pSaveNum)
207     {
208         *pSaveNum = *pActNum;
209         rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId ));
210         rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, bPreset));
211     }
212 
213     return bModified;
214 }
215 
ActivatePage(const SfxItemSet & rSet)216 void  SvxSingleNumPickTabPage::ActivatePage(const SfxItemSet& rSet)
217 {
218     bPreset = false;
219     bool bIsPreset = false;
220     const SfxItemSet* pExampleSet = GetDialogExampleSet();
221     if(pExampleSet)
222     {
223         if(const SfxBoolItem* pPresetItem = pExampleSet->GetItemIfSet(SID_PARAM_NUM_PRESET, false))
224             bIsPreset = pPresetItem->GetValue();
225         if(const SfxUInt16Item* pLevelItem = pExampleSet->GetItemIfSet(SID_PARAM_CUR_NUM_LEVEL, false))
226             nActNumLvl = pLevelItem->GetValue();
227     }
228     if(const SvxNumBulletItem* pNumItem = rSet.GetItemIfSet(nNumItemId, false))
229     {
230         pSaveNum.reset( new SvxNumRule(pNumItem->GetNumRule()) );
231     }
232     if(pActNum && *pSaveNum != *pActNum)
233     {
234         *pActNum = *pSaveNum;
235         m_xExamplesVS->SetNoSelection();
236     }
237 
238     if(pActNum && (!lcl_IsNumFmtSet(pActNum.get(), nActNumLvl) || bIsPreset))
239     {
240         m_xExamplesVS->SelectItem(1);
241         NumSelectHdl_Impl(m_xExamplesVS.get());
242         bPreset = true;
243     }
244     bPreset |= bIsPreset;
245 
246     bModified = false;
247 }
248 
DeactivatePage(SfxItemSet * _pSet)249 DeactivateRC SvxSingleNumPickTabPage::DeactivatePage(SfxItemSet *_pSet)
250 {
251     if(_pSet)
252         FillItemSet(_pSet);
253     return DeactivateRC::LeavePage;
254 }
255 
Reset(const SfxItemSet * rSet)256 void  SvxSingleNumPickTabPage::Reset( const SfxItemSet* rSet )
257 {
258     const SfxPoolItem* pItem;
259 
260     // in Draw the item exists as WhichId, in Writer only as SlotId
261     SfxItemState eState = rSet->GetItemState(SID_ATTR_NUMBERING_RULE, false, &pItem);
262     if(eState != SfxItemState::SET)
263     {
264         nNumItemId = rSet->GetPool()->GetWhichIDFromSlotID(SID_ATTR_NUMBERING_RULE);
265         eState = rSet->GetItemState(nNumItemId, false, &pItem);
266 
267         if( eState != SfxItemState::SET )
268         {
269             pItem = & rSet->Get( nNumItemId );
270             eState = SfxItemState::SET;
271         }
272     }
273     DBG_ASSERT(eState == SfxItemState::SET, "no item found!");
274     pSaveNum.reset( new SvxNumRule(static_cast<const SvxNumBulletItem*>(pItem)->GetNumRule()) );
275 
276     if(!pActNum)
277         pActNum.reset( new SvxNumRule(*pSaveNum) );
278     else if(*pSaveNum != *pActNum)
279         *pActNum = *pSaveNum;
280 }
281 
IMPL_LINK_NOARG(SvxSingleNumPickTabPage,NumSelectHdl_Impl,ValueSet *,void)282 IMPL_LINK_NOARG(SvxSingleNumPickTabPage, NumSelectHdl_Impl, ValueSet*, void)
283 {
284     if(!pActNum)
285         return;
286 
287     bPreset = false;
288     bModified = true;
289     sal_uInt16 nIdx = m_xExamplesVS->GetSelectedItemId() - 1;
290     DBG_ASSERT(aNumSettingsArr.size() > nIdx, "wrong index");
291     if(aNumSettingsArr.size() <= nIdx)
292         return;
293     SvxNumSettings_Impl* _pSet = aNumSettingsArr[nIdx].get();
294     SvxNumType eNewType = _pSet->nNumberType;
295     const sal_Unicode cLocalPrefix = !_pSet->sPrefix.isEmpty() ? _pSet->sPrefix[0] : 0;
296     const sal_Unicode cLocalSuffix = !_pSet->sSuffix.isEmpty() ? _pSet->sSuffix[0] : 0;
297 
298     sal_uInt16 nMask = 1;
299     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
300     {
301         if(nActNumLvl & nMask)
302         {
303             SvxNumberFormat aFmt(pActNum->GetLevel(i));
304             aFmt.SetNumberingType(eNewType);
305             aFmt.SetListFormat(cLocalPrefix == ' ' ? u""_ustr : _pSet->sPrefix,
306                                cLocalSuffix == ' ' ? u""_ustr : _pSet->sSuffix, i);
307             aFmt.SetCharFormatName(u""_ustr);
308             aFmt.SetBulletRelSize(100);
309             pActNum->SetLevel(i, aFmt);
310         }
311         nMask <<= 1;
312     }
313 }
314 
IMPL_LINK_NOARG(SvxSingleNumPickTabPage,DoubleClickHdl_Impl,ValueSet *,void)315 IMPL_LINK_NOARG(SvxSingleNumPickTabPage, DoubleClickHdl_Impl, ValueSet*, void)
316 {
317     NumSelectHdl_Impl(m_xExamplesVS.get());
318     weld::Button& rOk = GetDialogController()->GetOKButton();
319     rOk.clicked();
320 }
321 
SvxBulletPickTabPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)322 SvxBulletPickTabPage::SvxBulletPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
323     : SfxTabPage(pPage, pController, u"cui/ui/pickbulletpage.ui"_ustr, u"PickBulletPage"_ustr, &rSet)
324     , nActNumLvl(SAL_MAX_UINT16)
325     , bModified(false)
326     , bPreset(false)
327     , nNumItemId(SID_ATTR_NUMBERING_RULE)
328     , m_xBtChangeBullet(m_xBuilder->weld_button(u"changeBulletBtn"_ustr))
329     , m_xExamplesVS(new SvxNumValueSet(m_xBuilder->weld_scrolled_window(u"valuesetwin"_ustr, true)))
330     , m_xExamplesVSWin(new weld::CustomWeld(*m_xBuilder, u"valueset"_ustr, *m_xExamplesVS))
331 {
332     SetExchangeSupport();
333     m_xBtChangeBullet->set_sensitive(false);
334     m_xExamplesVS->init(NumberingPageType::BULLET);
335     m_xExamplesVS->SetSelectHdl(LINK(this, SvxBulletPickTabPage, NumSelectHdl_Impl));
336     m_xExamplesVS->SetDoubleClickHdl(LINK(this, SvxBulletPickTabPage, DoubleClickHdl_Impl));
337     m_xBtChangeBullet->connect_clicked(LINK(this, SvxBulletPickTabPage, ClickAddChangeHdl_Impl));
338 }
339 
~SvxBulletPickTabPage()340 SvxBulletPickTabPage::~SvxBulletPickTabPage()
341 {
342     m_xExamplesVSWin.reset();
343     m_xExamplesVS.reset();
344 }
345 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rAttrSet)346 std::unique_ptr<SfxTabPage> SvxBulletPickTabPage::Create(weld::Container* pPage, weld::DialogController* pController,
347                                                 const SfxItemSet* rAttrSet)
348 {
349     return std::make_unique<SvxBulletPickTabPage>(pPage, pController, *rAttrSet);
350 }
351 
FillItemSet(SfxItemSet * rSet)352 bool  SvxBulletPickTabPage::FillItemSet( SfxItemSet* rSet )
353 {
354     if( (bPreset || bModified) && pActNum)
355     {
356         *pSaveNum = *pActNum;
357         rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId ));
358         rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, bPreset));
359     }
360     return bModified;
361 }
362 
ActivatePage(const SfxItemSet & rSet)363 void  SvxBulletPickTabPage::ActivatePage(const SfxItemSet& rSet)
364 {
365     bPreset = false;
366     bool bIsPreset = false;
367     const SfxItemSet* pExampleSet = GetDialogExampleSet();
368     if(pExampleSet)
369     {
370         if(const SfxBoolItem* pPresetItem = pExampleSet->GetItemIfSet(SID_PARAM_NUM_PRESET, false))
371             bIsPreset = pPresetItem->GetValue();
372         if(const SfxUInt16Item* pLevelItem = pExampleSet->GetItemIfSet(SID_PARAM_CUR_NUM_LEVEL, false))
373             nActNumLvl = pLevelItem->GetValue();
374     }
375     if(const SvxNumBulletItem* pBulletItem = rSet.GetItemIfSet(nNumItemId, false))
376     {
377         pSaveNum.reset( new SvxNumRule(pBulletItem->GetNumRule()) );
378     }
379     if(pActNum && *pSaveNum != *pActNum)
380     {
381         *pActNum = *pSaveNum;
382         m_xExamplesVS->SetNoSelection();
383     }
384 
385     if(pActNum && (!lcl_IsNumFmtSet(pActNum.get(), nActNumLvl) || bIsPreset))
386     {
387         m_xExamplesVS->SelectItem(1);
388         NumSelectHdl_Impl(m_xExamplesVS.get());
389         bPreset = true;
390     }
391     bPreset |= bIsPreset;
392     bModified = false;
393 }
394 
DeactivatePage(SfxItemSet * _pSet)395 DeactivateRC SvxBulletPickTabPage::DeactivatePage(SfxItemSet *_pSet)
396 {
397     if(_pSet)
398         FillItemSet(_pSet);
399     return DeactivateRC::LeavePage;
400 }
401 
Reset(const SfxItemSet * rSet)402 void  SvxBulletPickTabPage::Reset( const SfxItemSet* rSet )
403 {
404     // in Draw the item exists as WhichId, in Writer only as SlotId
405     const SvxNumBulletItem* pItem = rSet->GetItemIfSet(SID_ATTR_NUMBERING_RULE, false);
406     if(!pItem)
407     {
408         nNumItemId = rSet->GetPool()->GetWhichIDFromSlotID(SID_ATTR_NUMBERING_RULE);
409         pItem = rSet->GetItemIfSet(nNumItemId, false);
410 
411         if( !pItem )
412         {
413             pItem = & rSet->Get( nNumItemId );
414         }
415 
416     }
417     pSaveNum.reset( new SvxNumRule(pItem->GetNumRule()) );
418 
419     if(!pActNum)
420         pActNum.reset( new SvxNumRule(*pSaveNum) );
421     else if(*pSaveNum != *pActNum)
422         *pActNum = *pSaveNum;
423 }
424 
IMPL_LINK_NOARG(SvxBulletPickTabPage,NumSelectHdl_Impl,ValueSet *,void)425 IMPL_LINK_NOARG(SvxBulletPickTabPage, NumSelectHdl_Impl, ValueSet*, void)
426 {
427     if(!pActNum)
428         return;
429 
430     m_xBtChangeBullet->set_sensitive(true);
431 
432     bPreset = false;
433     bModified = true;
434     sal_uInt16 nIndex = m_xExamplesVS->GetSelectedItemId() - 1;
435     sal_Unicode cChar = officecfg::Office::Common::BulletsNumbering::DefaultBullets::get()[nIndex].toChar();
436     vcl::Font& rActBulletFont = lcl_GetDefaultBulletFont();
437     rActBulletFont.SetFamilyName(
438         officecfg::Office::Common::BulletsNumbering::DefaultBulletsFonts::get()[nIndex]);
439 
440     sal_uInt16 nMask = 1;
441     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
442     {
443         if(nActNumLvl & nMask)
444         {
445             SvxNumberFormat aFmt(pActNum->GetLevel(i));
446             aFmt.SetNumberingType( SVX_NUM_CHAR_SPECIAL );
447             // #i93908# clear suffix for bullet lists
448             aFmt.SetListFormat(u""_ustr, u""_ustr, i);
449             aFmt.SetBulletFont(&rActBulletFont);
450             aFmt.SetBulletChar(cChar );
451             aFmt.SetCharFormatName(sBulletCharFormatName);
452             aFmt.SetBulletRelSize(45);
453             pActNum->SetLevel(i, aFmt);
454         }
455         nMask <<= 1;
456     }
457 }
458 
IMPL_LINK_NOARG(SvxBulletPickTabPage,DoubleClickHdl_Impl,ValueSet *,void)459 IMPL_LINK_NOARG(SvxBulletPickTabPage, DoubleClickHdl_Impl, ValueSet*, void)
460 {
461     NumSelectHdl_Impl(m_xExamplesVS.get());
462     weld::Button& rOk = GetDialogController()->GetOKButton();
463     rOk.clicked();
464 }
465 
IMPL_LINK_NOARG(SvxBulletPickTabPage,ClickAddChangeHdl_Impl,weld::Button &,void)466 IMPL_LINK_NOARG(SvxBulletPickTabPage, ClickAddChangeHdl_Impl, weld::Button&, void)
467 {
468     SvxCharacterMap aMap(GetFrameWeld(), nullptr, nullptr);
469 
470     sal_uInt16 nMask = 1;
471     std::optional<vcl::Font> pFmtFont;
472     bool bSameBullet = true;
473     sal_UCS4 cBullet = 0;
474     bool bFirst = true;
475     for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
476     {
477         if (nActNumLvl & nMask)
478         {
479             const SvxNumberFormat& rCurFmt = pActNum->GetLevel(i);
480             if (bFirst)
481             {
482                 cBullet = rCurFmt.GetBulletChar();
483             }
484             else if (rCurFmt.GetBulletChar() != cBullet)
485             {
486                 bSameBullet = false;
487                 break;
488             }
489             if (!pFmtFont)
490                 pFmtFont = rCurFmt.GetBulletFont();
491             bFirst = false;
492         }
493         nMask <<= 1;
494     }
495 
496     if (pFmtFont)
497         aMap.SetCharFont(*pFmtFont);
498     if (bSameBullet)
499         aMap.SetChar(cBullet);
500     if (aMap.run() != RET_OK)
501         return;
502 
503     sal_Unicode cChar = aMap.GetChar();
504     vcl::Font aActBulletFont = aMap.GetCharFont();
505 
506     sal_uInt16 _nMask = 1;
507     for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
508     {
509         if (nActNumLvl & _nMask)
510         {
511             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
512             aNumFmt.SetBulletFont(&aActBulletFont);
513             aNumFmt.SetBulletChar(cChar);
514             pActNum->SetLevel(i, aNumFmt);
515         }
516         _nMask <<= 1;
517     }
518 
519     css::uno::Sequence<OUString> aBulletSymbols(officecfg::Office::Common::BulletsNumbering::DefaultBullets::get());
520     css::uno::Sequence<OUString> aBulletSymbolsFonts(officecfg::Office::Common::BulletsNumbering::DefaultBulletsFonts::get());
521     css::uno::Sequence<OUString> aBulletSymbolsList(aBulletSymbols.size());
522     css::uno::Sequence<OUString> aBulletSymbolsFontsList(aBulletSymbolsFonts.size());
523     auto aBulletSymbolsListRange = asNonConstRange(aBulletSymbolsList);
524     auto aBulletSymbolsFontsListRange = asNonConstRange(aBulletSymbolsFontsList);
525 
526     sal_uInt16 nIndex = m_xExamplesVS->GetSelectedItemId() - 1;
527     for (size_t i = 0; i < aBulletSymbols.size(); ++i)
528     {
529         if (i == nIndex)
530         {
531             aBulletSymbolsListRange[i] = OUStringChar(cChar);
532             aBulletSymbolsFontsListRange[i] = aActBulletFont.GetFamilyName();
533         }
534         else
535         {
536             aBulletSymbolsListRange[i] = aBulletSymbols[i];
537             aBulletSymbolsFontsListRange[i] = aBulletSymbolsFonts[i];
538         }
539     }
540 
541     std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
542     officecfg::Office::Common::BulletsNumbering::DefaultBullets::set(aBulletSymbolsList, batch);
543     officecfg::Office::Common::BulletsNumbering::DefaultBulletsFonts::set(aBulletSymbolsFontsList, batch);
544     batch->commit();
545 
546     m_xExamplesVS->SetFormat();
547     m_xExamplesVS->Invalidate();
548 }
549 
PageCreated(const SfxAllItemSet & aSet)550 void SvxBulletPickTabPage::PageCreated(const SfxAllItemSet& aSet)
551 {
552     const SfxStringItem* pBulletCharFmt = aSet.GetItem<SfxStringItem>(SID_BULLET_CHAR_FMT, false);
553 
554     if (pBulletCharFmt)
555         sBulletCharFormatName = pBulletCharFmt->GetValue();
556 }
557 
SvxNumPickTabPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)558 SvxNumPickTabPage::SvxNumPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
559     : SfxTabPage(pPage, pController, u"cui/ui/pickoutlinepage.ui"_ustr, u"PickOutlinePage"_ustr, &rSet)
560     , nActNumLvl(SAL_MAX_UINT16)
561     , nNumItemId(SID_ATTR_NUMBERING_RULE)
562     , bModified(false)
563     , bPreset(false)
564     , m_xExamplesVS(new SvxNumValueSet(m_xBuilder->weld_scrolled_window(u"valuesetwin"_ustr, true)))
565     , m_xExamplesVSWin(new weld::CustomWeld(*m_xBuilder, u"valueset"_ustr, *m_xExamplesVS))
566 {
567     SetExchangeSupport();
568 
569     m_xExamplesVS->init(NumberingPageType::OUTLINE);
570     m_xExamplesVS->SetSelectHdl(LINK(this, SvxNumPickTabPage, NumSelectHdl_Impl));
571     m_xExamplesVS->SetDoubleClickHdl(LINK(this, SvxNumPickTabPage, DoubleClickHdl_Impl));
572 
573     Reference<XDefaultNumberingProvider> xDefNum = SvxNumOptionsTabPageHelper::GetNumberingProvider();
574     if(!xDefNum.is())
575         return;
576 
577     Sequence<Reference<XIndexAccess> > aOutlineAccess;
578     const Locale& rLocale = Application::GetSettings().GetLanguageTag().getLocale();
579     try
580     {
581         aOutlineAccess = xDefNum->getDefaultOutlineNumberings( rLocale );
582 
583         for(sal_Int32 nItem = 0;
584             nItem < aOutlineAccess.getLength() && nItem < NUM_VALUSET_COUNT;
585             nItem++ )
586         {
587             SvxNumSettingsArr_Impl& rItemArr = aNumSettingsArrays[ nItem ];
588 
589             Reference<XIndexAccess> xLevel = aOutlineAccess[nItem];
590             for(sal_Int32 nLevel = 0; nLevel < SVX_MAX_NUM; nLevel++)
591             {
592                 // use the last locale-defined level for all remaining levels.
593                 sal_Int32 nLocaleLevel = std::min(nLevel, xLevel->getCount() - 1);
594                 Sequence<PropertyValue> aLevelProps;
595                 if (nLocaleLevel >= 0)
596                     xLevel->getByIndex(nLocaleLevel) >>= aLevelProps;
597 
598                 SvxNumSettings_Impl* pNew = lcl_CreateNumSettingsPtr(aLevelProps);
599                 rItemArr.push_back( std::unique_ptr<SvxNumSettings_Impl>(pNew) );
600             }
601         }
602     }
603     catch(const Exception&)
604     {
605     }
606     Reference<XNumberingFormatter> xFormat(xDefNum, UNO_QUERY);
607     m_xExamplesVS->SetOutlineNumberingSettings(aOutlineAccess, xFormat, rLocale);
608 }
609 
~SvxNumPickTabPage()610 SvxNumPickTabPage::~SvxNumPickTabPage()
611 {
612     m_xExamplesVSWin.reset();
613     m_xExamplesVS.reset();
614 }
615 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rAttrSet)616 std::unique_ptr<SfxTabPage> SvxNumPickTabPage::Create(weld::Container* pPage, weld::DialogController* pController,
617                                              const SfxItemSet* rAttrSet)
618 {
619     return std::make_unique<SvxNumPickTabPage>(pPage, pController, *rAttrSet);
620 }
621 
FillItemSet(SfxItemSet * rSet)622 bool  SvxNumPickTabPage::FillItemSet( SfxItemSet* rSet )
623 {
624     if( (bPreset || bModified) && pActNum)
625     {
626         *pSaveNum = *pActNum;
627         rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId ));
628         rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, bPreset));
629     }
630     return bModified;
631 }
632 
ActivatePage(const SfxItemSet & rSet)633 void  SvxNumPickTabPage::ActivatePage(const SfxItemSet& rSet)
634 {
635     bPreset = false;
636     bool bIsPreset = false;
637     const SfxItemSet* pExampleSet = GetDialogExampleSet();
638     if(pExampleSet)
639     {
640         if(const SfxBoolItem* pPresetItem = pExampleSet->GetItemIfSet(SID_PARAM_NUM_PRESET, false))
641             bIsPreset = pPresetItem->GetValue();
642         if(const SfxUInt16Item* pLevelItem = pExampleSet->GetItemIfSet(SID_PARAM_CUR_NUM_LEVEL, false))
643             nActNumLvl = pLevelItem->GetValue();
644     }
645     if(const SvxNumBulletItem* pBulletItem = rSet.GetItemIfSet(nNumItemId, false))
646     {
647         pSaveNum.reset( new SvxNumRule(pBulletItem->GetNumRule()) );
648     }
649     if(pActNum && *pSaveNum != *pActNum)
650     {
651         *pActNum = *pSaveNum;
652         m_xExamplesVS->SetNoSelection();
653     }
654 
655     if(pActNum && (!lcl_IsNumFmtSet(pActNum.get(), nActNumLvl) || bIsPreset))
656     {
657         m_xExamplesVS->SelectItem(1);
658         NumSelectHdl_Impl(m_xExamplesVS.get());
659         bPreset = true;
660     }
661     bPreset |= bIsPreset;
662     bModified = false;
663 }
664 
DeactivatePage(SfxItemSet * _pSet)665 DeactivateRC SvxNumPickTabPage::DeactivatePage(SfxItemSet *_pSet)
666 {
667     if(_pSet)
668         FillItemSet(_pSet);
669     return DeactivateRC::LeavePage;
670 }
671 
Reset(const SfxItemSet * rSet)672 void  SvxNumPickTabPage::Reset( const SfxItemSet* rSet )
673 {
674     // in Draw the item exists as WhichId, in Writer only as SlotId
675     const SvxNumBulletItem* pItem = rSet->GetItemIfSet(SID_ATTR_NUMBERING_RULE, false);
676     if(!pItem)
677     {
678         nNumItemId = rSet->GetPool()->GetWhichIDFromSlotID(SID_ATTR_NUMBERING_RULE);
679         pItem = rSet->GetItemIfSet(nNumItemId, false);
680 
681         if( !pItem )
682         {
683             pItem = & rSet->Get( nNumItemId );
684         }
685     }
686     pSaveNum.reset( new SvxNumRule(pItem->GetNumRule()) );
687 
688     if(!pActNum)
689         pActNum.reset( new SvxNumRule(*pSaveNum) );
690     else if(*pSaveNum != *pActNum)
691         *pActNum = *pSaveNum;
692 
693 }
694 
695 // all levels are changed here
IMPL_LINK_NOARG(SvxNumPickTabPage,NumSelectHdl_Impl,ValueSet *,void)696 IMPL_LINK_NOARG(SvxNumPickTabPage, NumSelectHdl_Impl, ValueSet*, void)
697 {
698     if(!pActNum)
699         return;
700 
701     bPreset = false;
702     bModified = true;
703 
704     const FontList*  pList = nullptr;
705 
706     SvxNumSettingsArr_Impl& rItemArr = aNumSettingsArrays[m_xExamplesVS->GetSelectedItemId() - 1];
707 
708     const vcl::Font& rActBulletFont = lcl_GetDefaultBulletFont();
709     SvxNumSettings_Impl* pLevelSettings = nullptr;
710     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
711     {
712         if(rItemArr.size() > i)
713             pLevelSettings = rItemArr[i].get();
714         if(!pLevelSettings)
715             break;
716         SvxNumberFormat aFmt(pActNum->GetLevel(i));
717         aFmt.SetNumberingType( pLevelSettings->nNumberType );
718         sal_uInt16 nUpperLevelOrChar = static_cast<sal_uInt16>(pLevelSettings->nParentNumbering);
719         if(aFmt.GetNumberingType() == SVX_NUM_CHAR_SPECIAL)
720         {
721             // #i93908# clear suffix for bullet lists
722             aFmt.SetListFormat(u""_ustr, u""_ustr, i);
723             if( !pLevelSettings->sBulletFont.isEmpty() &&
724                 pLevelSettings->sBulletFont != rActBulletFont.GetFamilyName())
725             {
726                 //search for the font
727                 if(!pList)
728                 {
729                     if (SfxObjectShell* pCurDocShell = SfxObjectShell::Current())
730                     {
731                         const SvxFontListItem* pFontListItem =
732                                 static_cast<const SvxFontListItem*>( pCurDocShell
733                                                     ->GetItem( SID_ATTR_CHAR_FONTLIST ));
734                         pList = pFontListItem ? pFontListItem->GetFontList() : nullptr;
735                     }
736                 }
737                 if(pList && pList->IsAvailable( pLevelSettings->sBulletFont ) )
738                 {
739                     vcl::Font aFont(pList->Get(
740                         pLevelSettings->sBulletFont,WEIGHT_NORMAL, ITALIC_NONE));
741                     aFmt.SetBulletFont(&aFont);
742                 }
743                 else
744                 {
745                     //if it cannot be found then create a new one
746                     vcl::Font aCreateFont( pLevelSettings->sBulletFont,
747                                             OUString(), Size( 0, 14 ) );
748                     aCreateFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW );
749                     aCreateFont.SetFamily( FAMILY_DONTKNOW );
750                     aCreateFont.SetPitch( PITCH_DONTKNOW );
751                     aCreateFont.SetWeight( WEIGHT_DONTKNOW );
752                     aCreateFont.SetTransparent( true );
753                     aFmt.SetBulletFont( &aCreateFont );
754                 }
755             }
756             else
757                 aFmt.SetBulletFont( &rActBulletFont );
758 
759             aFmt.SetBulletChar( !pLevelSettings->sBulletChar.isEmpty()
760                                     ? pLevelSettings->sBulletChar.iterateCodePoints(
761                                         &o3tl::temporary(sal_Int32(0)))
762                                     : 0 );
763             aFmt.SetCharFormatName( sBulletCharFormatName );
764             aFmt.SetBulletRelSize(45);
765         }
766         else
767         {
768             aFmt.SetIncludeUpperLevels(sal::static_int_cast< sal_uInt8 >(0 != nUpperLevelOrChar ? pActNum->GetLevelCount() : 1));
769             aFmt.SetCharFormatName(sNumCharFmtName);
770             aFmt.SetBulletRelSize(100);
771 
772             // Completely ignore the Left/Right value provided by the locale outline definition,
773             // because this function doesn't actually modify the indents at all,
774             // and right-adjusted numbering definitely needs a different FirstLineIndent.
775 
776             // #i93908#
777             aFmt.SetListFormat(pLevelSettings->sPrefix, pLevelSettings->sSuffix, i);
778         }
779         pActNum->SetLevel(i, aFmt);
780     }
781 }
782 
IMPL_LINK_NOARG(SvxNumPickTabPage,DoubleClickHdl_Impl,ValueSet *,void)783 IMPL_LINK_NOARG(SvxNumPickTabPage, DoubleClickHdl_Impl, ValueSet*, void)
784 {
785     NumSelectHdl_Impl(m_xExamplesVS.get());
786     weld::Button& rOk = GetDialogController()->GetOKButton();
787     rOk.clicked();
788 }
789 
PageCreated(const SfxAllItemSet & aSet)790 void SvxNumPickTabPage::PageCreated(const SfxAllItemSet& aSet)
791 {
792     const SfxStringItem* pNumCharFmt = aSet.GetItem<SfxStringItem>(SID_NUM_CHAR_FMT, false);
793     const SfxStringItem* pBulletCharFmt = aSet.GetItem<SfxStringItem>(SID_BULLET_CHAR_FMT, false);
794 
795 
796     if (pNumCharFmt &&pBulletCharFmt)
797         SetCharFormatNames( pNumCharFmt->GetValue(),pBulletCharFmt->GetValue());
798 }
799 
SvxBitmapPickTabPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)800 SvxBitmapPickTabPage::SvxBitmapPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
801     : SfxTabPage(pPage, pController, u"cui/ui/pickgraphicpage.ui"_ustr, u"PickGraphicPage"_ustr, &rSet)
802     , nActNumLvl(SAL_MAX_UINT16)
803     , nNumItemId(SID_ATTR_NUMBERING_RULE)
804     , bModified(false)
805     , bPreset(false)
806     , m_xErrorText(m_xBuilder->weld_label(u"errorft"_ustr))
807     , m_xBtBrowseFile(m_xBuilder->weld_button(u"browseBtn"_ustr))
808     , m_xExamplesVS(new SvxBmpNumValueSet(m_xBuilder->weld_scrolled_window(u"valuesetwin"_ustr, true)))
809     , m_xExamplesVSWin(new weld::CustomWeld(*m_xBuilder, u"valueset"_ustr, *m_xExamplesVS))
810 {
811     SetExchangeSupport();
812 
813     m_xExamplesVS->init();
814     m_xExamplesVS->SetSelectHdl(LINK(this, SvxBitmapPickTabPage, NumSelectHdl_Impl));
815     m_xExamplesVS->SetDoubleClickHdl(LINK(this, SvxBitmapPickTabPage, DoubleClickHdl_Impl));
816     m_xBtBrowseFile->connect_clicked(LINK(this, SvxBitmapPickTabPage, ClickAddBrowseHdl_Impl));
817 
818     if(comphelper::LibreOfficeKit::isActive())
819         m_xBtBrowseFile->hide();
820 
821     eCoreUnit = rSet.GetPool()->GetMetric(rSet.GetPool()->GetWhichIDFromSlotID(SID_ATTR_NUMBERING_RULE));
822 
823     // determine graphic name
824     GalleryExplorer::FillObjList(GALLERY_THEME_BULLETS, aGrfNames);
825 
826     size_t i = 0;
827     for (auto & grfName : aGrfNames)
828     {
829         m_xExamplesVS->InsertItem( i + 1, i);
830 
831         INetURLObject aObj(grfName);
832         if (aObj.GetProtocol() == INetProtocol::File)
833         {
834             // tdf#114070 - only show the last name of the filename without its extension
835             aObj.removeExtension();
836             grfName = aObj.GetLastName(INetURLObject::DecodeMechanism::Unambiguous);
837         }
838 
839         m_xExamplesVS->SetItemText( i + 1, grfName );
840         ++i;
841     }
842 
843     if(aGrfNames.empty())
844     {
845         m_xErrorText->show();
846     }
847     else
848     {
849         m_xExamplesVS->Show();
850         m_xExamplesVS->SetFormat();
851         m_xExamplesVS->Invalidate();
852     }
853 }
854 
~SvxBitmapPickTabPage()855 SvxBitmapPickTabPage::~SvxBitmapPickTabPage()
856 {
857     m_xExamplesVSWin.reset();
858     m_xExamplesVS.reset();
859 }
860 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rAttrSet)861 std::unique_ptr<SfxTabPage> SvxBitmapPickTabPage::Create(weld::Container* pPage, weld::DialogController* pController,
862                                                 const SfxItemSet* rAttrSet)
863 {
864     return std::make_unique<SvxBitmapPickTabPage>(pPage, pController, *rAttrSet);
865 }
866 
ActivatePage(const SfxItemSet & rSet)867 void  SvxBitmapPickTabPage::ActivatePage(const SfxItemSet& rSet)
868 {
869     bPreset = false;
870     bool bIsPreset = false;
871     const SfxItemSet* pExampleSet = GetDialogExampleSet();
872     if(pExampleSet)
873     {
874         if(const SfxBoolItem* pPresetItem = pExampleSet->GetItemIfSet(SID_PARAM_NUM_PRESET, false))
875             bIsPreset = pPresetItem->GetValue();
876         if(const SfxUInt16Item* pLevelItem = pExampleSet->GetItemIfSet(SID_PARAM_CUR_NUM_LEVEL, false))
877             nActNumLvl = pLevelItem->GetValue();
878     }
879     if(const SvxNumBulletItem* pBulletItem = rSet.GetItemIfSet(nNumItemId, false))
880     {
881         pSaveNum.reset( new SvxNumRule(pBulletItem->GetNumRule()) );
882     }
883     if(pActNum && *pSaveNum != *pActNum)
884     {
885         *pActNum = *pSaveNum;
886         m_xExamplesVS->SetNoSelection();
887     }
888 
889     if(!aGrfNames.empty() &&
890         (pActNum && (!lcl_IsNumFmtSet(pActNum.get(), nActNumLvl) || bIsPreset)))
891     {
892         m_xExamplesVS->SelectItem(1);
893         NumSelectHdl_Impl(m_xExamplesVS.get());
894         bPreset = true;
895     }
896     bPreset |= bIsPreset;
897     bModified = false;
898 }
899 
DeactivatePage(SfxItemSet * _pSet)900 DeactivateRC SvxBitmapPickTabPage::DeactivatePage(SfxItemSet *_pSet)
901 {
902     if(_pSet)
903         FillItemSet(_pSet);
904     return DeactivateRC::LeavePage;
905 }
906 
FillItemSet(SfxItemSet * rSet)907 bool  SvxBitmapPickTabPage::FillItemSet( SfxItemSet* rSet )
908 {
909     if ( aGrfNames.empty() )
910     {
911         return false;
912     }
913     if( (bPreset || bModified) && pActNum)
914     {
915         *pSaveNum = *pActNum;
916         rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId ) );
917         rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, bPreset));
918     }
919 
920     return bModified;
921 }
922 
Reset(const SfxItemSet * rSet)923 void  SvxBitmapPickTabPage::Reset( const SfxItemSet* rSet )
924 {
925     // in Draw the item exists as WhichId, in Writer only as SlotId
926     const SvxNumBulletItem* pItem = rSet->GetItemIfSet(SID_ATTR_NUMBERING_RULE, false);
927     if(!pItem)
928     {
929         nNumItemId = rSet->GetPool()->GetWhichIDFromSlotID(SID_ATTR_NUMBERING_RULE);
930         pItem = rSet->GetItemIfSet(nNumItemId, false);
931 
932         if( !pItem )
933         {
934             pItem = & rSet->Get( nNumItemId );
935         }
936 
937     }
938     DBG_ASSERT(pItem, "no item found!");
939     pSaveNum.reset( new SvxNumRule(pItem->GetNumRule()) );
940 
941     if(!pActNum)
942         pActNum.reset( new SvxNumRule(*pSaveNum) );
943     else if(*pSaveNum != *pActNum)
944         *pActNum = *pSaveNum;
945 }
946 
IMPL_LINK_NOARG(SvxBitmapPickTabPage,NumSelectHdl_Impl,ValueSet *,void)947 IMPL_LINK_NOARG(SvxBitmapPickTabPage, NumSelectHdl_Impl, ValueSet*, void)
948 {
949     if(!pActNum)
950         return;
951 
952     bPreset = false;
953     bModified = true;
954     sal_uInt16 nIdx = m_xExamplesVS->GetSelectedItemId() - 1;
955 
956     sal_uInt16 nMask = 1;
957     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
958     {
959         if(nActNumLvl & nMask)
960         {
961             SvxNumberFormat aFmt(pActNum->GetLevel(i));
962             aFmt.SetNumberingType(SVX_NUM_BITMAP);
963             aFmt.SetListFormat(u""_ustr, u""_ustr, i);
964             aFmt.SetCharFormatName( u""_ustr );
965 
966             Graphic aGraphic;
967             if(GalleryExplorer::GetGraphicObj( GALLERY_THEME_BULLETS, nIdx, &aGraphic))
968             {
969                 Size aSize = SvxNumberFormat::GetGraphicSizeMM100(&aGraphic);
970                 sal_Int16 eOrient = text::VertOrientation::LINE_CENTER;
971                 aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(eCoreUnit));
972                 SvxBrushItem aBrush(aGraphic, GPOS_AREA, SID_ATTR_BRUSH );
973                 aFmt.SetGraphicBrush( &aBrush, &aSize, &eOrient );
974             }
975             else if(aGrfNames.size() > nIdx)
976                 aFmt.SetGraphic( aGrfNames[nIdx] );
977             pActNum->SetLevel(i, aFmt);
978         }
979         nMask <<= 1;
980     }
981 }
982 
IMPL_LINK_NOARG(SvxBitmapPickTabPage,DoubleClickHdl_Impl,ValueSet *,void)983 IMPL_LINK_NOARG(SvxBitmapPickTabPage, DoubleClickHdl_Impl, ValueSet*, void)
984 {
985     NumSelectHdl_Impl(m_xExamplesVS.get());
986     weld::Button& rOk = GetDialogController()->GetOKButton();
987     rOk.clicked();
988 }
989 
IMPL_LINK_NOARG(SvxBitmapPickTabPage,ClickAddBrowseHdl_Impl,weld::Button &,void)990 IMPL_LINK_NOARG(SvxBitmapPickTabPage, ClickAddBrowseHdl_Impl, weld::Button&, void)
991 {
992     sfx2::FileDialogHelper aFileDialog(0, FileDialogFlags::NONE, GetFrameWeld());
993     aFileDialog.SetContext(sfx2::FileDialogHelper::BulletsAddImage);
994     aFileDialog.SetTitle(CuiResId(RID_CUISTR_ADD_IMAGE));
995     if ( aFileDialog.Execute() != ERRCODE_NONE )
996         return;
997 
998     OUString aPath = SvtPathOptions().GetGalleryPath();
999     std::u16string_view aPathToken = o3tl::getToken(aPath, 1 , SEARCHPATH_DELIMITER );
1000 
1001     OUString aUserImageURL = aFileDialog.GetPath();
1002 
1003     OUString aFileName;
1004     const sal_Int32 nPos {aUserImageURL.lastIndexOf(SEARCHFILENAME_DELIMITER)+1};
1005     if (nPos<=0)
1006         aFileName = aUserImageURL;
1007     else if (nPos<aUserImageURL.getLength())
1008         aFileName = aUserImageURL.copy(nPos);
1009 
1010     OUString aUserGalleryURL = OUString::Concat(aPathToken) + "/" + aFileName;
1011     INetURLObject aURL( aUserImageURL );
1012     DBG_ASSERT( aURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" );
1013 
1014     GraphicDescriptor aDescriptor(aURL);
1015     if (!aDescriptor.Detect())
1016         return;
1017 
1018     uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
1019     uno::Reference<ucb::XSimpleFileAccess3> xSimpleFileAccess(
1020                  ucb::SimpleFileAccess::create( ::comphelper::getComponentContext(xFactory) ) );
1021     if ( !xSimpleFileAccess->exists( aUserImageURL ))
1022         return;
1023 
1024     xSimpleFileAccess->copy( aUserImageURL, aUserGalleryURL );
1025     INetURLObject gURL( aUserGalleryURL );
1026     std::unique_ptr<SvStream> pIn(::utl::UcbStreamHelper::CreateStream(
1027                   gURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ ));
1028     if ( !pIn )
1029         return;
1030 
1031     Graphic aGraphic;
1032     GraphicConverter::Import( *pIn, aGraphic );
1033 
1034     BitmapEx aBitmap = aGraphic.GetBitmapEx();
1035     tools::Long nPixelX = aBitmap.GetSizePixel().Width();
1036     tools::Long nPixelY = aBitmap.GetSizePixel().Height();
1037     double ratio = nPixelY/static_cast<double>(nPixelX);
1038     if(nPixelX > 30)
1039     {
1040         nPixelX = 30;
1041         nPixelY = static_cast<tools::Long>(nPixelX*ratio);
1042     }
1043     if(nPixelY > 30)
1044     {
1045         nPixelY = 30;
1046         nPixelX = static_cast<tools::Long>(nPixelY/ratio);
1047     }
1048 
1049     aBitmap.Scale( Size( nPixelX, nPixelY ), BmpScaleFlag::Fast );
1050     Graphic aScaledGraphic( aBitmap );
1051     GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
1052 
1053     Sequence< PropertyValue > aFilterData{
1054         comphelper::makePropertyValue(u"Compression"_ustr, sal_Int32(-1)),
1055         comphelper::makePropertyValue(u"Quality"_ustr, sal_Int32(1))
1056     };
1057 
1058     sal_uInt16 nFilterFormat = rFilter.GetExportFormatNumberForShortName( gURL.GetFileExtension() );
1059     rFilter.ExportGraphic( aScaledGraphic, gURL , nFilterFormat, &aFilterData );
1060     GalleryExplorer::InsertURL( GALLERY_THEME_BULLETS, aUserGalleryURL );
1061 
1062     aGrfNames.push_back(aUserGalleryURL);
1063     size_t i = 0;
1064     for (auto & grfName : aGrfNames)
1065     {
1066         m_xExamplesVS->InsertItem( i + 1, i);
1067         INetURLObject aObj(grfName);
1068         if (aObj.GetProtocol() == INetProtocol::File)
1069         {
1070             // tdf#114070 - only show the last name of the filename without its extension
1071             aObj.removeExtension();
1072             grfName = aObj.GetLastName(INetURLObject::DecodeMechanism::Unambiguous);
1073         }
1074         m_xExamplesVS->SetItemText( i + 1, grfName );
1075         ++i;
1076     }
1077 
1078     if(aGrfNames.empty())
1079     {
1080         m_xErrorText->show();
1081     }
1082     else
1083     {
1084         m_xExamplesVS->Show();
1085         m_xExamplesVS->SetFormat();
1086     }
1087 }
1088 
1089 // tabpage numbering options
SvxNumOptionsTabPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)1090 SvxNumOptionsTabPage::SvxNumOptionsTabPage(weld::Container* pPage, weld::DialogController* pController,
1091                                const SfxItemSet& rSet)
1092     : SfxTabPage(pPage, pController, u"cui/ui/numberingoptionspage.ui"_ustr, u"NumberingOptionsPage"_ustr, &rSet)
1093     , aInvalidateTimer("cui SvxNumOptionsTabPage aInvalidateTimer")
1094     , m_pLevelHdlEvent(nullptr)
1095     , bLastWidthModified(false)
1096     , bModified(false)
1097     , bPreset(false)
1098     , bAutomaticCharStyles(true)
1099     , bHTMLMode(false)
1100     , nBullet(0xff)
1101     , nActNumLvl(1)
1102     , nNumItemId(SID_ATTR_NUMBERING_RULE)
1103     , m_aRatioTop(ConnectorType::Top)
1104     , m_aRatioBottom(ConnectorType::Bottom)
1105     , m_xGrid(m_xBuilder->weld_widget(u"grid2"_ustr))
1106     , m_xLevelLB(m_xBuilder->weld_tree_view(u"levellb"_ustr))
1107     , m_xFmtLB(m_xBuilder->weld_combo_box(u"numfmtlb"_ustr))
1108     , m_xSeparatorFT(m_xBuilder->weld_label(u"separator"_ustr))
1109     , m_xPrefixFT(m_xBuilder->weld_label(u"prefixft"_ustr))
1110     , m_xPrefixED(m_xBuilder->weld_entry(u"prefix"_ustr))
1111     , m_xSuffixFT(m_xBuilder->weld_label(u"suffixft"_ustr))
1112     , m_xSuffixED(m_xBuilder->weld_entry(u"suffix"_ustr))
1113     , m_xCharFmtFT(m_xBuilder->weld_label(u"charstyleft"_ustr))
1114     , m_xCharFmtLB(m_xBuilder->weld_combo_box(u"charstyle"_ustr))
1115     , m_xBulColorFT(m_xBuilder->weld_label(u"colorft"_ustr))
1116     , m_xBulColLB(new ColorListBox(m_xBuilder->weld_menu_button(u"color"_ustr),
1117                 [this]{ return GetDialogController()->getDialog(); }))
1118     , m_xBulRelSizeFT(m_xBuilder->weld_label(u"relsizeft"_ustr))
1119     , m_xBulRelSizeMF(m_xBuilder->weld_metric_spin_button(u"relsize"_ustr, FieldUnit::PERCENT))
1120     , m_xAllLevelFT(m_xBuilder->weld_label(u"sublevelsft"_ustr))
1121     , m_xAllLevelNF(m_xBuilder->weld_spin_button(u"sublevels"_ustr))
1122     , m_xIsLegalCB(m_xBuilder->weld_check_button(u"islegal"_ustr))
1123     , m_xStartFT(m_xBuilder->weld_label(u"startatft"_ustr))
1124     , m_xStartED(m_xBuilder->weld_spin_button(u"startat"_ustr))
1125     , m_xBulletFT(m_xBuilder->weld_label(u"bulletft"_ustr))
1126     , m_xBulletPB(m_xBuilder->weld_button(u"bullet"_ustr))
1127     , m_xBitmapFT(m_xBuilder->weld_label(u"bitmapft"_ustr))
1128     , m_xBitmapMB(m_xBuilder->weld_menu_button(u"bitmap"_ustr))
1129     , m_xWidthFT(m_xBuilder->weld_label(u"widthft"_ustr))
1130     , m_xWidthMF(m_xBuilder->weld_metric_spin_button(u"widthmf"_ustr, FieldUnit::CM))
1131     , m_xHeightFT(m_xBuilder->weld_label(u"heightft"_ustr))
1132     , m_xHeightMF(m_xBuilder->weld_metric_spin_button(u"heightmf"_ustr, FieldUnit::CM))
1133     , m_xRatioCB(m_xBuilder->weld_check_button(u"keepratio"_ustr))
1134     , m_xCbxScaleImg(m_xBuilder->weld_image(u"imRatio"_ustr))
1135     , m_xImgRatioTop(new weld::CustomWeld(*m_xBuilder, u"daRatioTop"_ustr, m_aRatioTop))
1136     , m_xImgRatioBottom(new weld::CustomWeld(*m_xBuilder, u"daRatioBottom"_ustr, m_aRatioBottom))
1137     , m_xOrientFT(m_xBuilder->weld_label(u"orientft"_ustr))
1138     , m_xOrientLB(m_xBuilder->weld_combo_box(u"orientlb"_ustr))
1139     , m_xAllLevelsFrame(m_xBuilder->weld_widget(u"levelsframe"_ustr))
1140     , m_xSameLevelCB(m_xBuilder->weld_check_button(u"allsame"_ustr))
1141     , m_xPreviewWIN(new weld::CustomWeld(*m_xBuilder, u"preview"_ustr, m_aPreviewWIN))
1142 {
1143     m_xBulColLB->SetSlotId(SID_ATTR_CHAR_COLOR);
1144     m_xBulRelSizeMF->set_min(SVX_NUM_REL_SIZE_MIN, FieldUnit::PERCENT);
1145     m_xBulRelSizeMF->set_increments(5, 50, FieldUnit::PERCENT);
1146     SetExchangeSupport();
1147     aActBulletFont = lcl_GetDefaultBulletFont();
1148     // vertical alignment = fill makes the drawingarea expand the associated spinedits so we have to size it here
1149     const sal_Int16 aHeight
1150         = static_cast<sal_Int16>(std::max(int(m_xRatioCB->get_preferred_size().getHeight() / 2
1151                                               - m_xWidthMF->get_preferred_size().getHeight() / 2),
1152                                           12));
1153     const sal_Int16 aWidth
1154         = static_cast<sal_Int16>(m_xRatioCB->get_preferred_size().getWidth() / 2);
1155     m_xImgRatioTop->set_size_request(aWidth, aHeight);
1156     m_xImgRatioBottom->set_size_request(aWidth, aHeight);
1157     //init needed for gtk3
1158     m_xCbxScaleImg->set_from_icon_name(m_xRatioCB->get_active() ? RID_SVXBMP_LOCKED
1159                                                                 : RID_SVXBMP_UNLOCKED);
1160 
1161     m_xBulletPB->connect_clicked(LINK(this, SvxNumOptionsTabPage, BulletHdl_Impl));
1162     m_xFmtLB->connect_changed(LINK(this, SvxNumOptionsTabPage, NumberTypeSelectHdl_Impl));
1163     m_xBitmapMB->connect_selected(LINK(this, SvxNumOptionsTabPage, GraphicHdl_Impl));
1164     m_xBitmapMB->connect_toggled(LINK(this, SvxNumOptionsTabPage, PopupActivateHdl_Impl));
1165     m_xLevelLB->set_selection_mode(SelectionMode::Multiple);
1166     m_xLevelLB->connect_changed(LINK(this, SvxNumOptionsTabPage, LevelHdl_Impl));
1167     m_xCharFmtLB->connect_changed(LINK(this, SvxNumOptionsTabPage, CharFmtHdl_Impl));
1168     m_xWidthMF->connect_value_changed(LINK(this, SvxNumOptionsTabPage, SizeHdl_Impl));
1169     m_xHeightMF->connect_value_changed(LINK(this, SvxNumOptionsTabPage, SizeHdl_Impl));
1170     m_xRatioCB->connect_toggled(LINK(this, SvxNumOptionsTabPage, RatioHdl_Impl));
1171     m_xStartED->connect_value_changed(LINK(this, SvxNumOptionsTabPage, SpinModifyHdl_Impl));
1172     m_xPrefixED->connect_changed(LINK(this, SvxNumOptionsTabPage, EditModifyHdl_Impl));
1173     m_xSuffixED->connect_changed(LINK(this, SvxNumOptionsTabPage, EditModifyHdl_Impl));
1174     m_xAllLevelNF->connect_value_changed(LINK(this,SvxNumOptionsTabPage, AllLevelHdl_Impl));
1175     m_xIsLegalCB->connect_toggled(LINK(this, SvxNumOptionsTabPage, IsLegalHdl_Impl));
1176     m_xOrientLB->connect_changed(LINK(this, SvxNumOptionsTabPage, OrientHdl_Impl));
1177     m_xSameLevelCB->connect_toggled(LINK(this, SvxNumOptionsTabPage, SameLevelHdl_Impl));
1178     m_xBulRelSizeMF->connect_value_changed(LINK(this,SvxNumOptionsTabPage, BulRelSizeHdl_Impl));
1179     m_xBulColLB->SetSelectHdl(LINK(this, SvxNumOptionsTabPage, BulColorHdl_Impl));
1180     aInvalidateTimer.SetInvokeHandler(LINK(this, SvxNumOptionsTabPage, PreviewInvalidateHdl_Impl));
1181     aInvalidateTimer.SetTimeout(50);
1182 
1183     eCoreUnit = rSet.GetPool()->GetMetric(rSet.GetPool()->GetWhichIDFromSlotID(SID_ATTR_NUMBERING_RULE));
1184 
1185     // Fill ListBox with predefined / translated numbering types.
1186     sal_uInt32 nCount = SvxNumberingTypeTable::Count();
1187     for (sal_uInt32 i = 0; i < nCount; ++i)
1188     {
1189         int nValue = SvxNumberingTypeTable::GetValue(i);
1190         if (comphelper::LibreOfficeKit::isActive() && (nValue & SVX_NUM_BITMAP)) continue;
1191         m_xFmtLB->append(OUString::number(nValue), SvxNumberingTypeTable::GetString(i));
1192     }
1193 
1194     // Get advanced numbering types from the component.
1195     // Watch out for the ugly
1196     // 136 == 0x88 == SVX_NUM_BITMAP|0x80 == SVX_NUM_BITMAP|LINK_TOKEN
1197     // to not remove that.
1198     SvxNumOptionsTabPageHelper::GetI18nNumbering( *m_xFmtLB, (SVX_NUM_BITMAP | LINK_TOKEN));
1199 
1200     m_xFmtLB->set_active(0);
1201 
1202     m_xCharFmtLB->set_size_request(m_xCharFmtLB->get_approximate_digit_width() * 10, -1);
1203     Size aSize(m_xGrid->get_preferred_size());
1204     m_xGrid->set_size_request(aSize.Width(), -1);
1205 }
1206 
~SvxNumOptionsTabPage()1207 SvxNumOptionsTabPage::~SvxNumOptionsTabPage()
1208 {
1209     m_xPreviewWIN.reset();
1210     m_xBulColLB.reset();
1211     pActNum.reset();
1212     pSaveNum.reset();
1213     if (m_pLevelHdlEvent)
1214     {
1215         Application::RemoveUserEvent(m_pLevelHdlEvent);
1216         m_pLevelHdlEvent = nullptr;
1217     }
1218 }
1219 
SetMetric(FieldUnit eMetric)1220 void SvxNumOptionsTabPage::SetMetric(FieldUnit eMetric)
1221 {
1222     if(eMetric == FieldUnit::MM)
1223     {
1224         m_xWidthMF->set_digits(1);
1225         m_xHeightMF->set_digits(1);
1226     }
1227     m_xWidthMF->set_unit(eMetric);
1228     m_xHeightMF->set_unit(eMetric);
1229 }
1230 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rAttrSet)1231 std::unique_ptr<SfxTabPage> SvxNumOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController,
1232                                                 const SfxItemSet* rAttrSet)
1233 {
1234     return std::make_unique<SvxNumOptionsTabPage>(pPage, pController, *rAttrSet);
1235 };
1236 
ActivatePage(const SfxItemSet & rSet)1237 void    SvxNumOptionsTabPage::ActivatePage(const SfxItemSet& rSet)
1238 {
1239     const SfxItemSet* pExampleSet = GetDialogExampleSet();
1240     sal_uInt16 nTmpNumLvl = 1;
1241     if(pExampleSet)
1242     {
1243         if(const SfxBoolItem* pPresetItem = pExampleSet->GetItemIfSet(SID_PARAM_NUM_PRESET, false))
1244             bPreset = pPresetItem->GetValue();
1245         if(const SfxUInt16Item* pLevelItem = pExampleSet->GetItemIfSet(SID_PARAM_CUR_NUM_LEVEL, false))
1246             nTmpNumLvl = pLevelItem->GetValue();
1247     }
1248     if(const SvxNumBulletItem* pBulletItem = rSet.GetItemIfSet(nNumItemId, false))
1249     {
1250         pSaveNum.reset( new SvxNumRule(pBulletItem->GetNumRule()) );
1251     }
1252 
1253     bModified = (!pActNum->Get( 0 ) || bPreset);
1254     if(*pActNum == *pSaveNum && nActNumLvl == nTmpNumLvl)
1255         return;
1256 
1257     nActNumLvl = nTmpNumLvl;
1258     sal_uInt16 nMask = 1;
1259     m_xLevelLB->unselect_all();
1260     if (nActNumLvl == SAL_MAX_UINT16)
1261         m_xLevelLB->select(pActNum->GetLevelCount());
1262     if(nActNumLvl != SAL_MAX_UINT16)
1263     {
1264         for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
1265         {
1266             if(nActNumLvl & nMask)
1267                 m_xLevelLB->select(i);
1268             nMask <<= 1 ;
1269         }
1270     }
1271     *pActNum = *pSaveNum;
1272 
1273     InitControls();
1274 }
1275 
DeactivatePage(SfxItemSet * _pSet)1276 DeactivateRC SvxNumOptionsTabPage::DeactivatePage(SfxItemSet * _pSet)
1277 {
1278     if(_pSet)
1279         FillItemSet(_pSet);
1280     return DeactivateRC::LeavePage;
1281 }
1282 
FillItemSet(SfxItemSet * rSet)1283 bool    SvxNumOptionsTabPage::FillItemSet( SfxItemSet* rSet )
1284 {
1285     rSet->Put(SfxUInt16Item(SID_PARAM_CUR_NUM_LEVEL, nActNumLvl));
1286     if(bModified && pActNum)
1287     {
1288         *pSaveNum = *pActNum;
1289         rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId ));
1290         rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, false));
1291     }
1292     return bModified;
1293 };
1294 
Reset(const SfxItemSet * rSet)1295 void    SvxNumOptionsTabPage::Reset( const SfxItemSet* rSet )
1296 {
1297     // in Draw the item exists as WhichId, in Writer only as SlotId
1298     const SvxNumBulletItem* pBulletItem =
1299         rSet->GetItemIfSet(SID_ATTR_NUMBERING_RULE, false);
1300     if(!pBulletItem)
1301     {
1302         nNumItemId = rSet->GetPool()->GetWhichIDFromSlotID(SID_ATTR_NUMBERING_RULE);
1303         pBulletItem = rSet->GetItemIfSet(nNumItemId, false);
1304 
1305         if( !pBulletItem )
1306         {
1307             pBulletItem = & rSet->Get( nNumItemId );
1308         }
1309     }
1310     DBG_ASSERT(pBulletItem, "no item found!");
1311     pSaveNum.reset( new SvxNumRule(pBulletItem->GetNumRule()) );
1312 
1313     // insert levels
1314     if (!m_xLevelLB->n_children())
1315     {
1316         for(sal_uInt16 i = 1; i <= pSaveNum->GetLevelCount(); i++)
1317             m_xLevelLB->append_text(OUString::number(i));
1318         if(pSaveNum->GetLevelCount() > 1)
1319         {
1320             OUString sEntry = "1 - " + OUString::number( pSaveNum->GetLevelCount() );
1321             m_xLevelLB->append_text(sEntry);
1322             m_xLevelLB->select_text(sEntry);
1323         }
1324         else
1325             m_xLevelLB->select(0);
1326     }
1327     else
1328         m_xLevelLB->select(m_xLevelLB->n_children() - 1);
1329 
1330     sal_uInt16 nMask = 1;
1331     m_xLevelLB->unselect_all();
1332     if (nActNumLvl == SAL_MAX_UINT16)
1333     {
1334         m_xLevelLB->select( pSaveNum->GetLevelCount() );
1335     }
1336     else
1337     {
1338         for(sal_uInt16 i = 0; i < pSaveNum->GetLevelCount(); i++)
1339         {
1340             if(nActNumLvl & nMask)
1341                 m_xLevelLB->select( i );
1342             nMask <<= 1 ;
1343         }
1344     }
1345 
1346     if(!pActNum)
1347         pActNum.reset( new SvxNumRule(*pSaveNum) );
1348     else if(*pSaveNum != *pActNum)
1349         *pActNum = *pSaveNum;
1350     m_aPreviewWIN.SetNumRule(pActNum.get());
1351     m_xSameLevelCB->set_active(pActNum->IsContinuousNumbering());
1352 
1353     const SfxUInt16Item* pHtmlModeItem =
1354         rSet->GetItemIfSet( SID_HTML_MODE, false );
1355     if (!pHtmlModeItem)
1356     {
1357         if (SfxObjectShell* pShell = SfxObjectShell::Current())
1358             pHtmlModeItem = pShell->GetItem( SID_HTML_MODE );
1359     }
1360     if ( pHtmlModeItem )
1361     {
1362         sal_uInt16 nHtmlMode = pHtmlModeItem->GetValue();
1363         bHTMLMode = 0 != (nHtmlMode&HTMLMODE_ON);
1364     }
1365 
1366     bool bCharFmt = pActNum->IsFeatureSupported(SvxNumRuleFlags::CHAR_STYLE);
1367     m_xCharFmtFT->set_visible(bCharFmt);
1368     m_xCharFmtLB->set_visible(bCharFmt);
1369 
1370     bool bContinuous = pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS);
1371 
1372     bool bAllLevel = bContinuous && !bHTMLMode;
1373     m_xAllLevelFT->set_visible(bAllLevel);
1374     m_xAllLevelNF->set_visible(bAllLevel);
1375     m_xIsLegalCB->set_visible(bAllLevel);
1376 
1377     m_xAllLevelsFrame->set_visible(bContinuous);
1378 
1379     // again misusage: in Draw there is numeration only until the bitmap
1380     // without SVX_NUM_NUMBER_NONE
1381     //remove types that are unsupported by Draw/Impress
1382     if(!bContinuous)
1383     {
1384         sal_Int32 nFmtCount = m_xFmtLB->get_count();
1385         for(sal_Int32 i = nFmtCount; i; i--)
1386         {
1387             sal_uInt16 nEntryData = m_xFmtLB->get_id(i - 1).toUInt32();
1388             if(/*SVX_NUM_NUMBER_NONE == nEntryData ||*/
1389                 (SVX_NUM_BITMAP|LINK_TOKEN) ==  nEntryData)
1390                 m_xFmtLB->remove(i - 1);
1391         }
1392     }
1393     //one must be enabled
1394     if(!pActNum->IsFeatureSupported(SvxNumRuleFlags::ENABLE_LINKED_BMP))
1395     {
1396         auto nPos = m_xFmtLB->find_id(OUString::number(SVX_NUM_BITMAP|LINK_TOKEN));
1397         if (nPos != -1)
1398             m_xFmtLB->remove(nPos);
1399     }
1400     else if(!pActNum->IsFeatureSupported(SvxNumRuleFlags::ENABLE_EMBEDDED_BMP))
1401     {
1402         auto nPos = m_xFmtLB->find_id(OUString::number(SVX_NUM_BITMAP));
1403         if (nPos != -1)
1404             m_xFmtLB->remove(nPos);
1405     }
1406 
1407     // MegaHack: because of a not-fixable 'design mistake/error' in Impress
1408     // delete all kinds of numeric enumerations
1409     if(pActNum->IsFeatureSupported(SvxNumRuleFlags::NO_NUMBERS))
1410     {
1411         sal_Int32 nFmtCount = m_xFmtLB->get_count();
1412         for(sal_Int32 i = nFmtCount; i; i--)
1413         {
1414             sal_uInt16 nEntryData = m_xFmtLB->get_id(i - 1).toUInt32();
1415             if( /*nEntryData >= SVX_NUM_CHARS_UPPER_LETTER &&*/  nEntryData <= SVX_NUM_NUMBER_NONE)
1416                 m_xFmtLB->remove(i - 1);
1417         }
1418     }
1419 
1420     InitControls();
1421     bModified = false;
1422 }
1423 
InitControls()1424 void SvxNumOptionsTabPage::InitControls()
1425 {
1426     bool bShowBullet    = true;
1427     bool bShowBitmap    = true;
1428     bool bSameType      = true;
1429     bool bSameStart     = true;
1430     bool bSamePrefix    = true;
1431     bool bSameSuffix    = true;
1432     bool bAllLevel      = true;
1433     bool bSameCharFmt   = true;
1434     bool bSameVOrient   = true;
1435     bool bSameSize      = true;
1436     bool bSameBulColor  = true;
1437     bool bSameBulRelSize= true;
1438 
1439     TriState isLegal = TRISTATE_INDET;
1440 
1441     const SvxNumberFormat* aNumFmtArr[SVX_MAX_NUM];
1442     OUString sFirstCharFmt;
1443     sal_Int16 eFirstOrient = text::VertOrientation::NONE;
1444     Size aFirstSize(0,0);
1445     sal_uInt16 nMask = 1;
1446     sal_uInt16 nLvl = SAL_MAX_UINT16;
1447     sal_uInt16 nHighestLevel = 0;
1448 
1449     bool bBullColor = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_COLOR);
1450     bool bBullRelSize = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE);
1451     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
1452     {
1453         if(nActNumLvl & nMask)
1454         {
1455             aNumFmtArr[i] = &pActNum->GetLevel(i);
1456             bShowBullet &= aNumFmtArr[i]->GetNumberingType() == SVX_NUM_CHAR_SPECIAL;
1457             bShowBitmap &= (aNumFmtArr[i]->GetNumberingType()&(~LINK_TOKEN)) == SVX_NUM_BITMAP;
1458             if(SAL_MAX_UINT16 == nLvl)
1459             {
1460                 nLvl = i;
1461                 sFirstCharFmt = aNumFmtArr[i]->GetCharFormatName();
1462                 eFirstOrient = aNumFmtArr[i]->GetVertOrient();
1463                 if(bShowBitmap)
1464                     aFirstSize = aNumFmtArr[i]->GetGraphicSize();
1465                 isLegal = aNumFmtArr[i]->GetIsLegal() ? TRISTATE_TRUE : TRISTATE_FALSE;
1466             }
1467             if( i > nLvl)
1468             {
1469                 bSameType &=   aNumFmtArr[i]->GetNumberingType() == aNumFmtArr[nLvl]->GetNumberingType();
1470                 bSameStart = aNumFmtArr[i]->GetStart() == aNumFmtArr[nLvl]->GetStart();
1471 
1472                 bSamePrefix = aNumFmtArr[i]->GetPrefix() == aNumFmtArr[nLvl]->GetPrefix();
1473                 bSameSuffix = aNumFmtArr[i]->GetSuffix() == aNumFmtArr[nLvl]->GetSuffix();
1474                 bAllLevel &= aNumFmtArr[i]->GetIncludeUpperLevels() == aNumFmtArr[nLvl]->GetIncludeUpperLevels();
1475                 if (aNumFmtArr[i]->GetIsLegal() != aNumFmtArr[nLvl]->GetIsLegal())
1476                     isLegal = TRISTATE_INDET;
1477                 bSameCharFmt    &= sFirstCharFmt == aNumFmtArr[i]->GetCharFormatName();
1478                 bSameVOrient    &= eFirstOrient == aNumFmtArr[i]->GetVertOrient();
1479                 if(bShowBitmap && bSameSize)
1480                     bSameSize &= aNumFmtArr[i]->GetGraphicSize() == aFirstSize;
1481                 bSameBulColor &= aNumFmtArr[i]->GetBulletColor() == aNumFmtArr[nLvl]->GetBulletColor();
1482                 bSameBulRelSize &= aNumFmtArr[i]->GetBulletRelSize() == aNumFmtArr[nLvl]->GetBulletRelSize();
1483             }
1484             nHighestLevel = i;
1485         }
1486         else
1487             aNumFmtArr[i] = nullptr;
1488 
1489         nMask <<= 1 ;
1490     }
1491     SwitchNumberType(bShowBullet ? 1 : bShowBitmap ? 2 : 0);
1492 
1493     sal_uInt16 nNumberingType;
1494     if (nLvl != SAL_MAX_UINT16)
1495         nNumberingType = aNumFmtArr[nLvl]->GetNumberingType();
1496     else
1497     {
1498         nNumberingType = SVX_NUM_NUMBER_NONE;
1499         bAllLevel = false;
1500         bSameBulRelSize = false;
1501         bSameBulColor = false;
1502         bSameStart = false;
1503         bSamePrefix = false;
1504         bSameSuffix = false;
1505     }
1506 
1507     CheckForStartValue_Impl(nNumberingType);
1508 
1509     if(bShowBitmap)
1510     {
1511         if(!bSameVOrient || eFirstOrient == text::VertOrientation::NONE)
1512             m_xOrientLB->set_active(-1);
1513         else
1514             m_xOrientLB->set_active(
1515                 sal::static_int_cast< sal_Int32 >(eFirstOrient - 1));
1516                 // no text::VertOrientation::NONE
1517 
1518         if(bSameSize)
1519         {
1520             SetMetricValue(*m_xHeightMF, aFirstSize.Height(), eCoreUnit);
1521             SetMetricValue(*m_xWidthMF, aFirstSize.Width(), eCoreUnit);
1522         }
1523         else
1524         {
1525             m_xHeightMF->set_text(u""_ustr);
1526             m_xWidthMF->set_text(u""_ustr);
1527         }
1528     }
1529 
1530     if(bSameType)
1531     {
1532         sal_uInt16 nLBData = nNumberingType;
1533         m_xFmtLB->set_active_id(OUString::number(nLBData));
1534     }
1535     else
1536         m_xFmtLB->set_active(-1);
1537 
1538     m_xAllLevelNF->set_sensitive(nHighestLevel > 0 && !m_xSameLevelCB->get_active());
1539     m_xAllLevelNF->set_max(nHighestLevel + 1);
1540     if(bAllLevel)
1541     {
1542         m_xAllLevelNF->set_value(aNumFmtArr[nLvl]->GetIncludeUpperLevels());
1543     }
1544     else
1545     {
1546         m_xAllLevelNF->set_text(u""_ustr);
1547     }
1548 
1549     m_xIsLegalCB->set_state(isLegal);
1550     m_xIsLegalCB->set_sensitive(!m_xSameLevelCB->get_active());
1551 
1552     if(bBullRelSize)
1553     {
1554         if(bSameBulRelSize)
1555             m_xBulRelSizeMF->set_value(aNumFmtArr[nLvl]->GetBulletRelSize(), FieldUnit::PERCENT);
1556         else
1557             m_xBulRelSizeMF->set_text(u""_ustr);
1558     }
1559     if(bBullColor)
1560     {
1561         if(bSameBulColor)
1562             m_xBulColLB->SelectEntry(aNumFmtArr[nLvl]->GetBulletColor());
1563         else
1564             m_xBulColLB->SetNoSelection();
1565     }
1566     m_xStartED->set_value(1); // If this isn't set then changing the bullet type to a numbered type doesn't reset the start level
1567     switch(nBullet)
1568     {
1569         case SHOW_NUMBERING:
1570             if(bSameStart)
1571             {
1572                 m_xStartED->set_value(aNumFmtArr[nLvl]->GetStart());
1573             }
1574             else
1575                 m_xStartED->set_text(u""_ustr);
1576         break;
1577         case SHOW_BULLET:
1578         break;
1579         case SHOW_BITMAP:
1580         break;
1581     }
1582 
1583     if(bSamePrefix)
1584         m_xPrefixED->set_text(aNumFmtArr[nLvl]->GetPrefix());
1585     else
1586         m_xPrefixED->set_text(u""_ustr);
1587     if(bSameSuffix)
1588         m_xSuffixED->set_text(aNumFmtArr[nLvl]->GetSuffix());
1589     else
1590         m_xSuffixED->set_text(u""_ustr);
1591 
1592     if(bSameCharFmt)
1593     {
1594         if (!sFirstCharFmt.isEmpty())
1595             m_xCharFmtLB->set_active_text(sFirstCharFmt);
1596         else if (m_xCharFmtLB->get_count())
1597             m_xCharFmtLB->set_active(0);
1598     }
1599     else
1600         m_xCharFmtLB->set_active(-1);
1601 
1602     m_aPreviewWIN.SetLevel(nActNumLvl);
1603     m_aPreviewWIN.Invalidate();
1604 }
1605 
1606 // 0 - Number; 1 - Bullet; 2 - Bitmap
SwitchNumberType(sal_uInt8 nType)1607 void SvxNumOptionsTabPage::SwitchNumberType( sal_uInt8 nType )
1608 {
1609     if(nBullet == nType)
1610         return;
1611     nBullet = nType;
1612     bool bBullet = (nType == SHOW_BULLET);
1613     bool bBitmap = (nType == SHOW_BITMAP);
1614     bool bEnableBitmap = (nType == SHOW_BITMAP);
1615     bool bNumeric = !(bBitmap||bBullet);
1616     m_xSeparatorFT->set_visible(bNumeric);
1617     m_xPrefixFT->set_visible(bNumeric);
1618     m_xPrefixED->set_visible(bNumeric);
1619     m_xSuffixFT->set_visible(bNumeric);
1620     m_xSuffixED->set_visible(bNumeric);
1621 
1622     bool bCharFmt = pActNum->IsFeatureSupported(SvxNumRuleFlags::CHAR_STYLE);
1623     m_xCharFmtFT->set_visible(!bBitmap && bCharFmt);
1624     m_xCharFmtLB->set_visible(!bBitmap && bCharFmt);
1625 
1626     // this is rather misusage, as there is no own flag
1627     // for complete numeration
1628     bool bAllLevelFeature = pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS);
1629     bool bAllLevel = bNumeric && bAllLevelFeature && !bHTMLMode;
1630     m_xAllLevelFT->set_visible(bAllLevel);
1631     m_xAllLevelNF->set_visible(bAllLevel);
1632     m_xIsLegalCB->set_visible(bAllLevel);
1633 
1634     m_xStartFT->set_visible(!(bBullet||bBitmap));
1635     m_xStartED->set_visible(!(bBullet||bBitmap));
1636 
1637     m_xBulletFT->set_visible(bBullet);
1638     m_xBulletPB->set_visible(bBullet);
1639     bool bBullColor = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_COLOR);
1640     m_xBulColorFT->set_visible(!bBitmap && bBullColor);
1641     m_xBulColLB->set_visible(!bBitmap && bBullColor);
1642     bool bBullResSize = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE);
1643     m_xBulRelSizeFT->set_visible(!bBitmap && bBullResSize);
1644     m_xBulRelSizeMF->set_visible(!bBitmap && bBullResSize);
1645 
1646     m_xBitmapFT->set_visible(bBitmap);
1647     m_xBitmapMB->set_visible(bBitmap);
1648 
1649     m_xWidthFT->set_visible(bBitmap);
1650     m_xWidthMF->set_visible(bBitmap);
1651     m_xHeightFT->set_visible(bBitmap);
1652     m_xHeightMF->set_visible(bBitmap);
1653     m_xRatioCB->set_visible(bBitmap);
1654     m_xCbxScaleImg->set_visible(bBitmap);
1655     m_xImgRatioTop->set_visible(bBitmap);
1656     m_xImgRatioBottom->set_visible(bBitmap);
1657 
1658     m_xOrientFT->set_visible(bBitmap && bAllLevelFeature);
1659     m_xOrientLB->set_visible(bBitmap && bAllLevelFeature);
1660 
1661     m_xWidthFT->set_sensitive(bEnableBitmap);
1662     m_xWidthMF->set_sensitive(bEnableBitmap);
1663     m_xHeightFT->set_sensitive(bEnableBitmap);
1664     m_xHeightMF->set_sensitive(bEnableBitmap);
1665     m_xRatioCB->set_sensitive(bEnableBitmap);
1666     m_xOrientFT->set_sensitive(bEnableBitmap);
1667     m_xOrientLB->set_sensitive(bEnableBitmap);
1668 }
1669 
IMPL_LINK_NOARG(SvxNumOptionsTabPage,LevelHdl_Impl,weld::TreeView &,void)1670 IMPL_LINK_NOARG(SvxNumOptionsTabPage, LevelHdl_Impl, weld::TreeView&, void)
1671 {
1672     if (m_pLevelHdlEvent)
1673         return;
1674     // tdf#127112 (borrowing tdf#127120 solution) multiselection may be implemented by deselect follow by select so
1675     // fire off the handler to happen on next event loop and only process the
1676     // final state
1677     m_pLevelHdlEvent = Application::PostUserEvent(LINK(this, SvxNumOptionsTabPage, LevelHdl));
1678 }
1679 
IMPL_LINK_NOARG(SvxNumOptionsTabPage,LevelHdl,void *,void)1680 IMPL_LINK_NOARG(SvxNumOptionsTabPage, LevelHdl, void*, void)
1681 {
1682     m_pLevelHdlEvent = nullptr;
1683 
1684     sal_uInt16 nSaveNumLvl = nActNumLvl;
1685     nActNumLvl = 0;
1686     std::vector<int> aSelectedRows = m_xLevelLB->get_selected_rows();
1687     if (std::find(aSelectedRows.begin(), aSelectedRows.end(), pActNum->GetLevelCount()) != aSelectedRows.end() &&
1688         (aSelectedRows.size() == 1 || nSaveNumLvl != 0xffff))
1689     {
1690         nActNumLvl = 0xFFFF;
1691         for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ )
1692              m_xLevelLB->unselect(i);
1693     }
1694     else if (!aSelectedRows.empty())
1695     {
1696         sal_uInt16 nMask = 1;
1697         for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ )
1698         {
1699             if (std::find(aSelectedRows.begin(), aSelectedRows.end(), i) != aSelectedRows.end())
1700                 nActNumLvl |= nMask;
1701             nMask <<= 1;
1702         }
1703         m_xLevelLB->unselect(pActNum->GetLevelCount());
1704     }
1705     else
1706     {
1707         nActNumLvl = nSaveNumLvl;
1708         sal_uInt16 nMask = 1;
1709         for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ )
1710         {
1711             if(nActNumLvl & nMask)
1712             {
1713                 m_xLevelLB->select(i);
1714                 break;
1715             }
1716             nMask <<=1;
1717         }
1718     }
1719     InitControls();
1720 }
1721 
IMPL_LINK_NOARG(SvxNumOptionsTabPage,PreviewInvalidateHdl_Impl,Timer *,void)1722 IMPL_LINK_NOARG(SvxNumOptionsTabPage, PreviewInvalidateHdl_Impl, Timer *, void)
1723 {
1724     m_aPreviewWIN.Invalidate();
1725 }
1726 
IMPL_LINK(SvxNumOptionsTabPage,AllLevelHdl_Impl,weld::SpinButton &,rBox,void)1727 IMPL_LINK(SvxNumOptionsTabPage, AllLevelHdl_Impl, weld::SpinButton&, rBox, void)
1728 {
1729     sal_uInt16 nMask = 1;
1730     for(sal_uInt16 e = 0; e < pActNum->GetLevelCount(); e++)
1731     {
1732         if(nActNumLvl & nMask)
1733         {
1734             SvxNumberFormat aNumFmt(pActNum->GetLevel(e));
1735             aNumFmt.SetIncludeUpperLevels(static_cast<sal_uInt8>(std::min(rBox.get_value(), sal_Int64(e + 1))) );
1736             // Set the same prefix/suffix to generate list format with changed IncludedUpperLevels
1737             aNumFmt.SetListFormat(aNumFmt.GetPrefix(), aNumFmt.GetSuffix(), e);
1738             pActNum->SetLevel(e, aNumFmt);
1739         }
1740         nMask <<= 1;
1741     }
1742     SetModified();
1743 }
1744 
IMPL_LINK(SvxNumOptionsTabPage,IsLegalHdl_Impl,weld::Toggleable &,rBox,void)1745 IMPL_LINK(SvxNumOptionsTabPage, IsLegalHdl_Impl, weld::Toggleable&, rBox, void)
1746 {
1747     bool bSet = rBox.get_active();
1748     for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
1749     {
1750         if (nActNumLvl & (sal_uInt16(1) << i))
1751         {
1752             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
1753             aNumFmt.SetIsLegal(bSet);
1754             pActNum->SetLevel(i, aNumFmt);
1755         }
1756     }
1757     SetModified();
1758 }
1759 
IMPL_LINK(SvxNumOptionsTabPage,NumberTypeSelectHdl_Impl,weld::ComboBox &,rBox,void)1760 IMPL_LINK(SvxNumOptionsTabPage, NumberTypeSelectHdl_Impl, weld::ComboBox&, rBox, void)
1761 {
1762     OUString sSelectStyle;
1763     bool bShowOrient = false;
1764     bool bBmp = false;
1765     sal_uInt16 nMask = 1;
1766     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
1767     {
1768         if(nActNumLvl & nMask)
1769         {
1770             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
1771             // PAGEDESC does not exist
1772             SvxNumType nNumType = static_cast<SvxNumType>(rBox.get_active_id().toUInt32());
1773             aNumFmt.SetNumberingType(nNumType);
1774             sal_uInt16 nNumberingType = aNumFmt.GetNumberingType();
1775             if(SVX_NUM_BITMAP == (nNumberingType&(~LINK_TOKEN)))
1776             {
1777                 bBmp |= nullptr != aNumFmt.GetBrush();
1778                 aNumFmt.SetIncludeUpperLevels( 1 );
1779                 aNumFmt.SetListFormat(u""_ustr, u""_ustr, i);
1780                 if(!bBmp)
1781                     aNumFmt.SetGraphic(u""_ustr);
1782                 pActNum->SetLevel(i, aNumFmt);
1783                 SwitchNumberType(SHOW_BITMAP);
1784                 bShowOrient = true;
1785             }
1786             else if( SVX_NUM_CHAR_SPECIAL == nNumberingType )
1787             {
1788                 aNumFmt.SetIncludeUpperLevels( 1 );
1789                 aNumFmt.SetListFormat(u""_ustr, u""_ustr, i);
1790                 if( !aNumFmt.GetBulletFont() )
1791                     aNumFmt.SetBulletFont(&aActBulletFont);
1792                 if( !aNumFmt.GetBulletChar() )
1793                     aNumFmt.SetBulletChar( SVX_DEF_BULLET );
1794                 pActNum->SetLevel(i, aNumFmt);
1795                 SwitchNumberType(SHOW_BULLET);
1796                 // allocation of the drawing pattern is automatic
1797                 if(bAutomaticCharStyles)
1798                 {
1799                     sSelectStyle = m_sBulletCharFormatName;
1800                 }
1801             }
1802             else
1803             {
1804                 aNumFmt.SetListFormat(m_xPrefixED->get_text(), m_xSuffixED->get_text(), i);
1805 
1806                 SwitchNumberType(SHOW_NUMBERING);
1807                 pActNum->SetLevel(i, aNumFmt);
1808                 CheckForStartValue_Impl(nNumberingType);
1809 
1810                 // allocation of the drawing pattern is automatic
1811                 if(bAutomaticCharStyles)
1812                 {
1813                     sSelectStyle = m_sNumCharFmtName;
1814                 }
1815             }
1816         }
1817         nMask <<= 1;
1818     }
1819     bool bAllLevelFeature = pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS);
1820     if(bShowOrient && bAllLevelFeature)
1821     {
1822         m_xOrientFT->show();
1823         m_xOrientLB->show();
1824     }
1825     else
1826     {
1827         m_xOrientFT->hide();
1828         m_xOrientLB->hide();
1829     }
1830     SetModified();
1831     if(!sSelectStyle.isEmpty())
1832     {
1833         m_xCharFmtLB->set_active_text(sSelectStyle);
1834         CharFmtHdl_Impl(*m_xCharFmtLB);
1835         bAutomaticCharStyles = true;
1836     }
1837 }
1838 
CheckForStartValue_Impl(sal_uInt16 nNumberingType)1839 void SvxNumOptionsTabPage::CheckForStartValue_Impl(sal_uInt16 nNumberingType)
1840 {
1841     bool bIsNull = m_xStartED->get_value() == 0;
1842     bool bNoZeroAllowed = nNumberingType < SVX_NUM_ARABIC ||
1843                         SVX_NUM_CHARS_UPPER_LETTER_N == nNumberingType ||
1844                         SVX_NUM_CHARS_LOWER_LETTER_N == nNumberingType;
1845     m_xStartED->set_min(bNoZeroAllowed ? 1 : 0);
1846     if (bIsNull && bNoZeroAllowed)
1847         EditModifyHdl_Impl(*m_xStartED);
1848 }
1849 
IMPL_LINK(SvxNumOptionsTabPage,OrientHdl_Impl,weld::ComboBox &,rBox,void)1850 IMPL_LINK(SvxNumOptionsTabPage, OrientHdl_Impl, weld::ComboBox&, rBox, void)
1851 {
1852     sal_Int32 nPos = rBox.get_active();
1853     nPos ++; // no VERT_NONE
1854 
1855     sal_uInt16 nMask = 1;
1856     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
1857     {
1858         if(nActNumLvl & nMask)
1859         {
1860             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
1861             if(SVX_NUM_BITMAP == (aNumFmt.GetNumberingType()&(~LINK_TOKEN)))
1862             {
1863                 const SvxBrushItem* pBrushItem =  aNumFmt.GetBrush();
1864                 const Size& rSize = aNumFmt.GetGraphicSize();
1865                 sal_Int16 eOrient = static_cast<sal_Int16>(nPos);
1866                 aNumFmt.SetGraphicBrush( pBrushItem, &rSize, &eOrient );
1867                 pActNum->SetLevel(i, aNumFmt);
1868             }
1869         }
1870         nMask <<= 1;
1871     }
1872     SetModified(false);
1873 }
1874 
IMPL_LINK(SvxNumOptionsTabPage,SameLevelHdl_Impl,weld::Toggleable &,rBox,void)1875 IMPL_LINK(SvxNumOptionsTabPage, SameLevelHdl_Impl, weld::Toggleable&, rBox, void)
1876 {
1877     bool bSet = rBox.get_active();
1878     pActNum->SetContinuousNumbering(bSet);
1879     bool bRepaint = false;
1880     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
1881     {
1882         SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
1883         if(aNumFmt.GetNumberingType() != SVX_NUM_NUMBER_NONE)
1884         {
1885             bRepaint = true;
1886             break;
1887         }
1888     }
1889     SetModified(bRepaint);
1890     InitControls();
1891 }
1892 
IMPL_LINK(SvxNumOptionsTabPage,BulColorHdl_Impl,ColorListBox &,rColorBox,void)1893 IMPL_LINK(SvxNumOptionsTabPage, BulColorHdl_Impl, ColorListBox&, rColorBox, void)
1894 {
1895     Color nSetColor = rColorBox.GetSelectEntryColor();
1896 
1897     sal_uInt16 nMask = 1;
1898     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
1899     {
1900         if(nActNumLvl & nMask)
1901         {
1902             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
1903             aNumFmt.SetBulletColor(nSetColor);
1904             pActNum->SetLevel(i, aNumFmt);
1905         }
1906         nMask <<= 1;
1907     }
1908     SetModified();
1909 }
1910 
IMPL_LINK(SvxNumOptionsTabPage,BulRelSizeHdl_Impl,weld::MetricSpinButton &,rField,void)1911 IMPL_LINK(SvxNumOptionsTabPage, BulRelSizeHdl_Impl, weld::MetricSpinButton&, rField, void)
1912 {
1913     sal_uInt16 nRelSize = rField.get_value(FieldUnit::PERCENT);
1914 
1915     sal_uInt16 nMask = 1;
1916     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
1917     {
1918         if(nActNumLvl & nMask)
1919         {
1920             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
1921             aNumFmt.SetBulletRelSize(nRelSize);
1922             pActNum->SetLevel(i, aNumFmt);
1923         }
1924         nMask <<= 1;
1925     }
1926     SetModified();
1927 }
1928 
IMPL_LINK(SvxNumOptionsTabPage,GraphicHdl_Impl,const OUString &,rIdent,void)1929 IMPL_LINK(SvxNumOptionsTabPage, GraphicHdl_Impl, const OUString&, rIdent, void)
1930 {
1931     OUString                aGrfName;
1932     Size                    aSize;
1933     bool                bSucc(false);
1934     SvxOpenGraphicDialog aGrfDlg(CuiResId(RID_CUISTR_EDIT_GRAPHIC), GetFrameWeld());
1935 
1936     OUString sNumber;
1937     if (rIdent.startsWith("gallery", &sNumber))
1938     {
1939         auto idx = sNumber.toUInt32();
1940         if (idx < aGrfNames.size())
1941         {
1942             aGrfName = aGrfNames[idx];
1943             Graphic aGraphic;
1944             if(GalleryExplorer::GetGraphicObj( GALLERY_THEME_BULLETS, idx, &aGraphic))
1945             {
1946                 aSize = SvxNumberFormat::GetGraphicSizeMM100(&aGraphic);
1947                 bSucc = true;
1948             }
1949         }
1950     }
1951     else if (rIdent == "fromfile")
1952     {
1953         aGrfDlg.EnableLink( false );
1954         aGrfDlg.AsLink( false );
1955         if ( !aGrfDlg.Execute() )
1956         {
1957             // memorize selected filter
1958             aGrfName = aGrfDlg.GetPath();
1959 
1960             Graphic aGraphic;
1961             if( !aGrfDlg.GetGraphic(aGraphic) )
1962             {
1963                 aSize = SvxNumberFormat::GetGraphicSizeMM100(&aGraphic);
1964                 bSucc = true;
1965             }
1966         }
1967     }
1968     if(!bSucc)
1969         return;
1970 
1971     aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(eCoreUnit));
1972 
1973     sal_uInt16 nMask = 1;
1974     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
1975     {
1976         if(nActNumLvl & nMask)
1977         {
1978             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
1979             aNumFmt.SetCharFormatName(m_sNumCharFmtName);
1980             aNumFmt.SetGraphic(aGrfName);
1981 
1982             // set size for a later comparison
1983             const SvxBrushItem* pBrushItem = aNumFmt.GetBrush();
1984             // initiate asynchronous loading
1985             sal_Int16 eOrient = aNumFmt.GetVertOrient();
1986             aNumFmt.SetGraphicBrush( pBrushItem, &aSize, &eOrient );
1987             aInitSize[i] = aNumFmt.GetGraphicSize();
1988 
1989             pActNum->SetLevel(i, aNumFmt);
1990         }
1991         nMask <<= 1;
1992     }
1993     m_xRatioCB->set_sensitive(true);
1994     m_xWidthFT->set_sensitive(true);
1995     m_xHeightFT->set_sensitive(true);
1996     m_xWidthMF->set_sensitive(true);
1997     m_xHeightMF->set_sensitive(true);
1998     SetMetricValue(*m_xWidthMF, aSize.Width(), eCoreUnit);
1999     SetMetricValue(*m_xHeightMF, aSize.Height(), eCoreUnit);
2000     m_xOrientFT->set_sensitive(true);
2001     m_xOrientLB->set_sensitive(true);
2002     SetModified();
2003     //needed due to asynchronous loading of graphics in the SvxBrushItem
2004     aInvalidateTimer.Start();
2005 }
2006 
IMPL_LINK_NOARG(SvxNumOptionsTabPage,PopupActivateHdl_Impl,weld::Toggleable &,void)2007 IMPL_LINK_NOARG(SvxNumOptionsTabPage, PopupActivateHdl_Impl, weld::Toggleable&, void)
2008 {
2009     if (m_xGalleryMenu)
2010         return;
2011 
2012     m_xGalleryMenu = m_xBuilder->weld_menu(u"gallerysubmenu"_ustr);
2013     weld::WaitObject aWait(GetFrameWeld());
2014 
2015     if (!GalleryExplorer::FillObjList(GALLERY_THEME_BULLETS, aGrfNames))
2016         return;
2017 
2018     GalleryExplorer::BeginLocking(GALLERY_THEME_BULLETS);
2019 
2020     Graphic aGraphic;
2021     OUString sGrfName;
2022     ScopedVclPtrInstance< VirtualDevice > pVD;
2023     size_t i = 0;
2024     for (const auto & grfName : aGrfNames)
2025     {
2026         sGrfName = grfName;
2027         OUString sItemId = "gallery" + OUString::number(i);
2028         INetURLObject aObj(sGrfName);
2029         if (aObj.GetProtocol() == INetProtocol::File)
2030         {
2031             // tdf#141334 - only show the last name of the filename without its extension
2032             aObj.removeExtension();
2033             sGrfName = aObj.GetLastName(INetURLObject::DecodeMechanism::Unambiguous);
2034         }
2035         if(GalleryExplorer::GetGraphicObj( GALLERY_THEME_BULLETS, i, &aGraphic))
2036         {
2037             BitmapEx aBitmap(aGraphic.GetBitmapEx());
2038             Size aSize(aBitmap.GetSizePixel());
2039             if(aSize.Width() > MAX_BMP_WIDTH ||
2040                 aSize.Height() > MAX_BMP_HEIGHT)
2041             {
2042                 bool bWidth = aSize.Width() > aSize.Height();
2043                 double nScale = bWidth ?
2044                                     double(MAX_BMP_WIDTH) / static_cast<double>(aSize.Width()):
2045                                         double(MAX_BMP_HEIGHT) / static_cast<double>(aSize.Height());
2046                 aBitmap.Scale(nScale, nScale);
2047             }
2048             pVD->SetOutputSizePixel(aBitmap.GetSizePixel(), false);
2049             pVD->DrawBitmapEx(Point(), aBitmap);
2050             m_xGalleryMenu->append(sItemId, sGrfName, *pVD);
2051         }
2052         else
2053         {
2054             m_xGalleryMenu->append(sItemId, sGrfName);
2055         }
2056         ++i;
2057     }
2058     GalleryExplorer::EndLocking(GALLERY_THEME_BULLETS);
2059 }
2060 
IMPL_LINK_NOARG(SvxNumOptionsTabPage,BulletHdl_Impl,weld::Button &,void)2061 IMPL_LINK_NOARG(SvxNumOptionsTabPage, BulletHdl_Impl, weld::Button&, void)
2062 {
2063     SvxCharacterMap aMap(GetFrameWeld(), nullptr, nullptr);
2064 
2065     sal_uInt16 nMask = 1;
2066     std::optional<vcl::Font> pFmtFont;
2067     bool bSameBullet = true;
2068     sal_UCS4 cBullet = 0;
2069     bool bFirst = true;
2070     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
2071     {
2072         if(nActNumLvl & nMask)
2073         {
2074             const SvxNumberFormat&  rCurFmt = pActNum->GetLevel(i);
2075             if(bFirst)
2076             {
2077                  cBullet = rCurFmt.GetBulletChar();
2078             }
2079             else if(rCurFmt.GetBulletChar() != cBullet )
2080             {
2081                 bSameBullet = false;
2082                 break;
2083             }
2084             if(!pFmtFont)
2085                 pFmtFont = rCurFmt.GetBulletFont();
2086             bFirst = false;
2087         }
2088         nMask <<= 1;
2089 
2090     }
2091 
2092     if (pFmtFont)
2093         aMap.SetCharFont(*pFmtFont);
2094     else
2095         aMap.SetCharFont(aActBulletFont);
2096     if (bSameBullet)
2097         aMap.SetChar(cBullet);
2098     if (aMap.run() != RET_OK)
2099         return;
2100 
2101     // change Font Numrules
2102     aActBulletFont = aMap.GetCharFont();
2103 
2104     sal_uInt16 _nMask = 1;
2105     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
2106     {
2107         if(nActNumLvl & _nMask)
2108         {
2109             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
2110             aNumFmt.SetBulletFont(&aActBulletFont);
2111             aNumFmt.SetBulletChar(aMap.GetChar());
2112             pActNum->SetLevel(i, aNumFmt);
2113         }
2114         _nMask <<= 1;
2115     }
2116 
2117     SetModified();
2118 }
2119 
IMPL_LINK(SvxNumOptionsTabPage,SizeHdl_Impl,weld::MetricSpinButton &,rField,void)2120 IMPL_LINK( SvxNumOptionsTabPage, SizeHdl_Impl, weld::MetricSpinButton&, rField, void)
2121 {
2122     bool bWidth = &rField == m_xWidthMF.get();
2123     bLastWidthModified = bWidth;
2124     bool bRatio = m_xRatioCB->get_active();
2125     tools::Long nWidthVal = static_cast<tools::Long>(m_xWidthMF->denormalize(m_xWidthMF->get_value(FieldUnit::MM_100TH)));
2126     tools::Long nHeightVal = static_cast<tools::Long>(m_xHeightMF->denormalize(m_xHeightMF->get_value(FieldUnit::MM_100TH)));
2127     nWidthVal = OutputDevice::LogicToLogic( nWidthVal ,
2128                                                 MapUnit::Map100thMM, eCoreUnit );
2129     nHeightVal = OutputDevice::LogicToLogic( nHeightVal,
2130                                                 MapUnit::Map100thMM, eCoreUnit);
2131     double  fSizeRatio;
2132 
2133     bool bRepaint = false;
2134     sal_uInt16 nMask = 1;
2135     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
2136     {
2137         if(nActNumLvl & nMask)
2138         {
2139             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
2140             if(SVX_NUM_BITMAP == (aNumFmt.GetNumberingType()&(~LINK_TOKEN)))
2141             {
2142                 Size aSize(aNumFmt.GetGraphicSize() );
2143                 Size aSaveSize(aSize);
2144 
2145                 if (aInitSize[i].Height())
2146                     fSizeRatio = static_cast<double>(aInitSize[i].Width()) / static_cast<double>(aInitSize[i].Height());
2147                 else
2148                     fSizeRatio = double(1);
2149 
2150                 if(bWidth)
2151                 {
2152                     tools::Long nDelta = nWidthVal - aInitSize[i].Width();
2153                     aSize.setWidth( nWidthVal );
2154                     if (bRatio)
2155                     {
2156                         aSize.setHeight( aInitSize[i].Height() + static_cast<tools::Long>(static_cast<double>(nDelta) / fSizeRatio) );
2157                         m_xHeightMF->set_value(m_xHeightMF->normalize(
2158                             OutputDevice::LogicToLogic( aSize.Height(), eCoreUnit, MapUnit::Map100thMM )),
2159                                 FieldUnit::MM_100TH);
2160                     }
2161                 }
2162                 else
2163                 {
2164                     tools::Long nDelta = nHeightVal - aInitSize[i].Height();
2165                     aSize.setHeight( nHeightVal );
2166                     if (bRatio)
2167                     {
2168                         aSize.setWidth( aInitSize[i].Width() + static_cast<tools::Long>(static_cast<double>(nDelta) * fSizeRatio) );
2169                         m_xWidthMF->set_value(m_xWidthMF->normalize(
2170                             OutputDevice::LogicToLogic( aSize.Width(), eCoreUnit, MapUnit::Map100thMM )),
2171                                 FieldUnit::MM_100TH);
2172                     }
2173                 }
2174                 const SvxBrushItem* pBrushItem =  aNumFmt.GetBrush();
2175                 sal_Int16 eOrient = aNumFmt.GetVertOrient();
2176                 if(aSize != aSaveSize)
2177                     bRepaint = true;
2178                 aNumFmt.SetGraphicBrush( pBrushItem, &aSize, &eOrient );
2179                 pActNum->SetLevel(i, aNumFmt);
2180             }
2181         }
2182         nMask <<= 1;
2183     }
2184     SetModified(bRepaint);
2185 }
2186 
IMPL_LINK(SvxNumOptionsTabPage,RatioHdl_Impl,weld::Toggleable &,rBox,void)2187 IMPL_LINK(SvxNumOptionsTabPage, RatioHdl_Impl, weld::Toggleable&, rBox, void)
2188 {
2189     m_xCbxScaleImg->set_from_icon_name(m_xRatioCB->get_active() ? RID_SVXBMP_LOCKED : RID_SVXBMP_UNLOCKED);
2190     if (rBox.get_active())
2191     {
2192         if (bLastWidthModified)
2193             SizeHdl_Impl(*m_xWidthMF);
2194         else
2195             SizeHdl_Impl(*m_xHeightMF);
2196     }
2197 }
2198 
IMPL_LINK_NOARG(SvxNumOptionsTabPage,CharFmtHdl_Impl,weld::ComboBox &,void)2199 IMPL_LINK_NOARG(SvxNumOptionsTabPage, CharFmtHdl_Impl, weld::ComboBox&, void)
2200 {
2201     bAutomaticCharStyles = false;
2202     sal_Int32 nEntryPos = m_xCharFmtLB->get_active();
2203     OUString sEntry = m_xCharFmtLB->get_active_text();
2204     sal_uInt16 nMask = 1;
2205     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
2206     {
2207         if(nActNumLvl & nMask)
2208         {
2209             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
2210             if( 0 == nEntryPos )
2211                 aNumFmt.SetCharFormatName(u""_ustr);
2212             else
2213             {
2214                 if(SVX_NUM_BITMAP != (aNumFmt.GetNumberingType()&(~LINK_TOKEN)))
2215                     aNumFmt.SetCharFormatName(sEntry);
2216             }
2217             pActNum->SetLevel(i, aNumFmt);
2218         }
2219         nMask <<= 1;
2220     }
2221     SetModified(false);
2222 };
2223 
IMPL_LINK(SvxNumOptionsTabPage,EditModifyHdl_Impl,weld::Entry &,rEdit,void)2224 IMPL_LINK(SvxNumOptionsTabPage, EditModifyHdl_Impl, weld::Entry&, rEdit, void)
2225 {
2226     EditModifyHdl_Impl(&rEdit);
2227 }
2228 
IMPL_LINK(SvxNumOptionsTabPage,SpinModifyHdl_Impl,weld::SpinButton &,rSpinButton,void)2229 IMPL_LINK(SvxNumOptionsTabPage, SpinModifyHdl_Impl, weld::SpinButton&, rSpinButton, void)
2230 {
2231     EditModifyHdl_Impl(&rSpinButton);
2232 }
2233 
EditModifyHdl_Impl(const weld::Entry * pEdit)2234 void SvxNumOptionsTabPage::EditModifyHdl_Impl(const weld::Entry* pEdit)
2235 {
2236     bool bPrefixSuffix = (pEdit == m_xPrefixED.get())|| (pEdit == m_xSuffixED.get());
2237     bool bStart = pEdit == m_xStartED.get();
2238     sal_uInt16 nMask = 1;
2239     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
2240     {
2241         if(nActNumLvl & nMask)
2242         {
2243             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
2244             if (bPrefixSuffix)
2245                 aNumFmt.SetListFormat(m_xPrefixED->get_text(), m_xSuffixED->get_text(), i);
2246             else if(bStart)
2247                 aNumFmt.SetStart(m_xStartED->get_value());
2248             pActNum->SetLevel(i, aNumFmt);
2249         }
2250         nMask <<= 1;
2251     }
2252     SetModified();
2253 }
2254 
2255 //See uiconfig/swriter/ui/outlinepositionpage.ui for effectively a duplicate
2256 //dialog to this one, except with a different preview window impl.
2257 //TODO, determine if SwNumPositionTabPage and SvxNumPositionTabPage can be
2258 //merged
SvxNumPositionTabPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)2259 SvxNumPositionTabPage::SvxNumPositionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
2260     : SfxTabPage(pPage, pController, u"cui/ui/numberingpositionpage.ui"_ustr, u"NumberingPositionPage"_ustr, &rSet)
2261     , m_pLevelHdlEvent(nullptr)
2262     , nActNumLvl(1)
2263     , nNumItemId(SID_ATTR_NUMBERING_RULE)
2264     , bModified(false)
2265     , bPreset(false)
2266     , bInInintControl(false)
2267     , bLabelAlignmentPosAndSpaceModeActive(false)
2268     , m_xLevelLB(m_xBuilder->weld_tree_view(u"levellb"_ustr))
2269     , m_xDistBorderFT(m_xBuilder->weld_label(u"indent"_ustr))
2270     , m_xDistBorderMF(m_xBuilder->weld_metric_spin_button(u"indentmf"_ustr, FieldUnit::CM))
2271     , m_xRelativeCB(m_xBuilder->weld_check_button(u"relative"_ustr))
2272     , m_xIndentFT(m_xBuilder->weld_label(u"numberingwidth"_ustr))
2273     , m_xIndentMF(m_xBuilder->weld_metric_spin_button(u"numberingwidthmf"_ustr, FieldUnit::CM))
2274     , m_xDistNumFT(m_xBuilder->weld_label(u"numdist"_ustr))
2275     , m_xDistNumMF(m_xBuilder->weld_metric_spin_button(u"numdistmf"_ustr, FieldUnit::CM))
2276     , m_xAlignFT(m_xBuilder->weld_label(u"numalign"_ustr))
2277     , m_xAlignLB(m_xBuilder->weld_combo_box(u"numalignlb"_ustr))
2278     , m_xLabelFollowedByFT(m_xBuilder->weld_label(u"numfollowedby"_ustr))
2279     , m_xLabelFollowedByLB(m_xBuilder->weld_combo_box(u"numfollowedbylb"_ustr))
2280     , m_xListtabFT(m_xBuilder->weld_label(u"at"_ustr))
2281     , m_xListtabMF(m_xBuilder->weld_metric_spin_button(u"atmf"_ustr, FieldUnit::CM))
2282     , m_xAlign2FT(m_xBuilder->weld_label(u"num2align"_ustr))
2283     , m_xAlign2LB(m_xBuilder->weld_combo_box(u"num2alignlb"_ustr))
2284     , m_xAlignedAtFT(m_xBuilder->weld_label(u"alignedat"_ustr))
2285     , m_xAlignedAtMF(m_xBuilder->weld_metric_spin_button(u"alignedatmf"_ustr, FieldUnit::CM))
2286     , m_xIndentAtFT(m_xBuilder->weld_label(u"indentat"_ustr))
2287     , m_xIndentAtMF(m_xBuilder->weld_metric_spin_button(u"indentatmf"_ustr, FieldUnit::CM))
2288     , m_xStandardPB(m_xBuilder->weld_button(u"standard"_ustr))
2289     , m_xPreviewWIN(new weld::CustomWeld(*m_xBuilder, u"preview"_ustr, m_aPreviewWIN))
2290 {
2291     SetExchangeSupport();
2292 
2293     // set metric
2294     FieldUnit eFUnit = GetModuleFieldUnit(rSet);
2295 
2296     SetFieldUnit( *m_xDistBorderMF, eFUnit );
2297     SetFieldUnit( *m_xIndentMF, eFUnit );
2298     SetFieldUnit( *m_xDistNumMF, eFUnit );
2299 
2300     m_xAlignedAtMF->set_range(0, SAL_MAX_INT32, FieldUnit::NONE);
2301     m_xListtabMF->set_range(0, SAL_MAX_INT32, FieldUnit::NONE);
2302     m_xIndentAtMF->set_range(0, SAL_MAX_INT32, FieldUnit::NONE);
2303 
2304     m_xRelativeCB->set_active(true);
2305     m_xAlignLB->connect_changed(LINK(this, SvxNumPositionTabPage, EditModifyHdl_Impl));
2306     m_xAlign2LB->connect_changed(LINK(this, SvxNumPositionTabPage, EditModifyHdl_Impl));
2307     for ( sal_Int32 i = 0; i < m_xAlignLB->get_count(); ++i )
2308     {
2309         m_xAlign2LB->append_text(m_xAlignLB->get_text(i));
2310     }
2311 
2312     Link<weld::MetricSpinButton&,void> aLk3 = LINK(this, SvxNumPositionTabPage, DistanceHdl_Impl);
2313     m_xDistBorderMF->connect_value_changed(aLk3);
2314     m_xDistNumMF->connect_value_changed(aLk3);
2315     m_xIndentMF->connect_value_changed(aLk3);
2316 
2317     m_xLabelFollowedByLB->connect_changed(LINK(this, SvxNumPositionTabPage, LabelFollowedByHdl_Impl));
2318 
2319     m_xListtabMF->connect_value_changed(LINK(this, SvxNumPositionTabPage, ListtabPosHdl_Impl));
2320     m_xAlignedAtMF->connect_value_changed(LINK(this, SvxNumPositionTabPage, AlignAtHdl_Impl));
2321     m_xIndentAtMF->connect_value_changed(LINK(this, SvxNumPositionTabPage, IndentAtHdl_Impl));
2322 
2323     m_xLevelLB->set_selection_mode(SelectionMode::Multiple);
2324     m_xLevelLB->connect_changed(LINK(this, SvxNumPositionTabPage, LevelHdl_Impl));
2325     m_xRelativeCB->connect_toggled(LINK(this, SvxNumPositionTabPage, RelativeHdl_Impl));
2326     m_xStandardPB->connect_clicked(LINK(this, SvxNumPositionTabPage, StandardHdl_Impl));
2327 
2328     m_xRelativeCB->set_active(bLastRelative);
2329     m_aPreviewWIN.SetPositionMode();
2330     eCoreUnit = rSet.GetPool()->GetMetric(rSet.GetPool()->GetWhichIDFromSlotID(SID_ATTR_NUMBERING_RULE));
2331 }
2332 
~SvxNumPositionTabPage()2333 SvxNumPositionTabPage::~SvxNumPositionTabPage()
2334 {
2335     if (m_pLevelHdlEvent)
2336     {
2337         Application::RemoveUserEvent(m_pLevelHdlEvent);
2338         m_pLevelHdlEvent = nullptr;
2339     }
2340     m_xPreviewWIN.reset();
2341 }
2342 
2343 /*-------------------------------------------------------*/
2344 
InitControls()2345 void SvxNumPositionTabPage::InitControls()
2346 {
2347     bInInintControl = true;
2348     const bool bRelative = !bLabelAlignmentPosAndSpaceModeActive &&
2349                      m_xRelativeCB->get_sensitive() && m_xRelativeCB->get_active();
2350     const bool bSingleSelection = m_xLevelLB->count_selected_rows() == 1 &&
2351                             SAL_MAX_UINT16 != nActNumLvl;
2352 
2353     m_xDistBorderMF->set_sensitive( !bLabelAlignmentPosAndSpaceModeActive &&
2354                           ( bSingleSelection || bRelative ) );
2355     m_xDistBorderFT->set_sensitive( !bLabelAlignmentPosAndSpaceModeActive &&
2356                           ( bSingleSelection || bRelative ) );
2357 
2358     bool bSetDistEmpty = false;
2359     bool bSameDistBorderNum = !bLabelAlignmentPosAndSpaceModeActive;
2360     bool bSameDist      = !bLabelAlignmentPosAndSpaceModeActive;
2361     bool bSameIndent    = !bLabelAlignmentPosAndSpaceModeActive;
2362     bool bSameAdjust    = true;
2363 
2364     bool bSameLabelFollowedBy = bLabelAlignmentPosAndSpaceModeActive;
2365     bool bSameListtab = bLabelAlignmentPosAndSpaceModeActive;
2366     bool bSameAlignAt = bLabelAlignmentPosAndSpaceModeActive;
2367     bool bSameIndentAt = bLabelAlignmentPosAndSpaceModeActive;
2368 
2369     const SvxNumberFormat* aNumFmtArr[SVX_MAX_NUM];
2370     sal_uInt16 nMask = 1;
2371     sal_uInt16 nLvl = SAL_MAX_UINT16;
2372     tools::Long nFirstBorderTextRelative = -1;
2373     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
2374     {
2375         aNumFmtArr[i] = &pActNum->GetLevel(i);
2376         if(nActNumLvl & nMask)
2377         {
2378             if(SAL_MAX_UINT16 == nLvl)
2379                 nLvl = i;
2380 
2381             if( i > nLvl)
2382             {
2383                 bSameAdjust &= aNumFmtArr[i]->GetNumAdjust() == aNumFmtArr[nLvl]->GetNumAdjust();
2384                 if ( !bLabelAlignmentPosAndSpaceModeActive )
2385                 {
2386                     if(bRelative)
2387                     {
2388                         if(nFirstBorderTextRelative == -1)
2389                             nFirstBorderTextRelative =
2390                             (aNumFmtArr[i]->GetAbsLSpace() + aNumFmtArr[i]->GetFirstLineOffset() -
2391                             aNumFmtArr[i - 1]->GetAbsLSpace() + aNumFmtArr[i - 1]->GetFirstLineOffset());
2392                         else
2393                             bSameDistBorderNum &= nFirstBorderTextRelative ==
2394                             (aNumFmtArr[i]->GetAbsLSpace() + aNumFmtArr[i]->GetFirstLineOffset() -
2395                             aNumFmtArr[i - 1]->GetAbsLSpace() + aNumFmtArr[i - 1]->GetFirstLineOffset());
2396                     }
2397                     else
2398                         bSameDistBorderNum &=
2399                         aNumFmtArr[i]->GetAbsLSpace() - aNumFmtArr[i]->GetFirstLineOffset() ==
2400                         aNumFmtArr[i - 1]->GetAbsLSpace() - aNumFmtArr[i - 1]->GetFirstLineOffset();
2401 
2402                     bSameDist       &= aNumFmtArr[i]->GetCharTextDistance() == aNumFmtArr[nLvl]->GetCharTextDistance();
2403                     bSameIndent     &= aNumFmtArr[i]->GetFirstLineOffset() == aNumFmtArr[nLvl]->GetFirstLineOffset();
2404                 }
2405                 else
2406                 {
2407                     bSameLabelFollowedBy &=
2408                         aNumFmtArr[i]->GetLabelFollowedBy() == aNumFmtArr[nLvl]->GetLabelFollowedBy();
2409                     bSameListtab &=
2410                         aNumFmtArr[i]->GetListtabPos() == aNumFmtArr[nLvl]->GetListtabPos();
2411                     bSameAlignAt &=
2412                         ( ( aNumFmtArr[i]->GetIndentAt() + aNumFmtArr[i]->GetFirstLineIndent() )
2413                             == ( aNumFmtArr[nLvl]->GetIndentAt() + aNumFmtArr[nLvl]->GetFirstLineIndent() ) );
2414                     bSameIndentAt &=
2415                         aNumFmtArr[i]->GetIndentAt() == aNumFmtArr[nLvl]->GetIndentAt();
2416                 }
2417             }
2418         }
2419         nMask <<= 1;
2420 
2421     }
2422     if (SVX_MAX_NUM <= nLvl)
2423     {
2424         OSL_ENSURE(false, "cannot happen.");
2425         return;
2426     }
2427 
2428     if(bSameDistBorderNum)
2429     {
2430         tools::Long nDistBorderNum;
2431         if(bRelative)
2432         {
2433             nDistBorderNum = static_cast<tools::Long>(aNumFmtArr[nLvl]->GetAbsLSpace())+ aNumFmtArr[nLvl]->GetFirstLineOffset();
2434             if(nLvl)
2435                 nDistBorderNum -= static_cast<tools::Long>(aNumFmtArr[nLvl - 1]->GetAbsLSpace())+ aNumFmtArr[nLvl - 1]->GetFirstLineOffset();
2436         }
2437         else
2438         {
2439             nDistBorderNum = static_cast<tools::Long>(aNumFmtArr[nLvl]->GetAbsLSpace())+ aNumFmtArr[nLvl]->GetFirstLineOffset();
2440         }
2441         SetMetricValue(*m_xDistBorderMF, nDistBorderNum, eCoreUnit);
2442     }
2443     else
2444         bSetDistEmpty = true;
2445 
2446     if(bSameDist)
2447         SetMetricValue(*m_xDistNumMF, aNumFmtArr[nLvl]->GetCharTextDistance(), eCoreUnit);
2448     else
2449         m_xDistNumMF->set_text(u""_ustr);
2450     if(bSameIndent)
2451         SetMetricValue(*m_xIndentMF, - aNumFmtArr[nLvl]->GetFirstLineOffset(), eCoreUnit);
2452     else
2453         m_xIndentMF->set_text(u""_ustr);
2454 
2455     if(bSameAdjust)
2456     {
2457         sal_Int32 nPos = 1; // centered
2458         if(aNumFmtArr[nLvl]->GetNumAdjust() == SvxAdjust::Left)
2459             nPos = 0;
2460         else if(aNumFmtArr[nLvl]->GetNumAdjust() == SvxAdjust::Right)
2461             nPos = 2;
2462         m_xAlignLB->set_active(nPos);
2463         m_xAlign2LB->set_active(nPos);
2464     }
2465     else
2466     {
2467         m_xAlignLB->set_active(-1);
2468         m_xAlign2LB->set_active(-1);
2469     }
2470 
2471     if ( bSameLabelFollowedBy )
2472     {
2473         sal_Int32 nPos = 0; // LISTTAB
2474         if ( aNumFmtArr[nLvl]->GetLabelFollowedBy() == SvxNumberFormat::SPACE )
2475         {
2476             nPos = 1;
2477         }
2478         else if ( aNumFmtArr[nLvl]->GetLabelFollowedBy() == SvxNumberFormat::NOTHING )
2479         {
2480             nPos = 2;
2481         }
2482         else if ( aNumFmtArr[nLvl]->GetLabelFollowedBy() == SvxNumberFormat::NEWLINE )
2483         {
2484             nPos = 3;
2485         }
2486         m_xLabelFollowedByLB->set_active(nPos);
2487     }
2488     else
2489     {
2490         m_xLabelFollowedByLB->set_active(-1);
2491     }
2492 
2493     if ( aNumFmtArr[nLvl]->GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
2494     {
2495         m_xListtabFT->set_sensitive(true);
2496         m_xListtabMF->set_sensitive(true);
2497         if ( bSameListtab )
2498         {
2499             SetMetricValue(*m_xListtabMF, aNumFmtArr[nLvl]->GetListtabPos(), eCoreUnit);
2500         }
2501         else
2502         {
2503             m_xListtabMF->set_text(u""_ustr);
2504         }
2505     }
2506     else
2507     {
2508         m_xListtabFT->set_sensitive(false);
2509         m_xListtabMF->set_sensitive(false);
2510         m_xListtabMF->set_text(u""_ustr);
2511     }
2512 
2513     if ( bSameAlignAt )
2514     {
2515         SetMetricValue(*m_xAlignedAtMF,
2516                         aNumFmtArr[nLvl]->GetIndentAt() + aNumFmtArr[nLvl]->GetFirstLineIndent(),
2517                         eCoreUnit);
2518     }
2519     else
2520     {
2521         m_xAlignedAtMF->set_text(u""_ustr);
2522     }
2523 
2524     if ( bSameIndentAt )
2525     {
2526         SetMetricValue(*m_xIndentAtMF, aNumFmtArr[nLvl]->GetIndentAt(), eCoreUnit);
2527     }
2528     else
2529     {
2530         m_xIndentAtMF->set_text(u""_ustr);
2531     }
2532 
2533     if ( bSetDistEmpty )
2534         m_xDistBorderMF->set_text(u""_ustr);
2535 
2536     bInInintControl = false;
2537 }
2538 
ActivatePage(const SfxItemSet & rSet)2539 void SvxNumPositionTabPage::ActivatePage(const SfxItemSet& rSet)
2540 {
2541     sal_uInt16 nTmpNumLvl = 1;
2542     const SfxItemSet* pExampleSet = GetDialogExampleSet();
2543     if(pExampleSet)
2544     {
2545         if(const SfxBoolItem* pPresetItem = pExampleSet->GetItemIfSet(SID_PARAM_NUM_PRESET, false))
2546             bPreset = pPresetItem->GetValue();
2547         if(const SfxUInt16Item* pLevelItem = pExampleSet->GetItemIfSet(SID_PARAM_CUR_NUM_LEVEL, false))
2548             nTmpNumLvl = pLevelItem->GetValue();
2549     }
2550     if(const SvxNumBulletItem* pBulletItem = rSet.GetItemIfSet(nNumItemId, false))
2551     {
2552         pSaveNum.reset( new SvxNumRule(pBulletItem->GetNumRule()) );
2553     }
2554     bModified = (!pActNum->Get( 0 ) || bPreset);
2555     if(*pSaveNum != *pActNum ||
2556         nActNumLvl != nTmpNumLvl )
2557     {
2558         *pActNum = *pSaveNum;
2559         nActNumLvl = nTmpNumLvl;
2560         sal_uInt16 nMask = 1;
2561         m_xLevelLB->unselect_all();
2562         if (nActNumLvl == SAL_MAX_UINT16)
2563             m_xLevelLB->select(pActNum->GetLevelCount());
2564         if (nActNumLvl != SAL_MAX_UINT16)
2565             for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
2566             {
2567                 if (nActNumLvl & nMask)
2568                     m_xLevelLB->select(i);
2569                 nMask <<= 1 ;
2570             }
2571         m_xRelativeCB->set_sensitive(nActNumLvl != 1);
2572 
2573         InitPosAndSpaceMode();
2574         ShowControlsDependingOnPosAndSpaceMode();
2575 
2576         InitControls();
2577     }
2578     m_aPreviewWIN.SetLevel(nActNumLvl);
2579     m_aPreviewWIN.Invalidate();
2580 }
2581 
DeactivatePage(SfxItemSet * _pSet)2582 DeactivateRC SvxNumPositionTabPage::DeactivatePage(SfxItemSet *_pSet)
2583 {
2584     if(_pSet)
2585     {
2586         if (m_xDistBorderMF->get_sensitive())
2587             DistanceHdl_Impl(*m_xDistBorderMF);
2588         DistanceHdl_Impl(*m_xIndentMF);
2589         FillItemSet(_pSet);
2590     }
2591     return DeactivateRC::LeavePage;
2592 }
2593 
FillItemSet(SfxItemSet * rSet)2594 bool SvxNumPositionTabPage::FillItemSet( SfxItemSet* rSet )
2595 {
2596     rSet->Put(SfxUInt16Item(SID_PARAM_CUR_NUM_LEVEL, nActNumLvl));
2597 
2598     if(bModified && pActNum)
2599     {
2600         *pSaveNum = *pActNum;
2601         rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId ));
2602         rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, false));
2603     }
2604     return bModified;
2605 }
2606 
Reset(const SfxItemSet * rSet)2607 void SvxNumPositionTabPage::Reset( const SfxItemSet* rSet )
2608 {
2609     // in Draw the item exists as WhichId, in Writer only as SlotId
2610     const SvxNumBulletItem* pItem =
2611         rSet->GetItemIfSet(SID_ATTR_NUMBERING_RULE, false);
2612     if(!pItem)
2613     {
2614         nNumItemId = rSet->GetPool()->GetWhichIDFromSlotID(SID_ATTR_NUMBERING_RULE);
2615         pItem = rSet->GetItemIfSet(nNumItemId, false);
2616 
2617         if( !pItem )
2618         {
2619             pItem = & rSet->Get( nNumItemId );
2620         }
2621     }
2622     DBG_ASSERT(pItem, "no item found!");
2623     pSaveNum.reset( new SvxNumRule(pItem->GetNumRule()) );
2624 
2625     // insert levels
2626     if (!m_xLevelLB->count_selected_rows())
2627     {
2628         for(sal_uInt16 i = 1; i <= pSaveNum->GetLevelCount(); i++)
2629             m_xLevelLB->append_text(OUString::number(i));
2630         if(pSaveNum->GetLevelCount() > 1)
2631         {
2632             OUString sEntry = "1 - " + OUString::number( pSaveNum->GetLevelCount() );
2633             m_xLevelLB->append_text(sEntry);
2634             m_xLevelLB->select_text(sEntry);
2635         }
2636         else
2637             m_xLevelLB->select(0);
2638     }
2639     else
2640         m_xLevelLB->select(m_xLevelLB->count_selected_rows() - 1);
2641     sal_uInt16 nMask = 1;
2642     m_xLevelLB->unselect_all();
2643     if (nActNumLvl == SAL_MAX_UINT16)
2644     {
2645         m_xLevelLB->select(pSaveNum->GetLevelCount());
2646     }
2647     else
2648     {
2649         for(sal_uInt16 i = 0; i < pSaveNum->GetLevelCount(); i++)
2650         {
2651             if(nActNumLvl & nMask)
2652                 m_xLevelLB->select(i);
2653             nMask <<= 1;
2654         }
2655     }
2656 
2657     if(!pActNum)
2658         pActNum.reset( new SvxNumRule(*pSaveNum) );
2659     else if(*pSaveNum != *pActNum)
2660         *pActNum = *pSaveNum;
2661     m_aPreviewWIN.SetNumRule(pActNum.get());
2662 
2663     InitPosAndSpaceMode();
2664     ShowControlsDependingOnPosAndSpaceMode();
2665 
2666     InitControls();
2667     bModified = false;
2668 }
2669 
InitPosAndSpaceMode()2670 void SvxNumPositionTabPage::InitPosAndSpaceMode()
2671 {
2672     if ( pActNum == nullptr )
2673     {
2674         SAL_WARN( "cui.tabpages",
2675                 "<SvxNumPositionTabPage::InitPosAndSpaceMode()> - misusage of method -> <pAktNum> has to be already set!" );
2676         return;
2677     }
2678 
2679     SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode =
2680                                             SvxNumberFormat::LABEL_ALIGNMENT;
2681     sal_uInt16 nMask = 1;
2682     for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); ++i )
2683     {
2684         if(nActNumLvl & nMask)
2685         {
2686             SvxNumberFormat aNumFmt( pActNum->GetLevel(i) );
2687             ePosAndSpaceMode = aNumFmt.GetPositionAndSpaceMode();
2688             if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
2689             {
2690                 break;
2691             }
2692         }
2693         nMask <<= 1;
2694     }
2695 
2696     bLabelAlignmentPosAndSpaceModeActive =
2697                     ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT;
2698 }
2699 
ShowControlsDependingOnPosAndSpaceMode()2700 void SvxNumPositionTabPage::ShowControlsDependingOnPosAndSpaceMode()
2701 {
2702     m_xDistBorderFT->set_visible( !bLabelAlignmentPosAndSpaceModeActive );
2703     m_xDistBorderMF->set_visible( !bLabelAlignmentPosAndSpaceModeActive );
2704     m_xRelativeCB->set_visible( !bLabelAlignmentPosAndSpaceModeActive );
2705     m_xIndentFT->set_visible( !bLabelAlignmentPosAndSpaceModeActive );
2706     m_xIndentMF->set_visible( !bLabelAlignmentPosAndSpaceModeActive );
2707     m_xDistNumFT->set_visible( !bLabelAlignmentPosAndSpaceModeActive &&
2708                     pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS) );
2709     m_xDistNumMF->set_visible( !bLabelAlignmentPosAndSpaceModeActive &&
2710                     pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS));
2711     m_xAlignFT->set_visible( !bLabelAlignmentPosAndSpaceModeActive );
2712     m_xAlignLB->set_visible( !bLabelAlignmentPosAndSpaceModeActive );
2713 
2714     m_xLabelFollowedByFT->set_visible( bLabelAlignmentPosAndSpaceModeActive );
2715     m_xLabelFollowedByLB->set_visible( bLabelAlignmentPosAndSpaceModeActive );
2716     m_xListtabFT->set_visible( bLabelAlignmentPosAndSpaceModeActive );
2717     m_xListtabMF->set_visible( bLabelAlignmentPosAndSpaceModeActive );
2718     m_xAlign2FT->set_visible( bLabelAlignmentPosAndSpaceModeActive );
2719     m_xAlign2LB->set_visible( bLabelAlignmentPosAndSpaceModeActive );
2720     m_xAlignedAtFT->set_visible( bLabelAlignmentPosAndSpaceModeActive );
2721     m_xAlignedAtMF->set_visible( bLabelAlignmentPosAndSpaceModeActive );
2722     m_xIndentAtFT->set_visible( bLabelAlignmentPosAndSpaceModeActive );
2723     m_xIndentAtMF->set_visible( bLabelAlignmentPosAndSpaceModeActive );
2724 }
2725 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rAttrSet)2726 std::unique_ptr<SfxTabPage> SvxNumPositionTabPage::Create(weld::Container* pPage, weld::DialogController* pController,
2727                                                  const SfxItemSet* rAttrSet)
2728 {
2729     return std::make_unique<SvxNumPositionTabPage>(pPage, pController, *rAttrSet);
2730 }
2731 
SetMetric(FieldUnit eMetric)2732 void SvxNumPositionTabPage::SetMetric(FieldUnit eMetric)
2733 {
2734     if (eMetric == FieldUnit::MM)
2735     {
2736         m_xDistBorderMF->set_digits(1);
2737         m_xDistNumMF->set_digits(1);
2738         m_xIndentMF->set_digits(1);
2739         m_xListtabMF->set_digits(1);
2740         m_xAlignedAtMF->set_digits(1);
2741         m_xIndentAtMF->set_digits(1);
2742     }
2743     m_xDistBorderMF->set_unit(eMetric);
2744     m_xDistNumMF->set_unit(eMetric);
2745     m_xIndentMF->set_unit(eMetric);
2746     m_xListtabMF->set_unit(eMetric);
2747     m_xAlignedAtMF->set_unit(eMetric);
2748     m_xIndentAtMF->set_unit(eMetric);
2749 }
2750 
IMPL_LINK_NOARG(SvxNumPositionTabPage,EditModifyHdl_Impl,weld::ComboBox &,void)2751 IMPL_LINK_NOARG(SvxNumPositionTabPage, EditModifyHdl_Impl, weld::ComboBox&, void)
2752 {
2753     sal_uInt16 nMask = 1;
2754     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
2755     {
2756         if(nActNumLvl & nMask)
2757         {
2758             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
2759 
2760             const sal_Int32 nPos = m_xAlignLB->get_visible()
2761                                 ? m_xAlignLB->get_active()
2762                                 : m_xAlign2LB->get_active();
2763             SvxAdjust eAdjust = SvxAdjust::Center;
2764             if(nPos == 0)
2765                 eAdjust = SvxAdjust::Left;
2766             else if(nPos == 2)
2767                 eAdjust = SvxAdjust::Right;
2768             aNumFmt.SetNumAdjust( eAdjust );
2769             pActNum->SetLevel(i, aNumFmt);
2770         }
2771         nMask <<= 1;
2772     }
2773     SetModified();
2774 }
2775 
IMPL_LINK_NOARG(SvxNumPositionTabPage,LevelHdl_Impl,weld::TreeView &,void)2776 IMPL_LINK_NOARG(SvxNumPositionTabPage, LevelHdl_Impl, weld::TreeView&, void)
2777 {
2778     if (m_pLevelHdlEvent)
2779         return;
2780     // tdf#127120 multiselection may be implemented by deselect follow by select so
2781     // fire off the handler to happen on next event loop and only process the
2782     // final state
2783     m_pLevelHdlEvent = Application::PostUserEvent(LINK(this, SvxNumPositionTabPage, LevelHdl));
2784 }
2785 
IMPL_LINK_NOARG(SvxNumPositionTabPage,LevelHdl,void *,void)2786 IMPL_LINK_NOARG(SvxNumPositionTabPage, LevelHdl, void*, void)
2787 {
2788     m_pLevelHdlEvent = nullptr;
2789 
2790     sal_uInt16 nSaveNumLvl = nActNumLvl;
2791     nActNumLvl = 0;
2792     std::vector<int> aSelectedRows = m_xLevelLB->get_selected_rows();
2793     if (std::find(aSelectedRows.begin(), aSelectedRows.end(), pActNum->GetLevelCount()) != aSelectedRows.end() &&
2794             (aSelectedRows.size() == 1 || nSaveNumLvl != 0xffff))
2795     {
2796         nActNumLvl = 0xFFFF;
2797         for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ )
2798             m_xLevelLB->unselect(i);
2799     }
2800     else if (!aSelectedRows.empty())
2801     {
2802         sal_uInt16 nMask = 1;
2803         for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ )
2804         {
2805             if (std::find(aSelectedRows.begin(), aSelectedRows.end(), i) != aSelectedRows.end())
2806                 nActNumLvl |= nMask;
2807             nMask <<= 1;
2808         }
2809         m_xLevelLB->unselect(pActNum->GetLevelCount());
2810     }
2811     else
2812     {
2813         nActNumLvl = nSaveNumLvl;
2814         sal_uInt16 nMask = 1;
2815         for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ )
2816         {
2817             if(nActNumLvl & nMask)
2818             {
2819                 m_xLevelLB->select(i);
2820                 break;
2821             }
2822             nMask <<=1;
2823         }
2824     }
2825     m_xRelativeCB->set_sensitive(nActNumLvl != 1);
2826     SetModified();
2827     InitPosAndSpaceMode();
2828     ShowControlsDependingOnPosAndSpaceMode();
2829     InitControls();
2830 }
2831 
IMPL_LINK(SvxNumPositionTabPage,DistanceHdl_Impl,weld::MetricSpinButton &,rFld,void)2832 IMPL_LINK(SvxNumPositionTabPage, DistanceHdl_Impl, weld::MetricSpinButton&, rFld, void)
2833 {
2834     if(bInInintControl)
2835         return;
2836     tools::Long nValue = GetCoreValue(rFld, eCoreUnit);
2837     sal_uInt16 nMask = 1;
2838     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
2839     {
2840         if(nActNumLvl & nMask)
2841         {
2842             SvxNumberFormat aNumFmt( pActNum->GetLevel( i ) );
2843             if (&rFld == m_xDistBorderMF.get())
2844             {
2845 
2846                 if (m_xRelativeCB->get_active())
2847                 {
2848                     if(0 == i)
2849                     {
2850                         auto const nTmp = aNumFmt.GetFirstLineOffset();
2851                         aNumFmt.SetAbsLSpace( nValue - nTmp);
2852                     }
2853                     else
2854                     {
2855                         tools::Long nTmp = pActNum->GetLevel( i - 1 ).GetAbsLSpace() +
2856                                     pActNum->GetLevel( i - 1 ).GetFirstLineOffset() -
2857                                     pActNum->GetLevel( i ).GetFirstLineOffset();
2858 
2859                         aNumFmt.SetAbsLSpace( nValue + nTmp);
2860                     }
2861                 }
2862                 else
2863                 {
2864                     aNumFmt.SetAbsLSpace( nValue - aNumFmt.GetFirstLineOffset());
2865                 }
2866             }
2867             else if (&rFld == m_xDistNumMF.get())
2868             {
2869                 aNumFmt.SetCharTextDistance( static_cast<short>(nValue) );
2870             }
2871             else if (&rFld == m_xIndentMF.get())
2872             {
2873                 // together with the FirstLineOffset the AbsLSpace must be changed, too
2874                 tools::Long nDiff = nValue + aNumFmt.GetFirstLineOffset();
2875                 auto const nAbsLSpace = aNumFmt.GetAbsLSpace();
2876                 aNumFmt.SetAbsLSpace(nAbsLSpace + nDiff);
2877                 aNumFmt.SetFirstLineOffset( -nValue );
2878             }
2879 
2880             pActNum->SetLevel( i, aNumFmt );
2881         }
2882         nMask <<= 1;
2883     }
2884 
2885     SetModified();
2886     if (!m_xDistBorderMF->get_sensitive())
2887     {
2888         m_xDistBorderMF->set_text(u""_ustr);
2889     }
2890 }
2891 
IMPL_LINK(SvxNumPositionTabPage,RelativeHdl_Impl,weld::Toggleable &,rBox,void)2892 IMPL_LINK(SvxNumPositionTabPage, RelativeHdl_Impl, weld::Toggleable&, rBox, void)
2893 {
2894     bool bOn = rBox.get_active();
2895     bool bSingleSelection = m_xLevelLB->count_selected_rows() == 1 && SAL_MAX_UINT16 != nActNumLvl;
2896     bool bSetValue = false;
2897     tools::Long nValue = 0;
2898     if(bOn || bSingleSelection)
2899     {
2900         sal_uInt16 nMask = 1;
2901         bool bFirst = true;
2902         bSetValue = true;
2903         for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
2904         {
2905             if(nActNumLvl & nMask)
2906             {
2907                 const SvxNumberFormat &rNumFmt = pActNum->GetLevel(i);
2908                 if(bFirst)
2909                 {
2910                     nValue = rNumFmt.GetAbsLSpace() + rNumFmt.GetFirstLineOffset();
2911                     if(bOn && i)
2912                         nValue -= (pActNum->GetLevel(i - 1).GetAbsLSpace() + pActNum->GetLevel(i - 1).GetFirstLineOffset());
2913                 }
2914                 else
2915                     bSetValue = nValue ==
2916                         (rNumFmt.GetAbsLSpace() + rNumFmt.GetFirstLineOffset()) -
2917                             (pActNum->GetLevel(i - 1).GetAbsLSpace() + pActNum->GetLevel(i - 1).GetFirstLineOffset());
2918                 bFirst = false;
2919             }
2920             nMask <<= 1;
2921         }
2922 
2923     }
2924     if(bSetValue)
2925         SetMetricValue(*m_xDistBorderMF, nValue,   eCoreUnit);
2926     else
2927         m_xDistBorderMF->set_text(u""_ustr);
2928     m_xDistBorderMF->set_sensitive(bOn || bSingleSelection);
2929     m_xDistBorderFT->set_sensitive(bOn || bSingleSelection);
2930     bLastRelative = bOn;
2931 }
2932 
IMPL_LINK_NOARG(SvxNumPositionTabPage,LabelFollowedByHdl_Impl,weld::ComboBox &,void)2933 IMPL_LINK_NOARG(SvxNumPositionTabPage, LabelFollowedByHdl_Impl, weld::ComboBox&, void)
2934 {
2935     // determine value to be set at the chosen list levels
2936     SvxNumberFormat::LabelFollowedBy eLabelFollowedBy = SvxNumberFormat::LISTTAB;
2937     {
2938         const auto nPos = m_xLabelFollowedByLB->get_active();
2939         if ( nPos == 1 )
2940         {
2941             eLabelFollowedBy = SvxNumberFormat::SPACE;
2942         }
2943         else if ( nPos == 2 )
2944         {
2945             eLabelFollowedBy = SvxNumberFormat::NOTHING;
2946         }
2947         else if ( nPos == 3 )
2948         {
2949             eLabelFollowedBy = SvxNumberFormat::NEWLINE;
2950         }
2951     }
2952 
2953     // set value at the chosen list levels
2954     bool bSameListtabPos = true;
2955     sal_uInt16 nFirstLvl = SAL_MAX_UINT16;
2956     sal_uInt16 nMask = 1;
2957     for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); ++i )
2958     {
2959         if ( nActNumLvl & nMask )
2960         {
2961             SvxNumberFormat aNumFmt( pActNum->GetLevel(i) );
2962             aNumFmt.SetLabelFollowedBy( eLabelFollowedBy );
2963             pActNum->SetLevel( i, aNumFmt );
2964 
2965             if ( nFirstLvl == SAL_MAX_UINT16 )
2966             {
2967                 nFirstLvl = i;
2968             }
2969             else
2970             {
2971                 bSameListtabPos &= aNumFmt.GetListtabPos() ==
2972                         pActNum->GetLevel( nFirstLvl ).GetListtabPos();
2973             }
2974         }
2975         nMask <<= 1;
2976     }
2977 
2978     // enable/disable metric field for list tab stop position depending on
2979     // selected item following the list label.
2980     m_xListtabFT->set_sensitive( eLabelFollowedBy == SvxNumberFormat::LISTTAB );
2981     m_xListtabMF->set_sensitive( eLabelFollowedBy == SvxNumberFormat::LISTTAB );
2982     if ( bSameListtabPos && eLabelFollowedBy == SvxNumberFormat::LISTTAB )
2983     {
2984         SetMetricValue(*m_xListtabMF, pActNum->GetLevel( nFirstLvl ).GetListtabPos(), eCoreUnit);
2985     }
2986     else
2987     {
2988         m_xListtabMF->set_text(OUString());
2989     }
2990 
2991     SetModified();
2992 }
2993 
IMPL_LINK(SvxNumPositionTabPage,ListtabPosHdl_Impl,weld::MetricSpinButton &,rFld,void)2994 IMPL_LINK(SvxNumPositionTabPage, ListtabPosHdl_Impl, weld::MetricSpinButton&, rFld, void)
2995 {
2996     // determine value to be set at the chosen list levels
2997     const tools::Long nValue = GetCoreValue(rFld, eCoreUnit);
2998 
2999     // set value at the chosen list levels
3000     sal_uInt16 nMask = 1;
3001     for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); ++i )
3002     {
3003         if ( nActNumLvl & nMask )
3004         {
3005             SvxNumberFormat aNumFmt( pActNum->GetLevel(i) );
3006             aNumFmt.SetListtabPos( nValue );
3007             pActNum->SetLevel( i, aNumFmt );
3008         }
3009         nMask <<= 1;
3010     }
3011 
3012     SetModified();
3013 }
3014 
IMPL_LINK(SvxNumPositionTabPage,AlignAtHdl_Impl,weld::MetricSpinButton &,rFld,void)3015 IMPL_LINK(SvxNumPositionTabPage, AlignAtHdl_Impl, weld::MetricSpinButton&, rFld, void)
3016 {
3017     // determine value to be set at the chosen list levels
3018     const tools::Long nValue = GetCoreValue(rFld, eCoreUnit);
3019 
3020     // set value at the chosen list levels
3021     sal_uInt16 nMask = 1;
3022     for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); ++i )
3023     {
3024         if ( nActNumLvl & nMask )
3025         {
3026             SvxNumberFormat aNumFmt( pActNum->GetLevel(i) );
3027             const tools::Long nFirstLineIndent = nValue - aNumFmt.GetIndentAt();
3028             aNumFmt.SetFirstLineIndent( nFirstLineIndent );
3029             pActNum->SetLevel( i, aNumFmt );
3030         }
3031         nMask <<= 1;
3032     }
3033 
3034     SetModified();
3035 }
3036 
IMPL_LINK(SvxNumPositionTabPage,IndentAtHdl_Impl,weld::MetricSpinButton &,rFld,void)3037 IMPL_LINK(SvxNumPositionTabPage, IndentAtHdl_Impl, weld::MetricSpinButton&, rFld, void)
3038 {
3039     // determine value to be set at the chosen list levels
3040     const tools::Long nValue = GetCoreValue(rFld, eCoreUnit);
3041 
3042     // set value at the chosen list levels
3043     sal_uInt16 nMask = 1;
3044     for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); ++i )
3045     {
3046         if ( nActNumLvl & nMask )
3047         {
3048             SvxNumberFormat aNumFmt( pActNum->GetLevel(i) );
3049             const tools::Long nAlignedAt = aNumFmt.GetIndentAt() +
3050                                     aNumFmt.GetFirstLineIndent();
3051             aNumFmt.SetIndentAt( nValue );
3052             const tools::Long nNewFirstLineIndent = nAlignedAt - nValue;
3053             aNumFmt.SetFirstLineIndent( nNewFirstLineIndent );
3054             pActNum->SetLevel( i, aNumFmt );
3055         }
3056         nMask <<= 1;
3057     }
3058 
3059     SetModified();
3060 }
3061 
IMPL_LINK_NOARG(SvxNumPositionTabPage,StandardHdl_Impl,weld::Button &,void)3062 IMPL_LINK_NOARG(SvxNumPositionTabPage, StandardHdl_Impl, weld::Button&, void)
3063 {
3064     sal_uInt16 nMask = 1;
3065     SvxNumRule aTmpNumRule( pActNum->GetFeatureFlags(),
3066                             pActNum->GetLevelCount(),
3067                             pActNum->IsContinuousNumbering(),
3068                             SvxNumRuleType::NUMBERING,
3069                             pActNum->GetLevel( 0 ).GetPositionAndSpaceMode() );
3070     for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
3071     {
3072         if(nActNumLvl & nMask)
3073         {
3074             SvxNumberFormat aNumFmt( pActNum->GetLevel( i ) );
3075             const SvxNumberFormat& aTempFmt(aTmpNumRule.GetLevel( i ));
3076             aNumFmt.SetPositionAndSpaceMode( aTempFmt.GetPositionAndSpaceMode() );
3077             if ( aTempFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
3078             {
3079                 aNumFmt.SetAbsLSpace( aTempFmt.GetAbsLSpace() );
3080                 aNumFmt.SetCharTextDistance( aTempFmt.GetCharTextDistance() );
3081                 aNumFmt.SetFirstLineOffset( aTempFmt.GetFirstLineOffset() );
3082             }
3083             else if ( aTempFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
3084             {
3085                 aNumFmt.SetNumAdjust( aTempFmt.GetNumAdjust() );
3086                 aNumFmt.SetLabelFollowedBy( aTempFmt.GetLabelFollowedBy() );
3087                 aNumFmt.SetListtabPos( aTempFmt.GetListtabPos() );
3088                 aNumFmt.SetFirstLineIndent( aTempFmt.GetFirstLineIndent() );
3089                 aNumFmt.SetIndentAt( aTempFmt.GetIndentAt() );
3090             }
3091 
3092             pActNum->SetLevel( i, aNumFmt );
3093         }
3094         nMask <<= 1;
3095     }
3096 
3097     InitControls();
3098     SetModified();
3099 }
3100 
SetModified()3101 void SvxNumPositionTabPage::SetModified()
3102 {
3103     bModified = true;
3104     m_aPreviewWIN.SetLevel(nActNumLvl);
3105     m_aPreviewWIN.Invalidate();
3106 }
3107 
SetModified(bool bRepaint)3108 void SvxNumOptionsTabPage::SetModified(bool bRepaint)
3109 {
3110     bModified = true;
3111     if (bRepaint)
3112     {
3113         m_aPreviewWIN.SetLevel(nActNumLvl);
3114         m_aPreviewWIN.Invalidate();
3115     }
3116 }
3117 
PageCreated(const SfxAllItemSet & aSet)3118 void SvxNumOptionsTabPage::PageCreated(const SfxAllItemSet& aSet)
3119 {
3120     const SfxStringListItem* pListItem = aSet.GetItem<SfxStringListItem>(SID_CHAR_FMT_LIST_BOX, false);
3121     const SfxStringItem* pNumCharFmt = aSet.GetItem<SfxStringItem>(SID_NUM_CHAR_FMT, false);
3122     const SfxStringItem* pBulletCharFmt = aSet.GetItem<SfxStringItem>(SID_BULLET_CHAR_FMT, false);
3123     const SfxUInt16Item* pMetricItem = aSet.GetItem<SfxUInt16Item>(SID_METRIC_ITEM, false);
3124 
3125     if (pNumCharFmt &&pBulletCharFmt)
3126         SetCharFmts( pNumCharFmt->GetValue(),pBulletCharFmt->GetValue());
3127 
3128     if (pListItem)
3129     {
3130         const std::vector<OUString> &aList = pListItem->GetList();
3131         for (const auto& rItem : aList)
3132             m_xCharFmtLB->append_text(rItem);
3133     }
3134     if (pMetricItem)
3135         SetMetric(static_cast<FieldUnit>(pMetricItem->GetValue()));
3136 }
3137 
PageCreated(const SfxAllItemSet & aSet)3138 void SvxNumPositionTabPage::PageCreated(const SfxAllItemSet& aSet)
3139 {
3140     const SfxUInt16Item* pMetricItem = aSet.GetItem<SfxUInt16Item>(SID_METRIC_ITEM, false);
3141 
3142     if (pMetricItem)
3143         SetMetric(static_cast<FieldUnit>(pMetricItem->GetValue()));
3144 }
3145 
3146 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
3147