tdf#164393 Change themes UI as per UX feedback
[LibreOffice.git] / svx / source / dialog / framelink.cxx
blob60adda1d7136aa050665b7d441ba86a366fb75a6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <rtl/math.hxx>
23 #include <svx/framelink.hxx>
25 #include <editeng/borderline.hxx>
26 #include <o3tl/hash_combine.hxx>
29 using namespace ::com::sun::star;
30 using namespace editeng;
32 namespace svx::frame
35 Style::Style( double nP, double nD, double nS, SvxBorderLineStyle nType, double fScale )
37 Clear();
38 mnType = nType;
39 mfPatternScale = fScale;
40 Set( nP, nD, nS );
43 Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS, SvxBorderLineStyle nType, double fScale )
45 Clear();
46 mnType = nType;
47 mfPatternScale = fScale;
48 Set( rColorPrim, rColorSecn, rColorGap, bUseGapColor, nP, nD, nS );
51 Style::Style( const editeng::SvxBorderLine* pBorder, double fScale )
53 Clear();
54 if(nullptr != pBorder)
56 mfPatternScale = fScale;
57 Set( pBorder, fScale );
61 void Style::Clear()
63 maColorPrim = Color();
64 maColorSecn = Color();
65 maColorGap = Color();
66 mbUseGapColor = false;
67 meRefMode = RefMode::Centered;
68 mfPrim = 0.0;
69 mfDist = 0.0;
70 mfSecn = 0.0;
71 mfPatternScale = 1.0;
72 mnType = SvxBorderLineStyle::SOLID;
73 mbWordTableCell = false;
76 void Style::Set( double nP, double nD, double nS )
78 /* nP nD nS -> mfPrim mfDist mfSecn
79 --------------------------------------
80 any any 0 nP 0 0
81 0 any >0 nS 0 0
82 >0 0 >0 nP 0 0
83 >0 >0 >0 nP nD nS
85 mfPrim = rtl::math::round(nP ? nP : nS, 2);
86 mfDist = rtl::math::round((nP && nS) ? nD : 0, 2);
87 mfSecn = rtl::math::round((nP && nD) ? nS : 0, 2);
90 void Style::Set( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS )
92 maColorPrim = rColorPrim;
93 maColorSecn = rColorSecn;
94 maColorGap = rColorGap;
95 mbUseGapColor = bUseGapColor;
96 Set( nP, nD, nS );
99 void Style::Set( const SvxBorderLine* pBorder, double fScale, sal_uInt16 nMaxWidth )
101 if(nullptr == pBorder)
103 Clear();
104 return;
107 maColorPrim = pBorder->GetColorOut();
108 maColorSecn = pBorder->GetColorIn();
109 maColorGap = pBorder->GetColorGap();
110 mbUseGapColor = pBorder->HasGapColor();
112 const sal_uInt16 nPrim(pBorder->GetOutWidth());
113 const sal_uInt16 nDist(pBorder->GetDistance());
114 const sal_uInt16 nSecn(pBorder->GetInWidth());
116 mnType = pBorder->GetBorderLineStyle();
117 mfPatternScale = fScale;
119 if( !nSecn ) // no or single frame border
121 Set( std::min<double>(nPrim * fScale, nMaxWidth), 0, 0 );
123 else
125 Set(std::min<double>(nPrim * fScale, nMaxWidth), std::min<double>(nDist * fScale, nMaxWidth), std::min<double>(nSecn * fScale, nMaxWidth));
126 // Enlarge the style if distance is too small due to rounding losses.
127 double nPixWidth = std::min<double>((nPrim + nDist + nSecn) * fScale, nMaxWidth);
129 if( nPixWidth > GetWidth() )
131 mfDist = nPixWidth - mfPrim - mfSecn;
134 // Shrink the style if it is too thick for the control.
135 while( GetWidth() > nMaxWidth )
137 // First decrease space between lines.
138 if (mfDist)
140 --mfDist;
141 continue;
144 // Still too thick? Decrease the line widths.
145 if (mfPrim != 0.0 && rtl::math::approxEqual(mfPrim, mfSecn))
147 // Both lines equal - decrease both to keep symmetry.
148 --mfPrim;
149 --mfSecn;
150 continue;
153 // Decrease each line for itself
154 if (mfPrim)
155 --mfPrim;
157 if ((GetWidth() > nMaxWidth) && mfSecn != 0.0)
158 --mfSecn;
163 void Style::MirrorSelf()
165 if (mfSecn)
167 std::swap( mfPrim, mfSecn );
168 // also need to swap colors
169 std::swap( maColorPrim, maColorSecn );
172 if( meRefMode != RefMode::Centered )
174 meRefMode = (meRefMode == RefMode::Begin) ? RefMode::End : RefMode::Begin;
178 bool Style::operator==( const Style& rOther) const
180 if (this == &rOther)
181 // ptr compare (same instance)
182 return true;
184 return (Prim() == rOther.Prim()
185 && Dist() == rOther.Dist()
186 && Secn() == rOther.Secn()
187 && GetColorPrim() == rOther.GetColorPrim()
188 && GetColorSecn() == rOther.GetColorSecn()
189 && GetColorGap() == rOther.GetColorGap()
190 && GetRefMode() == rOther.GetRefMode()
191 && UseGapColor() == rOther.UseGapColor()
192 && Type() == rOther.Type());
195 size_t Style::hashCode() const
197 std::size_t seed = 0;
198 o3tl::hash_combine(seed, Prim());
199 o3tl::hash_combine(seed, Dist());
200 o3tl::hash_combine(seed, Secn());
201 o3tl::hash_combine(seed, static_cast<sal_Int32>(GetColorPrim()));
202 o3tl::hash_combine(seed, static_cast<sal_Int32>(GetColorSecn()));
203 o3tl::hash_combine(seed, static_cast<sal_Int32>(GetColorGap()));
204 o3tl::hash_combine(seed, GetRefMode());
205 o3tl::hash_combine(seed, UseGapColor());
206 o3tl::hash_combine(seed, Type());
207 return seed;
211 namespace
214 * Gets the weight of rStyle, according to [MS-OI29500] v20171130, 2.1.168 Part 1 Section 17.4.66,
215 * tcBorders (Table Cell Borders).
217 double GetWordTableCellBorderWeight(const Style& rStyle)
219 double fWidth = rStyle.GetWidth();
220 int nBorderNumber = 0;
222 // See lcl_convertBorderStyleFromToken() in writerfilter/ and ConvertBorderStyleFromWord() in
223 // editeng/, this is the opposite of the combination of those functions.
224 switch (rStyle.Type())
226 case SvxBorderLineStyle::NONE:
227 return 0.0;
228 case SvxBorderLineStyle::DOTTED:
229 case SvxBorderLineStyle::DASHED:
230 return 1.0;
231 case SvxBorderLineStyle::SOLID:
232 // single = 1
233 // thick = 2
234 // wave = 20
235 nBorderNumber = 1;
236 break;
237 case SvxBorderLineStyle::DOUBLE:
238 case SvxBorderLineStyle::DOUBLE_THIN:
239 // double = 3
240 // triple = 10
241 // doubleWave = 21
242 // dashDotStroked = 23
243 nBorderNumber = 3;
244 break;
245 case SvxBorderLineStyle::DASH_DOT:
246 // dotDash = 8
247 nBorderNumber = 8;
248 break;
249 case SvxBorderLineStyle::DASH_DOT_DOT:
250 // dotDotDash = 9
251 nBorderNumber = 9;
252 break;
253 case SvxBorderLineStyle::THINTHICK_SMALLGAP:
254 // thinThickSmallGap = 11
255 nBorderNumber = 11;
256 break;
257 case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
258 // thickThinSmallGap = 12
259 // thinThickThinSmallGap = 13
260 nBorderNumber = 12;
261 break;
262 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
263 // thinThickMediumGap = 14
264 nBorderNumber = 14;
265 break;
266 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
267 // thickThinMediumGap = 15
268 // thinThickThinMediumGap = 16
269 nBorderNumber = 15;
270 break;
271 case SvxBorderLineStyle::THINTHICK_LARGEGAP:
272 // thinThickLargeGap = 17
273 nBorderNumber = 17;
274 break;
275 case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
276 // thickThinLargeGap = 18
277 // thinThickThinLargeGap = 19
278 nBorderNumber = 18;
279 break;
280 case SvxBorderLineStyle::FINE_DASHED:
281 // dashSmallGap = 22
282 nBorderNumber = 22;
283 break;
284 case SvxBorderLineStyle::EMBOSSED:
285 // threeDEmboss = 24
286 nBorderNumber = 24;
287 break;
288 case SvxBorderLineStyle::ENGRAVED:
289 // threeDEngrave = 25
290 nBorderNumber = 25;
291 break;
292 case SvxBorderLineStyle::OUTSET:
293 // outset = 26
294 nBorderNumber = 25;
295 break;
296 case SvxBorderLineStyle::INSET:
297 // inset = 27
298 nBorderNumber = 27;
299 break;
302 return nBorderNumber * fWidth;
306 bool Style::operator<( const Style& rOther) const
308 if (mbWordTableCell)
310 // The below code would first compare based on the border width, Word compares based on its
311 // calculated weight, do that in the compat case.
312 double fLW = GetWordTableCellBorderWeight(*this);
313 double fRW = GetWordTableCellBorderWeight(rOther);
314 if (!rtl::math::approxEqual(fLW, fRW))
316 return fLW < fRW;
320 // different total widths -> this<rOther, if this is thinner
321 double nLW = GetWidth();
322 double nRW = rOther.GetWidth();
323 if( !rtl::math::approxEqual(nLW, nRW) ) return nLW < nRW;
325 // one line double, the other single -> this<rOther, if this is single
326 if( (Secn() == 0) != (rOther.Secn() == 0) ) return Secn() == 0;
328 // both lines double with different distances -> this<rOther, if distance of this greater
329 if( (Secn() && rOther.Secn()) && !rtl::math::approxEqual(Dist(), rOther.Dist()) ) return Dist() > rOther.Dist();
331 // both lines single and 1 unit thick, only one is dotted -> this<rOther, if this is dotted
332 if ((nLW == 1) && !Secn() && !rOther.Secn() && (Type() != rOther.Type())) return Type() > rOther.Type();
334 // seem to be equal
335 return false;
339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */