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>
44 #include <svx/svdpool.hxx>
46 using namespace com::sun::star
;
52 std::unique_ptr
<SfxItemSet
> TextProperties::CreateObjectSpecificItemSet(SfxItemPool
& rPool
)
54 return std::make_unique
<SfxItemSet
>(rPool
,
56 // range from SdrAttrObj
57 svl::Items
<SDRATTR_START
, SDRATTR_SHADOW_LAST
,
58 SDRATTR_MISC_FIRST
, SDRATTR_MISC_LAST
,
59 SDRATTR_TEXTDIRECTION
, SDRATTR_TEXTDIRECTION
,
61 // range from SdrTextObj
62 EE_ITEMS_START
, EE_ITEMS_END
>{});
65 TextProperties::TextProperties(SdrObject
& rObj
)
66 : AttributeProperties(rObj
),
71 TextProperties::TextProperties(const TextProperties
& rProps
, SdrObject
& rObj
)
72 : AttributeProperties(rProps
, rObj
),
73 maVersion(rProps
.getVersion())
77 TextProperties::~TextProperties()
81 std::unique_ptr
<BaseProperties
> TextProperties::Clone(SdrObject
& rObj
) const
83 return std::unique_ptr
<BaseProperties
>(new TextProperties(*this, rObj
));
86 void TextProperties::ItemSetChanged(const SfxItemSet
& rSet
)
88 SdrTextObj
& rObj
= static_cast<SdrTextObj
&>(GetSdrObject());
90 // #i101556# ItemSet has changed -> new version
93 const svx::ITextProvider
& rTextProvider(getTextProvider());
94 sal_Int32 nText
= rTextProvider
.getTextCount();
97 SdrText
* pText
= rTextProvider
.getText( nText
);
99 OutlinerParaObject
* pParaObj
= pText
? pText
->GetOutlinerParaObject() : nullptr;
103 const bool bTextEdit
= rObj
.IsTextEditActive() && (rObj
.getActiveText() == pText
);
105 // handle outliner attributes
107 Outliner
* pOutliner
= rObj
.GetTextEditOutliner();
111 pOutliner
= &rObj
.ImpGetDrawOutliner();
112 pOutliner
->SetText(*pParaObj
);
115 sal_Int32
nParaCount(pOutliner
->GetParagraphCount());
117 for(sal_Int32 nPara
= 0; nPara
< nParaCount
; nPara
++)
119 SfxItemSet
aSet(pOutliner
->GetParaAttribs(nPara
));
121 pOutliner
->SetParaAttribs(nPara
, aSet
);
131 SfxItemSet
aNewSet(pOutliner
->GetParaAttribs(0));
132 mpItemSet
->Put(aNewSet
);
135 std::unique_ptr
<OutlinerParaObject
> pTemp
= pOutliner
->CreateParaObject(0, nParaCount
);
138 rObj
.NbcSetOutlinerParaObjectForText(std::move(pTemp
),pText
);
143 // Extra-Repaint for radical layout changes (#43139#)
144 if(SfxItemState::SET
== rSet
.GetItemState(SDRATTR_TEXT_CONTOURFRAME
))
146 // Here only repaint wanted
147 rObj
.ActionChanged();
148 //rObj.BroadcastObjectChange();
152 AttributeProperties::ItemSetChanged(rSet
);
155 void TextProperties::ItemChange(const sal_uInt16 nWhich
, const SfxPoolItem
* pNewItem
)
157 SdrTextObj
& rObj
= static_cast<SdrTextObj
&>(GetSdrObject());
160 sal_Int32
nOldLineWidth(0);
162 if(XATTR_LINEWIDTH
== nWhich
&& rObj
.DoesSupportTextIndentingOnLineWidthChange())
164 nOldLineWidth
= GetItem(XATTR_LINEWIDTH
).GetValue();
167 if(pNewItem
&& (SDRATTR_TEXTDIRECTION
== nWhich
))
169 bool bVertical(css::text::WritingMode_TB_RL
== static_cast<const SvxWritingModeItem
*>(pNewItem
)->GetValue());
170 rObj
.SetVerticalWriting(bVertical
);
173 // #95501# reset to default
174 if(!pNewItem
&& !nWhich
&& rObj
.HasText() )
176 SdrOutliner
& rOutliner
= rObj
.ImpGetDrawOutliner();
178 const svx::ITextProvider
& rTextProvider(getTextProvider());
179 sal_Int32 nCount
= rTextProvider
.getTextCount();
182 SdrText
* pText
= rTextProvider
.getText( nCount
);
183 OutlinerParaObject
* pParaObj
= pText
->GetOutlinerParaObject();
186 rOutliner
.SetText(*pParaObj
);
187 sal_Int32
nParaCount(rOutliner
.GetParagraphCount());
191 ESelection
aSelection( 0, 0, EE_PARA_ALL
, EE_TEXTPOS_ALL
);
192 rOutliner
.RemoveAttribs(aSelection
, true, 0);
194 std::unique_ptr
<OutlinerParaObject
> pTemp
= rOutliner
.CreateParaObject(0, nParaCount
);
197 rObj
.NbcSetOutlinerParaObjectForText( std::move(pTemp
), pText
);
204 AttributeProperties::ItemChange( nWhich
, pNewItem
);
207 if(XATTR_LINEWIDTH
== nWhich
&& rObj
.DoesSupportTextIndentingOnLineWidthChange())
209 const sal_Int32
nNewLineWidth(GetItem(XATTR_LINEWIDTH
).GetValue());
210 const sal_Int32
nDifference((nNewLineWidth
- nOldLineWidth
) / 2);
214 const bool bLineVisible(drawing::LineStyle_NONE
!= GetItem(XATTR_LINESTYLE
).GetValue());
218 const sal_Int32
nLeftDist(GetItem(SDRATTR_TEXT_LEFTDIST
).GetValue());
219 const sal_Int32
nRightDist(GetItem(SDRATTR_TEXT_RIGHTDIST
).GetValue());
220 const sal_Int32
nUpperDist(GetItem(SDRATTR_TEXT_UPPERDIST
).GetValue());
221 const sal_Int32
nLowerDist(GetItem(SDRATTR_TEXT_LOWERDIST
).GetValue());
223 SetObjectItemDirect(makeSdrTextLeftDistItem(nLeftDist
+ nDifference
));
224 SetObjectItemDirect(makeSdrTextRightDistItem(nRightDist
+ nDifference
));
225 SetObjectItemDirect(makeSdrTextUpperDistItem(nUpperDist
+ nDifference
));
226 SetObjectItemDirect(makeSdrTextLowerDistItem(nLowerDist
+ nDifference
));
232 const svx::ITextProvider
& TextProperties::getTextProvider() const
234 return static_cast<const SdrTextObj
&>(GetSdrObject());
237 void TextProperties::SetStyleSheet(SfxStyleSheet
* pNewStyleSheet
, bool bDontRemoveHardAttr
)
239 // call parent (always first thing to do, may create the SfxItemSet)
240 AttributeProperties::SetStyleSheet(pNewStyleSheet
, bDontRemoveHardAttr
);
242 // #i101556# StyleSheet has changed -> new version
243 SdrTextObj
& rObj
= static_cast<SdrTextObj
&>(GetSdrObject());
246 if(!rObj
.IsLinkedText() )
248 SdrOutliner
& rOutliner
= rObj
.ImpGetDrawOutliner();
250 const svx::ITextProvider
& rTextProvider(getTextProvider());
251 sal_Int32 nText
= rTextProvider
.getTextCount();
254 SdrText
* pText
= rTextProvider
.getText( nText
);
256 OutlinerParaObject
* pParaObj
= pText
? pText
->GetOutlinerParaObject() : nullptr;
260 // apply StyleSheet to all paragraphs
261 rOutliner
.SetText(*pParaObj
);
262 sal_Int32
nParaCount(rOutliner
.GetParagraphCount());
266 for(sal_Int32 nPara
= 0; nPara
< nParaCount
; nPara
++)
268 std::unique_ptr
<SfxItemSet
> pTempSet
;
270 // since setting the stylesheet removes all para attributes
271 if(bDontRemoveHardAttr
)
273 // we need to remember them if we want to keep them
274 pTempSet
.reset(new SfxItemSet(rOutliner
.GetParaAttribs(nPara
)));
279 if((OBJ_OUTLINETEXT
== rObj
.GetTextKind()) && (SdrInventor::Default
== rObj
.GetObjInventor()))
281 OUString
aNewStyleSheetName(GetStyleSheet()->GetName());
282 aNewStyleSheetName
= aNewStyleSheetName
.copy(0, aNewStyleSheetName
.getLength() - 1);
283 sal_Int16 nDepth
= rOutliner
.GetDepth(nPara
);
284 aNewStyleSheetName
+= OUString::number( nDepth
<= 0 ? 1 : nDepth
+ 1);
285 SfxStyleSheetBasePool
* pStylePool(rObj
.getSdrModelFromSdrObject().GetStyleSheetPool());
286 SfxStyleSheet
* pNewStyle
= nullptr;
288 pNewStyle
= static_cast<SfxStyleSheet
*>(pStylePool
->Find(aNewStyleSheetName
, GetStyleSheet()->GetFamily()));
289 DBG_ASSERT( pNewStyle
, "AutoStyleSheetName - Style not found!" );
293 rOutliner
.SetStyleSheet(nPara
, pNewStyle
);
298 rOutliner
.SetStyleSheet(nPara
, GetStyleSheet());
304 rOutliner
.SetStyleSheet(nPara
, nullptr);
307 if(bDontRemoveHardAttr
)
311 // restore para attributes
312 rOutliner
.SetParaAttribs(nPara
, *pTempSet
);
319 // remove all hard paragraph attributes
320 // which occur in StyleSheet, take care of
322 SfxItemIter
aIter(pNewStyleSheet
->GetItemSet());
324 for (const SfxPoolItem
* pItem
= aIter
.GetCurItem(); pItem
;
325 pItem
= aIter
.NextItem())
327 if(!IsInvalidItem(pItem
))
329 sal_uInt16
nW(pItem
->Which());
331 if(nW
>= EE_ITEMS_START
&& nW
<= EE_ITEMS_END
)
333 rOutliner
.RemoveCharAttribs(nPara
, nW
);
341 std::unique_ptr
<OutlinerParaObject
> pTemp
= rOutliner
.CreateParaObject(0, nParaCount
);
343 rObj
.NbcSetOutlinerParaObjectForText(std::move(pTemp
), pText
);
348 if(rObj
.IsTextFrame())
350 rObj
.NbcAdjustTextFrameWidthAndHeight();
354 void TextProperties::ForceDefaultAttributes()
356 SdrTextObj
& rObj
= static_cast<SdrTextObj
&>(GetSdrObject());
358 if( rObj
.GetObjInventor() == SdrInventor::Default
)
360 const sal_uInt16 nSdrObjKind
= rObj
.GetObjIdentifier();
362 if( nSdrObjKind
== OBJ_TITLETEXT
|| nSdrObjKind
== OBJ_OUTLINETEXT
)
363 return; // no defaults for presentation objects
366 bool bTextFrame(rObj
.IsTextFrame());
373 mpItemSet
->Put(XLineStyleItem(drawing::LineStyle_NONE
));
374 mpItemSet
->Put(XFillColorItem(OUString(), COL_WHITE
));
375 mpItemSet
->Put(XFillStyleItem(drawing::FillStyle_NONE
));
379 mpItemSet
->Put(SvxAdjustItem(SvxAdjust::Center
, EE_PARA_JUST
));
380 mpItemSet
->Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER
));
381 mpItemSet
->Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER
));
385 void TextProperties::ForceStyleToHardAttributes()
387 // #i61284# call parent first to get the hard ObjectItemSet
388 AttributeProperties::ForceStyleToHardAttributes();
390 // #i61284# push hard ObjectItemSet to OutlinerParaObject attributes
391 // using existing functionality
392 GetObjectItemSet(); // force ItemSet
393 ItemSetChanged(*mpItemSet
);
395 // now the standard TextProperties stuff
396 SdrTextObj
& rObj
= static_cast<SdrTextObj
&>(GetSdrObject());
398 if(!rObj
.IsTextEditActive() && !rObj
.IsLinkedText())
400 std::unique_ptr
<Outliner
> pOutliner
= SdrMakeOutliner(OutlinerMode::OutlineObject
, rObj
.getSdrModelFromSdrObject());
401 const svx::ITextProvider
& rTextProvider(getTextProvider());
402 sal_Int32 nText
= rTextProvider
.getTextCount();
405 SdrText
* pText
= rTextProvider
.getText( nText
);
407 OutlinerParaObject
* pParaObj
= pText
? pText
->GetOutlinerParaObject() : nullptr;
411 pOutliner
->SetText(*pParaObj
);
413 sal_Int32
nParaCount(pOutliner
->GetParagraphCount());
419 for(sal_Int32 nPara
= 0; nPara
< nParaCount
; nPara
++)
421 SfxStyleSheet
* pSheet
= pOutliner
->GetStyleSheet(nPara
);
425 SfxItemSet
aParaSet(pOutliner
->GetParaAttribs(nPara
));
426 SfxItemSet
aSet(*aParaSet
.GetPool());
427 aSet
.Put(pSheet
->GetItemSet());
429 /** the next code handles a special case for paragraphs that contain a
430 url field. The color for URL fields is either the system color for
431 urls or the char color attribute that formats the portion in which the
432 url field is contained.
433 When we set a char color attribute to the paragraphs item set from the
434 styles item set, we would have this char color attribute as an attribute
435 that is spanned over the complete paragraph after xml import due to some
436 problems in the xml import (using a XCursor on import so it does not know
437 the paragraphs and can't set char attributes to paragraphs ).
439 To avoid this, as soon as we try to set a char color attribute from the style
441 1. check if we have at least one url field in this paragraph
442 2. if we found at least one url field, we span the char color attribute over
443 all portions that are not url fields and remove the char color attribute
444 from the paragraphs item set
449 if(aSet
.GetItemState(EE_CHAR_COLOR
) == SfxItemState::SET
)
451 EditEngine
* pEditEngine
= const_cast<EditEngine
*>(&(pOutliner
->GetEditEngine()));
452 std::vector
<EECharAttrib
> aAttribs
;
453 pEditEngine
->GetCharAttribs(nPara
, aAttribs
);
455 for(const auto& rAttrib
: aAttribs
)
457 if(rAttrib
.pAttr
&& EE_FEATURE_FIELD
== rAttrib
.pAttr
->Which())
459 const SvxFieldItem
* pFieldItem
= static_cast<const SvxFieldItem
*>(rAttrib
.pAttr
);
463 const SvxFieldData
* pData
= pFieldItem
->GetField();
465 if(dynamic_cast<const SvxURLField
*>( pData
))
476 SfxItemSet
aColorSet(*aSet
.GetPool(), svl::Items
<EE_CHAR_COLOR
, EE_CHAR_COLOR
>{} );
477 aColorSet
.Put(aSet
, false);
479 ESelection
aSel(nPara
, 0);
481 for(const auto& rAttrib
: aAttribs
)
483 if(EE_FEATURE_FIELD
== rAttrib
.pAttr
->Which())
485 aSel
.nEndPos
= rAttrib
.nStart
;
487 if(aSel
.nStartPos
!= aSel
.nEndPos
)
488 pEditEngine
->QuickSetAttribs(aColorSet
, aSel
);
490 aSel
.nStartPos
= rAttrib
.nEnd
;
494 aSel
.nEndPos
= pEditEngine
->GetTextLen(nPara
);
496 if(aSel
.nStartPos
!= aSel
.nEndPos
)
498 pEditEngine
->QuickSetAttribs( aColorSet
, aSel
);
504 aSet
.Put(aParaSet
, false);
508 aSet
.ClearItem(EE_CHAR_COLOR
);
511 pOutliner
->SetParaAttribs(nPara
, aSet
);
512 bBurnIn
= true; // #i51163# Flag was set wrong
518 std::unique_ptr
<OutlinerParaObject
> pTemp
= pOutliner
->CreateParaObject(0, nParaCount
);
519 rObj
.NbcSetOutlinerParaObjectForText(std::move(pTemp
),pText
);
528 void TextProperties::SetObjectItemNoBroadcast(const SfxPoolItem
& rItem
)
531 mpItemSet
->Put(rItem
);
535 void TextProperties::Notify(SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
538 AttributeProperties::Notify(rBC
, rHint
);
540 SdrTextObj
& rObj
= static_cast<SdrTextObj
&>(GetSdrObject());
543 const svx::ITextProvider
& rTextProvider(getTextProvider());
544 if(dynamic_cast<const SfxStyleSheet
*>(&rBC
) != nullptr)
546 SfxHintId
nId(rHint
.GetId());
548 if(SfxHintId::DataChanged
== nId
)
550 sal_Int32 nText
= rTextProvider
.getTextCount();
553 OutlinerParaObject
* pParaObj
= rTextProvider
.getText( nText
)->GetOutlinerParaObject();
555 pParaObj
->ClearPortionInfo();
557 rObj
.SetTextSizeDirty();
559 if(rObj
.IsTextFrame() && rObj
.NbcAdjustTextFrameWidthAndHeight())
561 // here only repaint wanted
562 rObj
.ActionChanged();
563 //rObj.BroadcastObjectChange();
566 // #i101556# content of StyleSheet has changed -> new version
570 if(SfxHintId::Dying
== nId
)
572 sal_Int32 nText
= rTextProvider
.getTextCount();
575 OutlinerParaObject
* pParaObj
= rTextProvider
.getText( nText
)->GetOutlinerParaObject();
577 pParaObj
->ClearPortionInfo();
581 else if(dynamic_cast<const SfxStyleSheetBasePool
*>(&rBC
) != nullptr)
583 const SfxStyleSheetModifiedHint
* pExtendedHint
= dynamic_cast<const SfxStyleSheetModifiedHint
*>(&rHint
);
586 && SfxHintId::StyleSheetModified
== pExtendedHint
->GetId())
588 const OUString
& aOldName(pExtendedHint
->GetOldName());
589 OUString
aNewName(pExtendedHint
->GetStyleSheet()->GetName());
590 SfxStyleFamily eFamily
= pExtendedHint
->GetStyleSheet()->GetFamily();
592 if(aOldName
!= aNewName
)
594 sal_Int32 nText
= rTextProvider
.getTextCount();
597 OutlinerParaObject
* pParaObj
= rTextProvider
.getText( nText
)->GetOutlinerParaObject();
599 pParaObj
->ChangeStyleSheetName(eFamily
, aOldName
, aNewName
);
607 // #i101556# Handout version information
608 sal_uInt32
TextProperties::getVersion() const
612 } // end of namespace properties
613 } // end of namespace sdr
615 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */