xref: /core/sd/source/ui/dlg/BulletAndPositionDlg.cxx (revision c91ec113)
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 <tools/mapunit.hxx>
21 #include <tools/urlobj.hxx>
22 #include <editeng/numitem.hxx>
23 #include <svl/eitem.hxx>
24 #include <svl/itempool.hxx>
25 #include <svx/colorbox.hxx>
26 #include <svx/strarray.hxx>
27 #include <svx/gallery.hxx>
28 #include <editeng/brushitem.hxx>
29 #include <svl/intitem.hxx>
30 #include <vcl/graph.hxx>
31 #include <svtools/unitconv.hxx>
32 #include <svx/svxids.hrc>
33 
34 #include <algorithm>
35 #include <memory>
36 #include <vector>
37 #include <sfx2/opengrf.hxx>
38 
39 #include <strings.hrc>
40 #include <svl/stritem.hxx>
41 #include <sal/log.hxx>
42 #include <vcl/virdev.hxx>
43 #include <svx/SvxNumOptionsTabPageHelper.hxx>
44 #include <View.hxx>
45 #include <drawdoc.hxx>
46 #include <cui/cuicharmap.hxx>
47 #include <BulletAndPositionDlg.hxx>
48 #include <sdresid.hxx>
49 #include <DrawViewShell.hxx>
50 
51 #define SHOW_NUMBERING 0
52 #define SHOW_BULLET 1
53 #define SHOW_BITMAP 2
54 
55 #define MAX_BMP_WIDTH 16
56 #define MAX_BMP_HEIGHT 16
57 
58 static bool bLastRelative = false;
59 
60 static const vcl::Font& lcl_GetDefaultBulletFont()
61 {
62     static vcl::Font aDefBulletFont = []() {
63         vcl::Font tmp("OpenSymbol", "", Size(0, 14));
64         tmp.SetCharSet(RTL_TEXTENCODING_SYMBOL);
65         tmp.SetFamily(FAMILY_DONTKNOW);
66         tmp.SetPitch(PITCH_DONTKNOW);
67         tmp.SetWeight(WEIGHT_DONTKNOW);
68         tmp.SetTransparent(true);
69         return tmp;
70     }();
71     return aDefBulletFont;
72 }
73 
74 class SdDrawDocument;
75 
76 SvxBulletAndPositionDlg::SvxBulletAndPositionDlg(weld::Window* pWindow, const SfxItemSet& rSet,
77                                                  const ::sd::View* pView)
78     : GenericDialogController(pWindow, "cui/ui/bulletandposition.ui", "BulletAndPosition")
79     , aInvalidateTimer("sd SvxBulletAndPositionDlg aInvalidateTimer")
80     , rFirstStateSet(rSet)
81     , bLastWidthModified(false)
82     , bModified(false)
83     , bInInitControl(false)
84     , bLabelAlignmentPosAndSpaceModeActive(false)
85     , bApplyToMaster(false)
86     , nBullet(0xff)
87     , nActNumLvl(1)
88     , p_Window(pWindow)
89     , nNumItemId(SID_ATTR_NUMBERING_RULE)
90     , m_xGrid(m_xBuilder->weld_widget("grid2"))
91     , m_xLevelLB(m_xBuilder->weld_tree_view("levellb"))
92     , m_xFmtLB(m_xBuilder->weld_combo_box("numfmtlb"))
93     , m_xPrefixFT(m_xBuilder->weld_label("prefixft"))
94     , m_xPrefixED(m_xBuilder->weld_entry("prefix"))
95     , m_xSuffixFT(m_xBuilder->weld_label("suffixft"))
96     , m_xSuffixED(m_xBuilder->weld_entry("suffix"))
97     , m_xBeforeAfter(m_xBuilder->weld_frame("beforeafter"))
98     , m_xBulColorFT(m_xBuilder->weld_label("colorft"))
99     , m_xBulColLB(new ColorListBox(m_xBuilder->weld_menu_button("color"),
100                                    [this] { return m_xDialog.get(); }))
101     , m_xBulRelSizeFT(m_xBuilder->weld_label("relsizeft"))
102     , m_xBulRelSizeMF(m_xBuilder->weld_metric_spin_button("relsize", FieldUnit::PERCENT))
103     , m_xStartFT(m_xBuilder->weld_label("startatft"))
104     , m_xStartED(m_xBuilder->weld_spin_button("startat"))
105     , m_xBulletFT(m_xBuilder->weld_label("bulletft"))
106     , m_xBulletPB(m_xBuilder->weld_button("bullet"))
107     , m_xBitmapMB(m_xBuilder->weld_menu_button("bitmap"))
108     , m_xWidthFT(m_xBuilder->weld_label("widthft"))
109     , m_xWidthMF(m_xBuilder->weld_metric_spin_button("widthmf", FieldUnit::CM))
110     , m_xHeightFT(m_xBuilder->weld_label("heightft"))
111     , m_xHeightMF(m_xBuilder->weld_metric_spin_button("heightmf", FieldUnit::CM))
112     , m_xRatioCB(m_xBuilder->weld_check_button("keepratio"))
113     , m_xPreviewWIN(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWIN))
114     , m_xDistBorderFT(m_xBuilder->weld_label("indent"))
115     , m_xDistBorderMF(m_xBuilder->weld_metric_spin_button("indentmf", FieldUnit::CM))
116     , m_xRelativeCB(m_xBuilder->weld_check_button("relative"))
117     , m_xIndentMF(m_xBuilder->weld_metric_spin_button("numberingwidthmf", FieldUnit::CM))
118     , m_xLeftTB(m_xBuilder->weld_toggle_button("left"))
119     , m_xCenterTB(m_xBuilder->weld_toggle_button("center"))
120     , m_xRightTB(m_xBuilder->weld_toggle_button("right"))
121     , m_xSlideRB(m_xBuilder->weld_radio_button("sliderb"))
122     , m_xSelectionRB(m_xBuilder->weld_radio_button("selectionrb"))
123     , m_xApplyToMaster(m_xBuilder->weld_toggle_button("applytomaster"))
124     , m_xReset(m_xBuilder->weld_button("reset"))
125 {
126     m_xBulColLB->SetSlotId(SID_ATTR_CHAR_COLOR);
127     m_xBulRelSizeMF->set_min(SVX_NUM_REL_SIZE_MIN, FieldUnit::PERCENT);
128     m_xBulRelSizeMF->set_increments(5, 50, FieldUnit::PERCENT);
129     aActBulletFont = lcl_GetDefaultBulletFont();
130 
131     m_xBulletPB->connect_clicked(LINK(this, SvxBulletAndPositionDlg, BulletHdl_Impl));
132     m_xFmtLB->connect_changed(LINK(this, SvxBulletAndPositionDlg, NumberTypeSelectHdl_Impl));
133     m_xBitmapMB->connect_selected(LINK(this, SvxBulletAndPositionDlg, GraphicHdl_Impl));
134     m_xBitmapMB->connect_toggled(LINK(this, SvxBulletAndPositionDlg, PopupActivateHdl_Impl));
135     m_xLevelLB->set_selection_mode(SelectionMode::Multiple);
136     m_xLevelLB->connect_changed(LINK(this, SvxBulletAndPositionDlg, LevelHdl_Impl));
137     m_xWidthMF->connect_value_changed(LINK(this, SvxBulletAndPositionDlg, SizeHdl_Impl));
138     m_xHeightMF->connect_value_changed(LINK(this, SvxBulletAndPositionDlg, SizeHdl_Impl));
139     m_xRatioCB->connect_toggled(LINK(this, SvxBulletAndPositionDlg, RatioHdl_Impl));
140     m_xStartED->connect_value_changed(LINK(this, SvxBulletAndPositionDlg, SpinModifyHdl_Impl));
141     m_xPrefixED->connect_changed(LINK(this, SvxBulletAndPositionDlg, EditModifyHdl_Impl));
142     m_xSuffixED->connect_changed(LINK(this, SvxBulletAndPositionDlg, EditModifyHdl_Impl));
143     m_xBulRelSizeMF->connect_value_changed(LINK(this, SvxBulletAndPositionDlg, BulRelSizeHdl_Impl));
144     m_xBulColLB->SetSelectHdl(LINK(this, SvxBulletAndPositionDlg, BulColorHdl_Impl));
145     m_xLeftTB->connect_toggled(LINK(this, SvxBulletAndPositionDlg, SelectLeftAlignmentHdl_Impl));
146     m_xCenterTB->connect_toggled(
147         LINK(this, SvxBulletAndPositionDlg, SelectCenterAlignmentHdl_Impl));
148     m_xRightTB->connect_toggled(LINK(this, SvxBulletAndPositionDlg, SelectRightAlignmentHdl_Impl));
149     m_xApplyToMaster->connect_toggled(LINK(this, SvxBulletAndPositionDlg, ApplyToMasterHdl_Impl));
150     m_xReset->connect_clicked(LINK(this, SvxBulletAndPositionDlg, ResetHdl_Impl));
151 
152     aInvalidateTimer.SetInvokeHandler(
153         LINK(this, SvxBulletAndPositionDlg, PreviewInvalidateHdl_Impl));
154     aInvalidateTimer.SetTimeout(50);
155 
156     eCoreUnit = rSet.GetPool()->GetMetric(rSet.GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE));
157 
158     // Fill ListBox with predefined / translated numbering types.
159     sal_uInt32 nCount = SvxNumberingTypeTable::Count();
160     for (sal_uInt32 i = 0; i < nCount; ++i)
161     {
162         m_xFmtLB->append(OUString::number(SvxNumberingTypeTable::GetValue(i)),
163                          SvxNumberingTypeTable::GetString(i));
164     }
165 
166     // Get advanced numbering types from the component.
167     // Watch out for the ugly
168     // 136 == 0x88 == SVX_NUM_BITMAP|0x80 == SVX_NUM_BITMAP|LINK_TOKEN
169     // to not remove that.
170     SvxNumOptionsTabPageHelper::GetI18nNumbering(*m_xFmtLB, (SVX_NUM_BITMAP | LINK_TOKEN));
171 
172     m_xFmtLB->set_active(0);
173     m_xRelativeCB->set_active(true);
174 
175     Link<weld::MetricSpinButton&, void> aLk3
176         = LINK(this, SvxBulletAndPositionDlg, DistanceHdl_Impl);
177     m_xDistBorderMF->connect_value_changed(aLk3);
178     m_xIndentMF->connect_value_changed(aLk3);
179 
180     m_xRelativeCB->connect_toggled(LINK(this, SvxBulletAndPositionDlg, RelativeHdl_Impl));
181     m_xRelativeCB->set_active(bLastRelative);
182 
183     Size aSize(m_xGrid->get_preferred_size());
184     m_xGrid->set_size_request(aSize.Width(), -1);
185 
186     // PageCreated
187     FieldUnit eMetric = pView->GetDoc().GetUIUnit();
188     SfxAllItemSet aSet(*(rSet.GetPool()));
189     aSet.Put(SfxUInt16Item(SID_METRIC_ITEM, static_cast<sal_uInt16>(eMetric)));
190 
191     const SfxStringItem* pNumCharFmt = aSet.GetItem<SfxStringItem>(SID_NUM_CHAR_FMT, false);
192     const SfxUInt16Item* pMetricItem = aSet.GetItem<SfxUInt16Item>(SID_METRIC_ITEM, false);
193 
194     if (pNumCharFmt)
195         SetCharFmt(pNumCharFmt->GetValue());
196 
197     if (pMetricItem)
198         SetMetric(static_cast<FieldUnit>(pMetricItem->GetValue()));
199 
200     // tdf#130526: Hide "Apply To Master"-button in Draw and rename "Slide" to "Page"
201     DocumentType aDocumentType = pView->GetDoc().GetDocumentType();
202     if (aDocumentType == DocumentType::Draw)
203     {
204         m_xApplyToMaster->hide();
205         m_xSlideRB->set_label(SdResId(STR_PAGE_NAME));
206     }
207     // tdf#137406: Crash when clicking "Apply to Master" in Slide Master mode on Bullets and Numbering dialog
208     EditMode aEditmode = static_cast<::sd::DrawViewShell*>(pView->GetViewShell())->GetEditMode();
209     if (aDocumentType == DocumentType::Impress && aEditmode == EditMode::MasterPage)
210         m_xApplyToMaster->hide();
211 
212     // End PageCreated
213 
214     Reset(&rSet);
215 
216     // ActivatePage part
217 
218     const SfxItemSet* pExampleSet = &rSet;
219     sal_uInt16 nTmpNumLvl = 1;
220     bool bPreset = false;
221     if (pExampleSet)
222     {
223         if (const SfxBoolItem* pItem = pExampleSet->GetItemIfSet(SID_PARAM_NUM_PRESET, false))
224             bPreset = pItem->GetValue();
225         if (const SfxUInt16Item* pItem = pExampleSet->GetItemIfSet(SID_PARAM_CUR_NUM_LEVEL, false))
226             nTmpNumLvl = pItem->GetValue();
227     }
228     if (const SvxNumBulletItem* pItem = rSet.GetItemIfSet(nNumItemId, false))
229     {
230         pSaveNum.reset(new SvxNumRule(pItem->GetNumRule()));
231     }
232 
233     bModified = (!pActNum->Get(0) || bPreset);
234     if (*pActNum != *pSaveNum || nActNumLvl != nTmpNumLvl)
235     {
236         nActNumLvl = nTmpNumLvl;
237         sal_uInt16 nMask = 1;
238         if (nActNumLvl == SAL_MAX_UINT16)
239             m_xLevelLB->select(pActNum->GetLevelCount());
240         if (nActNumLvl != SAL_MAX_UINT16)
241         {
242             for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
243             {
244                 if (nActNumLvl & nMask)
245                     m_xLevelLB->select(i);
246                 nMask <<= 1;
247             }
248         }
249         *pActNum = *pSaveNum;
250 
251         m_xRelativeCB->set_sensitive(nActNumLvl != 1);
252 
253         InitPosAndSpaceMode();
254         InitControls();
255     }
256 
257     m_aPreviewWIN.SetLevel(nActNumLvl);
258     m_aPreviewWIN.Invalidate();
259 
260     // End of the ActivatePage part
261 }
262 
263 SvxBulletAndPositionDlg::~SvxBulletAndPositionDlg() {}
264 
265 void SvxBulletAndPositionDlg::SetMetric(FieldUnit eMetric)
266 {
267     if (eMetric == FieldUnit::MM)
268     {
269         m_xWidthMF->set_digits(1);
270         m_xHeightMF->set_digits(1);
271         m_xDistBorderMF->set_digits(1);
272         m_xIndentMF->set_digits(1);
273     }
274     m_xWidthMF->set_unit(eMetric);
275     m_xHeightMF->set_unit(eMetric);
276     m_xDistBorderMF->set_unit(eMetric);
277     m_xIndentMF->set_unit(eMetric);
278 }
279 
280 SfxItemSet* SvxBulletAndPositionDlg::GetOutputItemSet(SfxItemSet* pSet)
281 {
282     pSet->Put(SfxUInt16Item(SID_PARAM_CUR_NUM_LEVEL, nActNumLvl));
283     if (bModified && pActNum)
284     {
285         *pSaveNum = *pActNum;
286         pSet->Put(SvxNumBulletItem(*pSaveNum, nNumItemId));
287         pSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, false));
288     }
289     return pSet;
290 };
291 
292 bool SvxBulletAndPositionDlg::IsApplyToMaster() const { return bApplyToMaster; }
293 bool SvxBulletAndPositionDlg::IsSlideScope() const { return m_xSlideRB->get_active(); }
294 
295 void SvxBulletAndPositionDlg::Reset(const SfxItemSet* rSet)
296 {
297     const SvxNumBulletItem* pItem = rSet->GetItemIfSet(SID_ATTR_NUMBERING_RULE, false);
298     // in Draw the item exists as WhichId, in Writer only as SlotId
299     if (!pItem)
300     {
301         nNumItemId = rSet->GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE);
302         pItem = rSet->GetItemIfSet(nNumItemId, false);
303 
304         if (!pItem)
305         {
306             pItem = &rSet->Get(nNumItemId);
307         }
308     }
309     DBG_ASSERT(pItem, "no item found!");
310     pSaveNum.reset(new SvxNumRule(pItem->GetNumRule()));
311 
312     // insert levels
313     if (!m_xLevelLB->n_children())
314     {
315         for (sal_uInt16 i = 1; i <= pSaveNum->GetLevelCount(); i++)
316             m_xLevelLB->append_text(OUString::number(i));
317         if (pSaveNum->GetLevelCount() > 1)
318         {
319             OUString sEntry = "1 - " + OUString::number(pSaveNum->GetLevelCount());
320             m_xLevelLB->append_text(sEntry);
321             m_xLevelLB->select_text(sEntry);
322         }
323         else
324             m_xLevelLB->select(0);
325     }
326     else
327         m_xLevelLB->select(m_xLevelLB->n_children() - 1);
328 
329     sal_uInt16 nMask = 1;
330     m_xLevelLB->unselect_all();
331     if (nActNumLvl == SAL_MAX_UINT16)
332     {
333         m_xLevelLB->select(pSaveNum->GetLevelCount());
334     }
335     else
336     {
337         for (sal_uInt16 i = 0; i < pSaveNum->GetLevelCount(); i++)
338         {
339             if (nActNumLvl & nMask)
340                 m_xLevelLB->select(i);
341             nMask <<= 1;
342         }
343     }
344 
345     if (!pActNum)
346         pActNum.reset(new SvxNumRule(*pSaveNum));
347     else if (*pSaveNum != *pActNum)
348         *pActNum = *pSaveNum;
349     m_aPreviewWIN.SetNumRule(pActNum.get());
350 
351     bool bContinuous = pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS);
352 
353     // again misusage: in Draw there is numeration only until the bitmap
354     // without SVX_NUM_NUMBER_NONE
355     //remove types that are unsupported by Draw/Impress
356     if (!bContinuous)
357     {
358         sal_Int32 nFmtCount = m_xFmtLB->get_count();
359         for (sal_Int32 i = nFmtCount; i; i--)
360         {
361             sal_uInt16 nEntryData = m_xFmtLB->get_id(i - 1).toUInt32();
362             if (/*SVX_NUM_NUMBER_NONE == nEntryData ||*/
363                 (SVX_NUM_BITMAP | LINK_TOKEN) == nEntryData)
364                 m_xFmtLB->remove(i - 1);
365         }
366     }
367     //one must be enabled
368     if (!pActNum->IsFeatureSupported(SvxNumRuleFlags::ENABLE_LINKED_BMP))
369     {
370         auto nPos = m_xFmtLB->find_id(OUString::number(SVX_NUM_BITMAP | LINK_TOKEN));
371         if (nPos != -1)
372             m_xFmtLB->remove(nPos);
373     }
374     else if (!pActNum->IsFeatureSupported(SvxNumRuleFlags::ENABLE_EMBEDDED_BMP))
375     {
376         auto nPos = m_xFmtLB->find_id(OUString::number(SVX_NUM_BITMAP));
377         if (nPos != -1)
378             m_xFmtLB->remove(nPos);
379     }
380 
381     // MegaHack: because of a not-fixable 'design mistake/error' in Impress
382     // delete all kinds of numeric enumerations
383     if (pActNum->IsFeatureSupported(SvxNumRuleFlags::NO_NUMBERS))
384     {
385         sal_Int32 nFmtCount = m_xFmtLB->get_count();
386         for (sal_Int32 i = nFmtCount; i; i--)
387         {
388             sal_uInt16 nEntryData = m_xFmtLB->get_id(i - 1).toUInt32();
389             if (/*nEntryData >= SVX_NUM_CHARS_UPPER_LETTER &&*/ nEntryData <= SVX_NUM_NUMBER_NONE)
390                 m_xFmtLB->remove(i - 1);
391         }
392     }
393 
394     InitPosAndSpaceMode();
395 
396     InitControls();
397     bModified = false;
398 }
399 
400 void SvxBulletAndPositionDlg::InitControls()
401 {
402     bInInitControl = true;
403 
404     const bool bRelative = !bLabelAlignmentPosAndSpaceModeActive && m_xRelativeCB->get_sensitive()
405                            && m_xRelativeCB->get_active();
406     const bool bSingleSelection
407         = m_xLevelLB->count_selected_rows() == 1 && SAL_MAX_UINT16 != nActNumLvl;
408 
409     m_xDistBorderMF->set_sensitive(!bLabelAlignmentPosAndSpaceModeActive
410                                    && (bSingleSelection || bRelative));
411     m_xDistBorderFT->set_sensitive(!bLabelAlignmentPosAndSpaceModeActive
412                                    && (bSingleSelection || bRelative));
413 
414     bool bShowBullet = true;
415     bool bShowBitmap = true;
416     bool bSameType = true;
417     bool bSameStart = true;
418     bool bSamePrefix = true;
419     bool bSameSuffix = true;
420     bool bSameSize = true;
421     bool bSameBulColor = true;
422     bool bSameBulRelSize = true;
423     bool bSameDistBorderNum = !bLabelAlignmentPosAndSpaceModeActive;
424     bool bSetDistEmpty = false;
425     bool bSameIndent = !bLabelAlignmentPosAndSpaceModeActive;
426 
427     const SvxNumberFormat* aNumFmtArr[SVX_MAX_NUM];
428     SvxAdjust eFirstAdjust = SvxAdjust::Left;
429     Size aFirstSize(0, 0);
430     sal_uInt16 nMask = 1;
431     sal_uInt16 nLvl = SAL_MAX_UINT16;
432 
433     bool bBullColor = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_COLOR);
434     bool bBullRelSize = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE);
435     for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
436     {
437         aNumFmtArr[i] = &pActNum->GetLevel(i);
438 
439         if (nActNumLvl & nMask)
440         {
441             bShowBullet &= aNumFmtArr[i]->GetNumberingType() == SVX_NUM_CHAR_SPECIAL;
442             bShowBitmap &= (aNumFmtArr[i]->GetNumberingType() & (~LINK_TOKEN)) == SVX_NUM_BITMAP;
443             eFirstAdjust = aNumFmtArr[i]->GetNumAdjust();
444             if (SAL_MAX_UINT16 == nLvl)
445             {
446                 nLvl = i;
447                 if (bShowBitmap)
448                     aFirstSize = aNumFmtArr[i]->GetGraphicSize();
449             }
450             if (i > nLvl)
451             {
452                 bSameType
453                     &= aNumFmtArr[i]->GetNumberingType() == aNumFmtArr[nLvl]->GetNumberingType();
454                 bSameStart = aNumFmtArr[i]->GetStart() == aNumFmtArr[nLvl]->GetStart();
455 
456                 bSamePrefix = aNumFmtArr[i]->GetPrefix() == aNumFmtArr[nLvl]->GetPrefix();
457                 bSameSuffix = aNumFmtArr[i]->GetSuffix() == aNumFmtArr[nLvl]->GetSuffix();
458                 //bSameAdjust &= eFirstAdjust == aNumFmtArr[i]->GetNumAdjust();
459                 if (bShowBitmap && bSameSize)
460                     bSameSize &= aNumFmtArr[i]->GetGraphicSize() == aFirstSize;
461                 bSameBulColor
462                     &= aNumFmtArr[i]->GetBulletColor() == aNumFmtArr[nLvl]->GetBulletColor();
463                 bSameBulRelSize
464                     &= aNumFmtArr[i]->GetBulletRelSize() == aNumFmtArr[nLvl]->GetBulletRelSize();
465                 bSameIndent //?
466                     &= aNumFmtArr[i]->GetFirstLineOffset()
467                        == aNumFmtArr[nLvl]->GetFirstLineOffset();
468             }
469         }
470 
471         nMask <<= 1;
472     }
473     SwitchNumberType(bShowBullet ? 1 : bShowBitmap ? 2 : 0);
474 
475     sal_uInt16 nNumberingType;
476     if (nLvl != SAL_MAX_UINT16)
477         nNumberingType = aNumFmtArr[nLvl]->GetNumberingType();
478     else
479     {
480         nNumberingType = SVX_NUM_NUMBER_NONE;
481         bSameDistBorderNum = false;
482         bSameIndent = false;
483         bSameBulRelSize = false;
484         bSameBulColor = false;
485         bSameStart = false;
486         bSamePrefix = false;
487         bSameSuffix = false;
488     }
489 
490     CheckForStartValue_Impl(nNumberingType);
491 
492     if (bShowBitmap)
493     {
494         if (bSameSize)
495         {
496             SetMetricValue(*m_xHeightMF, aFirstSize.Height(), eCoreUnit);
497             SetMetricValue(*m_xWidthMF, aFirstSize.Width(), eCoreUnit);
498         }
499         else
500         {
501             m_xHeightMF->set_text("");
502             m_xWidthMF->set_text("");
503         }
504     }
505 
506     if (bSameType)
507     {
508         sal_uInt16 nLBData = nNumberingType;
509         m_xFmtLB->set_active_id(OUString::number(nLBData));
510     }
511     else
512         m_xFmtLB->set_active(-1);
513 
514     if (bBullRelSize)
515     {
516         if (bSameBulRelSize)
517             m_xBulRelSizeMF->set_value(aNumFmtArr[nLvl]->GetBulletRelSize(), FieldUnit::PERCENT);
518         else
519             m_xBulRelSizeMF->set_text("");
520     }
521     if (bBullColor)
522     {
523         if (bSameBulColor)
524             m_xBulColLB->SelectEntry(aNumFmtArr[nLvl]->GetBulletColor());
525         else
526             m_xBulColLB->SetNoSelection();
527     }
528     switch (nBullet)
529     {
530         case SHOW_NUMBERING:
531             if (bSameStart)
532             {
533                 m_xStartED->set_value(aNumFmtArr[nLvl]->GetStart());
534             }
535             else
536                 m_xStartED->set_text("");
537             break;
538         case SHOW_BULLET:
539             break;
540         case SHOW_BITMAP:
541             break;
542     }
543 
544     switch (eFirstAdjust)
545     {
546         case SvxAdjust::Left:
547             m_xLeftTB->set_active(true);
548             m_xCenterTB->set_active(false);
549             m_xRightTB->set_active(false);
550             break;
551         case SvxAdjust::Center:
552             m_xLeftTB->set_active(false);
553             m_xCenterTB->set_active(true);
554             m_xRightTB->set_active(false);
555             break;
556         case SvxAdjust::Right:
557             m_xLeftTB->set_active(false);
558             m_xCenterTB->set_active(false);
559             m_xRightTB->set_active(true);
560             break;
561         default:
562             break;
563     }
564 
565     if (bSamePrefix)
566         m_xPrefixED->set_text(aNumFmtArr[nLvl]->GetPrefix());
567     else
568         m_xPrefixED->set_text("");
569     if (bSameSuffix)
570         m_xSuffixED->set_text(aNumFmtArr[nLvl]->GetSuffix());
571     else
572         m_xSuffixED->set_text("");
573 
574     if (bSameDistBorderNum)
575     {
576         tools::Long nDistBorderNum;
577         if (bRelative)
578         {
579             nDistBorderNum = static_cast<tools::Long>(aNumFmtArr[nLvl]->GetAbsLSpace())
580                              + aNumFmtArr[nLvl]->GetFirstLineOffset();
581             if (nLvl)
582                 nDistBorderNum -= static_cast<tools::Long>(aNumFmtArr[nLvl - 1]->GetAbsLSpace())
583                                   + aNumFmtArr[nLvl - 1]->GetFirstLineOffset();
584         }
585         else
586         {
587             nDistBorderNum = static_cast<tools::Long>(aNumFmtArr[nLvl]->GetAbsLSpace())
588                              + aNumFmtArr[nLvl]->GetFirstLineOffset();
589         }
590         SetMetricValue(*m_xDistBorderMF, nDistBorderNum, eCoreUnit);
591     }
592     else
593         bSetDistEmpty = true;
594 
595     if (bSetDistEmpty)
596         m_xDistBorderMF->set_text("");
597 
598     if (bSameIndent)
599         SetMetricValue(*m_xIndentMF, -aNumFmtArr[nLvl]->GetFirstLineOffset(), eCoreUnit);
600     else
601         m_xIndentMF->set_text("");
602 
603     m_xSelectionRB->set_active(true);
604 
605     m_aPreviewWIN.SetLevel(nActNumLvl);
606     m_aPreviewWIN.Invalidate();
607     bInInitControl = false;
608 }
609 
610 // 0 - Number; 1 - Bullet; 2 - Bitmap
611 void SvxBulletAndPositionDlg::SwitchNumberType(sal_uInt8 nType)
612 {
613     if (nBullet == nType)
614         return;
615     nBullet = nType;
616     bool bBullet = (nType == SHOW_BULLET);
617     bool bBitmap = (nType == SHOW_BITMAP);
618     bool bEnableBitmap = (nType == SHOW_BITMAP);
619     bool bNumeric = !(bBitmap || bBullet);
620     m_xPrefixFT->set_visible(bNumeric);
621     m_xPrefixED->set_visible(bNumeric);
622     m_xSuffixFT->set_visible(bNumeric);
623     m_xSuffixED->set_visible(bNumeric);
624     m_xBeforeAfter->set_visible(bNumeric);
625 
626     m_xStartFT->set_visible(!(bBullet || bBitmap));
627     m_xStartED->set_visible(!(bBullet || bBitmap));
628 
629     m_xBulletFT->set_visible(bBullet);
630     m_xBulletPB->set_visible(bBullet);
631     bool bBullColor = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_COLOR);
632     m_xBulColorFT->set_visible(!bBitmap && bBullColor);
633     m_xBulColLB->set_visible(!bBitmap && bBullColor);
634     bool bBullResSize = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE);
635     m_xBulRelSizeFT->set_visible(!bBitmap && bBullResSize);
636     m_xBulRelSizeMF->set_visible(!bBitmap && bBullResSize);
637 
638     m_xBitmapMB->set_visible(bBitmap);
639 
640     m_xWidthFT->set_visible(bBitmap);
641     m_xWidthMF->set_visible(bBitmap);
642     m_xHeightFT->set_visible(bBitmap);
643     m_xHeightMF->set_visible(bBitmap);
644     m_xRatioCB->set_visible(bBitmap);
645 
646     m_xWidthFT->set_sensitive(bEnableBitmap);
647     m_xWidthMF->set_sensitive(bEnableBitmap);
648     m_xHeightFT->set_sensitive(bEnableBitmap);
649     m_xHeightMF->set_sensitive(bEnableBitmap);
650     m_xRatioCB->set_sensitive(bEnableBitmap);
651 }
652 
653 void SvxBulletAndPositionDlg::CheckForStartValue_Impl(sal_uInt16 nNumberingType)
654 {
655     bool bIsNull = m_xStartED->get_value() == 0;
656     bool bNoZeroAllowed = nNumberingType < SVX_NUM_ARABIC
657                           || SVX_NUM_CHARS_UPPER_LETTER_N == nNumberingType
658                           || SVX_NUM_CHARS_LOWER_LETTER_N == nNumberingType;
659     m_xStartED->set_min(bNoZeroAllowed ? 1 : 0);
660     if (bIsNull && bNoZeroAllowed)
661         SpinModifyHdl_Impl(*m_xStartED);
662 }
663 
664 IMPL_LINK(SvxBulletAndPositionDlg, LevelHdl_Impl, weld::TreeView&, rBox, void)
665 {
666     sal_uInt16 nSaveNumLvl = nActNumLvl;
667     nActNumLvl = 0;
668     auto aSelectedRows = rBox.get_selected_rows();
669     if (std::find(aSelectedRows.begin(), aSelectedRows.end(), pActNum->GetLevelCount())
670             != aSelectedRows.end()
671         && (aSelectedRows.size() == 1 || nSaveNumLvl != 0xffff))
672     {
673         nActNumLvl = 0xFFFF;
674         for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
675             rBox.unselect(i);
676     }
677     else if (!aSelectedRows.empty())
678     {
679         sal_uInt16 nMask = 1;
680         for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
681         {
682             if (std::find(aSelectedRows.begin(), aSelectedRows.end(), i) != aSelectedRows.end())
683                 nActNumLvl |= nMask;
684             nMask <<= 1;
685         }
686         rBox.unselect(pActNum->GetLevelCount());
687     }
688     else
689         nActNumLvl = nSaveNumLvl;
690 
691     InitControls();
692 }
693 
694 IMPL_LINK_NOARG(SvxBulletAndPositionDlg, PreviewInvalidateHdl_Impl, Timer*, void)
695 {
696     m_aPreviewWIN.Invalidate();
697 }
698 
699 IMPL_LINK(SvxBulletAndPositionDlg, NumberTypeSelectHdl_Impl, weld::ComboBox&, rBox, void)
700 {
701     bool bBmp = false;
702     sal_uInt16 nMask = 1;
703     for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
704     {
705         if (nActNumLvl & nMask)
706         {
707             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
708             // PAGEDESC does not exist
709             SvxNumType nNumType = static_cast<SvxNumType>(rBox.get_active_id().toUInt32());
710             aNumFmt.SetNumberingType(nNumType);
711             sal_uInt16 nNumberingType = aNumFmt.GetNumberingType();
712             if (SVX_NUM_BITMAP == (nNumberingType & (~LINK_TOKEN)))
713             {
714                 bBmp |= nullptr != aNumFmt.GetBrush();
715                 aNumFmt.SetIncludeUpperLevels(0);
716                 aNumFmt.SetListFormat("", "", i);
717                 if (!bBmp)
718                     aNumFmt.SetGraphic("");
719                 pActNum->SetLevel(i, aNumFmt);
720                 SwitchNumberType(SHOW_BITMAP);
721             }
722             else if (SVX_NUM_CHAR_SPECIAL == nNumberingType)
723             {
724                 aNumFmt.SetIncludeUpperLevels(0);
725                 aNumFmt.SetListFormat("", "", i);
726                 if (!aNumFmt.GetBulletFont())
727                     aNumFmt.SetBulletFont(&aActBulletFont);
728                 if (!aNumFmt.GetBulletChar())
729                     aNumFmt.SetBulletChar(SVX_DEF_BULLET);
730                 pActNum->SetLevel(i, aNumFmt);
731                 SwitchNumberType(SHOW_BULLET);
732                 // allocation of the drawing pattern is automatic
733             }
734             else
735             {
736                 aNumFmt.SetListFormat(m_xPrefixED->get_text(), m_xSuffixED->get_text(), i);
737                 SwitchNumberType(SHOW_NUMBERING);
738                 pActNum->SetLevel(i, aNumFmt);
739                 CheckForStartValue_Impl(nNumberingType);
740 
741                 // allocation of the drawing pattern is automatic
742             }
743         }
744         nMask <<= 1;
745     }
746 
747     SetModified();
748 }
749 
750 IMPL_LINK(SvxBulletAndPositionDlg, BulColorHdl_Impl, ColorListBox&, rColorBox, void)
751 {
752     Color nSetColor = rColorBox.GetSelectEntryColor();
753 
754     sal_uInt16 nMask = 1;
755     for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
756     {
757         if (nActNumLvl & nMask)
758         {
759             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
760             aNumFmt.SetBulletColor(nSetColor);
761             pActNum->SetLevel(i, aNumFmt);
762         }
763         nMask <<= 1;
764     }
765     SetModified();
766 }
767 
768 IMPL_LINK(SvxBulletAndPositionDlg, BulRelSizeHdl_Impl, weld::MetricSpinButton&, rField, void)
769 {
770     sal_uInt16 nRelSize = rField.get_value(FieldUnit::PERCENT);
771 
772     sal_uInt16 nMask = 1;
773     for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
774     {
775         if (nActNumLvl & nMask)
776         {
777             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
778             aNumFmt.SetBulletRelSize(nRelSize);
779             pActNum->SetLevel(i, aNumFmt);
780         }
781         nMask <<= 1;
782     }
783     SetModified();
784 }
785 
786 IMPL_LINK(SvxBulletAndPositionDlg, GraphicHdl_Impl, const OString&, rIdent, void)
787 {
788     OUString aGrfName;
789     Size aSize;
790     bool bSucc(false);
791     SvxOpenGraphicDialog aGrfDlg(SdResId(RID_SVXSTR_EDIT_GRAPHIC), p_Window);
792 
793     OString sNumber;
794     if (rIdent.startsWith("gallery", &sNumber))
795     {
796         auto idx = sNumber.toUInt32();
797         if (idx < aGrfNames.size())
798         {
799             aGrfName = aGrfNames[idx];
800             Graphic aGraphic;
801             if (GalleryExplorer::GetGraphicObj(GALLERY_THEME_BULLETS, idx, &aGraphic))
802             {
803                 aSize = SvxNumberFormat::GetGraphicSizeMM100(&aGraphic);
804                 bSucc = true;
805             }
806         }
807     }
808     else if (rIdent == "fromfile")
809     {
810         aGrfDlg.EnableLink(false);
811         aGrfDlg.AsLink(false);
812         if (!aGrfDlg.Execute())
813         {
814             // memorize selected filter
815             aGrfName = aGrfDlg.GetPath();
816 
817             Graphic aGraphic;
818             if (!aGrfDlg.GetGraphic(aGraphic))
819             {
820                 aSize = SvxNumberFormat::GetGraphicSizeMM100(&aGraphic);
821                 bSucc = true;
822             }
823         }
824     }
825     if (!bSucc)
826         return;
827 
828     aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(eCoreUnit));
829 
830     sal_uInt16 nMask = 1;
831     for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
832     {
833         if (nActNumLvl & nMask)
834         {
835             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
836             aNumFmt.SetCharFormatName(m_sNumCharFmtName);
837             aNumFmt.SetGraphic(aGrfName);
838 
839             // set size for a later comparison
840             const SvxBrushItem* pBrushItem = aNumFmt.GetBrush();
841             // initiate asynchronous loading
842             sal_Int16 eOrient = aNumFmt.GetVertOrient();
843             aNumFmt.SetGraphicBrush(pBrushItem, &aSize, &eOrient);
844             aInitSize[i] = aNumFmt.GetGraphicSize();
845 
846             pActNum->SetLevel(i, aNumFmt);
847         }
848         nMask <<= 1;
849     }
850     m_xRatioCB->set_sensitive(true);
851     m_xWidthFT->set_sensitive(true);
852     m_xHeightFT->set_sensitive(true);
853     m_xWidthMF->set_sensitive(true);
854     m_xHeightMF->set_sensitive(true);
855     SetMetricValue(*m_xWidthMF, aSize.Width(), eCoreUnit);
856     SetMetricValue(*m_xHeightMF, aSize.Height(), eCoreUnit);
857 
858     SetModified();
859     //needed due to asynchronous loading of graphics in the SvxBrushItem
860     aInvalidateTimer.Start();
861 }
862 
863 IMPL_LINK_NOARG(SvxBulletAndPositionDlg, PopupActivateHdl_Impl, weld::Toggleable&, void)
864 {
865     if (m_xGalleryMenu)
866         return;
867 
868     m_xGalleryMenu = m_xBuilder->weld_menu("gallerysubmenu");
869     weld::WaitObject aWait(p_Window);
870 
871     if (!GalleryExplorer::FillObjList(GALLERY_THEME_BULLETS, aGrfNames))
872         return;
873 
874     GalleryExplorer::BeginLocking(GALLERY_THEME_BULLETS);
875 
876     Graphic aGraphic;
877     OUString sGrfName;
878     ScopedVclPtrInstance<VirtualDevice> pVD;
879     size_t i = 0;
880     for (const auto& grfName : aGrfNames)
881     {
882         sGrfName = grfName;
883         OUString sItemId = "gallery" + OUString::number(i);
884         INetURLObject aObj(sGrfName);
885         if (aObj.GetProtocol() == INetProtocol::File)
886             sGrfName = aObj.PathToFileName();
887         if (GalleryExplorer::GetGraphicObj(GALLERY_THEME_BULLETS, i, &aGraphic))
888         {
889             BitmapEx aBitmap(aGraphic.GetBitmapEx());
890             Size aSize(aBitmap.GetSizePixel());
891             if (aSize.Width() > MAX_BMP_WIDTH || aSize.Height() > MAX_BMP_HEIGHT)
892             {
893                 bool bWidth = aSize.Width() > aSize.Height();
894                 double nScale = bWidth
895                                     ? double(MAX_BMP_WIDTH) / static_cast<double>(aSize.Width())
896                                     : double(MAX_BMP_HEIGHT) / static_cast<double>(aSize.Height());
897                 aBitmap.Scale(nScale, nScale);
898             }
899             pVD->SetOutputSizePixel(aBitmap.GetSizePixel(), false);
900             pVD->DrawBitmapEx(Point(), aBitmap);
901 
902             // We want to show only icon names not full path.
903             aObj.removeExtension();
904             OUString sIconName = aObj.GetLastName(INetURLObject::DecodeMechanism::WithCharset);
905 
906             m_xGalleryMenu->append(sItemId, sIconName, *pVD);
907         }
908         else
909         {
910             m_xGalleryMenu->append(sItemId, sGrfName);
911         }
912         ++i;
913     }
914     GalleryExplorer::EndLocking(GALLERY_THEME_BULLETS);
915 }
916 
917 IMPL_LINK_NOARG(SvxBulletAndPositionDlg, BulletHdl_Impl, weld::Button&, void)
918 {
919     SvxCharacterMap aMap(p_Window, nullptr, nullptr);
920 
921     sal_uInt16 nMask = 1;
922     std::optional<vcl::Font> pFmtFont;
923     bool bSameBullet = true;
924     sal_UCS4 cBullet = 0;
925     bool bFirst = true;
926     for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
927     {
928         if (nActNumLvl & nMask)
929         {
930             const SvxNumberFormat& rCurFmt = pActNum->GetLevel(i);
931             if (bFirst)
932             {
933                 cBullet = rCurFmt.GetBulletChar();
934             }
935             else if (rCurFmt.GetBulletChar() != cBullet)
936             {
937                 bSameBullet = false;
938                 break;
939             }
940             if (!pFmtFont)
941                 pFmtFont = rCurFmt.GetBulletFont();
942             bFirst = false;
943         }
944         nMask <<= 1;
945     }
946 
947     if (pFmtFont)
948         aMap.SetCharFont(*pFmtFont);
949     else
950         aMap.SetCharFont(aActBulletFont);
951     if (bSameBullet)
952         aMap.SetChar(cBullet);
953     if (aMap.run() != RET_OK)
954         return;
955 
956     // change Font Numrules
957     aActBulletFont = aMap.GetCharFont();
958 
959     sal_uInt16 _nMask = 1;
960     for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
961     {
962         if (nActNumLvl & _nMask)
963         {
964             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
965             aNumFmt.SetBulletFont(&aActBulletFont);
966             aNumFmt.SetBulletChar(aMap.GetChar());
967             pActNum->SetLevel(i, aNumFmt);
968         }
969         _nMask <<= 1;
970     }
971 
972     SetModified();
973 }
974 
975 IMPL_LINK(SvxBulletAndPositionDlg, SizeHdl_Impl, weld::MetricSpinButton&, rField, void)
976 {
977     bool bWidth = &rField == m_xWidthMF.get();
978     bLastWidthModified = bWidth;
979     bool bRatio = m_xRatioCB->get_active();
980     tools::Long nWidthVal = static_cast<tools::Long>(
981         m_xWidthMF->denormalize(m_xWidthMF->get_value(FieldUnit::MM_100TH)));
982     tools::Long nHeightVal = static_cast<tools::Long>(
983         m_xHeightMF->denormalize(m_xHeightMF->get_value(FieldUnit::MM_100TH)));
984     nWidthVal = OutputDevice::LogicToLogic(nWidthVal, MapUnit::Map100thMM, eCoreUnit);
985     nHeightVal = OutputDevice::LogicToLogic(nHeightVal, MapUnit::Map100thMM, eCoreUnit);
986     double fSizeRatio;
987 
988     bool bRepaint = false;
989     sal_uInt16 nMask = 1;
990     for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
991     {
992         if (nActNumLvl & nMask)
993         {
994             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
995             if (SVX_NUM_BITMAP == (aNumFmt.GetNumberingType() & (~LINK_TOKEN)))
996             {
997                 Size aSize(aNumFmt.GetGraphicSize());
998                 Size aSaveSize(aSize);
999 
1000                 if (aInitSize[i].Height())
1001                     fSizeRatio = static_cast<double>(aInitSize[i].Width())
1002                                  / static_cast<double>(aInitSize[i].Height());
1003                 else
1004                     fSizeRatio = double(1);
1005 
1006                 if (bWidth)
1007                 {
1008                     tools::Long nDelta = nWidthVal - aInitSize[i].Width();
1009                     aSize.setWidth(nWidthVal);
1010                     if (bRatio)
1011                     {
1012                         aSize.setHeight(
1013                             aInitSize[i].Height()
1014                             + static_cast<tools::Long>(static_cast<double>(nDelta) / fSizeRatio));
1015                         m_xHeightMF->set_value(m_xHeightMF->normalize(OutputDevice::LogicToLogic(
1016                                                    aSize.Height(), eCoreUnit, MapUnit::Map100thMM)),
1017                                                FieldUnit::MM_100TH);
1018                     }
1019                 }
1020                 else
1021                 {
1022                     tools::Long nDelta = nHeightVal - aInitSize[i].Height();
1023                     aSize.setHeight(nHeightVal);
1024                     if (bRatio)
1025                     {
1026                         aSize.setWidth(
1027                             aInitSize[i].Width()
1028                             + static_cast<tools::Long>(static_cast<double>(nDelta) * fSizeRatio));
1029                         m_xWidthMF->set_value(m_xWidthMF->normalize(OutputDevice::LogicToLogic(
1030                                                   aSize.Width(), eCoreUnit, MapUnit::Map100thMM)),
1031                                               FieldUnit::MM_100TH);
1032                     }
1033                 }
1034                 const SvxBrushItem* pBrushItem = aNumFmt.GetBrush();
1035                 sal_Int16 eOrient = aNumFmt.GetVertOrient();
1036                 if (aSize != aSaveSize)
1037                     bRepaint = true;
1038                 aNumFmt.SetGraphicBrush(pBrushItem, &aSize, &eOrient);
1039                 pActNum->SetLevel(i, aNumFmt);
1040             }
1041         }
1042         nMask <<= 1;
1043     }
1044     SetModified(bRepaint);
1045 }
1046 
1047 IMPL_LINK(SvxBulletAndPositionDlg, RatioHdl_Impl, weld::Toggleable&, rBox, void)
1048 {
1049     if (rBox.get_active())
1050     {
1051         if (bLastWidthModified)
1052             SizeHdl_Impl(*m_xWidthMF);
1053         else
1054             SizeHdl_Impl(*m_xHeightMF);
1055     }
1056 }
1057 
1058 IMPL_LINK(SvxBulletAndPositionDlg, SelectLeftAlignmentHdl_Impl, weld::Toggleable&, rButton, void)
1059 {
1060     if (rButton.get_active())
1061     {
1062         SetAlignmentHdl_Impl(SvxAdjust::Left);
1063 
1064         m_xCenterTB->set_active(false);
1065         m_xRightTB->set_active(false);
1066 
1067         SetModified();
1068     }
1069 }
1070 
1071 IMPL_LINK(SvxBulletAndPositionDlg, SelectCenterAlignmentHdl_Impl, weld::Toggleable&, rButton, void)
1072 {
1073     if (rButton.get_active())
1074     {
1075         SetAlignmentHdl_Impl(SvxAdjust::Center);
1076 
1077         m_xLeftTB->set_active(false);
1078         m_xRightTB->set_active(false);
1079 
1080         SetModified();
1081     }
1082 }
1083 
1084 IMPL_LINK(SvxBulletAndPositionDlg, SelectRightAlignmentHdl_Impl, weld::Toggleable&, rButton, void)
1085 {
1086     if (rButton.get_active())
1087     {
1088         SetAlignmentHdl_Impl(SvxAdjust::Right);
1089 
1090         m_xLeftTB->set_active(false);
1091         m_xCenterTB->set_active(false);
1092 
1093         SetModified();
1094     }
1095 }
1096 
1097 void SvxBulletAndPositionDlg::SetAlignmentHdl_Impl(SvxAdjust eAdjust)
1098 {
1099     sal_uInt16 nMask = 1;
1100     for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
1101     {
1102         if (nActNumLvl & nMask)
1103         {
1104             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
1105             aNumFmt.SetNumAdjust(eAdjust);
1106             pActNum->SetLevel(i, aNumFmt);
1107         }
1108         nMask <<= 1;
1109     }
1110 }
1111 
1112 IMPL_LINK(SvxBulletAndPositionDlg, ApplyToMasterHdl_Impl, weld::Toggleable&, rButton, void)
1113 {
1114     bApplyToMaster = rButton.get_active();
1115 }
1116 
1117 IMPL_LINK_NOARG(SvxBulletAndPositionDlg, ResetHdl_Impl, weld::Button&, void)
1118 {
1119     Reset(&rFirstStateSet);
1120 }
1121 
1122 IMPL_LINK(SvxBulletAndPositionDlg, EditModifyHdl_Impl, weld::Entry&, rEdit, void)
1123 {
1124     EditModifyHdl_Impl(&rEdit);
1125 }
1126 
1127 IMPL_LINK(SvxBulletAndPositionDlg, SpinModifyHdl_Impl, weld::SpinButton&, rSpinButton, void)
1128 {
1129     EditModifyHdl_Impl(&rSpinButton);
1130 }
1131 
1132 IMPL_LINK(SvxBulletAndPositionDlg, DistanceHdl_Impl, weld::MetricSpinButton&, rFld, void)
1133 {
1134     if (bInInitControl)
1135         return;
1136     tools::Long nValue = GetCoreValue(rFld, eCoreUnit);
1137     sal_uInt16 nMask = 1;
1138     for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
1139     {
1140         if (nActNumLvl & nMask)
1141         {
1142             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
1143             if (&rFld == m_xDistBorderMF.get())
1144             {
1145                 if (m_xRelativeCB->get_active())
1146                 {
1147                     if (0 == i)
1148                     {
1149                         auto const nTmp = aNumFmt.GetFirstLineOffset();
1150                         aNumFmt.SetAbsLSpace(nValue - nTmp);
1151                     }
1152                     else
1153                     {
1154                         tools::Long nTmp = pActNum->GetLevel(i - 1).GetAbsLSpace()
1155                                            + pActNum->GetLevel(i - 1).GetFirstLineOffset()
1156                                            - pActNum->GetLevel(i).GetFirstLineOffset();
1157 
1158                         aNumFmt.SetAbsLSpace(nValue + nTmp);
1159                     }
1160                 }
1161                 else
1162                 {
1163                     aNumFmt.SetAbsLSpace(nValue - aNumFmt.GetFirstLineOffset());
1164                 }
1165             }
1166             else if (&rFld == m_xIndentMF.get())
1167             {
1168                 // together with the FirstLineOffset the AbsLSpace must be changed, too
1169                 tools::Long nDiff = nValue + aNumFmt.GetFirstLineOffset();
1170                 auto const nAbsLSpace = aNumFmt.GetAbsLSpace();
1171                 aNumFmt.SetAbsLSpace(nAbsLSpace + nDiff);
1172                 aNumFmt.SetFirstLineOffset(-nValue);
1173             }
1174 
1175             pActNum->SetLevel(i, aNumFmt);
1176         }
1177         nMask <<= 1;
1178     }
1179 
1180     SetModified();
1181     if (!m_xDistBorderMF->get_sensitive())
1182     {
1183         m_xDistBorderMF->set_text("");
1184     }
1185 
1186     sal_Int32 aLastLevelLSpace
1187         = pActNum->GetLevel(pActNum->GetLevelCount() - 1).GetAbsLSpace() / 40;
1188     m_aPreviewWIN.set_size_request(aLastLevelLSpace, 300);
1189 }
1190 
1191 IMPL_LINK(SvxBulletAndPositionDlg, RelativeHdl_Impl, weld::Toggleable&, rBox, void)
1192 {
1193     bool bOn = rBox.get_active();
1194     bool bSingleSelection = m_xLevelLB->count_selected_rows() == 1 && SAL_MAX_UINT16 != nActNumLvl;
1195     bool bSetValue = false;
1196     tools::Long nValue = 0;
1197     if (bOn || bSingleSelection)
1198     {
1199         sal_uInt16 nMask = 1;
1200         bool bFirst = true;
1201         bSetValue = true;
1202         for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
1203         {
1204             if (nActNumLvl & nMask)
1205             {
1206                 const SvxNumberFormat& rNumFmt = pActNum->GetLevel(i);
1207                 if (bFirst)
1208                 {
1209                     nValue = rNumFmt.GetAbsLSpace() + rNumFmt.GetFirstLineOffset();
1210                     if (bOn && i)
1211                         nValue -= (pActNum->GetLevel(i - 1).GetAbsLSpace()
1212                                    + pActNum->GetLevel(i - 1).GetFirstLineOffset());
1213                 }
1214                 else
1215                     bSetValue = nValue
1216                                 == (rNumFmt.GetAbsLSpace() + rNumFmt.GetFirstLineOffset())
1217                                        - (pActNum->GetLevel(i - 1).GetAbsLSpace()
1218                                           + pActNum->GetLevel(i - 1).GetFirstLineOffset());
1219                 bFirst = false;
1220             }
1221             nMask <<= 1;
1222         }
1223     }
1224     if (bSetValue)
1225         SetMetricValue(*m_xDistBorderMF, nValue, eCoreUnit);
1226     else
1227         m_xDistBorderMF->set_text("");
1228     m_xDistBorderMF->set_sensitive(bOn || bSingleSelection);
1229     m_xDistBorderFT->set_sensitive(bOn || bSingleSelection);
1230     bLastRelative = bOn;
1231 }
1232 
1233 void SvxBulletAndPositionDlg::EditModifyHdl_Impl(const weld::Entry* pEdit)
1234 {
1235     bool bPrefixOrSuffix = (pEdit == m_xPrefixED.get()) || (pEdit == m_xSuffixED.get());
1236     bool bStart = pEdit == m_xStartED.get();
1237     sal_uInt16 nMask = 1;
1238     for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++)
1239     {
1240         if (nActNumLvl & nMask)
1241         {
1242             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
1243             if (bPrefixOrSuffix)
1244                 aNumFmt.SetListFormat(m_xPrefixED->get_text(), m_xSuffixED->get_text(), i);
1245             else if (bStart)
1246                 aNumFmt.SetStart(m_xStartED->get_value());
1247             pActNum->SetLevel(i, aNumFmt);
1248         }
1249         nMask <<= 1;
1250     }
1251     SetModified();
1252 }
1253 
1254 void SvxBulletAndPositionDlg::SetModified(bool bRepaint)
1255 {
1256     bModified = true;
1257     if (bRepaint)
1258     {
1259         m_aPreviewWIN.SetLevel(nActNumLvl);
1260         m_aPreviewWIN.Invalidate();
1261     }
1262 }
1263 
1264 void SvxBulletAndPositionDlg::InitPosAndSpaceMode()
1265 {
1266     if (pActNum == nullptr)
1267     {
1268         SAL_WARN("cui.tabpages", "<SvxNumPositionTabPage::InitPosAndSpaceMode()> - misusage of "
1269                                  "method -> <pAktNum> has to be already set!");
1270         return;
1271     }
1272 
1273     SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode = SvxNumberFormat::LABEL_ALIGNMENT;
1274     sal_uInt16 nMask = 1;
1275     for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); ++i)
1276     {
1277         if (nActNumLvl & nMask)
1278         {
1279             SvxNumberFormat aNumFmt(pActNum->GetLevel(i));
1280             ePosAndSpaceMode = aNumFmt.GetPositionAndSpaceMode();
1281             if (ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT)
1282             {
1283                 break;
1284             }
1285         }
1286         nMask <<= 1;
1287     }
1288 
1289     bLabelAlignmentPosAndSpaceModeActive = ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT;
1290 }
1291 
1292 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1293