tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / svx / source / sdr / properties / textproperties.cxx
blobcabe52ab68b71db937d7dc81dfc53a0c7a92e41a
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_GLOW_TEXT_FIRST, SDRATTR_GLOW_TEXT_LAST,
58 SDRATTR_TEXTCOLUMNS_FIRST, SDRATTR_TEXTCOLUMNS_LAST,
60 // range from SdrTextObj
61 EE_ITEMS_START, EE_ITEMS_END>);
64 TextProperties::TextProperties(SdrObject& rObj)
65 : AttributeProperties(rObj),
66 maVersion(0)
70 TextProperties::TextProperties(const TextProperties& rProps, SdrObject& rObj)
71 : AttributeProperties(rProps, rObj),
72 maVersion(rProps.getVersion())
76 TextProperties::~TextProperties()
80 std::unique_ptr<BaseProperties> TextProperties::Clone(SdrObject& rObj) const
82 return std::unique_ptr<BaseProperties>(new TextProperties(*this, rObj));
85 void TextProperties::ItemSetChanged(std::span< const SfxPoolItem* const > aChangedItems, sal_uInt16 nDeletedWhich, bool bAdjustTextFrameWidthAndHeight)
87 SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
89 // #i101556# ItemSet has changed -> new version
90 maVersion++;
92 if (auto pOutliner = rObj.GetTextEditOutliner())
94 pOutliner->SetTextColumns(rObj.GetTextColumnsNumber(),
95 rObj.GetTextColumnsSpacing());
98 const svx::ITextProvider& rTextProvider(getTextProvider());
99 sal_Int32 nText = rTextProvider.getTextCount();
100 while (nText--)
102 SdrText* pText = rTextProvider.getText( nText );
104 OutlinerParaObject* pParaObj = pText ? pText->GetOutlinerParaObject() : nullptr;
106 if(pParaObj)
108 const bool bTextEdit = rObj.IsTextEditActive() && (rObj.getActiveText() == pText);
110 // handle outliner attributes
111 GetObjectItemSet();
112 Outliner* pOutliner = rObj.GetTextEditOutliner();
114 if(!bTextEdit)
116 pOutliner = &rObj.ImpGetDrawOutliner();
117 pOutliner->SetText(*pParaObj);
120 sal_Int32 nParaCount(pOutliner->GetParagraphCount());
122 for(sal_Int32 nPara = 0; nPara < nParaCount; nPara++)
124 SfxItemSet aSet(pOutliner->GetParaAttribs(nPara));
125 for (const SfxPoolItem* pItem : aChangedItems)
126 aSet.Put(*pItem);
127 if (nDeletedWhich)
128 aSet.ClearItem(nDeletedWhich);
129 pOutliner->SetParaAttribs(nPara, aSet);
132 if(!bTextEdit)
134 if(nParaCount)
136 // force ItemSet
137 GetObjectItemSet();
139 moItemSet->Put(pOutliner->GetParaAttribs(0));
142 std::optional<OutlinerParaObject> pTemp = pOutliner->CreateParaObject(0, nParaCount);
143 pOutliner->Clear();
145 rObj.NbcSetOutlinerParaObjectForText(std::move(pTemp), pText, bAdjustTextFrameWidthAndHeight);
150 // Extra-Repaint for radical layout changes (#43139#)
151 for (const SfxPoolItem* pItem : aChangedItems)
152 if (pItem->Which() == SDRATTR_TEXT_CONTOURFRAME)
154 // Here only repaint wanted
155 rObj.ActionChanged();
156 //rObj.BroadcastObjectChange();
157 break;
160 // call parent
161 AttributeProperties::ItemSetChanged(aChangedItems, nDeletedWhich, bAdjustTextFrameWidthAndHeight);
164 void TextProperties::ItemChange(const sal_uInt16 nWhich, const SfxPoolItem* pNewItem)
166 SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
168 // #i25616#
169 sal_Int32 nOldLineWidth(0);
171 if(XATTR_LINEWIDTH == nWhich && rObj.DoesSupportTextIndentingOnLineWidthChange())
173 nOldLineWidth = GetItem(XATTR_LINEWIDTH).GetValue();
176 if(pNewItem && (SDRATTR_TEXTDIRECTION == nWhich))
178 bool bVertical(css::text::WritingMode_TB_RL == static_cast<const SvxWritingModeItem*>(pNewItem)->GetValue());
179 rObj.SetVerticalWriting(bVertical);
182 // #95501# reset to default
183 if(!pNewItem && !nWhich && rObj.HasText() )
185 SdrOutliner& rOutliner = rObj.ImpGetDrawOutliner();
187 const svx::ITextProvider& rTextProvider(getTextProvider());
188 sal_Int32 nCount = rTextProvider.getTextCount();
189 while (nCount--)
191 SdrText* pText = rTextProvider.getText( nCount );
192 OutlinerParaObject* pParaObj = pText->GetOutlinerParaObject();
193 if( pParaObj )
195 rOutliner.SetText(*pParaObj);
196 sal_Int32 nParaCount(rOutliner.GetParagraphCount());
198 if(nParaCount)
200 auto aSelection = ESelection::All();
201 rOutliner.RemoveAttribs(aSelection, true, 0);
203 std::optional<OutlinerParaObject> pTemp = rOutliner.CreateParaObject(0, nParaCount);
204 rOutliner.Clear();
206 rObj.NbcSetOutlinerParaObjectForText( std::move(pTemp), pText );
212 // call parent
213 AttributeProperties::ItemChange( nWhich, pNewItem );
215 // #i25616#
216 if(!(XATTR_LINEWIDTH == nWhich && rObj.DoesSupportTextIndentingOnLineWidthChange()))
217 return;
219 const sal_Int32 nNewLineWidth(GetItem(XATTR_LINEWIDTH).GetValue());
220 const sal_Int32 nDifference((nNewLineWidth - nOldLineWidth) / 2);
222 if(!nDifference)
223 return;
225 const bool bLineVisible(drawing::LineStyle_NONE != GetItem(XATTR_LINESTYLE).GetValue());
227 if(bLineVisible)
229 const sal_Int32 nLeftDist(GetItem(SDRATTR_TEXT_LEFTDIST).GetValue());
230 const sal_Int32 nRightDist(GetItem(SDRATTR_TEXT_RIGHTDIST).GetValue());
231 const sal_Int32 nUpperDist(GetItem(SDRATTR_TEXT_UPPERDIST).GetValue());
232 const sal_Int32 nLowerDist(GetItem(SDRATTR_TEXT_LOWERDIST).GetValue());
234 SetObjectItemDirect(makeSdrTextLeftDistItem(nLeftDist + nDifference));
235 SetObjectItemDirect(makeSdrTextRightDistItem(nRightDist + nDifference));
236 SetObjectItemDirect(makeSdrTextUpperDistItem(nUpperDist + nDifference));
237 SetObjectItemDirect(makeSdrTextLowerDistItem(nLowerDist + nDifference));
241 const svx::ITextProvider& TextProperties::getTextProvider() const
243 return static_cast<const SdrTextObj&>(GetSdrObject());
246 void TextProperties::SetStyleSheet(SfxStyleSheet* pNewStyleSheet, bool bDontRemoveHardAttr,
247 bool bBroadcast, bool bAdjustTextFrameWidthAndHeight)
249 // call parent (always first thing to do, may create the SfxItemSet)
250 AttributeProperties::SetStyleSheet(pNewStyleSheet, bDontRemoveHardAttr, bBroadcast, bAdjustTextFrameWidthAndHeight);
252 // #i101556# StyleSheet has changed -> new version
253 SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
254 maVersion++;
256 if(!rObj.IsLinkedText() )
258 SdrOutliner& rOutliner = rObj.ImpGetDrawOutliner();
260 const svx::ITextProvider& rTextProvider(getTextProvider());
261 sal_Int32 nText = rTextProvider.getTextCount();
262 while (nText--)
264 SdrText* pText = rTextProvider.getText( nText );
266 OutlinerParaObject* pParaObj = pText ? pText->GetOutlinerParaObject() : nullptr;
267 if( !pParaObj )
268 continue;
270 // apply StyleSheet to all paragraphs
271 rOutliner.SetText(*pParaObj);
272 sal_Int32 nParaCount(rOutliner.GetParagraphCount());
274 if(nParaCount)
276 for(sal_Int32 nPara = 0; nPara < nParaCount; nPara++)
278 std::optional<SfxItemSet> pTempSet;
280 // since setting the stylesheet removes all para attributes
281 if(bDontRemoveHardAttr)
283 // we need to remember them if we want to keep them
284 pTempSet.emplace(rOutliner.GetParaAttribs(nPara));
287 if(GetStyleSheet())
289 if((SdrObjKind::OutlineText == rObj.GetTextKind()) && (SdrInventor::Default == rObj.GetObjInventor()))
291 OUString aNewStyleSheetName(GetStyleSheet()->GetName());
292 aNewStyleSheetName = aNewStyleSheetName.copy(0, aNewStyleSheetName.getLength() - 1);
293 sal_Int16 nDepth = rOutliner.GetDepth(nPara);
294 aNewStyleSheetName += OUString::number( nDepth <= 0 ? 1 : nDepth + 1);
295 SfxStyleSheetBasePool* pStylePool(rObj.getSdrModelFromSdrObject().GetStyleSheetPool());
296 SfxStyleSheet* pNewStyle = nullptr;
297 if(pStylePool)
298 pNewStyle = static_cast<SfxStyleSheet*>(pStylePool->Find(aNewStyleSheetName, GetStyleSheet()->GetFamily()));
299 DBG_ASSERT( pNewStyle, "AutoStyleSheetName - Style not found!" );
301 if(pNewStyle)
303 rOutliner.SetStyleSheet(nPara, pNewStyle);
306 else
308 rOutliner.SetStyleSheet(nPara, GetStyleSheet());
311 else
313 // remove StyleSheet
314 rOutliner.SetStyleSheet(nPara, nullptr);
317 if(bDontRemoveHardAttr)
319 if(pTempSet)
321 // restore para attributes
322 rOutliner.SetParaAttribs(nPara, *pTempSet);
325 else
327 if(pNewStyleSheet)
329 // remove all hard paragraph attributes
330 // which occur in StyleSheet, take care of
331 // parents (!)
332 SfxItemIter aIter(pNewStyleSheet->GetItemSet());
334 for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem;
335 pItem = aIter.NextItem())
337 if(!IsInvalidItem(pItem))
339 sal_uInt16 nW(pItem->Which());
341 if(nW >= EE_ITEMS_START && nW <= EE_ITEMS_END)
343 rOutliner.RemoveCharAttribs(nPara, nW);
351 std::optional<OutlinerParaObject> pTemp = rOutliner.CreateParaObject(0, nParaCount);
352 rOutliner.Clear();
353 rObj.NbcSetOutlinerParaObjectForText(std::move(pTemp), pText, bAdjustTextFrameWidthAndHeight);
358 if(rObj.IsTextFrame() && !rObj.getSdrModelFromSdrObject().isLocked() && bAdjustTextFrameWidthAndHeight)
359 rObj.NbcAdjustTextFrameWidthAndHeight();
362 void TextProperties::ForceDefaultAttributes()
364 SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
366 if( rObj.GetObjInventor() == SdrInventor::Default )
368 const SdrObjKind nSdrObjKind = rObj.GetObjIdentifier();
370 if( nSdrObjKind == SdrObjKind::TitleText || nSdrObjKind == SdrObjKind::OutlineText )
371 return; // no defaults for presentation objects
374 bool bTextFrame(rObj.IsTextFrame());
376 if(bTextFrame)
378 moItemSet->Put(XLineStyleItem(drawing::LineStyle_NONE));
379 moItemSet->Put(XFillColorItem(OUString(), COL_WHITE));
380 moItemSet->Put(XFillStyleItem(drawing::FillStyle_NONE));
382 else
384 moItemSet->Put(SvxAdjustItem(SvxAdjust::Center, EE_PARA_JUST));
385 moItemSet->Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER));
386 moItemSet->Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER));
390 void TextProperties::ForceStyleToHardAttributes()
392 // #i61284# call parent first to get the hard ObjectItemSet
393 AttributeProperties::ForceStyleToHardAttributes();
395 // #i61284# push hard ObjectItemSet to OutlinerParaObject attributes
396 // using existing functionality
397 GetObjectItemSet(); // force ItemSet
398 std::vector<const SfxPoolItem*> aChangedItems;
400 { // own scope to get SfxItemIter aIter destroyed ASAP - it maybe detected
401 // as reading source to the ItemSet when Items get changed below, but it
402 // is no longer active/needed
403 SfxItemIter aIter(*moItemSet);
404 for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
406 if(!IsInvalidItem(pItem))
407 aChangedItems.push_back(pItem);
411 ItemSetChanged(aChangedItems, 0);
413 // now the standard TextProperties stuff
414 SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
416 if(rObj.IsTextEditActive() || rObj.IsLinkedText())
417 return;
419 std::unique_ptr<Outliner> pOutliner = SdrMakeOutliner(OutlinerMode::OutlineObject, rObj.getSdrModelFromSdrObject());
420 const svx::ITextProvider& rTextProvider(getTextProvider());
421 sal_Int32 nText = rTextProvider.getTextCount();
422 while (nText--)
424 SdrText* pText = rTextProvider.getText( nText );
426 OutlinerParaObject* pParaObj = pText ? pText->GetOutlinerParaObject() : nullptr;
427 if( !pParaObj )
428 continue;
430 pOutliner->SetText(*pParaObj);
432 sal_Int32 nParaCount(pOutliner->GetParagraphCount());
434 if(nParaCount)
436 bool bBurnIn(false);
438 for(sal_Int32 nPara = 0; nPara < nParaCount; nPara++)
440 SfxStyleSheet* pSheet = pOutliner->GetStyleSheet(nPara);
442 if(pSheet)
444 SfxItemSet aParaSet(pOutliner->GetParaAttribs(nPara));
445 SfxItemSet aSet(*aParaSet.GetPool());
446 aSet.Put(pSheet->GetItemSet());
448 /** the next code handles a special case for paragraphs that contain a
449 url field. The color for URL fields is either the system color for
450 urls or the char color attribute that formats the portion in which the
451 url field is contained.
452 When we set a char color attribute to the paragraphs item set from the
453 styles item set, we would have this char color attribute as an attribute
454 that is spanned over the complete paragraph after xml import due to some
455 problems in the xml import (using a XCursor on import so it does not know
456 the paragraphs and can't set char attributes to paragraphs ).
458 To avoid this, as soon as we try to set a char color attribute from the style
460 1. check if we have at least one url field in this paragraph
461 2. if we found at least one url field, we span the char color attribute over
462 all portions that are not url fields and remove the char color attribute
463 from the paragraphs item set
466 bool bHasURL(false);
468 if(aSet.GetItemState(EE_CHAR_COLOR) == SfxItemState::SET)
470 EditEngine* pEditEngine = const_cast<EditEngine*>(&(pOutliner->GetEditEngine()));
471 std::vector<EECharAttrib> aAttribs;
472 pEditEngine->GetCharAttribs(nPara, aAttribs);
474 for(const auto& rAttrib : aAttribs)
476 if(rAttrib.pAttr && EE_FEATURE_FIELD == rAttrib.pAttr->Which())
478 const SvxFieldItem* pFieldItem = static_cast<const SvxFieldItem*>(rAttrib.pAttr);
480 if(pFieldItem)
482 const SvxFieldData* pData = pFieldItem->GetField();
484 if(dynamic_cast<const SvxURLField*>( pData))
486 bHasURL = true;
487 break;
493 if(bHasURL)
495 SfxItemSetFixed<EE_CHAR_COLOR, EE_CHAR_COLOR> aColorSet(*aSet.GetPool());
496 aColorSet.Put(aSet, false);
498 ESelection aSel(nPara, 0);
500 for(const auto& rAttrib : aAttribs)
502 if(EE_FEATURE_FIELD == rAttrib.pAttr->Which())
504 aSel.end.nIndex = rAttrib.nStart;
506 if (aSel.start.nIndex != aSel.end.nIndex)
507 pEditEngine->QuickSetAttribs(aColorSet, aSel);
509 aSel.start.nIndex = rAttrib.nEnd;
513 aSel.end.nIndex = pEditEngine->GetTextLen(nPara);
515 if (aSel.start.nIndex != aSel.end.nIndex)
517 pEditEngine->QuickSetAttribs( aColorSet, aSel );
523 aSet.Put(aParaSet, false);
525 if(bHasURL)
527 aSet.ClearItem(EE_CHAR_COLOR);
530 pOutliner->SetParaAttribs(nPara, aSet);
531 bBurnIn = true; // #i51163# Flag was set wrong
535 if(bBurnIn)
537 std::optional<OutlinerParaObject> pTemp = pOutliner->CreateParaObject(0, nParaCount);
538 rObj.NbcSetOutlinerParaObjectForText(std::move(pTemp),pText);
542 pOutliner->Clear();
546 void TextProperties::SetObjectItemNoBroadcast(const SfxPoolItem& rItem)
548 GetObjectItemSet();
549 moItemSet->Put(rItem);
553 void TextProperties::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
555 // call parent
556 AttributeProperties::Notify(rBC, rHint);
558 SfxHintId nId(rHint.GetId());
560 if(SfxHintId::DataChanged == nId && rBC.IsSfxStyleSheet())
562 SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
563 if(!rObj.HasText())
564 return;
566 const svx::ITextProvider& rTextProvider(getTextProvider());
567 sal_Int32 nText = rTextProvider.getTextCount();
568 while (nText--)
570 OutlinerParaObject* pParaObj = rTextProvider.getText( nText )->GetOutlinerParaObject();
571 if( pParaObj )
572 pParaObj->ClearPortionInfo();
574 rObj.SetTextSizeDirty();
576 if(rObj.IsTextFrame() && rObj.NbcAdjustTextFrameWidthAndHeight())
578 // here only repaint wanted
579 rObj.ActionChanged();
580 //rObj.BroadcastObjectChange();
583 // #i101556# content of StyleSheet has changed -> new version
584 maVersion++;
586 else if(SfxHintId::Dying == nId && rBC.IsSfxStyleSheet())
588 SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
589 if(!rObj.HasText())
590 return;
592 const svx::ITextProvider& rTextProvider(getTextProvider());
593 sal_Int32 nText = rTextProvider.getTextCount();
594 while (nText--)
596 OutlinerParaObject* pParaObj = rTextProvider.getText( nText )->GetOutlinerParaObject();
597 if( pParaObj )
598 pParaObj->ClearPortionInfo();
601 else if (nId == SfxHintId::StyleSheetModifiedExtended)
603 assert(dynamic_cast<const SfxStyleSheetBasePool *>(&rBC) != nullptr);
604 const SfxStyleSheetModifiedHint& rExtendedHint = static_cast<const SfxStyleSheetModifiedHint&>(rHint);
605 const OUString& aOldName(rExtendedHint.GetOldName());
606 OUString aNewName(rExtendedHint.GetStyleSheet()->GetName());
607 SfxStyleFamily eFamily = rExtendedHint.GetStyleSheet()->GetFamily();
609 if(aOldName != aNewName)
611 const svx::ITextProvider& rTextProvider(getTextProvider());
612 sal_Int32 nText = rTextProvider.getTextCount();
613 while (nText--)
615 OutlinerParaObject* pParaObj = rTextProvider.getText( nText )->GetOutlinerParaObject();
616 if( pParaObj )
617 pParaObj->ChangeStyleSheetName(eFamily, aOldName, aNewName);
623 // #i101556# Handout version information
624 sal_uInt32 TextProperties::getVersion() const
626 return maVersion;
628 } // end of namespace
630 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */