Bump version to 24.04.3.4
[LibreOffice.git] / svx / source / sdr / properties / textproperties.cxx
blob17f63d044dcf13ceb08d3ad581af476a45cc51db
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <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),
65 maVersion(0)
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
89 maVersion++;
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();
99 while (nText--)
101 SdrText* pText = rTextProvider.getText( nText );
103 OutlinerParaObject* pParaObj = pText ? pText->GetOutlinerParaObject() : nullptr;
105 if(pParaObj)
107 const bool bTextEdit = rObj.IsTextEditActive() && (rObj.getActiveText() == pText);
109 // handle outliner attributes
110 GetObjectItemSet();
111 Outliner* pOutliner = rObj.GetTextEditOutliner();
113 if(!bTextEdit)
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)
125 aSet.Put(*pItem);
126 if (nDeletedWhich)
127 aSet.ClearItem(nDeletedWhich);
128 pOutliner->SetParaAttribs(nPara, aSet);
131 if(!bTextEdit)
133 if(nParaCount)
135 // force ItemSet
136 GetObjectItemSet();
138 moItemSet->Put(pOutliner->GetParaAttribs(0));
141 std::optional<OutlinerParaObject> pTemp = pOutliner->CreateParaObject(0, nParaCount);
142 pOutliner->Clear();
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();
156 break;
159 // call parent
160 AttributeProperties::ItemSetChanged(aChangedItems, nDeletedWhich);
163 void TextProperties::ItemChange(const sal_uInt16 nWhich, const SfxPoolItem* pNewItem)
165 SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
167 // #i25616#
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();
188 while (nCount--)
190 SdrText* pText = rTextProvider.getText( nCount );
191 OutlinerParaObject* pParaObj = pText->GetOutlinerParaObject();
192 if( pParaObj )
194 rOutliner.SetText(*pParaObj);
195 sal_Int32 nParaCount(rOutliner.GetParagraphCount());
197 if(nParaCount)
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);
203 rOutliner.Clear();
205 rObj.NbcSetOutlinerParaObjectForText( std::move(pTemp), pText );
211 // call parent
212 AttributeProperties::ItemChange( nWhich, pNewItem );
214 // #i25616#
215 if(!(XATTR_LINEWIDTH == nWhich && rObj.DoesSupportTextIndentingOnLineWidthChange()))
216 return;
218 const sal_Int32 nNewLineWidth(GetItem(XATTR_LINEWIDTH).GetValue());
219 const sal_Int32 nDifference((nNewLineWidth - nOldLineWidth) / 2);
221 if(!nDifference)
222 return;
224 const bool bLineVisible(drawing::LineStyle_NONE != GetItem(XATTR_LINESTYLE).GetValue());
226 if(bLineVisible)
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,
246 bool bBroadcast)
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());
253 maVersion++;
255 if(!rObj.IsLinkedText() )
257 SdrOutliner& rOutliner = rObj.ImpGetDrawOutliner();
259 const svx::ITextProvider& rTextProvider(getTextProvider());
260 sal_Int32 nText = rTextProvider.getTextCount();
261 while (nText--)
263 SdrText* pText = rTextProvider.getText( nText );
265 OutlinerParaObject* pParaObj = pText ? pText->GetOutlinerParaObject() : nullptr;
266 if( !pParaObj )
267 continue;
269 // apply StyleSheet to all paragraphs
270 rOutliner.SetText(*pParaObj);
271 sal_Int32 nParaCount(rOutliner.GetParagraphCount());
273 if(nParaCount)
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));
286 if(GetStyleSheet())
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;
296 if(pStylePool)
297 pNewStyle = static_cast<SfxStyleSheet*>(pStylePool->Find(aNewStyleSheetName, GetStyleSheet()->GetFamily()));
298 DBG_ASSERT( pNewStyle, "AutoStyleSheetName - Style not found!" );
300 if(pNewStyle)
302 rOutliner.SetStyleSheet(nPara, pNewStyle);
305 else
307 rOutliner.SetStyleSheet(nPara, GetStyleSheet());
310 else
312 // remove StyleSheet
313 rOutliner.SetStyleSheet(nPara, nullptr);
316 if(bDontRemoveHardAttr)
318 if(pTempSet)
320 // restore para attributes
321 rOutliner.SetParaAttribs(nPara, *pTempSet);
324 else
326 if(pNewStyleSheet)
328 // remove all hard paragraph attributes
329 // which occur in StyleSheet, take care of
330 // parents (!)
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);
351 rOutliner.Clear();
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());
377 if(bTextFrame)
379 moItemSet->Put(XLineStyleItem(drawing::LineStyle_NONE));
380 moItemSet->Put(XFillColorItem(OUString(), COL_WHITE));
381 moItemSet->Put(XFillStyleItem(drawing::FillStyle_NONE));
383 else
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())
412 return;
414 std::unique_ptr<Outliner> pOutliner = SdrMakeOutliner(OutlinerMode::OutlineObject, rObj.getSdrModelFromSdrObject());
415 const svx::ITextProvider& rTextProvider(getTextProvider());
416 sal_Int32 nText = rTextProvider.getTextCount();
417 while (nText--)
419 SdrText* pText = rTextProvider.getText( nText );
421 OutlinerParaObject* pParaObj = pText ? pText->GetOutlinerParaObject() : nullptr;
422 if( !pParaObj )
423 continue;
425 pOutliner->SetText(*pParaObj);
427 sal_Int32 nParaCount(pOutliner->GetParagraphCount());
429 if(nParaCount)
431 bool bBurnIn(false);
433 for(sal_Int32 nPara = 0; nPara < nParaCount; nPara++)
435 SfxStyleSheet* pSheet = pOutliner->GetStyleSheet(nPara);
437 if(pSheet)
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
461 bool bHasURL(false);
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);
475 if(pFieldItem)
477 const SvxFieldData* pData = pFieldItem->GetField();
479 if(dynamic_cast<const SvxURLField*>( pData))
481 bHasURL = true;
482 break;
488 if(bHasURL)
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);
520 if(bHasURL)
522 aSet.ClearItem(EE_CHAR_COLOR);
525 pOutliner->SetParaAttribs(nPara, aSet);
526 bBurnIn = true; // #i51163# Flag was set wrong
530 if(bBurnIn)
532 std::optional<OutlinerParaObject> pTemp = pOutliner->CreateParaObject(0, nParaCount);
533 rObj.NbcSetOutlinerParaObjectForText(std::move(pTemp),pText);
537 pOutliner->Clear();
541 void TextProperties::SetObjectItemNoBroadcast(const SfxPoolItem& rItem)
543 GetObjectItemSet();
544 moItemSet->Put(rItem);
548 void TextProperties::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
550 // call parent
551 AttributeProperties::Notify(rBC, rHint);
553 SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
554 if(!rObj.HasText())
555 return;
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();
563 while (nText--)
565 OutlinerParaObject* pParaObj = rTextProvider.getText( nText )->GetOutlinerParaObject();
566 if( pParaObj )
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
579 maVersion++;
581 else if(SfxHintId::Dying == nId && dynamic_cast<const SfxStyleSheet *>(&rBC) != nullptr)
583 sal_Int32 nText = rTextProvider.getTextCount();
584 while (nText--)
586 OutlinerParaObject* pParaObj = rTextProvider.getText( nText )->GetOutlinerParaObject();
587 if( pParaObj )
588 pParaObj->ClearPortionInfo();
591 else if (nId == SfxHintId::StyleSheetModified && dynamic_cast<const SfxStyleSheetBasePool *>(&rBC) != nullptr)
593 const SfxStyleSheetModifiedHint* pExtendedHint = dynamic_cast<const SfxStyleSheetModifiedHint*>(&rHint);
594 if (pExtendedHint)
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();
603 while (nText--)
605 OutlinerParaObject* pParaObj = rTextProvider.getText( nText )->GetOutlinerParaObject();
606 if( pParaObj )
607 pParaObj->ChangeStyleSheetName(eFamily, aOldName, aNewName);
614 // #i101556# Handout version information
615 sal_uInt32 TextProperties::getVersion() const
617 return maVersion;
619 } // end of namespace
621 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */