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