1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <sdr/properties/textproperties.hxx>
23 #include <svl/itemset.hxx>
24 #include <svl/style.hxx>
25 #include <svl/itemiter.hxx>
26 #include <svl/hint.hxx>
27 #include <svx/svddef.hxx>
28 #include <svx/svdotext.hxx>
29 #include <svx/svdoutl.hxx>
30 #include <svx/sdmetitm.hxx>
31 #include <svx/sdtditm.hxx>
32 #include <editeng/writingmodeitem.hxx>
33 #include <svx/svdmodel.hxx>
34 #include <editeng/eeitem.hxx>
35 #include <editeng/outlobj.hxx>
36 #include <svx/xfillit0.hxx>
37 #include <svx/xflclit.hxx>
38 #include <editeng/adjustitem.hxx>
39 #include <svx/svdetc.hxx>
40 #include <editeng/editeng.hxx>
41 #include <editeng/flditem.hxx>
42 #include <svx/xlineit0.hxx>
43 #include <svx/xlnwtit.hxx>
45 using namespace com::sun::star
;
47 namespace sdr::properties
49 SfxItemSet
TextProperties::CreateObjectSpecificItemSet(SfxItemPool
& rPool
)
51 return SfxItemSet(rPool
,
53 // range from SdrAttrObj
54 svl::Items
<SDRATTR_START
, SDRATTR_SHADOW_LAST
,
55 SDRATTR_MISC_FIRST
, SDRATTR_MISC_LAST
,
56 SDRATTR_TEXTDIRECTION
, SDRATTR_TEXTDIRECTION
,
57 SDRATTR_TEXTCOLUMNS_FIRST
, SDRATTR_TEXTCOLUMNS_LAST
,
59 // range from SdrTextObj
60 EE_ITEMS_START
, EE_ITEMS_END
>);
63 TextProperties::TextProperties(SdrObject
& rObj
)
64 : AttributeProperties(rObj
),
69 TextProperties::TextProperties(const TextProperties
& rProps
, SdrObject
& rObj
)
70 : AttributeProperties(rProps
, rObj
),
71 maVersion(rProps
.getVersion())
75 TextProperties::~TextProperties()
79 std::unique_ptr
<BaseProperties
> TextProperties::Clone(SdrObject
& rObj
) const
81 return std::unique_ptr
<BaseProperties
>(new TextProperties(*this, rObj
));
84 void TextProperties::ItemSetChanged(std::span
< const SfxPoolItem
* const > aChangedItems
, sal_uInt16 nDeletedWhich
)
86 SdrTextObj
& rObj
= static_cast<SdrTextObj
&>(GetSdrObject());
88 // #i101556# ItemSet has changed -> new version
91 if (auto pOutliner
= rObj
.GetTextEditOutliner())
93 pOutliner
->SetTextColumns(rObj
.GetTextColumnsNumber(),
94 rObj
.GetTextColumnsSpacing());
97 const svx::ITextProvider
& rTextProvider(getTextProvider());
98 sal_Int32 nText
= rTextProvider
.getTextCount();
101 SdrText
* pText
= rTextProvider
.getText( nText
);
103 OutlinerParaObject
* pParaObj
= pText
? pText
->GetOutlinerParaObject() : nullptr;
107 const bool bTextEdit
= rObj
.IsTextEditActive() && (rObj
.getActiveText() == pText
);
109 // handle outliner attributes
111 Outliner
* pOutliner
= rObj
.GetTextEditOutliner();
115 pOutliner
= &rObj
.ImpGetDrawOutliner();
116 pOutliner
->SetText(*pParaObj
);
119 sal_Int32
nParaCount(pOutliner
->GetParagraphCount());
121 for(sal_Int32 nPara
= 0; nPara
< nParaCount
; nPara
++)
123 SfxItemSet
aSet(pOutliner
->GetParaAttribs(nPara
));
124 for (const SfxPoolItem
* pItem
: aChangedItems
)
127 aSet
.ClearItem(nDeletedWhich
);
128 pOutliner
->SetParaAttribs(nPara
, aSet
);
138 moItemSet
->Put(pOutliner
->GetParaAttribs(0));
141 std::optional
<OutlinerParaObject
> pTemp
= pOutliner
->CreateParaObject(0, nParaCount
);
144 rObj
.NbcSetOutlinerParaObjectForText(std::move(pTemp
),pText
);
149 // Extra-Repaint for radical layout changes (#43139#)
150 for (const SfxPoolItem
* pItem
: aChangedItems
)
151 if (pItem
->Which() == SDRATTR_TEXT_CONTOURFRAME
)
153 // Here only repaint wanted
154 rObj
.ActionChanged();
155 //rObj.BroadcastObjectChange();
160 AttributeProperties::ItemSetChanged(aChangedItems
, nDeletedWhich
);
163 void TextProperties::ItemChange(const sal_uInt16 nWhich
, const SfxPoolItem
* pNewItem
)
165 SdrTextObj
& rObj
= static_cast<SdrTextObj
&>(GetSdrObject());
168 sal_Int32
nOldLineWidth(0);
170 if(XATTR_LINEWIDTH
== nWhich
&& rObj
.DoesSupportTextIndentingOnLineWidthChange())
172 nOldLineWidth
= GetItem(XATTR_LINEWIDTH
).GetValue();
175 if(pNewItem
&& (SDRATTR_TEXTDIRECTION
== nWhich
))
177 bool bVertical(css::text::WritingMode_TB_RL
== static_cast<const SvxWritingModeItem
*>(pNewItem
)->GetValue());
178 rObj
.SetVerticalWriting(bVertical
);
181 // #95501# reset to default
182 if(!pNewItem
&& !nWhich
&& rObj
.HasText() )
184 SdrOutliner
& rOutliner
= rObj
.ImpGetDrawOutliner();
186 const svx::ITextProvider
& rTextProvider(getTextProvider());
187 sal_Int32 nCount
= rTextProvider
.getTextCount();
190 SdrText
* pText
= rTextProvider
.getText( nCount
);
191 OutlinerParaObject
* pParaObj
= pText
->GetOutlinerParaObject();
194 rOutliner
.SetText(*pParaObj
);
195 sal_Int32
nParaCount(rOutliner
.GetParagraphCount());
199 ESelection
aSelection( 0, 0, EE_PARA_ALL
, EE_TEXTPOS_ALL
);
200 rOutliner
.RemoveAttribs(aSelection
, true, 0);
202 std::optional
<OutlinerParaObject
> pTemp
= rOutliner
.CreateParaObject(0, nParaCount
);
205 rObj
.NbcSetOutlinerParaObjectForText( std::move(pTemp
), pText
);
212 AttributeProperties::ItemChange( nWhich
, pNewItem
);
215 if(!(XATTR_LINEWIDTH
== nWhich
&& rObj
.DoesSupportTextIndentingOnLineWidthChange()))
218 const sal_Int32
nNewLineWidth(GetItem(XATTR_LINEWIDTH
).GetValue());
219 const sal_Int32
nDifference((nNewLineWidth
- nOldLineWidth
) / 2);
224 const bool bLineVisible(drawing::LineStyle_NONE
!= GetItem(XATTR_LINESTYLE
).GetValue());
228 const sal_Int32
nLeftDist(GetItem(SDRATTR_TEXT_LEFTDIST
).GetValue());
229 const sal_Int32
nRightDist(GetItem(SDRATTR_TEXT_RIGHTDIST
).GetValue());
230 const sal_Int32
nUpperDist(GetItem(SDRATTR_TEXT_UPPERDIST
).GetValue());
231 const sal_Int32
nLowerDist(GetItem(SDRATTR_TEXT_LOWERDIST
).GetValue());
233 SetObjectItemDirect(makeSdrTextLeftDistItem(nLeftDist
+ nDifference
));
234 SetObjectItemDirect(makeSdrTextRightDistItem(nRightDist
+ nDifference
));
235 SetObjectItemDirect(makeSdrTextUpperDistItem(nUpperDist
+ nDifference
));
236 SetObjectItemDirect(makeSdrTextLowerDistItem(nLowerDist
+ nDifference
));
240 const svx::ITextProvider
& TextProperties::getTextProvider() const
242 return static_cast<const SdrTextObj
&>(GetSdrObject());
245 void TextProperties::SetStyleSheet(SfxStyleSheet
* pNewStyleSheet
, bool bDontRemoveHardAttr
,
248 // call parent (always first thing to do, may create the SfxItemSet)
249 AttributeProperties::SetStyleSheet(pNewStyleSheet
, bDontRemoveHardAttr
, bBroadcast
);
251 // #i101556# StyleSheet has changed -> new version
252 SdrTextObj
& rObj
= static_cast<SdrTextObj
&>(GetSdrObject());
255 if(!rObj
.IsLinkedText() )
257 SdrOutliner
& rOutliner
= rObj
.ImpGetDrawOutliner();
259 const svx::ITextProvider
& rTextProvider(getTextProvider());
260 sal_Int32 nText
= rTextProvider
.getTextCount();
263 SdrText
* pText
= rTextProvider
.getText( nText
);
265 OutlinerParaObject
* pParaObj
= pText
? pText
->GetOutlinerParaObject() : nullptr;
269 // apply StyleSheet to all paragraphs
270 rOutliner
.SetText(*pParaObj
);
271 sal_Int32
nParaCount(rOutliner
.GetParagraphCount());
275 for(sal_Int32 nPara
= 0; nPara
< nParaCount
; nPara
++)
277 std::optional
<SfxItemSet
> pTempSet
;
279 // since setting the stylesheet removes all para attributes
280 if(bDontRemoveHardAttr
)
282 // we need to remember them if we want to keep them
283 pTempSet
.emplace(rOutliner
.GetParaAttribs(nPara
));
288 if((SdrObjKind::OutlineText
== rObj
.GetTextKind()) && (SdrInventor::Default
== rObj
.GetObjInventor()))
290 OUString
aNewStyleSheetName(GetStyleSheet()->GetName());
291 aNewStyleSheetName
= aNewStyleSheetName
.copy(0, aNewStyleSheetName
.getLength() - 1);
292 sal_Int16 nDepth
= rOutliner
.GetDepth(nPara
);
293 aNewStyleSheetName
+= OUString::number( nDepth
<= 0 ? 1 : nDepth
+ 1);
294 SfxStyleSheetBasePool
* pStylePool(rObj
.getSdrModelFromSdrObject().GetStyleSheetPool());
295 SfxStyleSheet
* pNewStyle
= nullptr;
297 pNewStyle
= static_cast<SfxStyleSheet
*>(pStylePool
->Find(aNewStyleSheetName
, GetStyleSheet()->GetFamily()));
298 DBG_ASSERT( pNewStyle
, "AutoStyleSheetName - Style not found!" );
302 rOutliner
.SetStyleSheet(nPara
, pNewStyle
);
307 rOutliner
.SetStyleSheet(nPara
, GetStyleSheet());
313 rOutliner
.SetStyleSheet(nPara
, nullptr);
316 if(bDontRemoveHardAttr
)
320 // restore para attributes
321 rOutliner
.SetParaAttribs(nPara
, *pTempSet
);
328 // remove all hard paragraph attributes
329 // which occur in StyleSheet, take care of
331 SfxItemIter
aIter(pNewStyleSheet
->GetItemSet());
333 for (const SfxPoolItem
* pItem
= aIter
.GetCurItem(); pItem
;
334 pItem
= aIter
.NextItem())
336 if(!IsInvalidItem(pItem
))
338 sal_uInt16
nW(pItem
->Which());
340 if(nW
>= EE_ITEMS_START
&& nW
<= EE_ITEMS_END
)
342 rOutliner
.RemoveCharAttribs(nPara
, nW
);
350 std::optional
<OutlinerParaObject
> pTemp
= rOutliner
.CreateParaObject(0, nParaCount
);
352 rObj
.NbcSetOutlinerParaObjectForText(std::move(pTemp
), pText
);
357 if(rObj
.IsTextFrame())
359 rObj
.NbcAdjustTextFrameWidthAndHeight();
363 void TextProperties::ForceDefaultAttributes()
365 SdrTextObj
& rObj
= static_cast<SdrTextObj
&>(GetSdrObject());
367 if( rObj
.GetObjInventor() == SdrInventor::Default
)
369 const SdrObjKind nSdrObjKind
= rObj
.GetObjIdentifier();
371 if( nSdrObjKind
== SdrObjKind::TitleText
|| nSdrObjKind
== SdrObjKind::OutlineText
)
372 return; // no defaults for presentation objects
375 bool bTextFrame(rObj
.IsTextFrame());
379 moItemSet
->Put(XLineStyleItem(drawing::LineStyle_NONE
));
380 moItemSet
->Put(XFillColorItem(OUString(), COL_WHITE
));
381 moItemSet
->Put(XFillStyleItem(drawing::FillStyle_NONE
));
385 moItemSet
->Put(SvxAdjustItem(SvxAdjust::Center
, EE_PARA_JUST
));
386 moItemSet
->Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER
));
387 moItemSet
->Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER
));
391 void TextProperties::ForceStyleToHardAttributes()
393 // #i61284# call parent first to get the hard ObjectItemSet
394 AttributeProperties::ForceStyleToHardAttributes();
396 // #i61284# push hard ObjectItemSet to OutlinerParaObject attributes
397 // using existing functionality
398 GetObjectItemSet(); // force ItemSet
399 std::vector
<const SfxPoolItem
*> aChangedItems
;
400 SfxItemIter
aIter(*moItemSet
);
401 for (const SfxPoolItem
* pItem
= aIter
.GetCurItem(); pItem
; pItem
= aIter
.NextItem())
403 if(!IsInvalidItem(pItem
))
404 aChangedItems
.push_back(pItem
);
406 ItemSetChanged(aChangedItems
, 0);
408 // now the standard TextProperties stuff
409 SdrTextObj
& rObj
= static_cast<SdrTextObj
&>(GetSdrObject());
411 if(rObj
.IsTextEditActive() || rObj
.IsLinkedText())
414 std::unique_ptr
<Outliner
> pOutliner
= SdrMakeOutliner(OutlinerMode::OutlineObject
, rObj
.getSdrModelFromSdrObject());
415 const svx::ITextProvider
& rTextProvider(getTextProvider());
416 sal_Int32 nText
= rTextProvider
.getTextCount();
419 SdrText
* pText
= rTextProvider
.getText( nText
);
421 OutlinerParaObject
* pParaObj
= pText
? pText
->GetOutlinerParaObject() : nullptr;
425 pOutliner
->SetText(*pParaObj
);
427 sal_Int32
nParaCount(pOutliner
->GetParagraphCount());
433 for(sal_Int32 nPara
= 0; nPara
< nParaCount
; nPara
++)
435 SfxStyleSheet
* pSheet
= pOutliner
->GetStyleSheet(nPara
);
439 SfxItemSet
aParaSet(pOutliner
->GetParaAttribs(nPara
));
440 SfxItemSet
aSet(*aParaSet
.GetPool());
441 aSet
.Put(pSheet
->GetItemSet());
443 /** the next code handles a special case for paragraphs that contain a
444 url field. The color for URL fields is either the system color for
445 urls or the char color attribute that formats the portion in which the
446 url field is contained.
447 When we set a char color attribute to the paragraphs item set from the
448 styles item set, we would have this char color attribute as an attribute
449 that is spanned over the complete paragraph after xml import due to some
450 problems in the xml import (using a XCursor on import so it does not know
451 the paragraphs and can't set char attributes to paragraphs ).
453 To avoid this, as soon as we try to set a char color attribute from the style
455 1. check if we have at least one url field in this paragraph
456 2. if we found at least one url field, we span the char color attribute over
457 all portions that are not url fields and remove the char color attribute
458 from the paragraphs item set
463 if(aSet
.GetItemState(EE_CHAR_COLOR
) == SfxItemState::SET
)
465 EditEngine
* pEditEngine
= const_cast<EditEngine
*>(&(pOutliner
->GetEditEngine()));
466 std::vector
<EECharAttrib
> aAttribs
;
467 pEditEngine
->GetCharAttribs(nPara
, aAttribs
);
469 for(const auto& rAttrib
: aAttribs
)
471 if(rAttrib
.pAttr
&& EE_FEATURE_FIELD
== rAttrib
.pAttr
->Which())
473 const SvxFieldItem
* pFieldItem
= static_cast<const SvxFieldItem
*>(rAttrib
.pAttr
);
477 const SvxFieldData
* pData
= pFieldItem
->GetField();
479 if(dynamic_cast<const SvxURLField
*>( pData
))
490 SfxItemSetFixed
<EE_CHAR_COLOR
, EE_CHAR_COLOR
> aColorSet(*aSet
.GetPool());
491 aColorSet
.Put(aSet
, false);
493 ESelection
aSel(nPara
, 0);
495 for(const auto& rAttrib
: aAttribs
)
497 if(EE_FEATURE_FIELD
== rAttrib
.pAttr
->Which())
499 aSel
.nEndPos
= rAttrib
.nStart
;
501 if(aSel
.nStartPos
!= aSel
.nEndPos
)
502 pEditEngine
->QuickSetAttribs(aColorSet
, aSel
);
504 aSel
.nStartPos
= rAttrib
.nEnd
;
508 aSel
.nEndPos
= pEditEngine
->GetTextLen(nPara
);
510 if(aSel
.nStartPos
!= aSel
.nEndPos
)
512 pEditEngine
->QuickSetAttribs( aColorSet
, aSel
);
518 aSet
.Put(aParaSet
, false);
522 aSet
.ClearItem(EE_CHAR_COLOR
);
525 pOutliner
->SetParaAttribs(nPara
, aSet
);
526 bBurnIn
= true; // #i51163# Flag was set wrong
532 std::optional
<OutlinerParaObject
> pTemp
= pOutliner
->CreateParaObject(0, nParaCount
);
533 rObj
.NbcSetOutlinerParaObjectForText(std::move(pTemp
),pText
);
541 void TextProperties::SetObjectItemNoBroadcast(const SfxPoolItem
& rItem
)
544 moItemSet
->Put(rItem
);
548 void TextProperties::Notify(SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
551 AttributeProperties::Notify(rBC
, rHint
);
553 SdrTextObj
& rObj
= static_cast<SdrTextObj
&>(GetSdrObject());
557 SfxHintId
nId(rHint
.GetId());
558 const svx::ITextProvider
& rTextProvider(getTextProvider());
560 if(SfxHintId::DataChanged
== nId
&& dynamic_cast<const SfxStyleSheet
*>(&rBC
) != nullptr)
562 sal_Int32 nText
= rTextProvider
.getTextCount();
565 OutlinerParaObject
* pParaObj
= rTextProvider
.getText( nText
)->GetOutlinerParaObject();
567 pParaObj
->ClearPortionInfo();
569 rObj
.SetTextSizeDirty();
571 if(rObj
.IsTextFrame() && rObj
.NbcAdjustTextFrameWidthAndHeight())
573 // here only repaint wanted
574 rObj
.ActionChanged();
575 //rObj.BroadcastObjectChange();
578 // #i101556# content of StyleSheet has changed -> new version
581 else if(SfxHintId::Dying
== nId
&& dynamic_cast<const SfxStyleSheet
*>(&rBC
) != nullptr)
583 sal_Int32 nText
= rTextProvider
.getTextCount();
586 OutlinerParaObject
* pParaObj
= rTextProvider
.getText( nText
)->GetOutlinerParaObject();
588 pParaObj
->ClearPortionInfo();
591 else if (nId
== SfxHintId::StyleSheetModified
&& dynamic_cast<const SfxStyleSheetBasePool
*>(&rBC
) != nullptr)
593 const SfxStyleSheetModifiedHint
* pExtendedHint
= dynamic_cast<const SfxStyleSheetModifiedHint
*>(&rHint
);
596 const OUString
& aOldName(pExtendedHint
->GetOldName());
597 OUString
aNewName(pExtendedHint
->GetStyleSheet()->GetName());
598 SfxStyleFamily eFamily
= pExtendedHint
->GetStyleSheet()->GetFamily();
600 if(aOldName
!= aNewName
)
602 sal_Int32 nText
= rTextProvider
.getTextCount();
605 OutlinerParaObject
* pParaObj
= rTextProvider
.getText( nText
)->GetOutlinerParaObject();
607 pParaObj
->ChangeStyleSheetName(eFamily
, aOldName
, aNewName
);
614 // #i101556# Handout version information
615 sal_uInt32
TextProperties::getVersion() const
619 } // end of namespace
621 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */