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 <utility>
23
24 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
25 #include <com/sun/star/drawing/Hatch.hpp>
26 #include <com/sun/star/drawing/LineStyle.hpp>
27 #include <com/sun/star/drawing/LineDash.hpp>
28 #include <com/sun/star/drawing/DashStyle.hpp>
29 #include <com/sun/star/drawing/FillStyle.hpp>
30 #include <com/sun/star/awt/Gradient2.hpp>
31 #include <com/sun/star/uno/Sequence.hxx>
32 #include <com/sun/star/beans/PropertyValue.hpp>
33
34 #include <comphelper/propertyvalue.hxx>
35 #include <o3tl/string_view.hxx>
36 #include <o3tl/any.hxx>
37 #include <svl/itempool.hxx>
38 #include <editeng/memberids.h>
39 #include <docmodel/uno/UnoGradientTools.hxx>
40 #include <docmodel/uno/UnoComplexColor.hxx>
41 #include <docmodel/color/ComplexColorJSON.hxx>
42 #include <tools/mapunit.hxx>
43 #include <tools/UnitConversion.hxx>
44 #include <osl/diagnose.h>
45
46 #include <svx/unoapi.hxx>
47 #include <svl/style.hxx>
48
49 #include <tools/bigint.hxx>
50 #include <svl/itemset.hxx>
51 #include <svx/strings.hrc>
52 #include <svx/xfillit0.hxx>
53 #include <svx/xflasit.hxx>
54 #include <svx/xlineit0.hxx>
55 #include <svx/xlnasit.hxx>
56 #include <svx/xtextit0.hxx>
57 #include <svx/xtable.hxx>
58 #include <svx/dialmgr.hxx>
59 #include <svx/xflclit.hxx>
60 #include <svx/xflgrit.hxx>
61 #include <svx/xflftrit.hxx>
62 #include <svx/xsflclit.hxx>
63 #include <svx/xflhtit.hxx>
64 #include <svx/xbtmpit.hxx>
65 #include <svx/xlndsit.hxx>
66 #include <svx/xlnwtit.hxx>
67 #include <svx/xlnclit.hxx>
68 #include <svx/xlnstit.hxx>
69 #include <svx/xlnedit.hxx>
70 #include <svx/xlnstwit.hxx>
71 #include <svx/xlnedwit.hxx>
72 #include <svx/xlnstcit.hxx>
73 #include <svx/xlnedcit.hxx>
74 #include <editeng/itemtype.hxx>
75 #include <editeng/eerdll.hxx>
76 #include <svx/xdef.hxx>
77 #include <svx/unomid.hxx>
78 #include <svx/svdmodel.hxx>
79 #include <svx/xftdiit.hxx>
80 #include <svx/xftstit.hxx>
81 #include <svx/xftmrit.hxx>
82 #include <svx/xftouit.hxx>
83 #include <svx/xftshit.hxx>
84 #include <svx/xftshcit.hxx>
85 #include <svx/xftshxy.hxx>
86 #include <svx/xftadit.hxx>
87 #include <svx/svddef.hxx>
88 #include <basegfx/polygon/b2dpolypolygontools.hxx>
89 #include <unotools/intlwrapper.hxx>
90 #include <unotools/syslocale.hxx>
91 #include <string>
92
93 #include <boost/property_tree/ptree.hpp>
94 #include <libxml/xmlwriter.h>
95
96 using namespace ::com::sun::star;
97
98 typedef std::map<OUString, OUString> StringMap;
99
NameOrIndex(TypedWhichId<NameOrIndex> _nWhich,sal_Int32 nIndex)100 NameOrIndex::NameOrIndex(TypedWhichId<NameOrIndex> _nWhich, sal_Int32 nIndex) :
101 SfxStringItem(_nWhich, OUString()),
102 m_nPalIndex(nIndex)
103 {
104 setNameOrIndex();
105 }
106
NameOrIndex(TypedWhichId<NameOrIndex> _nWhich,const OUString & rName)107 NameOrIndex::NameOrIndex(TypedWhichId<NameOrIndex> _nWhich, const OUString& rName) :
108 SfxStringItem(_nWhich, rName),
109 m_nPalIndex(-1)
110 {
111 setNameOrIndex();
112 }
113
NameOrIndex(const NameOrIndex & rNameOrIndex)114 NameOrIndex::NameOrIndex(const NameOrIndex& rNameOrIndex) :
115 SfxStringItem(rNameOrIndex),
116 m_nPalIndex(rNameOrIndex.m_nPalIndex)
117 {
118 setNameOrIndex();
119 }
120
operator ==(const SfxPoolItem & rItem) const121 bool NameOrIndex::operator==(const SfxPoolItem& rItem) const
122 {
123 return ( SfxStringItem::operator==(rItem) &&
124 static_cast<const NameOrIndex&>(rItem).m_nPalIndex == m_nPalIndex );
125 }
126
Clone(SfxItemPool *) const127 NameOrIndex* NameOrIndex::Clone(SfxItemPool* /*pPool*/) const
128 {
129 return new NameOrIndex(*this);
130 }
131
132 /** this static checks if the given NameOrIndex item has a unique name for its value.
133 The returned String is a unique name for an item with this value in both given pools.
134 Argument pPool2 can be null.
135 If returned string equals NameOrIndex->GetName(), the name was already unique.
136 */
CheckNamedItem(const sal_uInt16 nWhich,const SfxItemPool * pPool1,SvxCompareValueFunc pCompareValueFunc,TranslateId pPrefixResId,const XPropertyListRef & pDefaults) const137 OUString NameOrIndex::CheckNamedItem(const sal_uInt16 nWhich, const SfxItemPool* pPool1, SvxCompareValueFunc pCompareValueFunc, TranslateId pPrefixResId, const XPropertyListRef &pDefaults) const
138 {
139 bool bForceNew = false;
140
141 OUString aUniqueName = SvxUnogetInternalNameForItem(nWhich, GetName());
142
143 // 2. if we have a name check if there is already an item with the
144 // same name in the documents pool with a different line end or start
145
146 if (!aUniqueName.isEmpty() && pPool1)
147 {
148 // use special version to get buffered NameOrIndex Items
149 for (const SfxPoolItem* pItem : pPool1->GetItemSurrogatesForItem(*this))
150 {
151 const NameOrIndex *pNameOrIndex = static_cast<const NameOrIndex*>(pItem);
152
153 // need to check for WhichID, GetItemSurrogatesForItem does buffer on type only
154 if( pNameOrIndex != this && pNameOrIndex->Which() == nWhich && pNameOrIndex->GetName() == GetName() )
155 {
156 // if there is already an item with the same name and the same
157 // value it's ok to set it
158 if( !pCompareValueFunc( pNameOrIndex, this ) )
159 {
160 // same name but different value, we need a new name for this item
161 aUniqueName.clear();
162 bForceNew = true;
163 }
164 break;
165 }
166 }
167 }
168
169 // if we have no name yet, find existing item with same content or
170 // create a unique name
171 if (aUniqueName.isEmpty())
172 {
173 sal_Int32 nUserIndex = 1;
174 const OUString aUser(SvxResId(pPrefixResId) + " ");
175
176 if( pDefaults )
177 {
178 const int nCount = pDefaults->Count();
179 int nIndex;
180 for( nIndex = 0; nIndex < nCount; nIndex++ )
181 {
182 const XPropertyEntry* pEntry = pDefaults->Get(nIndex);
183 if( pEntry )
184 {
185 bool bFound = false;
186
187 switch( nWhich )
188 {
189 case XATTR_FILLBITMAP:
190 {
191 const GraphicObject& rGraphicObjectA(static_cast<const XFillBitmapItem*>(this)->GetGraphicObject());
192 const GraphicObject& rGraphicObjectB(static_cast<const XBitmapEntry*>(pEntry)->GetGraphicObject());
193
194 bFound = (rGraphicObjectA == rGraphicObjectB);
195 break;
196 }
197 case XATTR_LINEDASH:
198 bFound = static_cast<const XLineDashItem*>(this)->GetDashValue() == static_cast<const XDashEntry*>(pEntry)->GetDash();
199 break;
200 case XATTR_LINESTART:
201 bFound = static_cast<const XLineStartItem*>(this)->GetLineStartValue() == static_cast<const XLineEndEntry*>(pEntry)->GetLineEnd();
202 break;
203 case XATTR_LINEEND:
204 bFound = static_cast<const XLineEndItem*>(this)->GetLineEndValue() == static_cast<const XLineEndEntry*>(pEntry)->GetLineEnd();
205 break;
206 case XATTR_FILLGRADIENT:
207 bFound = static_cast<const XFillGradientItem*>(this)->GetGradientValue() == static_cast<const XGradientEntry*>(pEntry)->GetGradient();
208 break;
209 case XATTR_FILLHATCH:
210 bFound = static_cast<const XFillHatchItem*>(this)->GetHatchValue() == static_cast<const XHatchEntry*>(pEntry)->GetHatch();
211 break;
212 }
213
214 if( bFound )
215 {
216 aUniqueName = pEntry->GetName();
217 break;
218 }
219 else
220 {
221 const OUString& aEntryName = pEntry->GetName();
222 if(aEntryName.getLength() >= aUser.getLength())
223 {
224 sal_Int32 nThisIndex = o3tl::toInt32(aEntryName.subView( aUser.getLength() ));
225 if( nThisIndex >= nUserIndex )
226 nUserIndex = nThisIndex + 1;
227 }
228 }
229 }
230 }
231 }
232
233 if (aUniqueName.isEmpty() && pPool1)
234 {
235 // use special version to get buffered NameOrIndex Items
236 for (const SfxPoolItem* pItem : pPool1->GetItemSurrogatesForItem(*this))
237 {
238 const NameOrIndex *pNameOrIndex = static_cast<const NameOrIndex*>(pItem);
239
240 // need to check for WhichID, GetItemSurrogatesForItem does buffer on type only
241 if( pNameOrIndex != this && pNameOrIndex->Which() == nWhich && !pNameOrIndex->GetName().isEmpty() )
242 {
243 if( !bForceNew && pCompareValueFunc( pNameOrIndex, this ) )
244 return pNameOrIndex->GetName();
245
246 if( pNameOrIndex->GetName().startsWith( aUser ) )
247 {
248 sal_Int32 nThisIndex = o3tl::toInt32(pNameOrIndex->GetName().subView( aUser.getLength() ));
249 if( nThisIndex >= nUserIndex )
250 nUserIndex = nThisIndex + 1;
251 }
252 }
253 }
254 aUniqueName = aUser + OUString::number( nUserIndex );
255 }
256 }
257
258 return aUniqueName;
259 }
260
dumpAsXml(xmlTextWriterPtr pWriter) const261 void NameOrIndex::dumpAsXml(xmlTextWriterPtr pWriter) const
262 {
263 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("NameOrIndex"));
264 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
265 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("isIndex"), BAD_CAST(OString::boolean(IsIndex()).getStr()));
266 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("name"), BAD_CAST(GetName().toUtf8().getStr()));
267 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("index"), BAD_CAST(OString::number(m_nPalIndex).getStr()));
268 (void)xmlTextWriterEndElement(pWriter);
269 }
270
CreateDefault()271 SfxPoolItem* XColorItem::CreateDefault() { return new XColorItem(); }
272
XColorItem(TypedWhichId<XColorItem> _nWhich,sal_Int32 nIndex,const Color & rTheColor)273 XColorItem::XColorItem(TypedWhichId<XColorItem> _nWhich, sal_Int32 nIndex, const Color& rTheColor) :
274 NameOrIndex(_nWhich, nIndex),
275 m_aColor(rTheColor)
276 {
277 }
278
XColorItem(TypedWhichId<XColorItem> _nWhich,const OUString & rName,const Color & rTheColor)279 XColorItem::XColorItem(TypedWhichId<XColorItem> _nWhich, const OUString& rName, const Color& rTheColor) :
280 NameOrIndex(_nWhich, rName),
281 m_aColor(rTheColor)
282 {
283 }
284
XColorItem(TypedWhichId<XColorItem> _nWhich,const Color & rTheColor)285 XColorItem::XColorItem(TypedWhichId<XColorItem> _nWhich, const Color& rTheColor)
286 : NameOrIndex(_nWhich, OUString())
287 , m_aColor(rTheColor)
288 {
289 }
290
XColorItem(const XColorItem & rItem)291 XColorItem::XColorItem(const XColorItem& rItem) :
292 NameOrIndex(rItem),
293 m_aColor(rItem.m_aColor),
294 maComplexColor(rItem.maComplexColor)
295 {
296 }
297
Clone(SfxItemPool *) const298 XColorItem* XColorItem::Clone(SfxItemPool* /*pPool*/) const
299 {
300 return new XColorItem(*this);
301 }
302
operator ==(const SfxPoolItem & rItem) const303 bool XColorItem::operator==(const SfxPoolItem& rItem) const
304 {
305 return ( NameOrIndex::operator==(rItem) &&
306 static_cast<const XColorItem&>(rItem).m_aColor == m_aColor ) &&
307 static_cast<const XColorItem&>(rItem).maComplexColor == maComplexColor;
308 }
309
GetColorValue() const310 const Color& XColorItem::GetColorValue() const
311 {
312 assert(!IsIndex());
313 return m_aColor;
314
315 }
316
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const317 bool XColorItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId) const
318 {
319 nMemberId &= ~CONVERT_TWIPS;
320 switch (nMemberId)
321 {
322 case MID_COMPLEX_COLOR:
323 {
324 auto xComplexColor = model::color::createXComplexColor(getComplexColor());
325 rVal <<= xComplexColor;
326 break;
327 }
328 case MID_COMPLEX_COLOR_JSON:
329 {
330 rVal <<= OStringToOUString(model::color::convertToJSON(getComplexColor()), RTL_TEXTENCODING_UTF8);
331 break;
332 }
333 default:
334 {
335 rVal <<= GetColorValue().GetRGBColor();
336 break;
337 }
338 }
339 return true;
340 }
341
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)342 bool XColorItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId)
343 {
344 nMemberId &= ~CONVERT_TWIPS;
345 switch (nMemberId)
346 {
347 case MID_COMPLEX_COLOR:
348 {
349 css::uno::Reference<css::util::XComplexColor> xComplexColor;
350 if (!(rVal >>= xComplexColor))
351 return false;
352 setComplexColor(model::color::getFromXComplexColor(xComplexColor));
353 }
354 break;
355 case MID_COMPLEX_COLOR_JSON:
356 {
357 OUString sComplexColorJson;
358 if (!(rVal >>= sComplexColorJson))
359 return false;
360
361 if (sComplexColorJson.isEmpty())
362 return false;
363
364 OString aJSON = OUStringToOString(sComplexColorJson, RTL_TEXTENCODING_ASCII_US);
365 model::ComplexColor aComplexColor;
366 model::color::convertFromJSON(aJSON, aComplexColor);
367 setComplexColor(aComplexColor);
368 }
369 break;
370 default:
371 {
372 Color nValue;
373 if(!(rVal >>= nValue ))
374 return false;
375
376 SetColorValue( nValue );
377
378 }
379 break;
380 }
381 return true;
382 }
383
dumpAsXml(xmlTextWriterPtr pWriter) const384 void XColorItem::dumpAsXml(xmlTextWriterPtr pWriter) const
385 {
386 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("XColorItem"));
387 if (Which() == SDRATTR_SHADOWCOLOR)
388 {
389 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST("SDRATTR_SHADOWCOLOR"));
390 }
391 else if (Which() == XATTR_FILLCOLOR)
392 {
393 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST("XATTR_FILLCOLOR"));
394 }
395 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("aColor"),
396 BAD_CAST(m_aColor.AsRGBHexString().toUtf8().getStr()));
397
398 NameOrIndex::dumpAsXml(pWriter);
399
400 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("complex-color"));
401
402 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("scheme-index"),
403 BAD_CAST(OString::number(sal_Int16(maComplexColor.getThemeColorType())).getStr()));
404
405 for (auto const& rTransform : maComplexColor.getTransformations())
406 {
407 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("transformation"));
408 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("type"),
409 BAD_CAST(OString::number(sal_Int16(rTransform.meType)).getStr()));
410 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"),
411 BAD_CAST(OString::number(rTransform.mnValue).getStr()));
412 (void)xmlTextWriterEndElement(pWriter);
413 }
414
415 (void)xmlTextWriterEndElement(pWriter);
416
417 (void)xmlTextWriterEndElement(pWriter);
418 }
419
420 // --- line attributes ---
421
422
CreateDefault()423 SfxPoolItem* XLineStyleItem::CreateDefault() { return new XLineStyleItem; }
424
XLineStyleItem(css::drawing::LineStyle eTheLineStyle)425 XLineStyleItem::XLineStyleItem(css::drawing::LineStyle eTheLineStyle) :
426 SfxEnumItem(XATTR_LINESTYLE, eTheLineStyle)
427 {
428 }
429
Clone(SfxItemPool *) const430 XLineStyleItem* XLineStyleItem::Clone(SfxItemPool* /*pPool*/) const
431 {
432 return new XLineStyleItem( *this );
433 }
434
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const435 bool XLineStyleItem::GetPresentation
436 (
437 SfxItemPresentation /*ePres*/,
438 MapUnit /*eCoreUnit*/,
439 MapUnit /*ePresUnit*/,
440 OUString& rText, const IntlWrapper&
441 ) const
442 {
443 rText.clear();
444
445 TranslateId pId;
446
447 switch( GetValue() )
448 {
449 case css::drawing::LineStyle_NONE:
450 pId = RID_SVXSTR_INVISIBLE;
451 break;
452 case css::drawing::LineStyle_SOLID:
453 pId = RID_SVXSTR_SOLID;
454 break;
455 default: break;
456 }
457
458 if (pId)
459 rText = SvxResId(pId);
460 return true;
461 }
462
QueryValue(css::uno::Any & rVal,sal_uInt8) const463 bool XLineStyleItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
464 {
465 css::drawing::LineStyle eLS = GetValue();
466 rVal <<= eLS;
467 return true;
468 }
469
PutValue(const css::uno::Any & rVal,sal_uInt8)470 bool XLineStyleItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
471 {
472 css::drawing::LineStyle eLS;
473 if(!(rVal >>= eLS ))
474 {
475 // also try an int (for Basic)
476 sal_Int32 nLS = 0;
477 if(!(rVal >>= nLS))
478 return false;
479 eLS = static_cast<css::drawing::LineStyle>(nLS);
480 }
481
482 SetValue( eLS );
483 return true;
484 }
485
XDash(css::drawing::DashStyle eTheDash,sal_uInt16 nTheDots,double nTheDotLen,sal_uInt16 nTheDashes,double nTheDashLen,double nTheDistance)486 XDash::XDash(css::drawing::DashStyle eTheDash, sal_uInt16 nTheDots, double nTheDotLen,
487 sal_uInt16 nTheDashes, double nTheDashLen, double nTheDistance) :
488 m_eDash(eTheDash),
489 m_nDots(nTheDots),
490 m_nDashes(nTheDashes),
491 m_nDotLen(nTheDotLen),
492 m_nDashLen(nTheDashLen),
493 m_nDistance(nTheDistance)
494 {
495 }
496
operator ==(const XDash & rDash) const497 bool XDash::operator==(const XDash& rDash) const
498 {
499 return ( m_eDash == rDash.m_eDash &&
500 m_nDots == rDash.m_nDots &&
501 m_nDotLen == rDash.m_nDotLen &&
502 m_nDashes == rDash.m_nDashes &&
503 m_nDashLen == rDash.m_nDashLen &&
504 m_nDistance == rDash.m_nDistance );
505 }
506
507 // XDash is translated into an array of doubles which describe the lengths of the
508 // dashes, dots and empty passages. It returns the complete length of the full DashDot
509 // sequence and fills the given vector of doubles accordingly (also resizing, so deleting it).
510 const double SMALLEST_DASH_WIDTH(26.95);
511
CreateDotDashArray(::std::vector<double> & rDotDashArray,double fLineWidth) const512 double XDash::CreateDotDashArray(::std::vector< double >& rDotDashArray, double fLineWidth) const
513 {
514 double fFullDotDashLen(0.0);
515 const sal_uInt16 nNumDotDashArray = (GetDots() + GetDashes()) * 2;
516 rDotDashArray.resize( nNumDotDashArray, 0.0 );
517 sal_uInt16 a;
518 sal_uInt16 nIns(0);
519 double fDashDotDistance = GetDistance();
520 double fSingleDashLen = GetDashLen();
521 double fSingleDotLen = GetDotLen();
522
523 if (fLineWidth == 0.0)
524 fLineWidth = SMALLEST_DASH_WIDTH;
525
526 if(GetDashStyle() == css::drawing::DashStyle_RECTRELATIVE || GetDashStyle() == css::drawing::DashStyle_ROUNDRELATIVE)
527 {
528 double fFactor = fLineWidth / 100.0;
529
530 if(GetDashes())
531 {
532 if(GetDashLen())
533 {
534 // is a dash
535 fSingleDashLen *= fFactor;
536 }
537 else
538 {
539 // is a dot
540 fSingleDashLen = fLineWidth;
541 }
542 }
543
544 if(GetDots())
545 {
546 if(GetDotLen())
547 {
548 // is a dash
549 fSingleDotLen *= fFactor;
550 }
551 else
552 {
553 // is a dot
554 fSingleDotLen = fLineWidth;
555 }
556 }
557
558 if(GetDashes() || GetDots())
559 {
560 if(GetDistance())
561 {
562 // dash as distance
563 fDashDotDistance *= fFactor;
564 }
565 else
566 {
567 // dot as distance
568 fDashDotDistance = fLineWidth;
569 }
570 }
571 }
572 else
573 {
574 // absolute values
575 if(GetDashes())
576 {
577 if(GetDashLen())
578 {
579 // is a dash
580 if(fSingleDashLen < SMALLEST_DASH_WIDTH)
581 {
582 fSingleDashLen = SMALLEST_DASH_WIDTH;
583 }
584 }
585 else
586 {
587 // is a dot
588 if(fSingleDashLen < fLineWidth)
589 {
590 fSingleDashLen = fLineWidth;
591 }
592 }
593 }
594
595 if(GetDots())
596 {
597 if(GetDotLen())
598 {
599 // is a dash
600 if(fSingleDotLen < SMALLEST_DASH_WIDTH)
601 {
602 fSingleDotLen = SMALLEST_DASH_WIDTH;
603 }
604 }
605 else
606 {
607 // is a dot
608 if(fSingleDotLen < fLineWidth)
609 {
610 fSingleDotLen = fLineWidth;
611 }
612 }
613 }
614
615 if(GetDashes() || GetDots())
616 {
617 if(GetDistance())
618 {
619 // dash as distance
620 if(fDashDotDistance < SMALLEST_DASH_WIDTH)
621 {
622 fDashDotDistance = SMALLEST_DASH_WIDTH;
623 }
624 }
625 else
626 {
627 // dot as distance
628 if(fDashDotDistance < fLineWidth)
629 {
630 fDashDotDistance = fLineWidth;
631 }
632 }
633 }
634 }
635
636 for(a=0;a<GetDots();a++)
637 {
638 rDotDashArray[nIns++] = fSingleDotLen;
639 fFullDotDashLen += fSingleDotLen;
640 rDotDashArray[nIns++] = fDashDotDistance;
641 fFullDotDashLen += fDashDotDistance;
642 }
643
644 for(a=0;a<GetDashes();a++)
645 {
646 rDotDashArray[nIns++] = fSingleDashLen;
647 fFullDotDashLen += fSingleDashLen;
648 rDotDashArray[nIns++] = fDashDotDistance;
649 fFullDotDashLen += fDashDotDistance;
650 }
651
652 return fFullDotDashLen;
653 }
654
CreateDefault()655 SfxPoolItem* XLineDashItem::CreateDefault() {return new XLineDashItem;}
656
XLineDashItem(const OUString & rName,const XDash & rTheDash)657 XLineDashItem::XLineDashItem(const OUString& rName, const XDash& rTheDash) :
658 NameOrIndex(XATTR_LINEDASH, rName),
659 m_aDash(rTheDash)
660 {
661 }
662
XLineDashItem(const XLineDashItem & rItem)663 XLineDashItem::XLineDashItem(const XLineDashItem& rItem) :
664 NameOrIndex(rItem),
665 m_aDash(rItem.m_aDash)
666 {
667 }
668
XLineDashItem(const XDash & rTheDash)669 XLineDashItem::XLineDashItem(const XDash& rTheDash)
670 : NameOrIndex( XATTR_LINEDASH, -1 ),
671 m_aDash(rTheDash)
672 {
673 }
674
Clone(SfxItemPool *) const675 XLineDashItem* XLineDashItem::Clone(SfxItemPool* /*pPool*/) const
676 {
677 return new XLineDashItem(*this);
678 }
679
operator ==(const SfxPoolItem & rItem) const680 bool XLineDashItem::operator==(const SfxPoolItem& rItem) const
681 {
682 return ( NameOrIndex::operator==(rItem) &&
683 m_aDash == static_cast<const XLineDashItem&>(rItem).m_aDash );
684 }
685
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const686 bool XLineDashItem::GetPresentation
687 (
688 SfxItemPresentation /*ePres*/,
689 MapUnit /*eCoreUnit*/,
690 MapUnit /*ePresUnit*/,
691 OUString& rText, const IntlWrapper&
692 ) const
693 {
694 rText = GetName();
695 return true;
696 }
697
HasMetrics() const698 bool XLineDashItem::HasMetrics() const
699 {
700 return true;
701 }
702
ScaleMetrics(tools::Long nMul,tools::Long nDiv)703 void XLineDashItem::ScaleMetrics(tools::Long nMul, tools::Long nDiv)
704 {
705 m_aDash.SetDotLen( BigInt::Scale( m_aDash.GetDotLen(), nMul, nDiv ) );
706 m_aDash.SetDashLen( BigInt::Scale( m_aDash.GetDashLen(), nMul, nDiv ) );
707 m_aDash.SetDistance( BigInt::Scale( m_aDash.GetDistance(), nMul, nDiv ) );
708 }
709
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const710 bool XLineDashItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
711 {
712 nMemberId &= ~CONVERT_TWIPS;
713
714 switch ( nMemberId )
715 {
716 case 0:
717 {
718 css::drawing::LineDash aLineDash;
719
720 const XDash& rXD = GetDashValue();
721 aLineDash.Style = static_cast<css::drawing::DashStyle>(static_cast<sal_uInt16>(rXD.GetDashStyle()));
722 aLineDash.Dots = rXD.GetDots();
723 aLineDash.DotLen = rXD.GetDotLen();
724 aLineDash.Dashes = rXD.GetDashes();
725 aLineDash.DashLen = rXD.GetDashLen();
726 aLineDash.Distance = rXD.GetDistance();
727
728 uno::Sequence< beans::PropertyValue > aPropSeq{
729 comphelper::makePropertyValue(u"Name"_ustr, SvxUnogetApiNameForItem(Which(), GetName())),
730 comphelper::makePropertyValue(u"LineDash"_ustr, aLineDash)
731 };
732 rVal <<= aPropSeq;
733 break;
734 }
735
736 case MID_NAME:
737 {
738 rVal <<= SvxUnogetApiNameForItem(Which(), GetName());
739 break;
740 }
741
742 case MID_LINEDASH:
743 {
744 const XDash& rXD = GetDashValue();
745
746 css::drawing::LineDash aLineDash;
747
748 aLineDash.Style = static_cast<css::drawing::DashStyle>(static_cast<sal_uInt16>(rXD.GetDashStyle()));
749 aLineDash.Dots = rXD.GetDots();
750 aLineDash.DotLen = rXD.GetDotLen();
751 aLineDash.Dashes = rXD.GetDashes();
752 aLineDash.DashLen = rXD.GetDashLen();
753 aLineDash.Distance = rXD.GetDistance();
754
755 rVal <<= aLineDash;
756 break;
757 }
758
759 case MID_LINEDASH_STYLE:
760 {
761 const XDash& rXD = GetDashValue();
762 rVal <<= static_cast<css::drawing::DashStyle>(static_cast<sal_Int16>(rXD.GetDashStyle()));
763 break;
764 }
765
766 case MID_LINEDASH_DOTS:
767 {
768 const XDash& rXD = GetDashValue();
769 rVal <<= rXD.GetDots();
770 break;
771 }
772
773 case MID_LINEDASH_DOTLEN:
774 {
775 const XDash& rXD = GetDashValue();
776 rVal <<= rXD.GetDotLen();
777 break;
778 }
779
780 case MID_LINEDASH_DASHES:
781 {
782 const XDash& rXD = GetDashValue();
783 rVal <<= rXD.GetDashes();
784 break;
785 }
786
787 case MID_LINEDASH_DASHLEN:
788 {
789 const XDash& rXD = GetDashValue();
790 rVal <<= rXD.GetDashLen();
791 break;
792 }
793
794 case MID_LINEDASH_DISTANCE:
795 {
796 const XDash& rXD = GetDashValue();
797 rVal <<= rXD.GetDistance();
798 break;
799 }
800
801 default: OSL_FAIL("Wrong MemberId!"); return false;
802 }
803
804 return true;
805 }
806
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)807 bool XLineDashItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
808 {
809 nMemberId &= ~CONVERT_TWIPS;
810
811 switch ( nMemberId )
812 {
813 case 0:
814 {
815 uno::Sequence< beans::PropertyValue > aPropSeq;
816
817 if ( rVal >>= aPropSeq )
818 {
819 css::drawing::LineDash aLineDash;
820 OUString aName;
821 bool bLineDash( false );
822 for (const auto& rProp : aPropSeq)
823 {
824 if ( rProp.Name == "Name" )
825 rProp.Value >>= aName;
826 else if ( rProp.Name == "LineDash" )
827 {
828 if ( rProp.Value >>= aLineDash )
829 bLineDash = true;
830 }
831 }
832
833 SetName( aName );
834 if ( bLineDash )
835 {
836 XDash aXDash;
837
838 aXDash.SetDashStyle(static_cast<css::drawing::DashStyle>(static_cast<sal_uInt16>(aLineDash.Style)));
839 aXDash.SetDots(aLineDash.Dots);
840 aXDash.SetDotLen(aLineDash.DotLen);
841 aXDash.SetDashes(aLineDash.Dashes);
842 aXDash.SetDashLen(aLineDash.DashLen);
843 aXDash.SetDistance(aLineDash.Distance);
844
845 if((0 == aXDash.GetDots()) && (0 == aXDash.GetDashes()))
846 aXDash.SetDots(1);
847
848 SetDashValue( aXDash );
849 }
850
851 return true;
852 }
853
854 return false;
855 }
856
857 case MID_NAME:
858 {
859 OUString aName;
860 if (!(rVal >>= aName))
861 return false;
862 SetName( aName );
863 break;
864 }
865
866 case MID_LINEDASH:
867 {
868 css::drawing::LineDash aLineDash;
869 if(!(rVal >>= aLineDash))
870 return false;
871
872 XDash aXDash;
873
874 aXDash.SetDashStyle(static_cast<css::drawing::DashStyle>(static_cast<sal_uInt16>(aLineDash.Style)));
875 aXDash.SetDots(aLineDash.Dots);
876 aXDash.SetDotLen(aLineDash.DotLen);
877 aXDash.SetDashes(aLineDash.Dashes);
878 aXDash.SetDashLen(aLineDash.DashLen);
879 aXDash.SetDistance(aLineDash.Distance);
880
881 if((0 == aXDash.GetDots()) && (0 == aXDash.GetDashes()))
882 aXDash.SetDots(1);
883
884 SetDashValue( aXDash );
885 break;
886 }
887
888 case MID_LINEDASH_STYLE:
889 {
890 sal_Int16 nVal = sal_Int16();
891 if(!(rVal >>= nVal))
892 return false;
893
894 XDash aXDash = GetDashValue();
895 aXDash.SetDashStyle(static_cast<css::drawing::DashStyle>(static_cast<sal_uInt16>(nVal)));
896
897 if((0 == aXDash.GetDots()) && (0 == aXDash.GetDashes()))
898 aXDash.SetDots(1);
899
900 SetDashValue( aXDash );
901
902 break;
903 }
904
905 case MID_LINEDASH_DOTS:
906 case MID_LINEDASH_DASHES:
907 {
908 sal_Int16 nVal = sal_Int16();
909 if(!(rVal >>= nVal))
910 return false;
911
912 XDash aXDash = GetDashValue();
913 if ( nMemberId == MID_LINEDASH_DOTS )
914 aXDash.SetDots( nVal );
915 else
916 aXDash.SetDashes( nVal );
917
918 if((0 == aXDash.GetDots()) && (0 == aXDash.GetDashes()))
919 aXDash.SetDots(1);
920
921 SetDashValue( aXDash );
922 break;
923 }
924
925 case MID_LINEDASH_DOTLEN:
926 case MID_LINEDASH_DASHLEN:
927 case MID_LINEDASH_DISTANCE:
928 {
929 sal_uInt32 nVal = 0;
930 if(!(rVal >>= nVal))
931 return false;
932
933 XDash aXDash = GetDashValue();
934 if ( nMemberId == MID_LINEDASH_DOTLEN )
935 aXDash.SetDotLen( nVal );
936 else if ( nMemberId == MID_LINEDASH_DASHLEN )
937 aXDash.SetDashLen( nVal );
938 else
939 aXDash.SetDistance( nVal );
940
941 if((0 == aXDash.GetDots()) && (0 == aXDash.GetDashes()))
942 aXDash.SetDots(1);
943
944 SetDashValue( aXDash );
945 break;
946 }
947 }
948
949 return true;
950 }
951
CompareValueFunc(const NameOrIndex * p1,const NameOrIndex * p2)952 bool XLineDashItem::CompareValueFunc( const NameOrIndex* p1, const NameOrIndex* p2 )
953 {
954 return static_cast<const XLineDashItem*>(p1)->GetDashValue() == static_cast<const XLineDashItem*>(p2)->GetDashValue();
955 }
956
checkForUniqueItem(SdrModel & rModel) const957 std::unique_ptr<XLineDashItem> XLineDashItem::checkForUniqueItem( SdrModel& rModel ) const
958 {
959 const OUString aUniqueName(CheckNamedItem(
960 XATTR_LINEDASH, &rModel.GetItemPool(),
961 XLineDashItem::CompareValueFunc, RID_SVXSTR_DASH20,
962 rModel.GetPropertyList(XPropertyListType::Dash)));
963
964 // if the given name is not valid, replace it!
965 if( aUniqueName != GetName() )
966 return std::make_unique<XLineDashItem>( aUniqueName, m_aDash );
967
968 return nullptr;
969 }
970
CreateDefault()971 SfxPoolItem* XLineWidthItem::CreateDefault() {return new XLineWidthItem;}
972
XLineWidthItem(tools::Long nWidth)973 XLineWidthItem::XLineWidthItem(tools::Long nWidth) :
974 SfxMetricItem(XATTR_LINEWIDTH, nWidth)
975 {
976 }
977
Clone(SfxItemPool *) const978 XLineWidthItem* XLineWidthItem::Clone(SfxItemPool* /*pPool*/) const
979 {
980 return new XLineWidthItem(*this);
981 }
982
GetPresentation(SfxItemPresentation,MapUnit eCoreUnit,MapUnit ePresUnit,OUString & rText,const IntlWrapper & rIntl) const983 bool XLineWidthItem::GetPresentation
984 (
985 SfxItemPresentation /*ePres*/,
986 MapUnit eCoreUnit,
987 MapUnit ePresUnit,
988 OUString& rText, const IntlWrapper& rIntl
989 ) const
990 {
991 rText = GetMetricText( static_cast<tools::Long>(GetValue()),
992 eCoreUnit, ePresUnit, &rIntl) +
993 " " + EditResId( GetMetricId( ePresUnit) );
994 return true;
995 }
996
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const997 bool XLineWidthItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
998 {
999 sal_Int32 nValue = GetValue();
1000 if( 0 != (nMemberId&CONVERT_TWIPS) )
1001 nValue = convertTwipToMm100(nValue);
1002
1003 rVal <<= nValue;
1004 return true;
1005 }
1006
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)1007 bool XLineWidthItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
1008 {
1009 sal_Int32 nValue = 0;
1010 rVal >>= nValue;
1011 if( 0 != (nMemberId&CONVERT_TWIPS) )
1012 nValue = o3tl::toTwips(nValue, o3tl::Length::mm100);
1013
1014 SetValue( nValue );
1015 return true;
1016 }
1017
CreateDefault()1018 SfxPoolItem* XLineColorItem::CreateDefault() { return new XLineColorItem; }
1019
XLineColorItem(sal_Int32 nIndex,const Color & rTheColor)1020 XLineColorItem::XLineColorItem(sal_Int32 nIndex, const Color& rTheColor) :
1021 XColorItem(XATTR_LINECOLOR, nIndex, rTheColor)
1022 {
1023 }
1024
XLineColorItem(const OUString & rName,const Color & rTheColor)1025 XLineColorItem::XLineColorItem(const OUString& rName, const Color& rTheColor) :
1026 XColorItem(XATTR_LINECOLOR, rName, rTheColor)
1027 {
1028 }
1029
Clone(SfxItemPool *) const1030 XLineColorItem* XLineColorItem::Clone(SfxItemPool* /*pPool*/) const
1031 {
1032 return new XLineColorItem(*this);
1033 }
1034
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const1035 bool XLineColorItem::GetPresentation
1036 (
1037 SfxItemPresentation /*ePres*/,
1038 MapUnit /*eCoreUnit*/,
1039 MapUnit /*ePresUnit*/,
1040 OUString& rText, const IntlWrapper&
1041 ) const
1042 {
1043 rText = GetName();
1044 return true;
1045 }
1046
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const1047 bool XLineColorItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId) const
1048 {
1049 nMemberId &= ~CONVERT_TWIPS;
1050 switch (nMemberId)
1051 {
1052 case MID_COMPLEX_COLOR:
1053 {
1054 auto xComplexColor = model::color::createXComplexColor(getComplexColor());
1055 rVal <<= xComplexColor;
1056 break;
1057 }
1058 case MID_COMPLEX_COLOR_JSON:
1059 {
1060 rVal <<= OStringToOUString(model::color::convertToJSON(getComplexColor()), RTL_TEXTENCODING_UTF8);
1061 break;
1062 }
1063 default:
1064 {
1065 rVal <<= GetColorValue().GetRGBColor();
1066 break;
1067 }
1068 }
1069 return true;
1070 }
1071
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)1072 bool XLineColorItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId)
1073 {
1074 nMemberId &= ~CONVERT_TWIPS;
1075 switch(nMemberId)
1076 {
1077 case MID_COMPLEX_COLOR:
1078 {
1079 css::uno::Reference<css::util::XComplexColor> xComplexColor;
1080 if (!(rVal >>= xComplexColor))
1081 return false;
1082 setComplexColor(model::color::getFromXComplexColor(xComplexColor));
1083 }
1084 break;
1085 case MID_COMPLEX_COLOR_JSON:
1086 {
1087 OUString sComplexColorJson;
1088 if (!(rVal >>= sComplexColorJson))
1089 return false;
1090
1091 if (sComplexColorJson.isEmpty())
1092 return false;
1093 model::ComplexColor aComplexColor;
1094 OString aJSON = OUStringToOString(sComplexColorJson, RTL_TEXTENCODING_ASCII_US);
1095 model::color::convertFromJSON(aJSON, aComplexColor);
1096 setComplexColor(aComplexColor);
1097 }
1098 break;
1099 default:
1100 {
1101 sal_Int32 nValue;
1102 if(!(rVal >>= nValue ))
1103 return false;
1104
1105 SetColorValue( Color(ColorTransparency, nValue) );
1106 break;
1107 }
1108 }
1109 return true;
1110 }
1111
1112
CreateDefault()1113 SfxPoolItem* XLineStartItem::CreateDefault() {return new XLineStartItem;}
1114
XLineStartItem(sal_Int32 nIndex)1115 XLineStartItem::XLineStartItem(sal_Int32 nIndex)
1116 : NameOrIndex(XATTR_LINESTART, nIndex)
1117 {
1118 }
1119
XLineStartItem(const OUString & rName,basegfx::B2DPolyPolygon aPolyPolygon)1120 XLineStartItem::XLineStartItem(const OUString& rName, basegfx::B2DPolyPolygon aPolyPolygon)
1121 : NameOrIndex(XATTR_LINESTART, rName),
1122 maPolyPolygon(std::move(aPolyPolygon))
1123 {
1124 }
1125
XLineStartItem(const XLineStartItem & rItem)1126 XLineStartItem::XLineStartItem(const XLineStartItem& rItem)
1127 : NameOrIndex(rItem),
1128 maPolyPolygon(rItem.maPolyPolygon)
1129 {
1130 }
1131
XLineStartItem(basegfx::B2DPolyPolygon aPolyPolygon)1132 XLineStartItem::XLineStartItem(basegfx::B2DPolyPolygon aPolyPolygon)
1133 : NameOrIndex( XATTR_LINESTART, -1 ),
1134 maPolyPolygon(std::move(aPolyPolygon))
1135 {
1136 }
1137
Clone(SfxItemPool *) const1138 XLineStartItem* XLineStartItem::Clone(SfxItemPool* /*pPool*/) const
1139 {
1140 return new XLineStartItem(*this);
1141 }
1142
operator ==(const SfxPoolItem & rItem) const1143 bool XLineStartItem::operator==(const SfxPoolItem& rItem) const
1144 {
1145 return ( NameOrIndex::operator==(rItem) && static_cast<const XLineStartItem&>(rItem).maPolyPolygon == maPolyPolygon );
1146 }
1147
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const1148 bool XLineStartItem::GetPresentation
1149 (
1150 SfxItemPresentation /*ePres*/,
1151 MapUnit /*eCoreUnit*/,
1152 MapUnit /*ePresUnit*/,
1153 OUString& rText, const IntlWrapper&
1154 ) const
1155 {
1156 rText = GetName();
1157 return true;
1158 }
1159
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const1160 bool XLineStartItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
1161 {
1162 nMemberId &= ~CONVERT_TWIPS;
1163 if( nMemberId == MID_NAME )
1164 {
1165 rVal <<= SvxUnogetApiNameForItem(Which(), GetName());
1166 }
1167 else
1168 {
1169 css::drawing::PolyPolygonBezierCoords aBezier;
1170 basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords( maPolyPolygon, aBezier );
1171 rVal <<= aBezier;
1172 }
1173
1174 return true;
1175 }
1176
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)1177 bool XLineStartItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
1178 {
1179 nMemberId &= ~CONVERT_TWIPS;
1180 if( nMemberId == MID_NAME )
1181 {
1182 return false;
1183 }
1184 else
1185 {
1186 maPolyPolygon.clear();
1187
1188 if( rVal.hasValue() )
1189 {
1190 auto pCoords = o3tl::tryAccess<css::drawing::PolyPolygonBezierCoords>(
1191 rVal);
1192 if( !pCoords )
1193 return false;
1194
1195 if( pCoords->Coordinates.getLength() > 0 )
1196 {
1197 maPolyPolygon = basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon( *pCoords );
1198 // #i72807# close line start/end polygons hard
1199 // maPolyPolygon.setClosed(true);
1200 }
1201 }
1202 }
1203
1204 return true;
1205 }
1206
HasConflictingStartEndItems(const SfxItemPool & pool,std::u16string_view name,const basegfx::B2DPolyPolygon & value)1207 static bool HasConflictingStartEndItems(const SfxItemPool& pool, std::u16string_view name,
1208 const basegfx::B2DPolyPolygon& value)
1209 {
1210 // XATTR_LINESTART
1211 for (const SfxPoolItem* p : pool.GetItemSurrogatesForItem(SfxItemType::XLineStartItemType))
1212 {
1213 auto pItem = static_cast<const XLineStartItem*>(p);
1214
1215 if (pItem->GetName() == name)
1216 {
1217 // if there is already an item with the same name and the same value it's not a conflict
1218 if (pItem->GetLineStartValue() == value)
1219 break;
1220 // same name but different value
1221 return true;
1222 }
1223 }
1224 // XATTR_LINEEND
1225 for (const SfxPoolItem* p : pool.GetItemSurrogatesForItem(SfxItemType::XLineEndItemType))
1226 {
1227 auto pItem = static_cast<const XLineEndItem*>(p);
1228
1229 if (pItem->GetName() == name)
1230 {
1231 // if there is already an item with the same name and the same value it's not a conflict
1232 if (pItem->GetLineEndValue() == value)
1233 break;
1234 // same name but different value
1235 return true;
1236 }
1237 }
1238 return false;
1239 }
1240
1241 /** this function searches in both the models pool and the styles pool for XLineStartItem and
1242 XLineEndItem with the same name and returns true when it exists and has a different value. */
HasConflictingStartEndItems(const SdrModel & model,std::u16string_view name,const basegfx::B2DPolyPolygon & value)1243 static bool HasConflictingStartEndItems(const SdrModel& model, std::u16string_view name,
1244 const basegfx::B2DPolyPolygon& value)
1245 {
1246 return HasConflictingStartEndItems(model.GetItemPool(), name, value)
1247 || (model.GetStyleSheetPool()
1248 && HasConflictingStartEndItems(model.GetStyleSheetPool()->GetPool(), name, value));
1249 }
1250
CreateNameForValue(const SfxItemPool & pool,const basegfx::B2DPolyPolygon & value,bool forceNew)1251 static OUString CreateNameForValue(const SfxItemPool& pool, const basegfx::B2DPolyPolygon& value,
1252 bool forceNew)
1253 {
1254 sal_Int32 nUserIndex = 1;
1255 const OUString aUser(SvxResId(RID_SVXSTR_LINEEND));
1256
1257 // XATTR_LINEEND first, because previous code preferred existing name from it
1258 for (const SfxPoolItem* p : pool.GetItemSurrogatesForItem(SfxItemType::XLineEndItemType))
1259 {
1260 auto pItem = static_cast<const XLineEndItem*>(p);
1261
1262 if (!pItem->GetName().isEmpty())
1263 {
1264 if (!forceNew && pItem->GetLineEndValue() == value)
1265 return pItem->GetName(); // Found existing
1266
1267 if (pItem->GetName().startsWith(aUser))
1268 {
1269 sal_Int32 nThisIndex = o3tl::toInt32(pItem->GetName().subView(aUser.getLength()));
1270 if (nThisIndex >= nUserIndex)
1271 nUserIndex = nThisIndex + 1;
1272 }
1273 }
1274 }
1275
1276 // XATTR_LINESTART
1277 for (const SfxPoolItem* p : pool.GetItemSurrogatesForItem(SfxItemType::XLineStartItemType))
1278 {
1279 auto pItem = static_cast<const XLineStartItem*>(p);
1280
1281 if (!pItem->GetName().isEmpty())
1282 {
1283 if (!forceNew && pItem->GetLineStartValue() == value)
1284 return pItem->GetName(); // Found existing
1285
1286 if (pItem->GetName().startsWith(aUser))
1287 {
1288 sal_Int32 nThisIndex = o3tl::toInt32(pItem->GetName().subView(aUser.getLength()));
1289 if (nThisIndex >= nUserIndex)
1290 nUserIndex = nThisIndex + 1;
1291 }
1292 }
1293 }
1294
1295 return aUser + " " + OUString::number(nUserIndex);
1296 }
1297
1298 /** this function searches in both the models pool and the styles pool for XLineStartItem
1299 and XLineEndItem with the same value or name and returns an item with the value of
1300 this item and a unique name for an item with this value. */
checkForUniqueItem(SdrModel & rModel) const1301 std::unique_ptr<XLineStartItem> XLineStartItem::checkForUniqueItem( SdrModel& rModel ) const
1302 {
1303 std::unique_ptr<XLineStartItem> pTempItem;
1304 const XLineStartItem* pLineStartItem = this;
1305
1306 OUString aUniqueName( GetName() );
1307
1308 if( !maPolyPolygon.count() )
1309 {
1310 // if the polygon is empty, check if the name is empty
1311 if( aUniqueName.isEmpty() )
1312 return nullptr;
1313
1314 // force empty name for empty polygons
1315 return std::make_unique<XLineStartItem>( "", maPolyPolygon );
1316 }
1317
1318 if( maPolyPolygon.count() > 1 )
1319 {
1320 // check if the polygon is closed
1321 if(!maPolyPolygon.isClosed())
1322 {
1323 // force a closed polygon
1324 basegfx::B2DPolyPolygon aNew(maPolyPolygon);
1325 aNew.setClosed(true);
1326 pTempItem.reset(new XLineStartItem( aUniqueName, std::move(aNew) ));
1327 pLineStartItem = pTempItem.get();
1328 }
1329 }
1330
1331 bool bForceNew = false;
1332
1333 // 2. if we have a name check if there is already an item with the
1334 // same name in the documents pool with a different line end or start
1335
1336 if (!aUniqueName.isEmpty()
1337 && HasConflictingStartEndItems(rModel, pLineStartItem->GetName(),
1338 pLineStartItem->GetLineStartValue()))
1339 {
1340 bForceNew = true;
1341 aUniqueName.clear();
1342 }
1343
1344 // if we have no name yet, find existing item with same content or
1345 // create a unique name
1346 if( aUniqueName.isEmpty() )
1347 {
1348 aUniqueName = CreateNameForValue(rModel.GetItemPool(), pLineStartItem->GetLineStartValue(),
1349 bForceNew);
1350 }
1351
1352 // if the given name is not valid, replace it!
1353 if( aUniqueName != GetName() || pTempItem )
1354 {
1355 if( pTempItem )
1356 {
1357 pTempItem->SetName( aUniqueName );
1358 return pTempItem;
1359 }
1360 else
1361 {
1362 return std::make_unique<XLineStartItem>( aUniqueName, maPolyPolygon );
1363 }
1364 }
1365
1366 return nullptr;
1367 }
1368
CreateDefault()1369 SfxPoolItem* XLineEndItem::CreateDefault() {return new XLineEndItem;}
1370
XLineEndItem(sal_Int32 nIndex)1371 XLineEndItem::XLineEndItem(sal_Int32 nIndex)
1372 : NameOrIndex(XATTR_LINEEND, nIndex)
1373 {
1374 }
1375
XLineEndItem(const OUString & rName,basegfx::B2DPolyPolygon aPolyPolygon)1376 XLineEndItem::XLineEndItem(const OUString& rName, basegfx::B2DPolyPolygon aPolyPolygon)
1377 : NameOrIndex(XATTR_LINEEND, rName),
1378 maPolyPolygon(std::move(aPolyPolygon))
1379 {
1380 }
1381
XLineEndItem(const XLineEndItem & rItem)1382 XLineEndItem::XLineEndItem(const XLineEndItem& rItem)
1383 : NameOrIndex(rItem),
1384 maPolyPolygon(rItem.maPolyPolygon)
1385 {
1386 }
1387
XLineEndItem(basegfx::B2DPolyPolygon aPolyPolygon)1388 XLineEndItem::XLineEndItem(basegfx::B2DPolyPolygon aPolyPolygon)
1389 : NameOrIndex( XATTR_LINEEND, -1 ),
1390 maPolyPolygon(std::move(aPolyPolygon))
1391 {
1392 }
1393
Clone(SfxItemPool *) const1394 XLineEndItem* XLineEndItem::Clone(SfxItemPool* /*pPool*/) const
1395 {
1396 return new XLineEndItem(*this);
1397 }
1398
operator ==(const SfxPoolItem & rItem) const1399 bool XLineEndItem::operator==(const SfxPoolItem& rItem) const
1400 {
1401 return ( NameOrIndex::operator==(rItem) && static_cast<const XLineEndItem&>(rItem).maPolyPolygon == maPolyPolygon );
1402 }
1403
1404
1405 /** this function searches in both the models pool and the styles pool for XLineStartItem
1406 and XLineEndItem with the same value or name and returns an item with the value of
1407 this item and a unique name for an item with this value. */
checkForUniqueItem(SdrModel & rModel) const1408 std::unique_ptr<XLineEndItem> XLineEndItem::checkForUniqueItem( SdrModel& rModel ) const
1409 {
1410 std::unique_ptr<XLineEndItem> pTempItem;
1411 const XLineEndItem* pLineEndItem = this;
1412
1413 OUString aUniqueName( GetName() );
1414
1415 if( !maPolyPolygon.count() )
1416 {
1417 // if the polygon is empty, check if the name is empty
1418 if( aUniqueName.isEmpty() )
1419 return nullptr;
1420
1421 // force empty name for empty polygons
1422 return std::make_unique<XLineEndItem>( "", maPolyPolygon );
1423 }
1424
1425 if( maPolyPolygon.count() > 1 )
1426 {
1427 // check if the polygon is closed
1428 if(!maPolyPolygon.isClosed())
1429 {
1430 // force a closed polygon
1431 basegfx::B2DPolyPolygon aNew(maPolyPolygon);
1432 aNew.setClosed(true);
1433 pTempItem.reset(new XLineEndItem( aUniqueName, std::move(aNew) ));
1434 pLineEndItem = pTempItem.get();
1435 }
1436 }
1437
1438 bool bForceNew = false;
1439
1440 // 2. if we have a name check if there is already an item with the
1441 // same name in the documents pool with a different line end or start
1442
1443 if (!aUniqueName.isEmpty()
1444 && HasConflictingStartEndItems(rModel, pLineEndItem->GetName(),
1445 pLineEndItem->GetLineEndValue()))
1446 {
1447 bForceNew = true;
1448 aUniqueName.clear();
1449 }
1450
1451 // if we have no name yet, find existing item with same content or
1452 // create a unique name
1453 if( aUniqueName.isEmpty() )
1454 {
1455 aUniqueName = CreateNameForValue(rModel.GetItemPool(), pLineEndItem->GetLineEndValue(),
1456 bForceNew);
1457 }
1458
1459 // if the given name is not valid, replace it!
1460 if( aUniqueName != GetName() || pTempItem )
1461 {
1462 if( pTempItem )
1463 {
1464 pTempItem->SetName( aUniqueName );
1465 return pTempItem;
1466 }
1467 else
1468 {
1469 return std::make_unique<XLineEndItem>( aUniqueName, maPolyPolygon );
1470 }
1471 }
1472
1473 return nullptr;
1474 }
1475
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const1476 bool XLineEndItem::GetPresentation
1477 (
1478 SfxItemPresentation /*ePres*/,
1479 MapUnit /*eCoreUnit*/,
1480 MapUnit /*ePresUnit*/,
1481 OUString& rText, const IntlWrapper&
1482 ) const
1483 {
1484 rText = GetName();
1485 return true;
1486 }
1487
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const1488 bool XLineEndItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
1489 {
1490 nMemberId &= ~CONVERT_TWIPS;
1491 if( nMemberId == MID_NAME )
1492 {
1493 rVal <<= SvxUnogetApiNameForItem(Which(), GetName());
1494 }
1495 else
1496 {
1497 css::drawing::PolyPolygonBezierCoords aBezier;
1498 basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords( maPolyPolygon, aBezier );
1499 rVal <<= aBezier;
1500 }
1501 return true;
1502 }
1503
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)1504 bool XLineEndItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
1505 {
1506 nMemberId &= ~CONVERT_TWIPS;
1507 if( nMemberId == MID_NAME )
1508 {
1509 return false;
1510 }
1511 else
1512 {
1513 maPolyPolygon.clear();
1514
1515 if( rVal.hasValue() )
1516 {
1517 auto pCoords = o3tl::tryAccess<css::drawing::PolyPolygonBezierCoords>(
1518 rVal);
1519 if( !pCoords )
1520 return false;
1521
1522 if( pCoords->Coordinates.getLength() > 0 )
1523 {
1524 maPolyPolygon = basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon( *pCoords );
1525 // #i72807# close line start/end polygons hard
1526 // maPolyPolygon.setClosed(true);
1527 }
1528 }
1529 }
1530
1531 return true;
1532 }
1533
XLineStartWidthItem(tools::Long nWidth)1534 XLineStartWidthItem::XLineStartWidthItem(tools::Long nWidth) :
1535 SfxMetricItem(XATTR_LINESTARTWIDTH, nWidth)
1536 {
1537 }
1538
Clone(SfxItemPool *) const1539 XLineStartWidthItem* XLineStartWidthItem::Clone(SfxItemPool* /*pPool*/) const
1540 {
1541 return new XLineStartWidthItem(*this);
1542 }
1543
GetPresentation(SfxItemPresentation,MapUnit eCoreUnit,MapUnit ePresUnit,OUString & rText,const IntlWrapper & rIntl) const1544 bool XLineStartWidthItem::GetPresentation
1545 (
1546 SfxItemPresentation /*ePres*/,
1547 MapUnit eCoreUnit,
1548 MapUnit ePresUnit,
1549 OUString& rText, const IntlWrapper& rIntl
1550 ) const
1551 {
1552 rText = GetMetricText( static_cast<tools::Long>(GetValue()),
1553 eCoreUnit, ePresUnit, &rIntl) +
1554 " " + EditResId( GetMetricId( ePresUnit) );
1555 return true;
1556 }
1557
QueryValue(css::uno::Any & rVal,sal_uInt8) const1558 bool XLineStartWidthItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
1559 {
1560 rVal <<= GetValue();
1561 return true;
1562 }
1563
PutValue(const css::uno::Any & rVal,sal_uInt8)1564 bool XLineStartWidthItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
1565 {
1566 sal_Int32 nValue = 0;
1567 rVal >>= nValue;
1568 SetValue( nValue );
1569 return true;
1570 }
1571
XLineEndWidthItem(tools::Long nWidth)1572 XLineEndWidthItem::XLineEndWidthItem(tools::Long nWidth) :
1573 SfxMetricItem(XATTR_LINEENDWIDTH, nWidth)
1574 {
1575 }
1576
Clone(SfxItemPool *) const1577 XLineEndWidthItem* XLineEndWidthItem::Clone(SfxItemPool* /*pPool*/) const
1578 {
1579 return new XLineEndWidthItem(*this);
1580 }
1581
GetPresentation(SfxItemPresentation,MapUnit eCoreUnit,MapUnit ePresUnit,OUString & rText,const IntlWrapper & rIntl) const1582 bool XLineEndWidthItem::GetPresentation
1583 (
1584 SfxItemPresentation /*ePres*/,
1585 MapUnit eCoreUnit,
1586 MapUnit ePresUnit,
1587 OUString& rText, const IntlWrapper& rIntl
1588 ) const
1589 {
1590 rText = GetMetricText( static_cast<tools::Long>(GetValue()),
1591 eCoreUnit, ePresUnit, &rIntl) +
1592 " " + EditResId( GetMetricId( ePresUnit) );
1593 return true;
1594 }
1595
QueryValue(css::uno::Any & rVal,sal_uInt8) const1596 bool XLineEndWidthItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
1597 {
1598 rVal <<= GetValue();
1599 return true;
1600 }
1601
PutValue(const css::uno::Any & rVal,sal_uInt8)1602 bool XLineEndWidthItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
1603 {
1604 sal_Int32 nValue = 0;
1605 rVal >>= nValue;
1606 SetValue( nValue );
1607 return true;
1608 }
1609
XLineStartCenterItem(bool bStartCenter)1610 XLineStartCenterItem::XLineStartCenterItem(bool bStartCenter) :
1611 SfxBoolItem(XATTR_LINESTARTCENTER, bStartCenter)
1612 {
1613 }
1614
Clone(SfxItemPool *) const1615 XLineStartCenterItem* XLineStartCenterItem::Clone(SfxItemPool* /*pPool*/) const
1616 {
1617 return new XLineStartCenterItem(*this);
1618 }
1619
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const1620 bool XLineStartCenterItem::GetPresentation
1621 (
1622 SfxItemPresentation /*ePres*/,
1623 MapUnit /*eCoreUnit*/,
1624 MapUnit /*ePresUnit*/,
1625 OUString& rText, const IntlWrapper&
1626 ) const
1627 {
1628 rText = SvxResId(GetValue() ? RID_SVXSTR_CENTERED : RID_SVXSTR_NOTCENTERED);
1629 return true;
1630 }
1631
QueryValue(css::uno::Any & rVal,sal_uInt8) const1632 bool XLineStartCenterItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
1633 {
1634 bool bValue = GetValue();
1635 rVal <<= bValue;
1636 return true;
1637 }
1638
PutValue(const css::uno::Any & rVal,sal_uInt8)1639 bool XLineStartCenterItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
1640 {
1641 auto b = o3tl::tryAccess<bool>(rVal);
1642 if( !b.has_value() )
1643 return false;
1644
1645 SetValue( *b );
1646 return true;
1647 }
1648
XLineEndCenterItem(bool bEndCenter)1649 XLineEndCenterItem::XLineEndCenterItem(bool bEndCenter) :
1650 SfxBoolItem(XATTR_LINEENDCENTER, bEndCenter)
1651 {
1652 }
1653
Clone(SfxItemPool *) const1654 XLineEndCenterItem* XLineEndCenterItem::Clone(SfxItemPool* /*pPool*/) const
1655 {
1656 return new XLineEndCenterItem(*this);
1657 }
1658
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const1659 bool XLineEndCenterItem::GetPresentation
1660 (
1661 SfxItemPresentation /*ePres*/,
1662 MapUnit /*eCoreUnit*/,
1663 MapUnit /*ePresUnit*/,
1664 OUString& rText, const IntlWrapper&
1665 ) const
1666 {
1667 rText = SvxResId(GetValue() ? RID_SVXSTR_CENTERED : RID_SVXSTR_NOTCENTERED);
1668 return true;
1669 }
1670
QueryValue(css::uno::Any & rVal,sal_uInt8) const1671 bool XLineEndCenterItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
1672 {
1673 bool bValue = GetValue();
1674 rVal <<= bValue;
1675 return true;
1676 }
1677
PutValue(const css::uno::Any & rVal,sal_uInt8)1678 bool XLineEndCenterItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
1679 {
1680 auto b = o3tl::tryAccess<bool>(rVal);
1681 if( !b.has_value() )
1682 return false;
1683
1684 SetValue( *b );
1685 return true;
1686 }
1687
1688 // --- fill attributes ---
1689
1690
CreateDefault()1691 SfxPoolItem* XFillStyleItem::CreateDefault() { return new XFillStyleItem; }
1692
XFillStyleItem(drawing::FillStyle eFillStyle)1693 XFillStyleItem::XFillStyleItem(drawing::FillStyle eFillStyle) :
1694 SfxEnumItem(XATTR_FILLSTYLE, eFillStyle)
1695 {
1696 }
1697
Clone(SfxItemPool *) const1698 XFillStyleItem* XFillStyleItem::Clone(SfxItemPool* /*pPool*/) const
1699 {
1700 return new XFillStyleItem( *this );
1701 }
1702
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const1703 bool XFillStyleItem::GetPresentation
1704 (
1705 SfxItemPresentation /*ePres*/,
1706 MapUnit /*eCoreUnit*/,
1707 MapUnit /*ePresUnit*/,
1708 OUString& rText, const IntlWrapper&
1709 ) const
1710 {
1711 rText.clear();
1712
1713 TranslateId pId;
1714
1715 switch( GetValue() )
1716 {
1717 case drawing::FillStyle_NONE:
1718 pId = RID_SVXSTR_INVISIBLE;
1719 break;
1720 case drawing::FillStyle_SOLID:
1721 pId = RID_SVXSTR_SOLID;
1722 break;
1723 case drawing::FillStyle_GRADIENT:
1724 pId = RID_SVXSTR_GRADIENT;
1725 break;
1726 case drawing::FillStyle_HATCH:
1727 pId = RID_SVXSTR_HATCH;
1728 break;
1729 case drawing::FillStyle_BITMAP:
1730 pId = RID_SVXSTR_BITMAP;
1731 break;
1732 default: break;
1733 }
1734
1735 if (pId)
1736 rText = SvxResId(pId);
1737 return true;
1738 }
1739
QueryValue(css::uno::Any & rVal,sal_uInt8) const1740 bool XFillStyleItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
1741 {
1742 css::drawing::FillStyle eFS = GetValue();
1743
1744 rVal <<= eFS;
1745
1746 return true;
1747 }
1748
PutValue(const css::uno::Any & rVal,sal_uInt8)1749 bool XFillStyleItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/)
1750 {
1751 css::drawing::FillStyle eFS;
1752 if(!(rVal >>= eFS))
1753 {
1754 // also try an int (for Basic)
1755 sal_Int32 nFS = 0;
1756 if(!(rVal >>= nFS))
1757 return false;
1758 eFS = static_cast<css::drawing::FillStyle>(nFS);
1759 }
1760
1761 SetValue( eFS );
1762
1763 return true;
1764 }
1765
dumpAsXml(xmlTextWriterPtr pWriter) const1766 void XFillStyleItem::dumpAsXml(xmlTextWriterPtr pWriter) const
1767 {
1768 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("XFillStyleItem"));
1769 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
1770 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::number(static_cast<sal_Int16>(GetValue())).getStr()));
1771
1772 OUString aPresentation;
1773 IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
1774 GetPresentation(SfxItemPresentation::Nameless, MapUnit::Map100thMM, MapUnit::Map100thMM, aPresentation, aIntlWrapper);
1775 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("presentation"), BAD_CAST(aPresentation.toUtf8().getStr()));
1776
1777 (void)xmlTextWriterEndElement(pWriter);
1778 }
1779
dumpAsJSON() const1780 boost::property_tree::ptree XFillStyleItem::dumpAsJSON() const
1781 {
1782 boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON();
1783
1784 if (Which() == XATTR_FILLSTYLE)
1785 aTree.put("commandName", ".uno:FillStyle");
1786
1787 OUString sValue;
1788
1789 switch( GetValue() )
1790 {
1791 case drawing::FillStyle_NONE:
1792 sValue = "NONE";
1793 break;
1794 case drawing::FillStyle_SOLID:
1795 sValue = "SOLID";
1796 break;
1797 case drawing::FillStyle_GRADIENT:
1798 sValue = "GRADIENT";
1799 break;
1800 case drawing::FillStyle_HATCH:
1801 sValue = "HATCH";
1802 break;
1803 case drawing::FillStyle_BITMAP:
1804 sValue = "BITMAP";
1805 break;
1806 default: break;
1807 }
1808
1809 aTree.put("state", sValue);
1810
1811 return aTree;
1812 }
1813
1814
CreateDefault()1815 SfxPoolItem* XFillColorItem::CreateDefault() { return new XFillColorItem; }
1816
XFillColorItem(sal_Int32 nIndex,const Color & rTheColor)1817 XFillColorItem::XFillColorItem(sal_Int32 nIndex, const Color& rTheColor) :
1818 XColorItem(XATTR_FILLCOLOR, nIndex, rTheColor)
1819 {
1820 }
1821
XFillColorItem(const OUString & rName,const Color & rTheColor)1822 XFillColorItem::XFillColorItem(const OUString& rName, const Color& rTheColor) :
1823 XColorItem(XATTR_FILLCOLOR, rName, rTheColor)
1824 {
1825 }
1826
Clone(SfxItemPool *) const1827 XFillColorItem* XFillColorItem::Clone(SfxItemPool* /*pPool*/) const
1828 {
1829 return new XFillColorItem(*this);
1830 }
1831
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const1832 bool XFillColorItem::GetPresentation
1833 (
1834 SfxItemPresentation /*ePres*/,
1835 MapUnit /*eCoreUnit*/,
1836 MapUnit /*ePresUnit*/,
1837 OUString& rText, const IntlWrapper&
1838 ) const
1839 {
1840 rText = GetName();
1841 return true;
1842 }
1843
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const1844 bool XFillColorItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
1845 {
1846 nMemberId &= ~CONVERT_TWIPS;
1847 switch (nMemberId)
1848 {
1849 case MID_COLOR_THEME_INDEX:
1850 {
1851 rVal <<= sal_Int16(getComplexColor().getThemeColorType());
1852 break;
1853 }
1854 case MID_COLOR_LUM_MOD:
1855 {
1856 sal_Int16 nValue = 10000;
1857 for (auto const& rTransform : getComplexColor().getTransformations())
1858 {
1859 if (rTransform.meType == model::TransformationType::LumMod)
1860 nValue = rTransform.mnValue;
1861 }
1862 rVal <<= nValue;
1863 break;
1864 }
1865 case MID_COLOR_LUM_OFF:
1866 {
1867 sal_Int16 nValue = 0;
1868 for (auto const& rTransform : getComplexColor().getTransformations())
1869 {
1870 if (rTransform.meType == model::TransformationType::LumOff)
1871 nValue = rTransform.mnValue;
1872 }
1873 rVal <<= nValue;
1874 break;
1875 }
1876 case MID_COMPLEX_COLOR:
1877 {
1878 auto xComplexColor = model::color::createXComplexColor(getComplexColor());
1879 rVal <<= xComplexColor;
1880 break;
1881 }
1882 case MID_COMPLEX_COLOR_JSON:
1883 {
1884 rVal <<= OStringToOUString(model::color::convertToJSON(getComplexColor()), RTL_TEXTENCODING_UTF8);
1885 break;
1886 }
1887 default:
1888 {
1889 rVal <<= GetColorValue().GetRGBColor();
1890 break;
1891 }
1892 }
1893
1894 return true;
1895 }
1896
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)1897 bool XFillColorItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
1898 {
1899 nMemberId &= ~CONVERT_TWIPS;
1900 switch(nMemberId)
1901 {
1902 case MID_COLOR_THEME_INDEX:
1903 {
1904 sal_Int16 nIndex = -1;
1905 if (!(rVal >>= nIndex))
1906 return false;
1907 getComplexColor().setThemeColor(model::convertToThemeColorType(nIndex));
1908 }
1909 break;
1910 case MID_COLOR_LUM_MOD:
1911 {
1912 sal_Int16 nLumMod = 10000;
1913 if (!(rVal >>= nLumMod))
1914 return false;
1915 getComplexColor().removeTransformations(model::TransformationType::LumMod);
1916 getComplexColor().addTransformation({model::TransformationType::LumMod, nLumMod});
1917 }
1918 break;
1919 case MID_COLOR_LUM_OFF:
1920 {
1921 sal_Int16 nLumOff = 0;
1922 if (!(rVal >>= nLumOff))
1923 return false;
1924 getComplexColor().removeTransformations(model::TransformationType::LumOff);
1925 getComplexColor().addTransformation({model::TransformationType::LumOff, nLumOff});
1926 }
1927 break;
1928 case MID_COMPLEX_COLOR:
1929 {
1930 css::uno::Reference<css::util::XComplexColor> xComplexColor;
1931 if (!(rVal >>= xComplexColor))
1932 return false;
1933 setComplexColor(model::color::getFromXComplexColor(xComplexColor));
1934 }
1935 break;
1936 case MID_COMPLEX_COLOR_JSON:
1937 {
1938 OUString sComplexColorJson;
1939 if (!(rVal >>= sComplexColorJson))
1940 return false;
1941
1942 if (sComplexColorJson.isEmpty())
1943 return false;
1944
1945 OString aJSON = OUStringToOString(sComplexColorJson, RTL_TEXTENCODING_ASCII_US);
1946 model::ComplexColor aComplexColor;
1947 model::color::convertFromJSON(aJSON, aComplexColor);
1948 setComplexColor(aComplexColor);
1949 }
1950 break;
1951 default:
1952 {
1953 Color nValue;
1954 if(!(rVal >>= nValue ))
1955 return false;
1956
1957 SetColorValue( nValue );
1958
1959 }
1960 break;
1961 }
1962 return true;
1963 }
1964
dumpAsXml(xmlTextWriterPtr pWriter) const1965 void XFillColorItem::dumpAsXml(xmlTextWriterPtr pWriter) const
1966 {
1967 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("XFillColorItem"));
1968 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
1969
1970 XColorItem::dumpAsXml(pWriter);
1971
1972 (void)xmlTextWriterEndElement(pWriter);
1973 }
1974
dumpAsJSON() const1975 boost::property_tree::ptree XFillColorItem::dumpAsJSON() const
1976 {
1977 boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON();
1978
1979 if (Which() == XATTR_FILLCOLOR)
1980 aTree.put("commandName", ".uno:FillPageColor");
1981
1982 aTree.put("state", GetColorValue().AsRGBHexString());
1983
1984 return aTree;
1985 }
1986
XSecondaryFillColorItem(const OUString & rName,const Color & rTheColor)1987 XSecondaryFillColorItem::XSecondaryFillColorItem(const OUString& rName, const Color& rTheColor) :
1988 XColorItem(XATTR_SECONDARYFILLCOLOR, rName, rTheColor)
1989 {
1990 }
1991
Clone(SfxItemPool *) const1992 XSecondaryFillColorItem* XSecondaryFillColorItem::Clone(SfxItemPool* /*pPool*/) const
1993 {
1994 return new XSecondaryFillColorItem(*this);
1995 }
1996
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const1997 bool XSecondaryFillColorItem::GetPresentation
1998 (
1999 SfxItemPresentation /*ePres*/,
2000 MapUnit /*eCoreUnit*/,
2001 MapUnit /*ePresUnit*/,
2002 OUString& rText, const IntlWrapper&
2003 ) const
2004 {
2005 rText = GetName();
2006 return true;
2007 }
2008
CreateDefault()2009 SfxPoolItem* XFillGradientItem::CreateDefault() { return new XFillGradientItem; }
2010
XFillGradientItem(sal_Int32 nIndex,const basegfx::BGradient & rTheGradient,TypedWhichId<XFillGradientItem> nWhich)2011 XFillGradientItem::XFillGradientItem(sal_Int32 nIndex,
2012 const basegfx::BGradient& rTheGradient,
2013 TypedWhichId<XFillGradientItem> nWhich) :
2014 NameOrIndex(nWhich, nIndex),
2015 m_aGradient(rTheGradient)
2016 {
2017 }
2018
XFillGradientItem(const OUString & rName,const basegfx::BGradient & rTheGradient,TypedWhichId<XFillGradientItem> nWhich)2019 XFillGradientItem::XFillGradientItem(const OUString& rName,
2020 const basegfx::BGradient& rTheGradient,
2021 TypedWhichId<XFillGradientItem> nWhich)
2022 : NameOrIndex(nWhich, rName)
2023 , m_aGradient(rTheGradient)
2024 {
2025 }
2026
XFillGradientItem(const XFillGradientItem & rItem)2027 XFillGradientItem::XFillGradientItem(const XFillGradientItem& rItem) :
2028 NameOrIndex(rItem),
2029 m_aGradient(rItem.m_aGradient)
2030 {
2031 }
2032
XFillGradientItem(const basegfx::BGradient & rTheGradient,TypedWhichId<XFillGradientItem> nWhich)2033 XFillGradientItem::XFillGradientItem( const basegfx::BGradient& rTheGradient,
2034 TypedWhichId<XFillGradientItem> nWhich)
2035 : NameOrIndex( nWhich, -1 ),
2036 m_aGradient(rTheGradient)
2037 {
2038 }
2039
Clone(SfxItemPool *) const2040 XFillGradientItem* XFillGradientItem::Clone(SfxItemPool* /*pPool*/) const
2041 {
2042 return new XFillGradientItem(*this);
2043 }
2044
operator ==(const SfxPoolItem & rItem) const2045 bool XFillGradientItem::operator==(const SfxPoolItem& rItem) const
2046 {
2047 return ( NameOrIndex::operator==(rItem) &&
2048 m_aGradient == static_cast<const XFillGradientItem&>(rItem).m_aGradient );
2049 }
2050
GetGradientValue() const2051 const basegfx::BGradient& XFillGradientItem::GetGradientValue() const // GetValue -> GetGradientValue
2052 {
2053 if (!IsIndex())
2054 return m_aGradient;
2055 // ToDo: This should fail. We never called this code with a table so this should always
2056 // have failed. Thus, I'm thinking that XFillGradientItem can't be an Index.
2057 return m_aGradient;
2058 }
2059
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const2060 bool XFillGradientItem::GetPresentation
2061 (
2062 SfxItemPresentation /*ePres*/,
2063 MapUnit /*eCoreUnit*/,
2064 MapUnit /*ePresUnit*/,
2065 OUString& rText, const IntlWrapper&
2066 ) const
2067 {
2068 rText = GetName();
2069 return true;
2070 }
2071
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const2072 bool XFillGradientItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
2073 {
2074 nMemberId &= ~CONVERT_TWIPS;
2075 switch ( nMemberId )
2076 {
2077 case 0:
2078 {
2079 // fill values
2080 const css::awt::Gradient2 aGradient2 = model::gradient::createUnoGradient2(GetGradientValue());
2081
2082 // create sequence
2083 uno::Sequence< beans::PropertyValue > aPropSeq{
2084 comphelper::makePropertyValue(u"Name"_ustr, SvxUnogetApiNameForItem(Which(), GetName())),
2085 comphelper::makePropertyValue(u"FillGradient"_ustr, aGradient2)
2086 };
2087 rVal <<= aPropSeq;
2088 break;
2089 }
2090
2091 case MID_FILLGRADIENT:
2092 {
2093 // fill values
2094 const css::awt::Gradient2 aGradient2 = model::gradient::createUnoGradient2(GetGradientValue());
2095
2096 // create sequence
2097 rVal <<= aGradient2;
2098 break;
2099 }
2100
2101 case MID_NAME:
2102 {
2103 rVal <<= SvxUnogetApiNameForItem(Which(), GetName());
2104 break;
2105 }
2106
2107 case MID_GRADIENT_COLORSTOPSEQUENCE:
2108 {
2109 // fill values
2110 const css::awt::ColorStopSequence aColorStopSequence = model::gradient::createColorStopSequence(GetGradientValue().GetColorStops());
2111
2112 // create sequence
2113 rVal <<= aColorStopSequence;
2114 break;
2115 }
2116
2117 case MID_GRADIENT_STYLE: rVal <<= static_cast<sal_Int16>(GetGradientValue().GetGradientStyle()); break;
2118 case MID_GRADIENT_STARTCOLOR: rVal <<= Color(GetGradientValue().GetColorStops().front().getStopColor()); break;
2119 case MID_GRADIENT_ENDCOLOR: rVal <<= Color(GetGradientValue().GetColorStops().back().getStopColor()); break;
2120 case MID_GRADIENT_ANGLE: rVal <<= static_cast<sal_Int16>(GetGradientValue().GetAngle()); break;
2121 case MID_GRADIENT_BORDER: rVal <<= GetGradientValue().GetBorder(); break;
2122 case MID_GRADIENT_XOFFSET: rVal <<= GetGradientValue().GetXOffset(); break;
2123 case MID_GRADIENT_YOFFSET: rVal <<= GetGradientValue().GetYOffset(); break;
2124 case MID_GRADIENT_STARTINTENSITY: rVal <<= GetGradientValue().GetStartIntens(); break;
2125 case MID_GRADIENT_ENDINTENSITY: rVal <<= GetGradientValue().GetEndIntens(); break;
2126 case MID_GRADIENT_STEPCOUNT: rVal <<= GetGradientValue().GetSteps(); break;
2127
2128 default: OSL_FAIL("Wrong MemberId!"); return false;
2129 }
2130
2131 return true;
2132 }
2133
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)2134 bool XFillGradientItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
2135 {
2136 nMemberId &= ~CONVERT_TWIPS;
2137
2138 switch ( nMemberId )
2139 {
2140 case 0:
2141 {
2142 uno::Sequence< beans::PropertyValue > aPropSeq;
2143 css::uno::Any aGradientAny;
2144
2145 if ( rVal >>= aPropSeq )
2146 {
2147 OUString aName;
2148
2149 for (const auto& rProp : aPropSeq)
2150 {
2151 if ( rProp.Name == "Name" )
2152 rProp.Value >>= aName;
2153 else if ( rProp.Name == "FillGradient" )
2154 aGradientAny = rProp.Value;
2155 }
2156
2157 SetName( aName );
2158
2159 if (aGradientAny.hasValue() && (aGradientAny.has<css::awt::Gradient>() || aGradientAny.has<css::awt::Gradient2>()))
2160 {
2161 SetGradientValue(model::gradient::getFromAny(aGradientAny));
2162 }
2163
2164 return true;
2165 }
2166
2167 return false;
2168 }
2169
2170 case MID_NAME:
2171 {
2172 OUString aName;
2173 if (!(rVal >>= aName ))
2174 return false;
2175 SetName( aName );
2176 break;
2177 }
2178
2179 case MID_FILLGRADIENT:
2180 {
2181 if (rVal.hasValue() && (rVal.has<css::awt::Gradient>() || rVal.has<css::awt::Gradient2>()))
2182 {
2183 SetGradientValue(model::gradient::getFromAny(rVal));
2184 }
2185
2186 break;
2187 }
2188
2189 case MID_GRADIENT_COLORSTOPSEQUENCE:
2190 {
2191 // check if we have a awt::ColorStopSequence
2192 if (rVal.hasValue() && rVal.has<css::awt::ColorStopSequence>())
2193 {
2194
2195 const basegfx::BColorStops aColorStops = model::gradient::getColorStopsFromAny(rVal);
2196
2197 if (!aColorStops.empty())
2198 {
2199 basegfx::BGradient aBGradient(GetGradientValue());
2200 aBGradient.SetColorStops(aColorStops);
2201 SetGradientValue(aBGradient);
2202 }
2203 }
2204 break;
2205 }
2206
2207 case MID_GRADIENT_STARTCOLOR:
2208 case MID_GRADIENT_ENDCOLOR:
2209 {
2210 Color nVal;
2211 if(!(rVal >>= nVal ))
2212 return false;
2213
2214 basegfx::BGradient aBGradient(GetGradientValue());
2215 basegfx::BColorStops aNewColorStops(aBGradient.GetColorStops());
2216
2217 if ( nMemberId == MID_GRADIENT_STARTCOLOR )
2218 {
2219 aNewColorStops.replaceStartColor(nVal.getBColor());
2220 }
2221 else
2222 {
2223 aNewColorStops.replaceEndColor(nVal.getBColor());
2224 }
2225
2226 aBGradient.SetColorStops(aNewColorStops);
2227 SetGradientValue( aBGradient );
2228 break;
2229 }
2230
2231 case MID_GRADIENT_STYLE:
2232 case MID_GRADIENT_ANGLE:
2233 case MID_GRADIENT_BORDER:
2234 case MID_GRADIENT_STARTINTENSITY:
2235 case MID_GRADIENT_ENDINTENSITY:
2236 case MID_GRADIENT_STEPCOUNT:
2237 case MID_GRADIENT_XOFFSET:
2238 case MID_GRADIENT_YOFFSET:
2239 {
2240 sal_Int16 nVal = sal_Int16();
2241 if(!(rVal >>= nVal ))
2242 return false;
2243
2244 basegfx::BGradient aBGradient = GetGradientValue();
2245
2246 switch ( nMemberId )
2247 {
2248 case MID_GRADIENT_STYLE:
2249 aBGradient.SetGradientStyle( static_cast<css::awt::GradientStyle>(nVal) ); break;
2250 case MID_GRADIENT_ANGLE:
2251 aBGradient.SetAngle( Degree10(nVal) ); break;
2252 case MID_GRADIENT_BORDER:
2253 aBGradient.SetBorder( nVal ); break;
2254 case MID_GRADIENT_STARTINTENSITY:
2255 aBGradient.SetStartIntens( nVal ); break;
2256 case MID_GRADIENT_ENDINTENSITY:
2257 aBGradient.SetEndIntens( nVal ); break;
2258 case MID_GRADIENT_STEPCOUNT:
2259 aBGradient.SetSteps( nVal ); break;
2260 case MID_GRADIENT_XOFFSET:
2261 aBGradient.SetXOffset( nVal ); break;
2262 case MID_GRADIENT_YOFFSET:
2263 aBGradient.SetYOffset( nVal ); break;
2264 }
2265
2266 SetGradientValue( aBGradient );
2267 break;
2268 }
2269 }
2270
2271 return true;
2272 }
2273
CompareValueFunc(const NameOrIndex * p1,const NameOrIndex * p2)2274 bool XFillGradientItem::CompareValueFunc( const NameOrIndex* p1, const NameOrIndex* p2 )
2275 {
2276 return static_cast<const XFillGradientItem*>(p1)->GetGradientValue() == static_cast<const XFillGradientItem*>(p2)->GetGradientValue();
2277 }
2278
checkForUniqueItem(SdrModel & rModel) const2279 std::unique_ptr<XFillGradientItem> XFillGradientItem::checkForUniqueItem( SdrModel& rModel ) const
2280 {
2281 const OUString aUniqueName(CheckNamedItem(
2282 Which(), &rModel.GetItemPool(),
2283 XFillGradientItem::CompareValueFunc, RID_SVXSTR_GRADIENT,
2284 rModel.GetPropertyList(XPropertyListType::Gradient)));
2285
2286 // if the given name is not valid, replace it!
2287 if( aUniqueName != GetName() )
2288 return std::make_unique<XFillGradientItem>( aUniqueName, m_aGradient, TypedWhichId<XFillGradientItem>(Which()) );
2289
2290 return nullptr;
2291 }
2292
dumpAsJSON() const2293 boost::property_tree::ptree XFillGradientItem::dumpAsJSON() const
2294 {
2295 boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON();
2296
2297 if (Which() == XATTR_FILLGRADIENT)
2298 aTree.put("commandName", ".uno:FillGradient");
2299
2300 aTree.push_back(std::make_pair("state", GetGradientValue().dumpAsJSON()));
2301
2302 return aTree;
2303 }
2304
2305
CreateDefault()2306 SfxPoolItem* XFillFloatTransparenceItem::CreateDefault() { return new XFillFloatTransparenceItem; }
2307
XFillFloatTransparenceItem()2308 XFillFloatTransparenceItem::XFillFloatTransparenceItem() :
2309 XFillGradientItem(XATTR_FILLFLOATTRANSPARENCE),
2310 m_bEnabled( false )
2311 {
2312 }
2313
XFillFloatTransparenceItem(const OUString & rName,const basegfx::BGradient & rGradient,bool bEnable)2314 XFillFloatTransparenceItem::XFillFloatTransparenceItem(const OUString& rName, const basegfx::BGradient& rGradient, bool bEnable ) :
2315 XFillGradientItem ( rName, rGradient, XATTR_FILLFLOATTRANSPARENCE ),
2316 m_bEnabled ( bEnable )
2317 {
2318 }
2319
XFillFloatTransparenceItem(const XFillFloatTransparenceItem & rItem)2320 XFillFloatTransparenceItem::XFillFloatTransparenceItem( const XFillFloatTransparenceItem& rItem ) :
2321 XFillGradientItem ( rItem ),
2322 m_bEnabled ( rItem.m_bEnabled )
2323 {
2324 }
2325
XFillFloatTransparenceItem(const basegfx::BGradient & rTheGradient,bool bEnable)2326 XFillFloatTransparenceItem::XFillFloatTransparenceItem(const basegfx::BGradient& rTheGradient, bool bEnable )
2327 : XFillGradientItem ( -1, rTheGradient, XATTR_FILLFLOATTRANSPARENCE ),
2328 m_bEnabled ( bEnable )
2329 {
2330 }
2331
operator ==(const SfxPoolItem & rItem) const2332 bool XFillFloatTransparenceItem::operator==( const SfxPoolItem& rItem ) const
2333 {
2334 return ( XFillGradientItem::operator==(rItem) ) &&
2335 ( m_bEnabled == static_cast<const XFillFloatTransparenceItem&>(rItem).m_bEnabled );
2336 }
2337
Clone(SfxItemPool *) const2338 XFillFloatTransparenceItem* XFillFloatTransparenceItem::Clone( SfxItemPool* /*pPool*/) const
2339 {
2340 return new XFillFloatTransparenceItem( *this );
2341 }
2342
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const2343 bool XFillFloatTransparenceItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
2344 {
2345 if (MID_GRADIENT_STARTINTENSITY == nMemberId
2346 || MID_GRADIENT_ENDINTENSITY == nMemberId
2347 || MID_GRADIENT_STEPCOUNT == nMemberId)
2348 {
2349 // tdf#155913 handle attributes not supported by transparency gradient as error
2350 return false;
2351 }
2352
2353 if (!IsEnabled() && nMemberId == MID_NAME)
2354 {
2355 // make sure that we return empty string in case of query for
2356 // "FillTransparenceGradientName" if the item is disabled
2357 rVal <<= OUString();
2358 return true;
2359 }
2360
2361 return XFillGradientItem::QueryValue( rVal, nMemberId );
2362 }
2363
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)2364 bool XFillFloatTransparenceItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
2365 {
2366 if (MID_GRADIENT_STARTINTENSITY == nMemberId
2367 || MID_GRADIENT_ENDINTENSITY == nMemberId
2368 || MID_GRADIENT_STEPCOUNT == nMemberId)
2369 {
2370 // tdf#155913 handle attributes not supported by transparency gradient as error
2371 return false;
2372 }
2373
2374 return XFillGradientItem::PutValue( rVal, nMemberId );
2375 }
2376
GetPresentation(SfxItemPresentation ePres,MapUnit eCoreUnit,MapUnit ePresUnit,OUString & rText,const IntlWrapper & rIntlWrapper) const2377 bool XFillFloatTransparenceItem::GetPresentation( SfxItemPresentation ePres,
2378 MapUnit eCoreUnit, MapUnit ePresUnit,
2379 OUString& rText,
2380 const IntlWrapper& rIntlWrapper ) const
2381 {
2382 return XFillGradientItem::GetPresentation( ePres, eCoreUnit, ePresUnit, rText, rIntlWrapper );
2383 }
2384
CompareValueFunc(const NameOrIndex * p1,const NameOrIndex * p2)2385 bool XFillFloatTransparenceItem::CompareValueFunc( const NameOrIndex* p1, const NameOrIndex* p2 )
2386 {
2387 return static_cast<const XFillFloatTransparenceItem*>(p1)->IsEnabled() == static_cast<const XFillFloatTransparenceItem*>(p2)->IsEnabled() &&
2388 static_cast<const XFillFloatTransparenceItem*>(p1)->GetGradientValue() == static_cast<const XFillFloatTransparenceItem*>(p2)->GetGradientValue();
2389 }
2390
checkForUniqueItem(SdrModel & rModel) const2391 std::unique_ptr<XFillFloatTransparenceItem> XFillFloatTransparenceItem::checkForUniqueItem( SdrModel& rModel ) const
2392 {
2393 // #85953# unique name only necessary when enabled
2394 if(IsEnabled())
2395 {
2396 const OUString aUniqueName(CheckNamedItem(
2397 XATTR_FILLFLOATTRANSPARENCE,
2398 &rModel.GetItemPool(),
2399 XFillFloatTransparenceItem::CompareValueFunc,
2400 RID_SVXSTR_TRASNGR0,
2401 XPropertyListRef()));
2402
2403 // if the given name is not valid, replace it!
2404 if( aUniqueName != GetName() )
2405 {
2406 return std::make_unique<XFillFloatTransparenceItem>( aUniqueName, GetGradientValue(), true );
2407 }
2408 }
2409 else
2410 {
2411 // #85953# if disabled, force name to empty string
2412 if( !GetName().isEmpty() )
2413 {
2414 return std::make_unique<XFillFloatTransparenceItem>(OUString(), GetGradientValue(), false);
2415 }
2416 }
2417
2418 return nullptr;
2419 }
2420
dumpAsJSON() const2421 boost::property_tree::ptree XFillFloatTransparenceItem::dumpAsJSON() const
2422 {
2423 boost::property_tree::ptree aTree = XFillGradientItem::dumpAsJSON();
2424 aTree.put("commandName", ".uno:FillFloatTransparence");
2425
2426 if (!m_bEnabled)
2427 {
2428 boost::property_tree::ptree& rState = aTree.get_child("state");
2429 // When gradient fill is disabled, the intensity fields contain the
2430 // constant encoded percent-transparency. However we use that here to just
2431 // distinguish between 'None' and 'Solid' types and correct the 'style'
2432 // property appropriately.
2433 if (GetGradientValue().GetStartIntens() == 100)
2434 rState.put("style", "NONE");
2435 else
2436 rState.put("style", "SOLID");
2437 }
2438
2439 return aTree;
2440 }
2441
XHatch(const Color & rCol,css::drawing::HatchStyle eTheStyle,tools::Long nTheDistance,Degree10 nTheAngle)2442 XHatch::XHatch(const Color& rCol, css::drawing::HatchStyle eTheStyle, tools::Long nTheDistance,
2443 Degree10 nTheAngle) :
2444 m_eStyle(eTheStyle),
2445 m_aColor(rCol),
2446 m_nDistance(nTheDistance),
2447 m_nAngle(nTheAngle)
2448 {
2449 }
2450
operator ==(const XHatch & rHatch) const2451 bool XHatch::operator==(const XHatch& rHatch) const
2452 {
2453 return ( m_eStyle == rHatch.m_eStyle &&
2454 m_aColor == rHatch.m_aColor &&
2455 m_nDistance == rHatch.m_nDistance &&
2456 m_nAngle == rHatch.m_nAngle );
2457 }
2458
2459
CreateDefault()2460 SfxPoolItem* XFillHatchItem::CreateDefault() { return new XFillHatchItem; }
2461
XFillHatchItem(const OUString & rName,const XHatch & rTheHatch)2462 XFillHatchItem::XFillHatchItem(const OUString& rName,
2463 const XHatch& rTheHatch) :
2464 NameOrIndex(XATTR_FILLHATCH, rName),
2465 m_aHatch(rTheHatch)
2466 {
2467 }
2468
XFillHatchItem(const XFillHatchItem & rItem)2469 XFillHatchItem::XFillHatchItem(const XFillHatchItem& rItem) :
2470 NameOrIndex(rItem),
2471 m_aHatch(rItem.m_aHatch)
2472 {
2473 }
2474
XFillHatchItem(const XHatch & rTheHatch)2475 XFillHatchItem::XFillHatchItem(const XHatch& rTheHatch)
2476 : NameOrIndex( XATTR_FILLHATCH, -1 ),
2477 m_aHatch(rTheHatch)
2478 {
2479 }
2480
Clone(SfxItemPool *) const2481 XFillHatchItem* XFillHatchItem::Clone(SfxItemPool* /*pPool*/) const
2482 {
2483 return new XFillHatchItem(*this);
2484 }
2485
operator ==(const SfxPoolItem & rItem) const2486 bool XFillHatchItem::operator==(const SfxPoolItem& rItem) const
2487 {
2488 return ( NameOrIndex::operator==(rItem) &&
2489 m_aHatch == static_cast<const XFillHatchItem&>(rItem).m_aHatch );
2490 }
2491
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const2492 bool XFillHatchItem::GetPresentation
2493 (
2494 SfxItemPresentation /*ePres*/,
2495 MapUnit /*eCoreUnit*/,
2496 MapUnit /*ePresUnit*/,
2497 OUString& rText, const IntlWrapper&
2498 ) const
2499 {
2500 rText = GetName();
2501 return true;
2502 }
2503
HasMetrics() const2504 bool XFillHatchItem::HasMetrics() const
2505 {
2506 return true;
2507 }
2508
ScaleMetrics(tools::Long nMul,tools::Long nDiv)2509 void XFillHatchItem::ScaleMetrics(tools::Long nMul, tools::Long nDiv)
2510 {
2511 m_aHatch.SetDistance( BigInt::Scale( m_aHatch.GetDistance(), nMul, nDiv ) );
2512 }
2513
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const2514 bool XFillHatchItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
2515 {
2516 nMemberId &= ~CONVERT_TWIPS;
2517
2518 switch ( nMemberId )
2519 {
2520 case 0:
2521 {
2522 css::drawing::Hatch aUnoHatch;
2523
2524 aUnoHatch.Style = m_aHatch.GetHatchStyle();
2525 aUnoHatch.Color = sal_Int32(m_aHatch.GetColor());
2526 aUnoHatch.Distance = m_aHatch.GetDistance();
2527 aUnoHatch.Angle = m_aHatch.GetAngle().get();
2528
2529 uno::Sequence< beans::PropertyValue > aPropSeq{
2530 comphelper::makePropertyValue(u"Name"_ustr, SvxUnogetApiNameForItem(Which(), GetName())),
2531 comphelper::makePropertyValue(u"FillHatch"_ustr, aUnoHatch)
2532 };
2533 rVal <<= aPropSeq;
2534 break;
2535 }
2536
2537 case MID_FILLHATCH:
2538 {
2539 css::drawing::Hatch aUnoHatch;
2540
2541 aUnoHatch.Style = m_aHatch.GetHatchStyle();
2542 aUnoHatch.Color = sal_Int32(m_aHatch.GetColor());
2543 aUnoHatch.Distance = m_aHatch.GetDistance();
2544 aUnoHatch.Angle = m_aHatch.GetAngle().get();
2545 rVal <<= aUnoHatch;
2546 break;
2547 }
2548
2549 case MID_NAME:
2550 {
2551 rVal <<= SvxUnogetApiNameForItem(Which(), GetName());
2552 break;
2553 }
2554
2555 case MID_HATCH_STYLE:
2556 rVal <<= m_aHatch.GetHatchStyle(); break;
2557 case MID_HATCH_COLOR:
2558 rVal <<= m_aHatch.GetColor(); break;
2559 case MID_HATCH_DISTANCE:
2560 rVal <<= m_aHatch.GetDistance(); break;
2561 case MID_HATCH_ANGLE:
2562 rVal <<= m_aHatch.GetAngle().get(); break;
2563
2564 default: OSL_FAIL("Wrong MemberId!"); return false;
2565 }
2566
2567 return true;
2568 }
2569
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)2570 bool XFillHatchItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
2571 {
2572 nMemberId &= ~CONVERT_TWIPS;
2573
2574 switch ( nMemberId )
2575 {
2576 case 0:
2577 {
2578 uno::Sequence< beans::PropertyValue > aPropSeq;
2579 if ( rVal >>= aPropSeq )
2580 {
2581 css::drawing::Hatch aUnoHatch;
2582 OUString aName;
2583 bool bHatch( false );
2584 for (const auto& rProp : aPropSeq)
2585 {
2586 if ( rProp.Name == "Name" )
2587 rProp.Value >>= aName;
2588 else if ( rProp.Name == "FillHatch" )
2589 {
2590 if ( rProp.Value >>= aUnoHatch )
2591 bHatch = true;
2592 }
2593 }
2594
2595 SetName( aName );
2596 if ( bHatch )
2597 {
2598 m_aHatch.SetHatchStyle( aUnoHatch.Style );
2599 m_aHatch.SetColor( Color(ColorTransparency, aUnoHatch.Color) );
2600 m_aHatch.SetDistance( aUnoHatch.Distance );
2601 m_aHatch.SetAngle( Degree10(aUnoHatch.Angle) );
2602 }
2603
2604 return true;
2605 }
2606
2607 return false;
2608 }
2609
2610 case MID_FILLHATCH:
2611 {
2612 css::drawing::Hatch aUnoHatch;
2613 if(!(rVal >>= aUnoHatch))
2614 return false;
2615
2616 m_aHatch.SetHatchStyle( aUnoHatch.Style );
2617 m_aHatch.SetColor( Color(ColorTransparency, aUnoHatch.Color) );
2618 m_aHatch.SetDistance( aUnoHatch.Distance );
2619 m_aHatch.SetAngle( Degree10(aUnoHatch.Angle) );
2620 break;
2621 }
2622
2623 case MID_NAME:
2624 {
2625 OUString aName;
2626 if (!(rVal >>= aName ))
2627 return false;
2628 SetName( aName );
2629 break;
2630 }
2631
2632 case MID_HATCH_STYLE:
2633 {
2634 sal_Int16 nVal = sal_Int16();
2635 if (!(rVal >>= nVal ))
2636 return false;
2637 m_aHatch.SetHatchStyle( static_cast<css::drawing::HatchStyle>(nVal) );
2638 break;
2639 }
2640
2641 case MID_HATCH_COLOR:
2642 case MID_HATCH_DISTANCE:
2643 case MID_HATCH_ANGLE:
2644 {
2645 sal_Int32 nVal = 0;
2646 if (!(rVal >>= nVal ))
2647 return false;
2648
2649 if ( nMemberId == MID_HATCH_COLOR )
2650 m_aHatch.SetColor( Color(ColorTransparency, nVal) );
2651 else if ( nMemberId == MID_HATCH_DISTANCE )
2652 m_aHatch.SetDistance( nVal );
2653 else
2654 m_aHatch.SetAngle( Degree10(nVal) );
2655 break;
2656 }
2657
2658 default: OSL_FAIL("Wrong MemberId!"); return false;
2659 }
2660
2661 return true;
2662 }
2663
CompareValueFunc(const NameOrIndex * p1,const NameOrIndex * p2)2664 bool XFillHatchItem::CompareValueFunc( const NameOrIndex* p1, const NameOrIndex* p2 )
2665 {
2666 return static_cast<const XFillHatchItem*>(p1)->GetHatchValue() == static_cast<const XFillHatchItem*>(p2)->GetHatchValue();
2667 }
2668
checkForUniqueItem(SdrModel & rModel) const2669 std::unique_ptr<XFillHatchItem> XFillHatchItem::checkForUniqueItem( SdrModel& rModel ) const
2670 {
2671 const OUString aUniqueName(CheckNamedItem(
2672 XATTR_FILLHATCH, &rModel.GetItemPool(),
2673 XFillHatchItem::CompareValueFunc, RID_SVXSTR_HATCH10,
2674 rModel.GetPropertyList(XPropertyListType::Hatch)));
2675
2676 // if the given name is not valid, replace it!
2677 if( aUniqueName != GetName() )
2678 return std::make_unique<XFillHatchItem>( aUniqueName, m_aHatch );
2679
2680 return nullptr;
2681 }
2682
2683 // --- form text attributes ---
2684
2685
CreateDefault()2686 SfxPoolItem* XFormTextStyleItem::CreateDefault() { return new XFormTextStyleItem; }
2687
XFormTextStyleItem(XFormTextStyle eTheStyle)2688 XFormTextStyleItem::XFormTextStyleItem(XFormTextStyle eTheStyle) :
2689 SfxEnumItem(XATTR_FORMTXTSTYLE, eTheStyle)
2690 {
2691 }
2692
Clone(SfxItemPool *) const2693 XFormTextStyleItem* XFormTextStyleItem::Clone(SfxItemPool* /*pPool*/) const
2694 {
2695 return new XFormTextStyleItem( *this );
2696 }
2697
QueryValue(uno::Any & rVal,sal_uInt8) const2698 bool XFormTextStyleItem::QueryValue( uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
2699 {
2700 rVal <<= static_cast<sal_Int32>(GetValue());
2701 return true;
2702 }
2703
PutValue(const uno::Any & rVal,sal_uInt8)2704 bool XFormTextStyleItem::PutValue( const uno::Any& rVal, sal_uInt8 /*nMemberId*/)
2705 {
2706 sal_Int32 nValue = 0;
2707 rVal >>= nValue;
2708 SetValue(static_cast<XFormTextStyle>(nValue));
2709
2710 return true;
2711 }
2712
2713
CreateDefault()2714 SfxPoolItem* XFormTextAdjustItem::CreateDefault() { return new XFormTextAdjustItem; }
2715
XFormTextAdjustItem(XFormTextAdjust eTheAdjust)2716 XFormTextAdjustItem::XFormTextAdjustItem(XFormTextAdjust eTheAdjust) :
2717 SfxEnumItem(XATTR_FORMTXTADJUST, eTheAdjust)
2718 {
2719 }
2720
Clone(SfxItemPool *) const2721 XFormTextAdjustItem* XFormTextAdjustItem::Clone(SfxItemPool* /*pPool*/) const
2722 {
2723 return new XFormTextAdjustItem( *this );
2724 }
2725
QueryValue(uno::Any & rVal,sal_uInt8) const2726 bool XFormTextAdjustItem::QueryValue( uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
2727 {
2728 rVal <<= static_cast<sal_Int32>(GetValue());
2729 return true;
2730 }
2731
PutValue(const uno::Any & rVal,sal_uInt8)2732 bool XFormTextAdjustItem::PutValue( const uno::Any& rVal, sal_uInt8 /*nMemberId*/)
2733 {
2734 sal_Int32 nValue = 0;
2735 rVal >>= nValue;
2736 SetValue(static_cast<XFormTextAdjust>(nValue));
2737
2738 return true;
2739 }
2740
2741
CreateDefault()2742 SfxPoolItem* XFormTextDistanceItem::CreateDefault() { return new XFormTextDistanceItem; }
2743
XFormTextDistanceItem(tools::Long nDist)2744 XFormTextDistanceItem::XFormTextDistanceItem(tools::Long nDist) :
2745 SfxMetricItem(XATTR_FORMTXTDISTANCE, nDist)
2746 {
2747 }
2748
Clone(SfxItemPool *) const2749 XFormTextDistanceItem* XFormTextDistanceItem::Clone(SfxItemPool* /*pPool*/) const
2750 {
2751 return new XFormTextDistanceItem(*this);
2752 }
2753
CreateDefault()2754 SfxPoolItem* XFormTextStartItem::CreateDefault() { return new XFormTextStartItem; }
2755
XFormTextStartItem(tools::Long nStart)2756 XFormTextStartItem::XFormTextStartItem(tools::Long nStart) :
2757 SfxMetricItem(XATTR_FORMTXTSTART, nStart)
2758 {
2759 }
2760
Clone(SfxItemPool *) const2761 XFormTextStartItem* XFormTextStartItem::Clone(SfxItemPool* /*pPool*/) const
2762 {
2763 return new XFormTextStartItem(*this);
2764 }
2765
CreateDefault()2766 SfxPoolItem* XFormTextMirrorItem::CreateDefault() { return new XFormTextMirrorItem; }
2767
XFormTextMirrorItem(bool bMirror)2768 XFormTextMirrorItem::XFormTextMirrorItem(bool bMirror) :
2769 SfxBoolItem(XATTR_FORMTXTMIRROR, bMirror)
2770 {
2771 }
2772
Clone(SfxItemPool *) const2773 XFormTextMirrorItem* XFormTextMirrorItem::Clone(SfxItemPool* /*pPool*/) const
2774 {
2775 return new XFormTextMirrorItem(*this);
2776 }
2777
CreateDefault()2778 SfxPoolItem* XFormTextOutlineItem::CreateDefault() { return new XFormTextOutlineItem; }
2779
XFormTextOutlineItem(bool bOutline)2780 XFormTextOutlineItem::XFormTextOutlineItem(bool bOutline) :
2781 SfxBoolItem(XATTR_FORMTXTOUTLINE, bOutline)
2782 {
2783 }
2784
Clone(SfxItemPool *) const2785 XFormTextOutlineItem* XFormTextOutlineItem::Clone(SfxItemPool* /*pPool*/) const
2786 {
2787 return new XFormTextOutlineItem(*this);
2788 }
2789
CreateDefault()2790 SfxPoolItem* XFormTextShadowItem::CreateDefault() { return new XFormTextShadowItem; }
2791
XFormTextShadowItem(XFormTextShadow eFormTextShadow)2792 XFormTextShadowItem::XFormTextShadowItem(XFormTextShadow eFormTextShadow) :
2793 SfxEnumItem(XATTR_FORMTXTSHADOW, eFormTextShadow)
2794 {
2795 }
2796
Clone(SfxItemPool *) const2797 XFormTextShadowItem* XFormTextShadowItem::Clone(SfxItemPool* /*pPool*/) const
2798 {
2799 return new XFormTextShadowItem( *this );
2800 }
2801
QueryValue(uno::Any & rVal,sal_uInt8) const2802 bool XFormTextShadowItem::QueryValue( uno::Any& rVal, sal_uInt8 /*nMemberId*/) const
2803 {
2804 rVal <<= static_cast<sal_Int32>(GetValue());
2805 return true;
2806 }
2807
PutValue(const uno::Any & rVal,sal_uInt8)2808 bool XFormTextShadowItem::PutValue( const uno::Any& rVal, sal_uInt8 /*nMemberId*/)
2809 {
2810 sal_Int32 nValue = 0;
2811 rVal >>= nValue;
2812 SetValue(static_cast<XFormTextShadow>(nValue));
2813
2814 return true;
2815 }
2816
2817
CreateDefault()2818 SfxPoolItem* XFormTextShadowColorItem::CreateDefault() { return new XFormTextShadowColorItem; }
2819
XFormTextShadowColorItem(const OUString & rName,const Color & rTheColor)2820 XFormTextShadowColorItem::XFormTextShadowColorItem(const OUString& rName,
2821 const Color& rTheColor) :
2822 XColorItem(XATTR_FORMTXTSHDWCOLOR, rName, rTheColor)
2823 {
2824 }
2825
Clone(SfxItemPool *) const2826 XFormTextShadowColorItem* XFormTextShadowColorItem::Clone(SfxItemPool* /*pPool*/) const
2827 {
2828 return new XFormTextShadowColorItem(*this);
2829 }
2830
CreateDefault()2831 SfxPoolItem* XFormTextShadowXValItem::CreateDefault() { return new XFormTextShadowXValItem; }
2832
XFormTextShadowXValItem(tools::Long nVal)2833 XFormTextShadowXValItem::XFormTextShadowXValItem(tools::Long nVal) :
2834 SfxMetricItem(XATTR_FORMTXTSHDWXVAL, nVal)
2835 {
2836 }
2837
Clone(SfxItemPool *) const2838 XFormTextShadowXValItem* XFormTextShadowXValItem::Clone(SfxItemPool* /*pPool*/) const
2839 {
2840 return new XFormTextShadowXValItem(*this);
2841 }
2842
CreateDefault()2843 SfxPoolItem* XFormTextShadowYValItem::CreateDefault() { return new XFormTextShadowYValItem; }
2844
XFormTextShadowYValItem(tools::Long nVal)2845 XFormTextShadowYValItem::XFormTextShadowYValItem(tools::Long nVal) :
2846 SfxMetricItem(XATTR_FORMTXTSHDWYVAL, nVal)
2847 {
2848 }
2849
Clone(SfxItemPool *) const2850 XFormTextShadowYValItem* XFormTextShadowYValItem::Clone(SfxItemPool* /*pPool*/) const
2851 {
2852 return new XFormTextShadowYValItem(*this);
2853 }
2854
CreateDefault()2855 SfxPoolItem* XFormTextHideFormItem::CreateDefault() { return new XFormTextHideFormItem; }
2856
XFormTextHideFormItem(bool bHide)2857 XFormTextHideFormItem::XFormTextHideFormItem(bool bHide) :
2858 SfxBoolItem(XATTR_FORMTXTHIDEFORM, bHide)
2859 {
2860 }
2861
Clone(SfxItemPool *) const2862 XFormTextHideFormItem* XFormTextHideFormItem::Clone(SfxItemPool* /*pPool*/) const
2863 {
2864 return new XFormTextHideFormItem(*this);
2865 }
2866
2867 // --- SetItems ---
2868
2869
2870 /// a line attribute set item
XLineAttrSetItem(SfxItemSet && pItemSet)2871 XLineAttrSetItem::XLineAttrSetItem( SfxItemSet&& pItemSet ) :
2872 SfxSetItem( XATTRSET_LINE, std::move(pItemSet))
2873 {
2874 }
2875
XLineAttrSetItem(SfxItemPool * pItemPool)2876 XLineAttrSetItem::XLineAttrSetItem( SfxItemPool* pItemPool ) :
2877 SfxSetItem(XATTRSET_LINE,
2878 SfxItemSet::makeFixedSfxItemSet<XATTR_LINE_FIRST, XATTR_LINE_LAST>(*pItemPool))
2879 {
2880 }
2881
XLineAttrSetItem(const XLineAttrSetItem & rLineAttr)2882 XLineAttrSetItem::XLineAttrSetItem( const XLineAttrSetItem& rLineAttr ) :
2883 SfxSetItem( rLineAttr )
2884 {
2885 }
2886
XLineAttrSetItem(const XLineAttrSetItem & rLineAttr,SfxItemPool * pItemPool)2887 XLineAttrSetItem::XLineAttrSetItem( const XLineAttrSetItem& rLineAttr,
2888 SfxItemPool* pItemPool) :
2889 SfxSetItem( rLineAttr, pItemPool )
2890 {
2891 }
2892
Clone(SfxItemPool * pPool) const2893 XLineAttrSetItem* XLineAttrSetItem::Clone( SfxItemPool* pPool ) const
2894 {
2895 return new XLineAttrSetItem( *this, pPool );
2896 }
2897
2898 /// fill attribute set item
XFillAttrSetItem(SfxItemSet && pItemSet)2899 XFillAttrSetItem::XFillAttrSetItem( SfxItemSet&& pItemSet ) :
2900 SfxSetItem( XATTRSET_FILL, std::move(pItemSet))
2901 {
2902 }
2903
XFillAttrSetItem(SfxItemPool * pItemPool)2904 XFillAttrSetItem::XFillAttrSetItem( SfxItemPool* pItemPool ) :
2905 SfxSetItem(XATTRSET_FILL,
2906 SfxItemSet::makeFixedSfxItemSet<XATTR_FILL_FIRST, XATTR_FILL_LAST>(*pItemPool))
2907 {
2908 }
2909
XFillAttrSetItem(const XFillAttrSetItem & rFillAttr)2910 XFillAttrSetItem::XFillAttrSetItem( const XFillAttrSetItem& rFillAttr ) :
2911 SfxSetItem( rFillAttr )
2912 {
2913 }
2914
XFillAttrSetItem(const XFillAttrSetItem & rFillAttr,SfxItemPool * pItemPool)2915 XFillAttrSetItem::XFillAttrSetItem( const XFillAttrSetItem& rFillAttr,
2916 SfxItemPool* pItemPool ) :
2917 SfxSetItem( rFillAttr, pItemPool )
2918 {
2919 }
2920
Clone(SfxItemPool * pPool) const2921 XFillAttrSetItem* XFillAttrSetItem::Clone( SfxItemPool* pPool ) const
2922 {
2923 return new XFillAttrSetItem( *this, pPool );
2924 }
2925
2926 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2927