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