summaryrefslogtreecommitdiffstats
path: root/svx/source/sdr/properties/textproperties.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/sdr/properties/textproperties.cxx')
-rw-r--r--svx/source/sdr/properties/textproperties.cxx631
1 files changed, 631 insertions, 0 deletions
diff --git a/svx/source/sdr/properties/textproperties.cxx b/svx/source/sdr/properties/textproperties.cxx
new file mode 100644
index 000000000..d8cdf80df
--- /dev/null
+++ b/svx/source/sdr/properties/textproperties.cxx
@@ -0,0 +1,631 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <sdr/properties/textproperties.hxx>
+#include <svl/itemset.hxx>
+#include <svl/style.hxx>
+#include <svl/itemiter.hxx>
+#include <svl/hint.hxx>
+#include <svx/svddef.hxx>
+#include <svx/svdotext.hxx>
+#include <svx/svdoutl.hxx>
+#include <svx/sdmetitm.hxx>
+#include <svx/sdtditm.hxx>
+#include <editeng/writingmodeitem.hxx>
+#include <svx/svdmodel.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/outlobj.hxx>
+#include <svx/xfillit0.hxx>
+#include <svx/xflclit.hxx>
+#include <editeng/adjustitem.hxx>
+#include <svx/svdetc.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/flditem.hxx>
+#include <svx/xlineit0.hxx>
+#include <svx/xlnwtit.hxx>
+
+using namespace com::sun::star;
+
+namespace sdr::properties
+{
+ SfxItemSet TextProperties::CreateObjectSpecificItemSet(SfxItemPool& rPool)
+ {
+ return SfxItemSet(rPool,
+
+ // range from SdrAttrObj
+ svl::Items<SDRATTR_START, SDRATTR_SHADOW_LAST,
+ SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST,
+ SDRATTR_TEXTDIRECTION, SDRATTR_TEXTDIRECTION,
+ SDRATTR_TEXTCOLUMNS_FIRST, SDRATTR_TEXTCOLUMNS_LAST,
+
+ // range from SdrTextObj
+ EE_ITEMS_START, EE_ITEMS_END>);
+ }
+
+ TextProperties::TextProperties(SdrObject& rObj)
+ : AttributeProperties(rObj),
+ maVersion(0)
+ {
+ }
+
+ TextProperties::TextProperties(const TextProperties& rProps, SdrObject& rObj)
+ : AttributeProperties(rProps, rObj),
+ maVersion(rProps.getVersion())
+ {
+ }
+
+ TextProperties::~TextProperties()
+ {
+ }
+
+ std::unique_ptr<BaseProperties> TextProperties::Clone(SdrObject& rObj) const
+ {
+ return std::unique_ptr<BaseProperties>(new TextProperties(*this, rObj));
+ }
+
+ void TextProperties::ItemSetChanged(o3tl::span< const SfxPoolItem* const > aChangedItems, sal_uInt16 nDeletedWhich)
+ {
+ SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
+
+ // #i101556# ItemSet has changed -> new version
+ maVersion++;
+
+ if (auto pOutliner = rObj.GetTextEditOutliner())
+ {
+ pOutliner->SetTextColumns(rObj.GetTextColumnsNumber(),
+ rObj.GetTextColumnsSpacing());
+ }
+
+ const svx::ITextProvider& rTextProvider(getTextProvider());
+ sal_Int32 nText = rTextProvider.getTextCount();
+ while (nText--)
+ {
+ SdrText* pText = rTextProvider.getText( nText );
+
+ OutlinerParaObject* pParaObj = pText ? pText->GetOutlinerParaObject() : nullptr;
+
+ if(pParaObj)
+ {
+ const bool bTextEdit = rObj.IsTextEditActive() && (rObj.getActiveText() == pText);
+
+ // handle outliner attributes
+ GetObjectItemSet();
+ Outliner* pOutliner = rObj.GetTextEditOutliner();
+
+ if(!bTextEdit)
+ {
+ pOutliner = &rObj.ImpGetDrawOutliner();
+ pOutliner->SetText(*pParaObj);
+ }
+
+ sal_Int32 nParaCount(pOutliner->GetParagraphCount());
+
+ for(sal_Int32 nPara = 0; nPara < nParaCount; nPara++)
+ {
+ SfxItemSet aSet(pOutliner->GetParaAttribs(nPara));
+ for (const SfxPoolItem* pItem : aChangedItems)
+ aSet.Put(*pItem);
+ if (nDeletedWhich)
+ aSet.ClearItem(nDeletedWhich);
+ pOutliner->SetParaAttribs(nPara, aSet);
+ }
+
+ if(!bTextEdit)
+ {
+ if(nParaCount)
+ {
+ // force ItemSet
+ GetObjectItemSet();
+
+ SfxItemSet aNewSet(pOutliner->GetParaAttribs(0));
+ mxItemSet->Put(aNewSet);
+ }
+
+ std::optional<OutlinerParaObject> pTemp = pOutliner->CreateParaObject(0, nParaCount);
+ pOutliner->Clear();
+
+ rObj.NbcSetOutlinerParaObjectForText(std::move(pTemp),pText);
+ }
+ }
+ }
+
+ // Extra-Repaint for radical layout changes (#43139#)
+ for (const SfxPoolItem* pItem : aChangedItems)
+ if (pItem->Which() == SDRATTR_TEXT_CONTOURFRAME)
+ {
+ // Here only repaint wanted
+ rObj.ActionChanged();
+ //rObj.BroadcastObjectChange();
+ break;
+ }
+
+ // call parent
+ AttributeProperties::ItemSetChanged(aChangedItems, nDeletedWhich);
+ }
+
+ void TextProperties::ItemChange(const sal_uInt16 nWhich, const SfxPoolItem* pNewItem)
+ {
+ SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
+
+ // #i25616#
+ sal_Int32 nOldLineWidth(0);
+
+ if(XATTR_LINEWIDTH == nWhich && rObj.DoesSupportTextIndentingOnLineWidthChange())
+ {
+ nOldLineWidth = GetItem(XATTR_LINEWIDTH).GetValue();
+ }
+
+ if(pNewItem && (SDRATTR_TEXTDIRECTION == nWhich))
+ {
+ bool bVertical(css::text::WritingMode_TB_RL == static_cast<const SvxWritingModeItem*>(pNewItem)->GetValue());
+ rObj.SetVerticalWriting(bVertical);
+ }
+
+ // #95501# reset to default
+ if(!pNewItem && !nWhich && rObj.HasText() )
+ {
+ SdrOutliner& rOutliner = rObj.ImpGetDrawOutliner();
+
+ const svx::ITextProvider& rTextProvider(getTextProvider());
+ sal_Int32 nCount = rTextProvider.getTextCount();
+ while (nCount--)
+ {
+ SdrText* pText = rTextProvider.getText( nCount );
+ OutlinerParaObject* pParaObj = pText->GetOutlinerParaObject();
+ if( pParaObj )
+ {
+ rOutliner.SetText(*pParaObj);
+ sal_Int32 nParaCount(rOutliner.GetParagraphCount());
+
+ if(nParaCount)
+ {
+ ESelection aSelection( 0, 0, EE_PARA_ALL, EE_TEXTPOS_ALL);
+ rOutliner.RemoveAttribs(aSelection, true, 0);
+
+ std::optional<OutlinerParaObject> pTemp = rOutliner.CreateParaObject(0, nParaCount);
+ rOutliner.Clear();
+
+ rObj.NbcSetOutlinerParaObjectForText( std::move(pTemp), pText );
+ }
+ }
+ }
+ }
+
+ // call parent
+ AttributeProperties::ItemChange( nWhich, pNewItem );
+
+ // #i25616#
+ if(!(XATTR_LINEWIDTH == nWhich && rObj.DoesSupportTextIndentingOnLineWidthChange()))
+ return;
+
+ const sal_Int32 nNewLineWidth(GetItem(XATTR_LINEWIDTH).GetValue());
+ const sal_Int32 nDifference((nNewLineWidth - nOldLineWidth) / 2);
+
+ if(!nDifference)
+ return;
+
+ const bool bLineVisible(drawing::LineStyle_NONE != GetItem(XATTR_LINESTYLE).GetValue());
+
+ if(bLineVisible)
+ {
+ const sal_Int32 nLeftDist(GetItem(SDRATTR_TEXT_LEFTDIST).GetValue());
+ const sal_Int32 nRightDist(GetItem(SDRATTR_TEXT_RIGHTDIST).GetValue());
+ const sal_Int32 nUpperDist(GetItem(SDRATTR_TEXT_UPPERDIST).GetValue());
+ const sal_Int32 nLowerDist(GetItem(SDRATTR_TEXT_LOWERDIST).GetValue());
+
+ SetObjectItemDirect(makeSdrTextLeftDistItem(nLeftDist + nDifference));
+ SetObjectItemDirect(makeSdrTextRightDistItem(nRightDist + nDifference));
+ SetObjectItemDirect(makeSdrTextUpperDistItem(nUpperDist + nDifference));
+ SetObjectItemDirect(makeSdrTextLowerDistItem(nLowerDist + nDifference));
+ }
+ }
+
+ const svx::ITextProvider& TextProperties::getTextProvider() const
+ {
+ return static_cast<const SdrTextObj&>(GetSdrObject());
+ }
+
+ void TextProperties::SetStyleSheet(SfxStyleSheet* pNewStyleSheet, bool bDontRemoveHardAttr,
+ bool bBroadcast)
+ {
+ // call parent (always first thing to do, may create the SfxItemSet)
+ AttributeProperties::SetStyleSheet(pNewStyleSheet, bDontRemoveHardAttr, bBroadcast);
+
+ // #i101556# StyleSheet has changed -> new version
+ SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
+ maVersion++;
+
+ if(!rObj.IsLinkedText() )
+ {
+ SdrOutliner& rOutliner = rObj.ImpGetDrawOutliner();
+
+ const svx::ITextProvider& rTextProvider(getTextProvider());
+ sal_Int32 nText = rTextProvider.getTextCount();
+ while (nText--)
+ {
+ SdrText* pText = rTextProvider.getText( nText );
+
+ OutlinerParaObject* pParaObj = pText ? pText->GetOutlinerParaObject() : nullptr;
+ if( !pParaObj )
+ continue;
+
+ // apply StyleSheet to all paragraphs
+ rOutliner.SetText(*pParaObj);
+ sal_Int32 nParaCount(rOutliner.GetParagraphCount());
+
+ if(nParaCount)
+ {
+ for(sal_Int32 nPara = 0; nPara < nParaCount; nPara++)
+ {
+ std::optional<SfxItemSet> pTempSet;
+
+ // since setting the stylesheet removes all para attributes
+ if(bDontRemoveHardAttr)
+ {
+ // we need to remember them if we want to keep them
+ pTempSet.emplace(rOutliner.GetParaAttribs(nPara));
+ }
+
+ if(GetStyleSheet())
+ {
+ if((SdrObjKind::OutlineText == rObj.GetTextKind()) && (SdrInventor::Default == rObj.GetObjInventor()))
+ {
+ OUString aNewStyleSheetName(GetStyleSheet()->GetName());
+ aNewStyleSheetName = aNewStyleSheetName.copy(0, aNewStyleSheetName.getLength() - 1);
+ sal_Int16 nDepth = rOutliner.GetDepth(nPara);
+ aNewStyleSheetName += OUString::number( nDepth <= 0 ? 1 : nDepth + 1);
+ SfxStyleSheetBasePool* pStylePool(rObj.getSdrModelFromSdrObject().GetStyleSheetPool());
+ SfxStyleSheet* pNewStyle = nullptr;
+ if(pStylePool)
+ pNewStyle = static_cast<SfxStyleSheet*>(pStylePool->Find(aNewStyleSheetName, GetStyleSheet()->GetFamily()));
+ DBG_ASSERT( pNewStyle, "AutoStyleSheetName - Style not found!" );
+
+ if(pNewStyle)
+ {
+ rOutliner.SetStyleSheet(nPara, pNewStyle);
+ }
+ }
+ else
+ {
+ rOutliner.SetStyleSheet(nPara, GetStyleSheet());
+ }
+ }
+ else
+ {
+ // remove StyleSheet
+ rOutliner.SetStyleSheet(nPara, nullptr);
+ }
+
+ if(bDontRemoveHardAttr)
+ {
+ if(pTempSet)
+ {
+ // restore para attributes
+ rOutliner.SetParaAttribs(nPara, *pTempSet);
+ }
+ }
+ else
+ {
+ if(pNewStyleSheet)
+ {
+ // remove all hard paragraph attributes
+ // which occur in StyleSheet, take care of
+ // parents (!)
+ SfxItemIter aIter(pNewStyleSheet->GetItemSet());
+
+ for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem;
+ pItem = aIter.NextItem())
+ {
+ if(!IsInvalidItem(pItem))
+ {
+ sal_uInt16 nW(pItem->Which());
+
+ if(nW >= EE_ITEMS_START && nW <= EE_ITEMS_END)
+ {
+ rOutliner.RemoveCharAttribs(nPara, nW);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ std::optional<OutlinerParaObject> pTemp = rOutliner.CreateParaObject(0, nParaCount);
+ rOutliner.Clear();
+ rObj.NbcSetOutlinerParaObjectForText(std::move(pTemp), pText);
+ }
+ }
+ }
+
+ if(rObj.IsTextFrame())
+ {
+ rObj.NbcAdjustTextFrameWidthAndHeight();
+ }
+ }
+
+ void TextProperties::ForceDefaultAttributes()
+ {
+ SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
+
+ if( rObj.GetObjInventor() == SdrInventor::Default )
+ {
+ const SdrObjKind nSdrObjKind = rObj.GetObjIdentifier();
+
+ if( nSdrObjKind == SdrObjKind::TitleText || nSdrObjKind == SdrObjKind::OutlineText )
+ return; // no defaults for presentation objects
+ }
+
+ bool bTextFrame(rObj.IsTextFrame());
+
+ // force ItemSet
+ GetObjectItemSet();
+
+ if(bTextFrame)
+ {
+ mxItemSet->Put(XLineStyleItem(drawing::LineStyle_NONE));
+ mxItemSet->Put(XFillColorItem(OUString(), COL_WHITE));
+ mxItemSet->Put(XFillStyleItem(drawing::FillStyle_NONE));
+ }
+ else
+ {
+ mxItemSet->Put(SvxAdjustItem(SvxAdjust::Center, EE_PARA_JUST));
+ mxItemSet->Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER));
+ mxItemSet->Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER));
+ }
+ }
+
+ void TextProperties::ForceStyleToHardAttributes()
+ {
+ // #i61284# call parent first to get the hard ObjectItemSet
+ AttributeProperties::ForceStyleToHardAttributes();
+
+ // #i61284# push hard ObjectItemSet to OutlinerParaObject attributes
+ // using existing functionality
+ GetObjectItemSet(); // force ItemSet
+ std::vector<const SfxPoolItem*> aChangedItems;
+ SfxItemIter aIter(*mxItemSet);
+ for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
+ {
+ if(!IsInvalidItem(pItem))
+ aChangedItems.push_back(pItem);
+ }
+ ItemSetChanged(aChangedItems, 0);
+
+ // now the standard TextProperties stuff
+ SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
+
+ if(rObj.IsTextEditActive() || rObj.IsLinkedText())
+ return;
+
+ std::unique_ptr<Outliner> pOutliner = SdrMakeOutliner(OutlinerMode::OutlineObject, rObj.getSdrModelFromSdrObject());
+ const svx::ITextProvider& rTextProvider(getTextProvider());
+ sal_Int32 nText = rTextProvider.getTextCount();
+ while (nText--)
+ {
+ SdrText* pText = rTextProvider.getText( nText );
+
+ OutlinerParaObject* pParaObj = pText ? pText->GetOutlinerParaObject() : nullptr;
+ if( !pParaObj )
+ continue;
+
+ pOutliner->SetText(*pParaObj);
+
+ sal_Int32 nParaCount(pOutliner->GetParagraphCount());
+
+ if(nParaCount)
+ {
+ bool bBurnIn(false);
+
+ for(sal_Int32 nPara = 0; nPara < nParaCount; nPara++)
+ {
+ SfxStyleSheet* pSheet = pOutliner->GetStyleSheet(nPara);
+
+ if(pSheet)
+ {
+ SfxItemSet aParaSet(pOutliner->GetParaAttribs(nPara));
+ SfxItemSet aSet(*aParaSet.GetPool());
+ aSet.Put(pSheet->GetItemSet());
+
+ /** the next code handles a special case for paragraphs that contain a
+ url field. The color for URL fields is either the system color for
+ urls or the char color attribute that formats the portion in which the
+ url field is contained.
+ When we set a char color attribute to the paragraphs item set from the
+ styles item set, we would have this char color attribute as an attribute
+ that is spanned over the complete paragraph after xml import due to some
+ problems in the xml import (using a XCursor on import so it does not know
+ the paragraphs and can't set char attributes to paragraphs ).
+
+ To avoid this, as soon as we try to set a char color attribute from the style
+ we
+ 1. check if we have at least one url field in this paragraph
+ 2. if we found at least one url field, we span the char color attribute over
+ all portions that are not url fields and remove the char color attribute
+ from the paragraphs item set
+ */
+
+ bool bHasURL(false);
+
+ if(aSet.GetItemState(EE_CHAR_COLOR) == SfxItemState::SET)
+ {
+ EditEngine* pEditEngine = const_cast<EditEngine*>(&(pOutliner->GetEditEngine()));
+ std::vector<EECharAttrib> aAttribs;
+ pEditEngine->GetCharAttribs(nPara, aAttribs);
+
+ for(const auto& rAttrib : aAttribs)
+ {
+ if(rAttrib.pAttr && EE_FEATURE_FIELD == rAttrib.pAttr->Which())
+ {
+ const SvxFieldItem* pFieldItem = static_cast<const SvxFieldItem*>(rAttrib.pAttr);
+
+ if(pFieldItem)
+ {
+ const SvxFieldData* pData = pFieldItem->GetField();
+
+ if(dynamic_cast<const SvxURLField*>( pData))
+ {
+ bHasURL = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if(bHasURL)
+ {
+ SfxItemSetFixed<EE_CHAR_COLOR, EE_CHAR_COLOR> aColorSet(*aSet.GetPool());
+ aColorSet.Put(aSet, false);
+
+ ESelection aSel(nPara, 0);
+
+ for(const auto& rAttrib : aAttribs)
+ {
+ if(EE_FEATURE_FIELD == rAttrib.pAttr->Which())
+ {
+ aSel.nEndPos = rAttrib.nStart;
+
+ if(aSel.nStartPos != aSel.nEndPos)
+ pEditEngine->QuickSetAttribs(aColorSet, aSel);
+
+ aSel.nStartPos = rAttrib.nEnd;
+ }
+ }
+
+ aSel.nEndPos = pEditEngine->GetTextLen(nPara);
+
+ if(aSel.nStartPos != aSel.nEndPos)
+ {
+ pEditEngine->QuickSetAttribs( aColorSet, aSel );
+ }
+ }
+
+ }
+
+ aSet.Put(aParaSet, false);
+
+ if(bHasURL)
+ {
+ aSet.ClearItem(EE_CHAR_COLOR);
+ }
+
+ pOutliner->SetParaAttribs(nPara, aSet);
+ bBurnIn = true; // #i51163# Flag was set wrong
+ }
+ }
+
+ if(bBurnIn)
+ {
+ std::optional<OutlinerParaObject> pTemp = pOutliner->CreateParaObject(0, nParaCount);
+ rObj.NbcSetOutlinerParaObjectForText(std::move(pTemp),pText);
+ }
+ }
+
+ pOutliner->Clear();
+ }
+ }
+
+ void TextProperties::SetObjectItemNoBroadcast(const SfxPoolItem& rItem)
+ {
+ GetObjectItemSet();
+ mxItemSet->Put(rItem);
+ }
+
+
+ void TextProperties::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
+ {
+ // call parent
+ AttributeProperties::Notify(rBC, rHint);
+
+ SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
+ if(!rObj.HasText())
+ return;
+
+ const svx::ITextProvider& rTextProvider(getTextProvider());
+ if(dynamic_cast<const SfxStyleSheet *>(&rBC) != nullptr)
+ {
+ SfxHintId nId(rHint.GetId());
+
+ if(SfxHintId::DataChanged == nId)
+ {
+ sal_Int32 nText = rTextProvider.getTextCount();
+ while (nText--)
+ {
+ OutlinerParaObject* pParaObj = rTextProvider.getText( nText )->GetOutlinerParaObject();
+ if( pParaObj )
+ pParaObj->ClearPortionInfo();
+ }
+ rObj.SetTextSizeDirty();
+
+ if(rObj.IsTextFrame() && rObj.NbcAdjustTextFrameWidthAndHeight())
+ {
+ // here only repaint wanted
+ rObj.ActionChanged();
+ //rObj.BroadcastObjectChange();
+ }
+
+ // #i101556# content of StyleSheet has changed -> new version
+ maVersion++;
+ }
+
+ if(SfxHintId::Dying == nId)
+ {
+ sal_Int32 nText = rTextProvider.getTextCount();
+ while (nText--)
+ {
+ OutlinerParaObject* pParaObj = rTextProvider.getText( nText )->GetOutlinerParaObject();
+ if( pParaObj )
+ pParaObj->ClearPortionInfo();
+ }
+ }
+ }
+ else if(dynamic_cast<const SfxStyleSheetBasePool *>(&rBC) != nullptr)
+ {
+ const SfxStyleSheetModifiedHint* pExtendedHint = dynamic_cast<const SfxStyleSheetModifiedHint*>(&rHint);
+
+ if(pExtendedHint
+ && SfxHintId::StyleSheetModified == pExtendedHint->GetId())
+ {
+ const OUString& aOldName(pExtendedHint->GetOldName());
+ OUString aNewName(pExtendedHint->GetStyleSheet()->GetName());
+ SfxStyleFamily eFamily = pExtendedHint->GetStyleSheet()->GetFamily();
+
+ if(aOldName != aNewName)
+ {
+ sal_Int32 nText = rTextProvider.getTextCount();
+ while (nText--)
+ {
+ OutlinerParaObject* pParaObj = rTextProvider.getText( nText )->GetOutlinerParaObject();
+ if( pParaObj )
+ pParaObj->ChangeStyleSheetName(eFamily, aOldName, aNewName);
+ }
+ }
+ }
+ }
+ }
+
+ // #i101556# Handout version information
+ sal_uInt32 TextProperties::getVersion() const
+ {
+ return maVersion;
+ }
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */