xref: /core/cui/source/tabpages/border.cxx (revision 4a6dc219)
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 <sfx2/app.hxx>
21 #include <sfx2/objsh.hxx>
22 #include <sfx2/module.hxx>
23 #include <svx/dialogs.hrc>
24 #include <svx/dialmgr.hxx>
25 #include <svx/strings.hrc>
26 
27 #include <strings.hrc>
28 #include <bitmaps.hlst>
29 
30 #include <svx/xtable.hxx>
31 #include <svx/drawitem.hxx>
32 #include <editeng/boxitem.hxx>
33 #include <editeng/lineitem.hxx>
34 #include <border.hxx>
35 #include <svx/dlgutil.hxx>
36 #include <dialmgr.hxx>
37 #include <sfx2/htmlmode.hxx>
38 #include <vcl/event.hxx>
39 #include <vcl/settings.hxx>
40 #include <svx/flagsdef.hxx>
41 #include <sfx2/request.hxx>
42 #include <svl/grabbagitem.hxx>
43 #include <svl/intitem.hxx>
44 #include <svl/ilstitem.hxx>
45 #include <svl/int64item.hxx>
46 #include <sal/macros.h>
47 #include <com/sun/star/lang/XServiceInfo.hpp>
48 #include <comphelper/lok.hxx>
49 
50 using namespace ::editeng;
51 using ::com::sun::star::uno::Reference;
52 using ::com::sun::star::lang::XServiceInfo;
53 using ::com::sun::star::uno::UNO_QUERY;
54 
55 
56 /*
57  * [Description:]
58  * TabPage for setting the border attributes.
59  * Needs
60  *      a SvxShadowItem: shadow
61  *      a SvxBoxItem:    lines left, right, top, bottom,
62  *      a SvxBoxInfo:    lines vertical, horizontal, distance, flags
63  *
64  * Lines can have three conditions:
65  *      1. Show     ( -> valid values )
66  *      2. Hide     ( -> NULL-Pointer )
67  *      3. DontCare ( -> special Valid-Flags in the InfoItem )
68  */
69 
70 // static ----------------------------------------------------------------
71 
72 const sal_uInt16 SvxBorderTabPage::pRanges[] =
73 {
74     SID_ATTR_BORDER_INNER,      SID_ATTR_BORDER_SHADOW,
75     SID_ATTR_ALIGN_MARGIN,      SID_ATTR_ALIGN_MARGIN,
76     SID_ATTR_BORDER_CONNECT,    SID_ATTR_BORDER_CONNECT,
77     SID_SW_COLLAPSING_BORDERS,  SID_SW_COLLAPSING_BORDERS,
78     SID_ATTR_BORDER_DIAG_TLBR,  SID_ATTR_BORDER_DIAG_BLTR,
79     0
80 };
81 
82 static void lcl_SetDecimalDigitsTo1(weld::MetricSpinButton& rField)
83 {
84     auto nMin = rField.denormalize(rField.get_min(FieldUnit::TWIP));
85     rField.set_digits(1);
86     rField.set_min(rField.normalize(nMin), FieldUnit::TWIP);
87 }
88 
89 // number of preset images to show
90 const sal_uInt16 SVX_BORDER_PRESET_COUNT = 5;
91 
92 // number of shadow images to show
93 const sal_uInt16 SVX_BORDER_SHADOW_COUNT = 5;
94 
95 ShadowControlsWrapper::ShadowControlsWrapper(SvtValueSet& rVsPos, weld::MetricSpinButton& rMfSize, ColorListBox& rLbColor)
96     : mrVsPos(rVsPos)
97     , mrMfSize(rMfSize)
98     , mrLbColor(rLbColor)
99 {
100 }
101 
102 SvxShadowItem ShadowControlsWrapper::GetControlValue(const SvxShadowItem& rItem) const
103 {
104     SvxShadowItem aItem(rItem);
105     if (!mrVsPos.IsNoSelection())
106     {
107         switch (mrVsPos.GetSelectedItemId())
108         {
109             case 1:
110                 aItem.SetLocation(SvxShadowLocation::NONE);
111                 break;
112             case 2:
113                 aItem.SetLocation(SvxShadowLocation::BottomRight);
114                 break;
115             case 3:
116                 aItem.SetLocation(SvxShadowLocation::TopRight);
117                 break;
118             case 4:
119                 aItem.SetLocation(SvxShadowLocation::BottomLeft);
120                 break;
121             case 5:
122                 aItem.SetLocation(SvxShadowLocation::TopLeft);
123                 break;
124             default:
125                 aItem.SetLocation(SvxShadowLocation::NONE);
126                 break;
127         }
128     }
129     // Default value was saved; so don't change the aItem's width if the control
130     // has not changed its value, to avoid round-trip errors (like twip->cm->twip)
131     // E.g., initial 100 twip will become 0.18 cm, which will return as 102 twip
132     if (mrMfSize.get_value_changed_from_saved())
133         aItem.SetWidth(mrMfSize.denormalize(mrMfSize.get_value(FieldUnit::TWIP)));
134     if (!mrLbColor.IsNoSelection())
135         aItem.SetColor(mrLbColor.GetSelectEntryColor());
136     return aItem;
137 }
138 
139 void ShadowControlsWrapper::SetControlValue(const SvxShadowItem& rItem)
140 {
141     switch (rItem.GetLocation())
142     {
143         case SvxShadowLocation::NONE:
144             mrVsPos.SelectItem(1);
145             break;
146         case SvxShadowLocation::BottomRight:
147             mrVsPos.SelectItem(2);
148             break;
149         case SvxShadowLocation::TopRight:
150             mrVsPos.SelectItem(3);
151             break;
152         case SvxShadowLocation::BottomLeft:
153             mrVsPos.SelectItem(4);
154             break;
155         case SvxShadowLocation::TopLeft:
156             mrVsPos.SelectItem(5);
157             break;
158         default:
159             mrVsPos.SetNoSelection();
160             break;
161     }
162     mrMfSize.set_value(mrMfSize.normalize(rItem.GetWidth()), FieldUnit::TWIP);
163     mrLbColor.SelectEntry(rItem.GetColor());
164     mrMfSize.save_value();
165 }
166 
167 void ShadowControlsWrapper::SetControlDontKnow()
168 {
169     mrVsPos.SetNoSelection();
170     mrMfSize.set_text("");
171     mrLbColor.SetNoSelection();
172 }
173 
174 MarginControlsWrapper::MarginControlsWrapper(weld::MetricSpinButton& rMfLeft, weld::MetricSpinButton& rMfRight,
175                                              weld::MetricSpinButton& rMfTop, weld::MetricSpinButton& rMfBottom)
176     : mrLeftWrp(rMfLeft)
177     , mrRightWrp(rMfRight)
178     , mrTopWrp(rMfTop)
179     , mrBottomWrp(rMfBottom)
180 {
181 }
182 
183 SvxMarginItem MarginControlsWrapper::GetControlValue(const SvxMarginItem &rItem) const
184 {
185     SvxMarginItem aItem(rItem);
186     if (mrLeftWrp.get_sensitive())
187         aItem.SetLeftMargin(mrLeftWrp.denormalize(mrLeftWrp.get_value(FieldUnit::TWIP)));
188     if (mrRightWrp.get_sensitive())
189         aItem.SetRightMargin(mrRightWrp.denormalize(mrRightWrp.get_value(FieldUnit::TWIP)));
190     if (mrTopWrp.get_sensitive())
191         aItem.SetTopMargin(mrTopWrp.denormalize(mrTopWrp.get_value(FieldUnit::TWIP)));
192     if (mrBottomWrp.get_sensitive())
193         aItem.SetBottomMargin(mrBottomWrp.denormalize(mrBottomWrp.get_value(FieldUnit::TWIP)));
194     return aItem;
195 }
196 
197 bool MarginControlsWrapper::get_value_changed_from_saved() const
198 {
199     return mrLeftWrp.get_value_changed_from_saved() ||
200            mrRightWrp.get_value_changed_from_saved() ||
201            mrTopWrp.get_value_changed_from_saved() ||
202            mrBottomWrp.get_value_changed_from_saved();
203 }
204 
205 void MarginControlsWrapper::SetControlValue(const SvxMarginItem& rItem)
206 {
207     mrLeftWrp.set_value(mrLeftWrp.normalize(rItem.GetLeftMargin()), FieldUnit::TWIP);
208     mrRightWrp.set_value(mrRightWrp.normalize(rItem.GetRightMargin()), FieldUnit::TWIP);
209     mrTopWrp.set_value(mrTopWrp.normalize(rItem.GetTopMargin()), FieldUnit::TWIP);
210     mrBottomWrp.set_value(mrBottomWrp.normalize(rItem.GetBottomMargin()), FieldUnit::TWIP);
211     mrLeftWrp.save_value();
212     mrRightWrp.save_value();
213     mrTopWrp.save_value();
214     mrBottomWrp.save_value();
215 }
216 
217 void MarginControlsWrapper::SetControlDontKnow()
218 {
219     const OUString sEmpty;
220     mrLeftWrp.set_text(sEmpty);
221     mrRightWrp.set_text(sEmpty);
222     mrTopWrp.set_text(sEmpty);
223     mrBottomWrp.set_text(sEmpty);
224 }
225 
226 SvxBorderTabPage::SvxBorderTabPage(TabPageParent pParent, const SfxItemSet& rCoreAttrs)
227     : SfxTabPage(pParent, "cui/ui/borderpage.ui", "BorderPage", &rCoreAttrs)
228     , nMinValue(0)
229     , nSWMode(SwBorderModes::NONE)
230     , mnBoxSlot(SID_ATTR_BORDER_OUTER)
231     , mnShadowSlot(SID_ATTR_BORDER_SHADOW)
232     , mbHorEnabled(false)
233     , mbVerEnabled(false)
234     , mbTLBREnabled(false)
235     , mbBLTREnabled(false)
236     , mbUseMarginItem(false)
237     , mbLeftModified(false)
238     , mbRightModified(false)
239     , mbTopModified(false)
240     , mbBottomModified(false)
241     , mbSync(true)
242     , mbRemoveAdjacentCellBorders(false)
243     , bIsCalcDoc(false)
244     , m_xWndPresets(new SvtValueSet(m_xBuilder->weld_scrolled_window("presetswin")))
245     , m_xWndPresetsWin(new weld::CustomWeld(*m_xBuilder, "presets", *m_xWndPresets))
246     , m_xUserDefFT(m_xBuilder->weld_label("userdefft"))
247     , m_xFrameSelWin(new weld::CustomWeld(*m_xBuilder, "framesel", m_aFrameSel))
248     , m_xLbLineStyle(new SvtLineListBox(m_xBuilder->weld_menu_button("linestylelb")))
249     , m_xLbLineColor(new ColorListBox(m_xBuilder->weld_menu_button("linecolorlb"), pParent.GetFrameWeld()))
250     , m_xLineWidthMF(m_xBuilder->weld_metric_spin_button("linewidthmf", FieldUnit::POINT))
251     , m_xSpacingFrame(m_xBuilder->weld_container("spacing"))
252     , m_xLeftFT(m_xBuilder->weld_label("leftft"))
253     , m_xLeftMF(m_xBuilder->weld_metric_spin_button("leftmf", FieldUnit::MM))
254     , m_xRightFT(m_xBuilder->weld_label("rightft"))
255     , m_xRightMF(m_xBuilder->weld_metric_spin_button("rightmf", FieldUnit::MM))
256     , m_xTopFT(m_xBuilder->weld_label("topft"))
257     , m_xTopMF(m_xBuilder->weld_metric_spin_button("topmf", FieldUnit::MM))
258     , m_xBottomFT(m_xBuilder->weld_label("bottomft"))
259     , m_xBottomMF(m_xBuilder->weld_metric_spin_button("bottommf", FieldUnit::MM))
260     , m_xSynchronizeCB(m_xBuilder->weld_check_button("sync"))
261     , m_xShadowFrame(m_xBuilder->weld_container("shadow"))
262     , m_xWndShadows(new SvtValueSet(m_xBuilder->weld_scrolled_window("shadowswin")))
263     , m_xWndShadowsWin(new weld::CustomWeld(*m_xBuilder, "shadows", *m_xWndShadows))
264     , m_xFtShadowSize(m_xBuilder->weld_label("distanceft"))
265     , m_xEdShadowSize(m_xBuilder->weld_metric_spin_button("distancemf", FieldUnit::MM))
266     , m_xFtShadowColor(m_xBuilder->weld_label("shadowcolorft"))
267     , m_xLbShadowColor(new ColorListBox(m_xBuilder->weld_menu_button("shadowcolorlb"), pParent.GetFrameWeld()))
268     , m_xPropertiesFrame(m_xBuilder->weld_container("properties"))
269     , m_xMergeWithNextCB(m_xBuilder->weld_check_button("mergewithnext"))
270     , m_xMergeAdjacentBordersCB(m_xBuilder->weld_check_button("mergeadjacent"))
271     , m_xRemoveAdjcentCellBordersCB(m_xBuilder->weld_check_button("rmadjcellborders"))
272     , m_xRemoveAdjcentCellBordersFT(m_xBuilder->weld_label("rmadjcellbordersft"))
273 {
274     static std::vector<OUStringLiteral> aBorderImageIds;
275 
276     if (aBorderImageIds.empty())
277     {
278         if (comphelper::LibreOfficeKit::isActive())
279         {
280             aBorderImageIds.insert(aBorderImageIds.end(), {
281                 RID_SVXBMP_CELL_NONE_32,
282                 RID_SVXBMP_CELL_ALL_32,
283                 RID_SVXBMP_CELL_LR_32,
284                 RID_SVXBMP_CELL_TB_32,
285                 RID_SVXBMP_CELL_L_32,
286                 RID_SVXBMP_CELL_DIAG_32
287             });
288         }
289         else
290         {
291             aBorderImageIds.insert(aBorderImageIds.end(), {
292                 RID_SVXBMP_CELL_NONE,
293                 RID_SVXBMP_CELL_ALL,
294                 RID_SVXBMP_CELL_LR,
295                 RID_SVXBMP_CELL_TB,
296                 RID_SVXBMP_CELL_L,
297                 RID_SVXBMP_CELL_DIAG
298             });
299         }
300         aBorderImageIds.insert(aBorderImageIds.end(), {
301             RID_SVXBMP_HOR_NONE,
302             RID_SVXBMP_HOR_OUTER,
303             RID_SVXBMP_HOR_HOR,
304             RID_SVXBMP_HOR_ALL,
305             RID_SVXBMP_HOR_OUTER2,
306             RID_SVXBMP_VER_NONE,
307             RID_SVXBMP_VER_OUTER,
308             RID_SVXBMP_VER_VER,
309             RID_SVXBMP_VER_ALL,
310             RID_SVXBMP_VER_OUTER2,
311             RID_SVXBMP_TABLE_NONE,
312             RID_SVXBMP_TABLE_OUTER,
313             RID_SVXBMP_TABLE_OUTERH,
314             RID_SVXBMP_TABLE_ALL,
315             RID_SVXBMP_TABLE_OUTER2
316         });
317     }
318 
319     for (auto const & rImageId : aBorderImageIds)
320         m_aBorderImgVec.emplace_back(StockImage::Yes, rImageId);
321 
322     static std::vector<OUStringLiteral> aShadowImageIds;
323     if (aShadowImageIds.empty())
324     {
325         if (comphelper::LibreOfficeKit::isActive())
326         {
327             aShadowImageIds.insert(aShadowImageIds.end(), {
328                 RID_SVXBMP_SHADOWNONE_32,
329                 RID_SVXBMP_SHADOW_BOT_RIGHT_32,
330                 RID_SVXBMP_SHADOW_TOP_RIGHT_32,
331                 RID_SVXBMP_SHADOW_BOT_LEFT_32,
332                 RID_SVXBMP_SHADOW_TOP_LEFT_32
333             });
334         }
335         else
336         {
337             aShadowImageIds.insert(aShadowImageIds.end(), {
338                 RID_SVXBMP_SHADOWNONE,
339                 RID_SVXBMP_SHADOW_BOT_RIGHT,
340                 RID_SVXBMP_SHADOW_TOP_RIGHT,
341                 RID_SVXBMP_SHADOW_BOT_LEFT,
342                 RID_SVXBMP_SHADOW_TOP_LEFT
343             });
344         }
345     }
346 
347     for (auto const & rImageId : aShadowImageIds)
348         m_aShadowImgVec.emplace_back(StockImage::Yes, rImageId);
349 
350     assert(m_aShadowImgVec.size() == SVX_BORDER_SHADOW_COUNT);
351 
352     // this page needs ExchangeSupport
353     SetExchangeSupport();
354 
355     /*  Use SvxMarginItem instead of margins from SvxBoxItem, if present.
356         ->  Remember this state in mbUseMarginItem, because other special handling
357             is needed across various functions... */
358     mbUseMarginItem = rCoreAttrs.GetItemState(GetWhich(SID_ATTR_ALIGN_MARGIN)) != SfxItemState::UNKNOWN;
359 
360     const SfxPoolItem* pItem = nullptr;
361     if (rCoreAttrs.HasItem(SID_ATTR_BORDER_STYLES, &pItem))
362     {
363         const SfxIntegerListItem* p = static_cast<const SfxIntegerListItem*>(pItem);
364         std::vector<sal_Int32> aUsedStyles = p->GetList();
365         for (int aUsedStyle : aUsedStyles)
366             maUsedBorderStyles.insert(static_cast<SvxBorderLineStyle>(aUsedStyle));
367     }
368 
369     if (rCoreAttrs.HasItem(SID_ATTR_BORDER_DEFAULT_WIDTH, &pItem))
370     {
371         // The caller specifies default line width.  Honor it.
372         const SfxInt64Item* p = static_cast<const SfxInt64Item*>(pItem);
373         m_xLineWidthMF->set_value(p->GetValue(), FieldUnit::POINT);
374     }
375 
376     // set metric
377     FieldUnit eFUnit = GetModuleFieldUnit( rCoreAttrs );
378 
379     if( mbUseMarginItem )
380     {
381         // copied from SvxAlignmentTabPage
382         switch ( eFUnit )
383         {
384             //  #103396# the default value (1pt) can't be accurately represented in
385             //  inches or pica with two decimals, so point is used instead.
386             case FieldUnit::PICA:
387             case FieldUnit::INCH:
388             case FieldUnit::FOOT:
389             case FieldUnit::MILE:
390                 eFUnit = FieldUnit::POINT;
391                 break;
392 
393             case FieldUnit::CM:
394             case FieldUnit::M:
395             case FieldUnit::KM:
396                 eFUnit = FieldUnit::MM;
397                 break;
398             default: ;//prevent warning
399         }
400     }
401     else
402     {
403         switch ( eFUnit )
404         {
405             case FieldUnit::M:
406             case FieldUnit::KM:
407                 eFUnit = FieldUnit::MM;
408                 break;
409             default: ; //prevent warning
410         }
411     }
412 
413     SetFieldUnit(*m_xEdShadowSize, eFUnit);
414 
415     sal_uInt16 nWhich = GetWhich( SID_ATTR_BORDER_INNER, false );
416     bool bIsDontCare = true;
417 
418     if ( rCoreAttrs.GetItemState( nWhich ) >= SfxItemState::DEFAULT )
419     {
420         // paragraph or table
421         const SvxBoxInfoItem* pBoxInfo =
422             static_cast<const SvxBoxInfoItem*>(&( rCoreAttrs.Get( nWhich ) ));
423 
424         mbHorEnabled = pBoxInfo->IsHorEnabled();
425         mbVerEnabled = pBoxInfo->IsVerEnabled();
426         mbTLBREnabled = rCoreAttrs.GetItemState(GetWhich(SID_ATTR_BORDER_DIAG_TLBR)) != SfxItemState::UNKNOWN;
427         mbBLTREnabled = rCoreAttrs.GetItemState(GetWhich(SID_ATTR_BORDER_DIAG_BLTR)) != SfxItemState::UNKNOWN;
428 
429         if(pBoxInfo->IsDist())
430         {
431             SetFieldUnit(*m_xLeftMF, eFUnit);
432             SetFieldUnit(*m_xRightMF, eFUnit);
433             SetFieldUnit(*m_xTopMF, eFUnit);
434             SetFieldUnit(*m_xBottomMF, eFUnit);
435             m_xSynchronizeCB->connect_toggled(LINK(this, SvxBorderTabPage, SyncHdl_Impl));
436             m_xLeftMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyDistanceHdl_Impl));
437             m_xRightMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyDistanceHdl_Impl));
438             m_xTopMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyDistanceHdl_Impl));
439             m_xBottomMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyDistanceHdl_Impl));
440         }
441         else
442         {
443             m_xSpacingFrame->hide();
444         }
445         bIsDontCare = !pBoxInfo->IsValid( SvxBoxInfoItemValidFlags::DISABLE );
446     }
447     if(!mbUseMarginItem && eFUnit == FieldUnit::MM && MapUnit::MapTwip == rCoreAttrs.GetPool()->GetMetric( GetWhich( SID_ATTR_BORDER_INNER ) ))
448     {
449         //#i91548# changing the number of decimal digits changes the minimum values, too
450         lcl_SetDecimalDigitsTo1(*m_xLeftMF);
451         lcl_SetDecimalDigitsTo1(*m_xRightMF);
452         lcl_SetDecimalDigitsTo1(*m_xTopMF);
453         lcl_SetDecimalDigitsTo1(*m_xBottomMF);
454         lcl_SetDecimalDigitsTo1(*m_xEdShadowSize);
455     }
456 
457     FrameSelFlags nFlags = FrameSelFlags::Outer;
458     if( mbHorEnabled )
459         nFlags |= FrameSelFlags::InnerHorizontal;
460     if( mbVerEnabled )
461         nFlags |= FrameSelFlags::InnerVertical;
462     if( mbTLBREnabled )
463         nFlags |= FrameSelFlags::DiagonalTLBR;
464     if( mbBLTREnabled )
465         nFlags |= FrameSelFlags::DiagonalBLTR;
466     if( bIsDontCare )
467         nFlags |= FrameSelFlags::DontCare;
468     m_aFrameSel.Initialize( nFlags );
469 
470     m_aFrameSel.SetSelectHdl(LINK(this, SvxBorderTabPage, LinesChanged_Impl));
471     m_xLbLineStyle->SetSelectHdl( LINK( this, SvxBorderTabPage, SelStyleHdl_Impl ) );
472     m_xLbLineColor->SetSelectHdl( LINK( this, SvxBorderTabPage, SelColHdl_Impl ) );
473     m_xLineWidthMF->connect_value_changed( LINK( this, SvxBorderTabPage, ModifyWidthHdl_Impl ) );
474     m_xWndPresets->SetSelectHdl( LINK( this, SvxBorderTabPage, SelPreHdl_Impl ) );
475     m_xWndShadows->SetSelectHdl( LINK( this, SvxBorderTabPage, SelSdwHdl_Impl ) );
476 
477     FillValueSets();
478     FillLineListBox_Impl();
479 
480     // connections
481     if (rCoreAttrs.HasItem(GetWhich(SID_ATTR_CHAR_GRABBAG), &pItem))
482     {
483         const SfxGrabBagItem* pGrabBag = static_cast<const SfxGrabBagItem*>(pItem);
484         auto it = pGrabBag->GetGrabBag().find("DialogUseCharAttr");
485         if (it != pGrabBag->GetGrabBag().end())
486         {
487             bool bDialogUseCharAttr = false;
488             it->second >>= bDialogUseCharAttr;
489             if (bDialogUseCharAttr)
490             {
491                 mnShadowSlot = SID_ATTR_CHAR_SHADOW;
492                 mnBoxSlot = SID_ATTR_CHAR_BOX;
493             }
494         }
495     }
496 
497     bool bSupportsShadow = !SfxItemPool::IsSlot(GetWhich(mnShadowSlot));
498     if( bSupportsShadow )
499         m_xShadowControls.reset(new ShadowControlsWrapper(*m_xWndShadows, *m_xEdShadowSize, *m_xLbShadowColor));
500     else
501         HideShadowControls();
502 
503     if (mbUseMarginItem)
504         m_xMarginControls.reset(new MarginControlsWrapper(*m_xLeftMF, *m_xRightMF, *m_xTopMF, *m_xBottomMF));
505 
506     // checkbox "Merge with next paragraph" only visible for Writer dialog format.paragraph
507     m_xMergeWithNextCB->hide();
508     // checkbox "Merge adjacent line styles" only visible for Writer dialog format.table
509     m_xMergeAdjacentBordersCB->hide();
510 
511     SfxObjectShell* pDocSh = SfxObjectShell::Current();
512     if (pDocSh)
513     {
514         Reference< XServiceInfo > xSI( pDocSh->GetModel(), UNO_QUERY );
515         if ( xSI.is() )
516             bIsCalcDoc = xSI->supportsService("com.sun.star.sheet.SpreadsheetDocument");
517     }
518     if( bIsCalcDoc )
519     {
520         m_xRemoveAdjcentCellBordersCB->connect_toggled(LINK(this, SvxBorderTabPage, RemoveAdjacentCellBorderHdl_Impl));
521         m_xRemoveAdjcentCellBordersCB->show();
522         m_xRemoveAdjcentCellBordersCB->set_sensitive(false);
523     }
524     else
525     {
526         m_xRemoveAdjcentCellBordersCB->hide();
527         m_xRemoveAdjcentCellBordersFT->hide();
528     }
529 }
530 
531 SvxBorderTabPage::~SvxBorderTabPage()
532 {
533     disposeOnce();
534 }
535 
536 void SvxBorderTabPage::dispose()
537 {
538     m_xLbShadowColor.reset();
539     m_xWndShadowsWin.reset();
540     m_xWndShadows.reset();
541     m_xLbLineColor.reset();
542     m_xLbLineStyle.reset();
543     m_xFrameSelWin.reset();
544     m_xWndPresetsWin.reset();
545     m_xWndPresets.reset();
546     SfxTabPage::dispose();
547 }
548 
549 VclPtr<SfxTabPage> SvxBorderTabPage::Create( TabPageParent pParent,
550                                              const SfxItemSet* rAttrSet )
551 {
552     return VclPtr<SvxBorderTabPage>::Create(pParent, *rAttrSet);
553 }
554 
555 void SvxBorderTabPage::ResetFrameLine_Impl( svx::FrameBorderType eBorder, const SvxBorderLine* pCoreLine, bool bValid )
556 {
557     if( m_aFrameSel.IsBorderEnabled( eBorder ) )
558     {
559         if( bValid )
560             m_aFrameSel.ShowBorder( eBorder, pCoreLine );
561         else
562             m_aFrameSel.SetBorderDontCare( eBorder );
563     }
564 }
565 
566 bool SvxBorderTabPage::IsBorderLineStyleAllowed( SvxBorderLineStyle nStyle ) const
567 {
568     if (maUsedBorderStyles.empty())
569         // All border styles are allowed.
570         return true;
571 
572     return maUsedBorderStyles.count(nStyle) > 0;
573 }
574 
575 void SvxBorderTabPage::Reset( const SfxItemSet* rSet )
576 {
577     SfxItemPool* pPool = rSet->GetPool();
578 
579     if (m_aFrameSel.IsBorderEnabled(svx::FrameBorderType::TLBR))
580     {
581         sal_uInt16 nBorderDiagId = pPool->GetWhich(SID_ATTR_BORDER_DIAG_TLBR);
582         if (const SvxLineItem* pLineItem = static_cast<const SvxLineItem*>(rSet->GetItem(nBorderDiagId)))
583             m_aFrameSel.ShowBorder(svx::FrameBorderType::TLBR, pLineItem->GetLine());
584         else
585             m_aFrameSel.SetBorderDontCare(svx::FrameBorderType::TLBR);
586     }
587 
588     if (m_aFrameSel.IsBorderEnabled(svx::FrameBorderType::BLTR))
589     {
590         sal_uInt16 nBorderDiagId = pPool->GetWhich(SID_ATTR_BORDER_DIAG_BLTR);
591         if (const SvxLineItem* pLineItem = static_cast<const SvxLineItem*>(rSet->GetItem(nBorderDiagId)))
592             m_aFrameSel.ShowBorder(svx::FrameBorderType::BLTR, pLineItem->GetLine());
593         else
594             m_aFrameSel.SetBorderDontCare(svx::FrameBorderType::BLTR);
595     }
596 
597     if (m_xShadowControls)
598     {
599         sal_uInt16 nShadowId = pPool->GetWhich(mnShadowSlot);
600         const SfxPoolItem* pItem = rSet->GetItem(nShadowId);
601         if (pItem)
602             m_xShadowControls->SetControlValue(*static_cast<const SvxShadowItem*>(pItem));
603         else
604             m_xShadowControls->SetControlDontKnow();
605     }
606 
607     if (m_xMarginControls)
608     {
609         sal_uInt16 nAlignMarginId = pPool->GetWhich(SID_ATTR_ALIGN_MARGIN);
610         const SfxPoolItem* pItem = rSet->GetItem(nAlignMarginId);
611         if (pItem)
612             m_xMarginControls->SetControlValue(*static_cast<const SvxMarginItem*>(pItem));
613         else
614             m_xMarginControls->SetControlDontKnow();
615     }
616 
617     sal_uInt16 nMergeAdjacentBordersId = pPool->GetWhich(SID_SW_COLLAPSING_BORDERS);
618     const SfxBoolItem *pMergeAdjacentBorders = static_cast<const SfxBoolItem*>(rSet->GetItem(nMergeAdjacentBordersId));
619     if (!pMergeAdjacentBorders)
620         m_xMergeAdjacentBordersCB->set_state(TRISTATE_INDET);
621     else
622         m_xMergeAdjacentBordersCB->set_active(pMergeAdjacentBorders->GetValue());
623     m_xMergeAdjacentBordersCB->save_state();
624 
625     sal_uInt16 nMergeWithNextId = pPool->GetWhich(SID_ATTR_BORDER_CONNECT);
626     const SfxBoolItem *pMergeWithNext = static_cast<const SfxBoolItem*>(rSet->GetItem(nMergeWithNextId));
627     if (!pMergeWithNext)
628         m_xMergeWithNextCB->set_state(TRISTATE_INDET);
629     else
630         m_xMergeWithNextCB->set_active(pMergeWithNext->GetValue());
631     m_xMergeWithNextCB->save_state();
632 
633     const SvxBoxItem*       pBoxItem;
634     const SvxBoxInfoItem*   pBoxInfoItem;
635     sal_uInt16              nWhichBox       = GetWhich(mnBoxSlot);
636     MapUnit                 eCoreUnit;
637 
638     pBoxItem  = static_cast<const SvxBoxItem*>(GetItem( *rSet, mnBoxSlot ));
639 
640     pBoxInfoItem = GetItem( *rSet, SID_ATTR_BORDER_INNER, false );
641 
642     eCoreUnit = pPool->GetMetric( nWhichBox );
643 
644     if ( pBoxItem && pBoxInfoItem ) // -> Don't Care
645     {
646         ResetFrameLine_Impl( svx::FrameBorderType::Left,   pBoxItem->GetLeft(),     pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::LEFT ) );
647         ResetFrameLine_Impl( svx::FrameBorderType::Right,  pBoxItem->GetRight(),    pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::RIGHT ) );
648         ResetFrameLine_Impl( svx::FrameBorderType::Top,    pBoxItem->GetTop(),      pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::TOP ) );
649         ResetFrameLine_Impl( svx::FrameBorderType::Bottom, pBoxItem->GetBottom(),   pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::BOTTOM ) );
650         ResetFrameLine_Impl( svx::FrameBorderType::Vertical,    pBoxInfoItem->GetVert(), pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::VERT ) );
651         ResetFrameLine_Impl( svx::FrameBorderType::Horizontal,    pBoxInfoItem->GetHori(), pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::HORI ) );
652 
653 
654         // distance inside
655 
656         if( !mbUseMarginItem )
657         {
658             if (m_xLeftMF->get_visible())
659             {
660                 SetMetricValue(*m_xLeftMF,    pBoxInfoItem->GetDefDist(), eCoreUnit);
661                 SetMetricValue(*m_xRightMF,   pBoxInfoItem->GetDefDist(), eCoreUnit);
662                 SetMetricValue(*m_xTopMF,     pBoxInfoItem->GetDefDist(), eCoreUnit);
663                 SetMetricValue(*m_xBottomMF,  pBoxInfoItem->GetDefDist(), eCoreUnit);
664 
665                 nMinValue = m_xLeftMF->get_value(FieldUnit::NONE);
666 
667                 if ( pBoxInfoItem->IsDist() )
668                 {
669                     if( rSet->GetItemState( nWhichBox ) >= SfxItemState::DEFAULT )
670                     {
671                         bool bIsAnyBorderVisible = m_aFrameSel.IsAnyBorderVisible();
672                         if( !bIsAnyBorderVisible || !pBoxInfoItem->IsMinDist() )
673                         {
674                             m_xLeftMF->set_min(0, FieldUnit::NONE);
675                             m_xRightMF->set_min(0, FieldUnit::NONE);
676                             m_xTopMF->set_min(0, FieldUnit::NONE);
677                             m_xBottomMF->set_min(0, FieldUnit::NONE);
678                         }
679                         long nLeftDist = pBoxItem->GetDistance( SvxBoxItemLine::LEFT);
680                         SetMetricValue(*m_xLeftMF, nLeftDist, eCoreUnit);
681                         long nRightDist = pBoxItem->GetDistance( SvxBoxItemLine::RIGHT);
682                         SetMetricValue(*m_xRightMF, nRightDist, eCoreUnit);
683                         long nTopDist = pBoxItem->GetDistance( SvxBoxItemLine::TOP);
684                         SetMetricValue( *m_xTopMF, nTopDist, eCoreUnit );
685                         long nBottomDist = pBoxItem->GetDistance( SvxBoxItemLine::BOTTOM);
686                         SetMetricValue( *m_xBottomMF, nBottomDist, eCoreUnit );
687 
688                         // if the distance is set with no active border line
689                         // or it is null with an active border line
690                         // no automatic changes should be made
691                         const long nDefDist = bIsAnyBorderVisible ? pBoxInfoItem->GetDefDist() : 0;
692                         bool bDiffDist = (nDefDist != nLeftDist ||
693                                     nDefDist != nRightDist ||
694                                     nDefDist != nTopDist   ||
695                                     nDefDist != nBottomDist);
696                         if ((pBoxItem->GetSmallestDistance() || bIsAnyBorderVisible) && bDiffDist )
697                         {
698                             mbLeftModified = true;
699                             mbRightModified = true;
700                             mbTopModified = true;
701                             mbBottomModified = true;
702                         }
703                     }
704                     else
705                     {
706                         // #106224# different margins -> do not fill the edits
707                         m_xLeftMF->set_text( OUString() );
708                         m_xRightMF->set_text( OUString() );
709                         m_xTopMF->set_text( OUString() );
710                         m_xBottomMF->set_text( OUString() );
711                     }
712                 }
713                 m_xLeftMF->save_value();
714                 m_xRightMF->save_value();
715                 m_xTopMF->save_value();
716                 m_xBottomMF->save_value();
717             }
718         }
719     }
720     else
721     {
722         // avoid ResetFrameLine-calls:
723         m_aFrameSel.HideAllBorders();
724     }
725 
726     if( !m_aFrameSel.IsAnyBorderVisible() )
727         m_aFrameSel.DeselectAllBorders();
728 
729     // depict line (color) in controllers if unambiguous:
730 
731     {
732         // Do all visible lines show the same line widths?
733         long nWidth;
734         SvxBorderLineStyle nStyle;
735         bool bWidthEq = m_aFrameSel.GetVisibleWidth( nWidth, nStyle );
736         if( bWidthEq )
737         {
738             // Determine the width first as some styles can be missing depending on it
739             sal_Int64 nWidthPt =  static_cast<sal_Int64>(MetricField::ConvertDoubleValue(
740                         sal_Int64( nWidth ), m_xLineWidthMF->get_digits(),
741                         MapUnit::MapTwip, FieldUnit::POINT ));
742             m_xLineWidthMF->set_value(nWidthPt, FieldUnit::POINT);
743             m_xLbLineStyle->SetWidth(nWidth);
744 
745             // then set the style
746             m_xLbLineStyle->SelectEntry( nStyle );
747         }
748         else
749             m_xLbLineStyle->SelectEntry(SvxBorderLineStyle::SOLID);
750 
751         // Do all visible lines show the same line color?
752         Color aColor;
753         bool bColorEq = m_aFrameSel.GetVisibleColor( aColor );
754         if( !bColorEq )
755             aColor = COL_BLACK;
756 
757         m_xLbLineColor->SelectEntry(aColor);
758         m_xLbLineStyle->SetColor(GetTextColor());
759 
760         // Select all visible lines, if they are all equal.
761         if( bWidthEq && bColorEq )
762             m_aFrameSel.SelectAllVisibleBorders();
763 
764         // set the current style and color (caches style in control even if nothing is selected)
765         SelStyleHdl_Impl(*m_xLbLineStyle);
766         SelColHdl_Impl(*m_xLbLineColor);
767     }
768 
769     bool bEnable = m_xWndShadows->GetSelectedItemId() > 1 ;
770     m_xFtShadowSize->set_sensitive(bEnable);
771     m_xEdShadowSize->set_sensitive(bEnable);
772     m_xFtShadowColor->set_sensitive(bEnable);
773     m_xLbShadowColor->set_sensitive(bEnable);
774 
775     m_xWndPresets->SetNoSelection();
776 
777     // - no line - should not be selected
778 
779     if (m_xLbLineStyle->GetSelectEntryStyle() == SvxBorderLineStyle::NONE)
780     {
781         m_xLbLineStyle->SelectEntry(SvxBorderLineStyle::SOLID);
782         SelStyleHdl_Impl(*m_xLbLineStyle);
783     }
784 
785     const SfxPoolItem* pItem;
786     SfxObjectShell* pShell;
787     if(SfxItemState::SET == rSet->GetItemState(SID_HTML_MODE, false, &pItem) ||
788         ( nullptr != (pShell = SfxObjectShell::Current()) &&
789                     nullptr != (pItem = pShell->GetItem(SID_HTML_MODE))))
790     {
791         sal_uInt16 nHtmlMode = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
792         if(nHtmlMode & HTMLMODE_ON)
793         {
794             // there are no shadows in Html-mode and only complete borders
795             m_xShadowFrame->set_sensitive(false);
796 
797             if( !(nSWMode & SwBorderModes::TABLE) )
798             {
799                 m_xUserDefFT->set_sensitive(false);
800                 m_xFrameSelWin->set_sensitive(false);
801                 m_xWndPresets->RemoveItem(3);
802                 m_xWndPresets->RemoveItem(4);
803                 m_xWndPresets->RemoveItem(5);
804             }
805         }
806     }
807 
808     LinesChanged_Impl( nullptr );
809     if (m_xLeftMF->get_value(FieldUnit::NONE) == m_xRightMF->get_value(FieldUnit::NONE) &&
810         m_xTopMF->get_value(FieldUnit::NONE) == m_xBottomMF->get_value(FieldUnit::NONE) &&
811         m_xTopMF->get_value(FieldUnit::NONE) == m_xLeftMF->get_value(FieldUnit::NONE))
812     {
813         mbSync = true;
814     }
815     else
816         mbSync = false;
817     m_xSynchronizeCB->set_active(mbSync);
818 
819     mbRemoveAdjacentCellBorders = false;
820     m_xRemoveAdjcentCellBordersCB->set_active(false);
821     m_xRemoveAdjcentCellBordersCB->set_sensitive(false);
822 }
823 
824 void SvxBorderTabPage::ChangesApplied()
825 {
826     m_xLeftMF->save_value();
827     m_xRightMF->save_value();
828     m_xTopMF->save_value();
829     m_xBottomMF->save_value();
830     m_xMergeWithNextCB->save_state();
831     m_xMergeAdjacentBordersCB->save_state();
832 }
833 
834 DeactivateRC SvxBorderTabPage::DeactivatePage( SfxItemSet* _pSet )
835 {
836     if ( _pSet )
837         FillItemSet( _pSet );
838 
839     return DeactivateRC::LeavePage;
840 }
841 
842 bool SvxBorderTabPage::FillItemSet( SfxItemSet* rCoreAttrs )
843 {
844     bool bAttrsChanged = false;
845 
846     SfxItemPool* pPool = rCoreAttrs->GetPool();
847 
848     if (m_aFrameSel.IsBorderEnabled(svx::FrameBorderType::TLBR))
849     {
850         sal_uInt16 nBorderDiagId = pPool->GetWhich(SID_ATTR_BORDER_DIAG_TLBR);
851         SvxLineItem aLineItem(*static_cast<const SvxLineItem*>(rCoreAttrs->GetItem(nBorderDiagId)));
852         aLineItem.SetLine(m_aFrameSel.GetFrameBorderStyle(svx::FrameBorderType::TLBR));
853         rCoreAttrs->Put(aLineItem);
854         bAttrsChanged = true;
855     }
856 
857     if (m_aFrameSel.IsBorderEnabled(svx::FrameBorderType::BLTR))
858     {
859         sal_uInt16 nBorderDiagId = pPool->GetWhich(SID_ATTR_BORDER_DIAG_BLTR);
860         SvxLineItem aLineItem(*static_cast<const SvxLineItem*>(rCoreAttrs->GetItem(nBorderDiagId)));
861         aLineItem.SetLine(m_aFrameSel.GetFrameBorderStyle(svx::FrameBorderType::BLTR));
862         rCoreAttrs->Put(aLineItem);
863         bAttrsChanged = true;
864     }
865 
866     if (m_xShadowControls)
867     {
868         sal_uInt16 nShadowId = pPool->GetWhich(mnShadowSlot);
869         const SvxShadowItem& rOldShadowItem = *static_cast<const SvxShadowItem*>(rCoreAttrs->GetItem(nShadowId));
870         SvxShadowItem aNewShadowItem = m_xShadowControls->GetControlValue(rOldShadowItem);
871         if (aNewShadowItem != rOldShadowItem)
872         {
873             rCoreAttrs->Put(aNewShadowItem);
874             bAttrsChanged = true;
875         }
876     }
877 
878     if (m_xMarginControls && m_xMarginControls->get_value_changed_from_saved())
879     {
880         sal_uInt16 nAlignMarginId = pPool->GetWhich(SID_ATTR_ALIGN_MARGIN);
881         const SvxMarginItem& rOldMarginItem = *static_cast<const SvxMarginItem*>(rCoreAttrs->GetItem(nAlignMarginId));
882         rCoreAttrs->Put(m_xMarginControls->GetControlValue(rOldMarginItem));
883         bAttrsChanged = true;
884     }
885 
886     if (m_xMergeAdjacentBordersCB->get_state_changed_from_saved())
887     {
888         sal_uInt16 nMergeAdjacentBordersId = pPool->GetWhich(SID_SW_COLLAPSING_BORDERS);
889         auto nState = m_xMergeAdjacentBordersCB->get_state();
890         if (nState == TRISTATE_INDET)
891             rCoreAttrs->ClearItem(nMergeAdjacentBordersId);
892         else
893         {
894             std::unique_ptr<SfxBoolItem> xNewItem(static_cast<SfxBoolItem*>(rCoreAttrs->Get(nMergeAdjacentBordersId).Clone()));
895             xNewItem->SetValue(static_cast<bool>(nState));
896             rCoreAttrs->Put(*xNewItem);
897         }
898         bAttrsChanged = true;
899     }
900 
901     if (m_xMergeWithNextCB->get_state_changed_from_saved())
902     {
903         sal_uInt16 nMergeWithNextId = pPool->GetWhich(SID_ATTR_BORDER_CONNECT);
904         auto nState = m_xMergeWithNextCB->get_state();
905         if (nState == TRISTATE_INDET)
906             rCoreAttrs->ClearItem(nMergeWithNextId);
907         else
908         {
909             std::unique_ptr<SfxBoolItem> xNewItem(static_cast<SfxBoolItem*>(rCoreAttrs->Get(nMergeWithNextId).Clone()));
910             xNewItem->SetValue(static_cast<bool>(nState));
911             rCoreAttrs->Put(*xNewItem);
912         }
913         bAttrsChanged = true;
914     }
915 
916     bool                  bPut          = true;
917     sal_uInt16            nBoxWhich     = GetWhich( mnBoxSlot );
918     sal_uInt16            nBoxInfoWhich = pPool->GetWhich( SID_ATTR_BORDER_INNER, false );
919     const SfxItemSet&     rOldSet       = GetItemSet();
920     SvxBoxItem            aBoxItem      ( nBoxWhich );
921     SvxBoxInfoItem        aBoxInfoItem  ( nBoxInfoWhich );
922     const SvxBoxItem*     pOldBoxItem = static_cast<const SvxBoxItem*>(GetOldItem( *rCoreAttrs, mnBoxSlot ));
923 
924     MapUnit eCoreUnit = rOldSet.GetPool()->GetMetric( nBoxWhich );
925 
926 
927     // outer border:
928 
929     std::pair<svx::FrameBorderType,SvxBoxItemLine> eTypes1[] = {
930                                 { svx::FrameBorderType::Top,SvxBoxItemLine::TOP },
931                                 { svx::FrameBorderType::Bottom,SvxBoxItemLine::BOTTOM },
932                                 { svx::FrameBorderType::Left,SvxBoxItemLine::LEFT },
933                                 { svx::FrameBorderType::Right,SvxBoxItemLine::RIGHT },
934                             };
935 
936     for (std::pair<svx::FrameBorderType,SvxBoxItemLine> const & i : eTypes1)
937         aBoxItem.SetLine( m_aFrameSel.GetFrameBorderStyle( i.first ), i.second );
938 
939 
940     aBoxItem.SetRemoveAdjacentCellBorder( mbRemoveAdjacentCellBorders );
941     // border hor/ver and TableFlag
942 
943     std::pair<svx::FrameBorderType,SvxBoxInfoItemLine> eTypes2[] = {
944                                 { svx::FrameBorderType::Horizontal,SvxBoxInfoItemLine::HORI },
945                                 { svx::FrameBorderType::Vertical,SvxBoxInfoItemLine::VERT }
946                             };
947     for (std::pair<svx::FrameBorderType,SvxBoxInfoItemLine> const & j : eTypes2)
948         aBoxInfoItem.SetLine( m_aFrameSel.GetFrameBorderStyle( j.first ), j.second );
949 
950     aBoxInfoItem.EnableHor( mbHorEnabled );
951     aBoxInfoItem.EnableVer( mbVerEnabled );
952 
953 
954     // inner distance
955 
956     if (m_xLeftMF->get_visible())
957     {
958         // #i40405# enable distance controls for next dialog call
959         aBoxInfoItem.SetDist( true );
960 
961         if( !mbUseMarginItem )
962         {
963             // #106224# all edits empty: do nothing
964             if( !m_xLeftMF->get_text().isEmpty() || !m_xRightMF->get_text().isEmpty() ||
965                 !m_xTopMF->get_text().isEmpty() || !m_xBottomMF->get_text().isEmpty() )
966             {
967                 const SvxBoxInfoItem* pOldBoxInfoItem = GetOldItem( *rCoreAttrs, SID_ATTR_BORDER_INNER );
968                 if (
969                     !pOldBoxItem ||
970                     m_xLeftMF->get_value_changed_from_saved() ||
971                     m_xRightMF->get_value_changed_from_saved() ||
972                     m_xTopMF->get_value_changed_from_saved() ||
973                     m_xBottomMF->get_value_changed_from_saved() ||
974                     nMinValue == m_xLeftMF->get_value(FieldUnit::NONE) ||
975                     nMinValue == m_xRightMF->get_value(FieldUnit::NONE) ||
976                     nMinValue == m_xTopMF->get_value(FieldUnit::NONE) ||
977                     nMinValue == m_xBottomMF->get_value(FieldUnit::NONE) ||
978                     (pOldBoxInfoItem && !pOldBoxInfoItem->IsValid(SvxBoxInfoItemValidFlags::DISTANCE))
979                    )
980                 {
981                     aBoxItem.SetDistance( static_cast<sal_uInt16>(GetCoreValue(*m_xLeftMF, eCoreUnit )), SvxBoxItemLine::LEFT  );
982                     aBoxItem.SetDistance( static_cast<sal_uInt16>(GetCoreValue(*m_xRightMF, eCoreUnit )), SvxBoxItemLine::RIGHT );
983                     aBoxItem.SetDistance( static_cast<sal_uInt16>(GetCoreValue(*m_xTopMF, eCoreUnit )), SvxBoxItemLine::TOP   );
984                     aBoxItem.SetDistance( static_cast<sal_uInt16>(GetCoreValue(*m_xBottomMF, eCoreUnit )), SvxBoxItemLine::BOTTOM);
985                 }
986                 else
987                 {
988                     aBoxItem.SetDistance(pOldBoxItem->GetDistance(SvxBoxItemLine::LEFT ), SvxBoxItemLine::LEFT);
989                     aBoxItem.SetDistance(pOldBoxItem->GetDistance(SvxBoxItemLine::RIGHT),  SvxBoxItemLine::RIGHT);
990                     aBoxItem.SetDistance(pOldBoxItem->GetDistance(SvxBoxItemLine::TOP  ), SvxBoxItemLine::TOP);
991                     aBoxItem.SetDistance(pOldBoxItem->GetDistance(SvxBoxItemLine::BOTTOM), SvxBoxItemLine::BOTTOM);
992                 }
993                 aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::DISTANCE );
994             }
995         }
996     }
997 
998 
999     // note Don't Care Status in the Info-Item:
1000 
1001     aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::TOP,    m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Top )    != svx::FrameBorderState::DontCare );
1002     aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Bottom ) != svx::FrameBorderState::DontCare );
1003     aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::LEFT,   m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Left )   != svx::FrameBorderState::DontCare );
1004     aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::RIGHT,  m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Right )  != svx::FrameBorderState::DontCare );
1005     aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::HORI,   m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Horizontal )    != svx::FrameBorderState::DontCare );
1006     aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::VERT,   m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Vertical )    != svx::FrameBorderState::DontCare );
1007 
1008 
1009     // Put or Clear of the border?
1010 
1011     bPut = true;
1012 
1013     if (   SfxItemState::DEFAULT == rOldSet.GetItemState( nBoxWhich,     false ))
1014     {
1015         bPut = aBoxItem != static_cast<const SvxBoxItem&>(rOldSet.Get(nBoxWhich));
1016     }
1017     if(  SfxItemState::DEFAULT == rOldSet.GetItemState( nBoxInfoWhich, false ) )
1018     {
1019         const SvxBoxInfoItem& rOldBoxInfo = static_cast<const SvxBoxInfoItem&>(
1020                                 rOldSet.Get(nBoxInfoWhich));
1021 
1022         aBoxInfoItem.SetMinDist( rOldBoxInfo.IsMinDist() );
1023         aBoxInfoItem.SetDefDist( rOldBoxInfo.GetDefDist() );
1024         bPut |= (aBoxInfoItem != rOldBoxInfo );
1025     }
1026 
1027     if ( bPut )
1028     {
1029         if ( !pOldBoxItem || *pOldBoxItem != aBoxItem )
1030         {
1031             rCoreAttrs->Put( aBoxItem );
1032             bAttrsChanged = true;
1033         }
1034         const SfxPoolItem* pOld = GetOldItem( *rCoreAttrs, SID_ATTR_BORDER_INNER, false );
1035 
1036         if ( !pOld || *static_cast<const SvxBoxInfoItem*>(pOld) != aBoxInfoItem )
1037         {
1038             rCoreAttrs->Put( aBoxInfoItem );
1039             bAttrsChanged = true;
1040         }
1041     }
1042     else
1043     {
1044         rCoreAttrs->ClearItem( nBoxWhich );
1045         rCoreAttrs->ClearItem( nBoxInfoWhich );
1046     }
1047 
1048     return bAttrsChanged;
1049 }
1050 
1051 void SvxBorderTabPage::HideShadowControls()
1052 {
1053     m_xShadowFrame->hide();
1054 }
1055 
1056 #define IID_PRE_CELL_NONE       1
1057 #define IID_PRE_CELL_ALL        2
1058 #define IID_PRE_CELL_LR         3
1059 #define IID_PRE_CELL_TB         4
1060 #define IID_PRE_CELL_L          5
1061 #define IID_PRE_CELL_DIAG       6
1062 #define IID_PRE_HOR_NONE        7
1063 #define IID_PRE_HOR_OUTER       8
1064 #define IID_PRE_HOR_HOR         9
1065 #define IID_PRE_HOR_ALL         10
1066 #define IID_PRE_HOR_OUTER2      11
1067 #define IID_PRE_VER_NONE        12
1068 #define IID_PRE_VER_OUTER       13
1069 #define IID_PRE_VER_VER         14
1070 #define IID_PRE_VER_ALL         15
1071 #define IID_PRE_VER_OUTER2      16
1072 #define IID_PRE_TABLE_NONE      17
1073 #define IID_PRE_TABLE_OUTER     18
1074 #define IID_PRE_TABLE_OUTERH    19
1075 #define IID_PRE_TABLE_ALL       20
1076 #define IID_PRE_TABLE_OUTER2    21
1077 
1078 IMPL_LINK_NOARG(SvxBorderTabPage, SelPreHdl_Impl, SvtValueSet*, void)
1079 {
1080     const svx::FrameBorderState SHOW = svx::FrameBorderState::Show;
1081     const svx::FrameBorderState HIDE = svx::FrameBorderState::Hide;
1082     const svx::FrameBorderState DONT = svx::FrameBorderState::DontCare;
1083 
1084     static const svx::FrameBorderState ppeStates[][ svx::FRAMEBORDERTYPE_COUNT ] =
1085     {                   /*    Left  Right Top   Bot   Hor   Ver   TLBR  BLTR */
1086 /* ---------------------+--------------------------------------------------- */
1087 /* IID_PRE_CELL_NONE    */  { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE },
1088 /* IID_PRE_CELL_ALL     */  { SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE },
1089 /* IID_PRE_CELL_LR      */  { SHOW, SHOW, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE },
1090 /* IID_PRE_CELL_TB      */  { HIDE, HIDE, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE },
1091 /* IID_PRE_CELL_L       */  { SHOW, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE },
1092 /* IID_PRE_CELL_DIAG    */  { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, SHOW, SHOW },
1093 /* IID_PRE_HOR_NONE     */  { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE },
1094 /* IID_PRE_HOR_OUTER    */  { SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE },
1095 /* IID_PRE_HOR_HOR      */  { HIDE, HIDE, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE },
1096 /* IID_PRE_HOR_ALL      */  { SHOW, SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE },
1097 /* IID_PRE_HOR_OUTER2   */  { SHOW, SHOW, SHOW, SHOW, DONT, HIDE, HIDE, HIDE },
1098 /* IID_PRE_VER_NONE     */  { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE },
1099 /* IID_PRE_VER_OUTER    */  { SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE },
1100 /* IID_PRE_VER_VER      */  { SHOW, SHOW, HIDE, HIDE, HIDE, SHOW, HIDE, HIDE },
1101 /* IID_PRE_VER_ALL      */  { SHOW, SHOW, SHOW, SHOW, HIDE, SHOW, HIDE, HIDE },
1102 /* IID_PRE_VER_OUTER2   */  { SHOW, SHOW, SHOW, SHOW, HIDE, DONT, HIDE, HIDE },
1103 /* IID_PRE_TABLE_NONE   */  { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE },
1104 /* IID_PRE_TABLE_OUTER  */  { SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE },
1105 /* IID_PRE_TABLE_OUTERH */  { SHOW, SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE },
1106 /* IID_PRE_TABLE_ALL    */  { SHOW, SHOW, SHOW, SHOW, SHOW, SHOW, HIDE, HIDE },
1107 /* IID_PRE_TABLE_OUTER2 */  { SHOW, SHOW, SHOW, SHOW, DONT, DONT, HIDE, HIDE }
1108     };
1109 
1110     // first hide and deselect all frame borders
1111     m_aFrameSel.HideAllBorders();
1112     m_aFrameSel.DeselectAllBorders();
1113 
1114     // Using image ID to find correct line in table above.
1115     sal_uInt16 nLine = GetPresetImageId( m_xWndPresets->GetSelectedItemId() ) - 1;
1116 
1117     // Apply all styles from the table
1118     for( int nBorder = 0; nBorder < svx::FRAMEBORDERTYPE_COUNT; ++nBorder )
1119     {
1120         svx::FrameBorderType eBorder = svx::GetFrameBorderTypeFromIndex( nBorder );
1121         switch( ppeStates[ nLine ][ nBorder ] )
1122         {
1123             case SHOW:  m_aFrameSel.SelectBorder( eBorder );      break;
1124             case HIDE:  /* nothing to do */                     break;
1125             case DONT:  m_aFrameSel.SetBorderDontCare( eBorder ); break;
1126         }
1127     }
1128 
1129     // Show all lines that have been selected above
1130     if( m_aFrameSel.IsAnyBorderSelected() )
1131     {
1132         // any visible style, but "no-line" in line list box? -> use hair-line
1133         if (m_xLbLineStyle->GetSelectEntryStyle() == SvxBorderLineStyle::NONE)
1134             m_xLbLineStyle->SelectEntry(SvxBorderLineStyle::SOLID);
1135 
1136         // set current style to all previously selected lines
1137         SelStyleHdl_Impl(*m_xLbLineStyle);
1138         SelColHdl_Impl(*m_xLbLineColor);
1139     }
1140 
1141     // Presets ValueSet does not show a selection (used as push buttons).
1142     m_xWndPresets->SetNoSelection();
1143 
1144     LinesChanged_Impl( nullptr );
1145     UpdateRemoveAdjCellBorderCB( nLine + 1 );
1146 }
1147 
1148 IMPL_LINK_NOARG(SvxBorderTabPage, SelSdwHdl_Impl, SvtValueSet*, void)
1149 {
1150     bool bEnable = m_xWndShadows->GetSelectedItemId() > 1;
1151     m_xFtShadowSize->set_sensitive(bEnable);
1152     m_xEdShadowSize->set_sensitive(bEnable);
1153     m_xFtShadowColor->set_sensitive(bEnable);
1154     m_xLbShadowColor->set_sensitive(bEnable);
1155 }
1156 
1157 IMPL_LINK(SvxBorderTabPage, SelColHdl_Impl, ColorListBox&, rColorBox, void)
1158 {
1159     Color aColor = rColorBox.GetSelectEntryColor();
1160     m_aFrameSel.SetColorToSelection(aColor);
1161 }
1162 
1163 IMPL_LINK_NOARG(SvxBorderTabPage, ModifyWidthHdl_Impl, weld::MetricSpinButton&, void)
1164 {
1165     sal_Int64 nVal = m_xLineWidthMF->get_value(FieldUnit::NONE);
1166     nVal = static_cast<sal_Int64>(MetricField::ConvertDoubleValue(
1167                 nVal,
1168                 m_xLineWidthMF->get_digits(),
1169                 FieldUnit::POINT, MapUnit::MapTwip ));
1170     m_xLbLineStyle->SetWidth( nVal );
1171 
1172     m_aFrameSel.SetStyleToSelection( nVal,
1173         m_xLbLineStyle->GetSelectEntryStyle() );
1174 }
1175 
1176 IMPL_LINK_NOARG(SvxBorderTabPage, SelStyleHdl_Impl, SvtLineListBox&, void)
1177 {
1178     sal_Int64 nVal = m_xLineWidthMF->get_value(FieldUnit::NONE);
1179     nVal = static_cast<sal_Int64>(MetricField::ConvertDoubleValue(
1180                 nVal,
1181                 m_xLineWidthMF->get_digits(),
1182                 FieldUnit::POINT, MapUnit::MapTwip ));
1183     m_aFrameSel.SetStyleToSelection ( nVal,
1184         m_xLbLineStyle->GetSelectEntryStyle() );
1185 }
1186 
1187 // ValueSet handling
1188 sal_uInt16 SvxBorderTabPage::GetPresetImageId( sal_uInt16 nValueSetIdx ) const
1189 {
1190     // table with all sets of predefined border styles
1191     static const sal_uInt16 ppnImgIds[][ SVX_BORDER_PRESET_COUNT ] =
1192     {
1193         // simple cell without diagonal frame borders
1194         {   IID_PRE_CELL_NONE,  IID_PRE_CELL_ALL,       IID_PRE_CELL_LR,        IID_PRE_CELL_TB,    IID_PRE_CELL_L          },
1195         // simple cell with diagonal frame borders
1196         {   IID_PRE_CELL_NONE,  IID_PRE_CELL_ALL,       IID_PRE_CELL_LR,        IID_PRE_CELL_TB,    IID_PRE_CELL_DIAG       },
1197         // with horizontal inner frame border
1198         {   IID_PRE_HOR_NONE,   IID_PRE_HOR_OUTER,      IID_PRE_HOR_HOR,        IID_PRE_HOR_ALL,    IID_PRE_HOR_OUTER2      },
1199         // with vertical inner frame border
1200         {   IID_PRE_VER_NONE,   IID_PRE_VER_OUTER,      IID_PRE_VER_VER,        IID_PRE_VER_ALL,    IID_PRE_VER_OUTER2      },
1201         // with horizontal and vertical inner frame borders
1202         {   IID_PRE_TABLE_NONE, IID_PRE_TABLE_OUTER,    IID_PRE_TABLE_OUTERH,   IID_PRE_TABLE_ALL,  IID_PRE_TABLE_OUTER2    }
1203     };
1204 
1205     // find correct set of presets
1206     int nLine = 0;
1207     if( !mbHorEnabled && !mbVerEnabled )
1208         nLine = (mbTLBREnabled || mbBLTREnabled) ? 1 : 0;
1209     else if( mbHorEnabled && !mbVerEnabled )
1210         nLine = 2;
1211     else if( !mbHorEnabled && mbVerEnabled )
1212         nLine = 3;
1213     else
1214         nLine = 4;
1215 
1216     DBG_ASSERT( (1 <= nValueSetIdx) && (nValueSetIdx <= SVX_BORDER_PRESET_COUNT),
1217         "SvxBorderTabPage::GetPresetImageId - wrong index" );
1218     return ppnImgIds[ nLine ][ nValueSetIdx - 1 ];
1219 }
1220 
1221 const char* SvxBorderTabPage::GetPresetStringId( sal_uInt16 nValueSetIdx ) const
1222 {
1223     // string resource IDs for each image (in order of the IID_PRE_* image IDs)
1224     static const char* pnStrIds[] =
1225     {
1226         RID_SVXSTR_TABLE_PRESET_NONE,
1227         RID_SVXSTR_PARA_PRESET_ALL,
1228         RID_SVXSTR_PARA_PRESET_LEFTRIGHT,
1229         RID_SVXSTR_PARA_PRESET_TOPBOTTOM,
1230         RID_SVXSTR_PARA_PRESET_ONLYLEFT,
1231         RID_SVXSTR_PARA_PRESET_DIAGONAL,
1232 
1233         RID_SVXSTR_TABLE_PRESET_NONE,
1234         RID_SVXSTR_TABLE_PRESET_ONLYOUTER,
1235         RID_SVXSTR_HOR_PRESET_ONLYHOR,
1236         RID_SVXSTR_TABLE_PRESET_OUTERALL,
1237         RID_SVXSTR_TABLE_PRESET_OUTERINNER,
1238 
1239         RID_SVXSTR_TABLE_PRESET_NONE,
1240         RID_SVXSTR_TABLE_PRESET_ONLYOUTER,
1241         RID_SVXSTR_VER_PRESET_ONLYVER,
1242         RID_SVXSTR_TABLE_PRESET_OUTERALL,
1243         RID_SVXSTR_TABLE_PRESET_OUTERINNER,
1244 
1245         RID_SVXSTR_TABLE_PRESET_NONE,
1246         RID_SVXSTR_TABLE_PRESET_ONLYOUTER,
1247         RID_SVXSTR_TABLE_PRESET_OUTERHORI,
1248         RID_SVXSTR_TABLE_PRESET_OUTERALL,
1249         RID_SVXSTR_TABLE_PRESET_OUTERINNER
1250     };
1251     return pnStrIds[ GetPresetImageId( nValueSetIdx ) - 1 ];
1252 }
1253 
1254 void SvxBorderTabPage::FillPresetVS()
1255 {
1256     // basic initialization of the ValueSet
1257     m_xWndPresets->SetStyle( m_xWndPresets->GetStyle() | WB_ITEMBORDER | WB_DOUBLEBORDER );
1258     m_xWndPresets->SetColCount( SVX_BORDER_PRESET_COUNT );
1259 
1260     // insert images and help texts
1261     for( sal_uInt16 nVSIdx = 1; nVSIdx <= SVX_BORDER_PRESET_COUNT; ++nVSIdx )
1262     {
1263         m_xWndPresets->InsertItem( nVSIdx );
1264         m_xWndPresets->SetItemImage(nVSIdx, m_aBorderImgVec[GetPresetImageId(nVSIdx) - 1]);
1265         m_xWndPresets->SetItemText( nVSIdx, CuiResId( GetPresetStringId( nVSIdx ) ) );
1266     }
1267 
1268     // show the control
1269     m_xWndPresets->SetNoSelection();
1270     m_xWndPresets->SetOptimalSize();
1271     m_xWndPresets->Show();
1272 }
1273 
1274 void SvxBorderTabPage::FillShadowVS()
1275 {
1276     // basic initialization of the ValueSet
1277     m_xWndShadows->SetStyle( m_xWndShadows->GetStyle() | WB_ITEMBORDER | WB_DOUBLEBORDER );
1278     m_xWndShadows->SetColCount( SVX_BORDER_SHADOW_COUNT );
1279 
1280     // string resource IDs for each image
1281     static const char* pnStrIds[ SVX_BORDER_SHADOW_COUNT ] =
1282         { RID_SVXSTR_SHADOW_STYLE_NONE, RID_SVXSTR_SHADOW_STYLE_BOTTOMRIGHT, RID_SVXSTR_SHADOW_STYLE_TOPRIGHT, RID_SVXSTR_SHADOW_STYLE_BOTTOMLEFT, RID_SVXSTR_SHADOW_STYLE_TOPLEFT };
1283 
1284     // insert images and help texts
1285     for( sal_uInt16 nVSIdx = 1; nVSIdx <= SVX_BORDER_SHADOW_COUNT; ++nVSIdx )
1286     {
1287         m_xWndShadows->InsertItem( nVSIdx );
1288         m_xWndShadows->SetItemImage(nVSIdx, m_aShadowImgVec[nVSIdx-1]);
1289         m_xWndShadows->SetItemText( nVSIdx, CuiResId( pnStrIds[ nVSIdx - 1 ] ) );
1290     }
1291 
1292     // show the control
1293     m_xWndShadows->SelectItem( 1 );
1294     m_xWndShadows->SetOptimalSize();
1295     m_xWndShadows->Show();
1296 }
1297 
1298 
1299 void SvxBorderTabPage::FillValueSets()
1300 {
1301     FillPresetVS();
1302     FillShadowVS();
1303 }
1304 
1305 
1306 static Color lcl_mediumColor( Color aMain, Color /*aDefault*/ )
1307 {
1308     return SvxBorderLine::threeDMediumColor( aMain );
1309 }
1310 
1311 void SvxBorderTabPage::FillLineListBox_Impl()
1312 {
1313     using namespace ::com::sun::star::table::BorderLineStyle;
1314 
1315     static struct {
1316         SvxBorderLineStyle mnStyle;
1317         long mnMinWidth;
1318         SvtLineListBox::ColorFunc mpColor1Fn;
1319         SvtLineListBox::ColorFunc mpColor2Fn;
1320         SvtLineListBox::ColorDistFunc mpColorDistFn;
1321     } const aLines[] = {
1322         // Simple lines
1323         { SvxBorderLineStyle::SOLID,        0, &sameColor, &sameColor, &sameDistColor },
1324         { SvxBorderLineStyle::DOTTED,       0, &sameColor, &sameColor, &sameDistColor },
1325         { SvxBorderLineStyle::DASHED,       0, &sameColor, &sameColor, &sameDistColor },
1326         { SvxBorderLineStyle::FINE_DASHED,  0, &sameColor, &sameColor, &sameDistColor },
1327         { SvxBorderLineStyle::DASH_DOT,     0, &sameColor, &sameColor, &sameDistColor },
1328         { SvxBorderLineStyle::DASH_DOT_DOT, 0, &sameColor, &sameColor, &sameDistColor },
1329 
1330         // Double lines
1331         { SvxBorderLineStyle::DOUBLE,              10, &sameColor, &sameColor, &sameDistColor },
1332         { SvxBorderLineStyle::DOUBLE_THIN,         10, &sameColor, &sameColor, &sameDistColor },
1333         { SvxBorderLineStyle::THINTHICK_SMALLGAP,  20, &sameColor, &sameColor, &sameDistColor },
1334         { SvxBorderLineStyle::THINTHICK_MEDIUMGAP,  0, &sameColor, &sameColor, &sameDistColor },
1335         { SvxBorderLineStyle::THINTHICK_LARGEGAP,   0, &sameColor, &sameColor, &sameDistColor },
1336         { SvxBorderLineStyle::THICKTHIN_SMALLGAP,  20, &sameColor, &sameColor, &sameDistColor },
1337         { SvxBorderLineStyle::THICKTHIN_MEDIUMGAP,  0, &sameColor, &sameColor, &sameDistColor },
1338         { SvxBorderLineStyle::THICKTHIN_LARGEGAP,   0, &sameColor, &sameColor, &sameDistColor },
1339 
1340         { SvxBorderLineStyle::EMBOSSED, 15, &SvxBorderLine::threeDLightColor, &SvxBorderLine::threeDDarkColor, &lcl_mediumColor },
1341         { SvxBorderLineStyle::ENGRAVED, 15, &SvxBorderLine::threeDDarkColor, &SvxBorderLine::threeDLightColor, &lcl_mediumColor },
1342 
1343         { SvxBorderLineStyle::OUTSET, 10, &SvxBorderLine::lightColor, &SvxBorderLine::darkColor, &sameDistColor },
1344         { SvxBorderLineStyle::INSET,  10, &SvxBorderLine::darkColor, &SvxBorderLine::lightColor, &sameDistColor }
1345     };
1346 
1347     m_xLbLineStyle->SetSourceUnit( FieldUnit::TWIP );
1348 
1349     for (size_t i = 0; i < SAL_N_ELEMENTS(aLines); ++i)
1350     {
1351         if (!IsBorderLineStyleAllowed(aLines[i].mnStyle))
1352             continue;
1353 
1354         m_xLbLineStyle->InsertEntry(
1355             SvxBorderLine::getWidthImpl(aLines[i].mnStyle), aLines[i].mnStyle,
1356             aLines[i].mnMinWidth, aLines[i].mpColor1Fn, aLines[i].mpColor2Fn, aLines[i].mpColorDistFn);
1357     }
1358 
1359     sal_Int64 nVal = m_xLineWidthMF->get_value(FieldUnit::NONE);
1360     nVal = static_cast<sal_Int64>(MetricField::ConvertDoubleValue(nVal, m_xLineWidthMF->get_digits(),
1361                                                                   m_xLineWidthMF->get_unit(), MapUnit::MapTwip));
1362     m_xLbLineStyle->SetWidth( nVal );
1363 }
1364 
1365 
1366 IMPL_LINK_NOARG(SvxBorderTabPage, LinesChanged_Impl, LinkParamNone*, void)
1367 {
1368     if (!mbUseMarginItem && m_xLeftMF->get_visible())
1369     {
1370         bool bLineSet = m_aFrameSel.IsAnyBorderVisible();
1371         bool bSpaceModified =   mbLeftModified ||
1372                                 mbRightModified ||
1373                                 mbTopModified ||
1374                                 mbBottomModified;
1375 
1376         if(bLineSet)
1377         {
1378             if(!bSpaceModified)
1379             {
1380                 m_xLeftMF->set_value(nMinValue, FieldUnit::NONE);
1381                 m_xRightMF->set_value(nMinValue, FieldUnit::NONE);
1382                 m_xTopMF->set_value(nMinValue, FieldUnit::NONE);
1383                 m_xBottomMF->set_value(nMinValue, FieldUnit::NONE);
1384             }
1385         }
1386         else
1387         {
1388             m_xLeftMF->set_min(0, FieldUnit::NONE);
1389             m_xRightMF->set_min(0, FieldUnit::NONE);
1390             m_xTopMF->set_min(0, FieldUnit::NONE);
1391             m_xBottomMF->set_min(0, FieldUnit::NONE);
1392         }
1393         // for tables everything is allowed
1394         SvxBoxInfoItemValidFlags nValid = SvxBoxInfoItemValidFlags::TOP|SvxBoxInfoItemValidFlags::BOTTOM|SvxBoxInfoItemValidFlags::LEFT|SvxBoxInfoItemValidFlags::RIGHT;
1395 
1396         m_xLeftFT->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::LEFT) );
1397         m_xRightFT->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::RIGHT) );
1398         m_xTopFT->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::TOP) );
1399         m_xBottomFT->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::BOTTOM) );
1400         m_xLeftMF->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::LEFT) );
1401         m_xRightMF->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::RIGHT) );
1402         m_xTopMF->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::TOP) );
1403         m_xBottomMF->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::BOTTOM) );
1404         m_xSynchronizeCB->set_sensitive(m_xRightMF->get_sensitive() || m_xTopMF->get_sensitive() ||
1405                                         m_xBottomMF->get_sensitive() || m_xLeftMF->get_sensitive());
1406     }
1407     UpdateRemoveAdjCellBorderCB( SAL_MAX_UINT16 );
1408 }
1409 
1410 
1411 IMPL_LINK( SvxBorderTabPage, ModifyDistanceHdl_Impl, weld::MetricSpinButton&, rField, void)
1412 {
1413     if (&rField == m_xLeftMF.get())
1414         mbLeftModified = true;
1415     else if (&rField == m_xRightMF.get())
1416         mbRightModified = true;
1417     else if (&rField == m_xTopMF.get())
1418         mbTopModified = true;
1419     else if (&rField == m_xBottomMF.get())
1420         mbBottomModified = true;
1421 
1422     if (mbSync)
1423     {
1424         const auto nVal = rField.get_value(FieldUnit::NONE);
1425         if (&rField != m_xLeftMF.get())
1426             m_xLeftMF->set_value(nVal, FieldUnit::NONE);
1427         if (&rField != m_xRightMF.get())
1428             m_xRightMF->set_value(nVal, FieldUnit::NONE);
1429         if (&rField != m_xTopMF.get())
1430             m_xTopMF->set_value(nVal, FieldUnit::NONE);
1431         if (&rField != m_xBottomMF.get())
1432             m_xBottomMF->set_value(nVal, FieldUnit::NONE);
1433     }
1434 }
1435 
1436 IMPL_LINK( SvxBorderTabPage, SyncHdl_Impl, weld::ToggleButton&, rBox, void)
1437 {
1438     mbSync = rBox.get_active();
1439 }
1440 
1441 IMPL_LINK( SvxBorderTabPage, RemoveAdjacentCellBorderHdl_Impl, weld::ToggleButton&, rBox, void)
1442 {
1443     mbRemoveAdjacentCellBorders = rBox.get_active();
1444 }
1445 
1446 void SvxBorderTabPage::UpdateRemoveAdjCellBorderCB( sal_uInt16 nPreset )
1447 {
1448     if( !bIsCalcDoc )
1449         return;
1450     const SfxItemSet&     rOldSet         = GetItemSet();
1451     const SvxBoxInfoItem* pOldBoxInfoItem = GetOldItem( rOldSet, SID_ATTR_BORDER_INNER );
1452     const SvxBoxItem*     pOldBoxItem     = static_cast<const SvxBoxItem*>(GetOldItem( rOldSet, mnBoxSlot ));
1453     if( !pOldBoxInfoItem || !pOldBoxItem )
1454         return;
1455     std::pair<svx::FrameBorderType, SvxBoxInfoItemValidFlags> eTypes1[] = {
1456         { svx::FrameBorderType::Top,SvxBoxInfoItemValidFlags::TOP },
1457         { svx::FrameBorderType::Bottom,SvxBoxInfoItemValidFlags::BOTTOM },
1458         { svx::FrameBorderType::Left,SvxBoxInfoItemValidFlags::LEFT },
1459         { svx::FrameBorderType::Right,SvxBoxInfoItemValidFlags::RIGHT },
1460     };
1461     SvxBoxItemLine const eTypes2[] = {
1462         SvxBoxItemLine::TOP,
1463         SvxBoxItemLine::BOTTOM,
1464         SvxBoxItemLine::LEFT,
1465         SvxBoxItemLine::RIGHT,
1466     };
1467 
1468     // Check if current selection involves deletion of at least one border
1469     bool bBorderDeletionReq = false;
1470     for ( size_t i=0; i < SAL_N_ELEMENTS( eTypes1 ); ++i )
1471     {
1472         if( pOldBoxItem->GetLine( eTypes2[i] ) || !( pOldBoxInfoItem->IsValid( eTypes1[i].second ) ) )
1473         {
1474             if( m_aFrameSel.GetFrameBorderState( eTypes1[i].first ) == svx::FrameBorderState::Hide )
1475             {
1476                 bBorderDeletionReq = true;
1477                 break;
1478             }
1479         }
1480     }
1481 
1482     if( !bBorderDeletionReq && ( nPreset == IID_PRE_CELL_NONE || nPreset == IID_PRE_TABLE_NONE ) )
1483         bBorderDeletionReq = true;
1484 
1485     m_xRemoveAdjcentCellBordersCB->set_sensitive(bBorderDeletionReq);
1486 
1487     if( !bBorderDeletionReq )
1488     {
1489         mbRemoveAdjacentCellBorders = false;
1490         m_xRemoveAdjcentCellBordersCB->set_active(false);
1491     }
1492 }
1493 
1494 void SvxBorderTabPage::DataChanged( const DataChangedEvent& rDCEvt )
1495 {
1496     if( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
1497         FillValueSets();
1498 
1499     SfxTabPage::DataChanged( rDCEvt );
1500 }
1501 
1502 void SvxBorderTabPage::PageCreated(const SfxAllItemSet& aSet)
1503 {
1504     const SfxUInt16Item* pSWModeItem = aSet.GetItem<SfxUInt16Item>(SID_SWMODE_TYPE, false);
1505     const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
1506     if (pSWModeItem)
1507     {
1508         nSWMode = static_cast<SwBorderModes>(pSWModeItem->GetValue());
1509         // #i43593#
1510         // show checkbox <m_xMergeWithNextCB> for format.paragraph
1511         if ( nSWMode == SwBorderModes::PARA )
1512         {
1513             m_xMergeWithNextCB->show();
1514             m_xPropertiesFrame->show();
1515         }
1516         // show checkbox <m_xMergeAdjacentBordersCB> for format.paragraph
1517         else if ( nSWMode == SwBorderModes::TABLE )
1518         {
1519             m_xMergeAdjacentBordersCB->show();
1520             m_xPropertiesFrame->show();
1521         }
1522     }
1523     if (pFlagItem)
1524         if ( ( pFlagItem->GetValue() & SVX_HIDESHADOWCTL ) == SVX_HIDESHADOWCTL )
1525             HideShadowControls();
1526 }
1527 
1528 void SvxBorderTabPage::SetTableMode()
1529 {
1530     nSWMode = SwBorderModes::TABLE;
1531 }
1532 
1533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1534