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