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