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