SwFormatField::SwFormatField( const SwField &rField )
: SfxPoolItem( RES_TXTATR_FIELD )
, SfxBroadcaster()
, mpField( rField.CopyField() )
, mpTextField( nullptr )
{
setNonShareable();
rField.GetTyp()->Add(*this); if ( mpField->GetTyp()->Which() == SwFieldIds::Input )
{ // input field in-place editing
SetWhich( RES_TXTATR_INPUTFIELD ); static_cast<SwInputField*>(mpField.get())->SetFormatField( *this );
} elseif (mpField->GetTyp()->Which() == SwFieldIds::SetExp)
{ // see SwWrtShell::StartInputFieldDlg
SwSetExpField *const pSetField(static_cast<SwSetExpField *>(mpField.get())); if (pSetField->GetInputFlag() // only for string fields for now - inline editing of number fields // tends to produce error messages...
&& (static_cast<SwSetExpFieldType*>(pSetField->GetTyp())->GetType()
& nsSwGetSetExpType::GSE_STRING))
{
SetWhich( RES_TXTATR_INPUTFIELD );
}
pSetField->SetFormatField(*this);
} elseif ( mpField->GetTyp()->Which() == SwFieldIds::Postit )
{ // text annotation field
SetWhich( RES_TXTATR_ANNOTATION );
}
}
// #i24434# // Since Items are used in ItemPool and in default constructed ItemSets with // full pool range, all items need to be clonable. Thus, this one needed to be // corrected
SwFormatField::SwFormatField( const SwFormatField& rAttr )
: SfxPoolItem( rAttr )
, SfxBroadcaster()
, mpTextField( nullptr )
{
setNonShareable(); if ( !rAttr.mpField ) return;
namespace
{ bool lcl_ExpandField(const SwFieldIds eId)
{ switch(eId)
{ case SwFieldIds::DbSetNumber: case SwFieldIds::DbNumSet: case SwFieldIds::DbNextSet: case SwFieldIds::DatabaseName: returnfalse; default: returntrue;
}
}; bool lcl_TriggerNode(const SwFieldIds eId)
{ switch(eId)
{ case SwFieldIds::HiddenPara: case SwFieldIds::DbSetNumber: case SwFieldIds::DbNumSet: case SwFieldIds::DbNextSet: case SwFieldIds::DatabaseName: returntrue; default: returnfalse;
}
} void lcl_EnsureUserFieldValid(SwFieldType& rType)
{ if(rType.Which() != SwFieldIds::User) return; static_cast<SwUserFieldType*>(&rType)->EnsureValid();
} bool lcl_NeedsForcedUpdate(const SwField& rField)
{ if (rField.GetTyp()->Which() == SwFieldIds::DocInfo)
{ auto pDocInfoField = static_cast<const SwDocInfoField*>(&rField);
sal_uInt16 nSubType = pDocInfoField->GetSubType(); // Do not consider extended SubTypes.
nSubType &= 0xff; switch (nSubType)
{ case nsSwDocInfoSubType::DI_TITLE: case nsSwDocInfoSubType::DI_SUBJECT: case nsSwDocInfoSubType::DI_CHANGE: case nsSwDocInfoSubType::DI_CUSTOM: returnfalse;
}
} returntrue;
}
}
void SwFormatField::ForceUpdateTextNode()
{ if (!IsFieldInDoc()) return;
SwTextNode* pTextNd = &mpTextField->GetTextNode();
OSL_ENSURE(pTextNd, "Where is my Node?");
auto pType = mpField->GetTyp();
lcl_EnsureUserFieldValid(*pType); if(lcl_TriggerNode(pType->Which()))
pTextNd->TriggerNodeUpdate(sw::LegacyModifyHint(nullptr, nullptr)); if(!lcl_ExpandField(pType->Which())) return;
// Force notify was added for conditional text fields, // at least the below fields need no forced notify. bool bNeedForced = lcl_NeedsForcedUpdate(*mpTextField->GetFormatField().GetField());
mpTextField->ExpandTextField(bNeedForced);
} void SwFormatField::UpdateDocPos(const SwTwips nDocPos)
{ if (!IsFieldInDoc()) return; auto pTextNd = &mpTextField->GetTextNode();
pTextNd->UpdateDocPos(nDocPos, mpTextField->GetStart());
} void SwFormatField::UpdateTextNode(const SfxHint& rHint)
{ if(SfxHintId::SwHiddenParaPrint == rHint.GetId())
{ if (!IsFieldInDoc()) return; auto pType = mpField->GetTyp();
lcl_EnsureUserFieldValid(*pType); bool bTriggerNode = lcl_TriggerNode(pType->Which()); bool bExpand = lcl_ExpandField(pType->Which()); if(bTriggerNode)
{
SwTextNode* pTextNd = &mpTextField->GetTextNode();
OSL_ENSURE(pTextNd, "Where is my Node?");
pTextNd->TriggerNodeUpdate(sw::LegacyModifyHint(nullptr, nullptr));
} if(bExpand)
mpTextField->ExpandTextField(false);
} elseif(SfxHintId::SwRemoveUnoObject == rHint.GetId())
{ // invalidate cached UNO object
m_wXTextField.clear(); // ??? why does this Modify method not already do this?
CallSwClientNotify(rHint);
} elseif (rHint.GetId() == SfxHintId::SwFormatChange)
{ auto pChangeHint = static_cast<const SwFormatChangeHint*>(&rHint); if (pChangeHint->m_pOldFormat == nullptr && pChangeHint->m_pNewFormat == nullptr)
{
ForceUpdateTextNode(); return;
} if (!IsFieldInDoc()) return;
SwTextNode* pTextNd = &mpTextField->GetTextNode();
OSL_ENSURE(pTextNd, "Where is my Node?");
bool bTriggerNode = pChangeHint->m_pNewFormat != nullptr; if(bTriggerNode)
pTextNd->TriggerNodeUpdate(*pChangeHint);
} elseif (rHint.GetId() == SfxHintId::SwAttrSetChange)
{ auto pChangeHint = static_cast<const sw::AttrSetChangeHint*>(&rHint); auto pOld = pChangeHint->m_pOld; auto pNew = pChangeHint->m_pNew; if (pOld == nullptr && pNew == nullptr)
{
ForceUpdateTextNode(); return;
}
if (!IsFieldInDoc()) return;
SwTextNode* pTextNd = &mpTextField->GetTextNode();
OSL_ENSURE(pTextNd, "Where is my Node?");
bool bTriggerNode = pNew != nullptr; if(bTriggerNode)
pTextNd->TriggerNodeUpdate(sw::AttrSetChangeHint(pOld, pNew));
} elseif(SfxHintId::SwObjectDying == rHint.GetId())
{
assert(false && "do not expect this, might need to restore some code");
} elseif(SfxHintId::SwUpdateAttr == rHint.GetId())
{ auto pUpdateHint = static_cast<const sw::UpdateAttrHint*>(&rHint); auto pOld = pUpdateHint->m_pOld; auto pNew = pUpdateHint->m_pNew; if (pOld == nullptr && pNew == nullptr)
{
ForceUpdateTextNode(); return;
}
if (!IsFieldInDoc()) return;
SwTextNode* pTextNd = &mpTextField->GetTextNode();
OSL_ENSURE(pTextNd, "Where is my Node?");
SfxPoolItem::dumpAsXml(pWriter); if (mpField) // pool default doesn't have one
{
mpField->dumpAsXml(pWriter);
}
(void)xmlTextWriterEndElement(pWriter);
}
// class SwTextField ////////////////////////////////////////////////////
SwTextField::SwTextField( const SfxPoolItemHolder& rAttr,
sal_Int32 const nStartPos, boolconst bInClipboard)
: SwTextAttr( rAttr, nStartPos ) // fdo#39694 the ExpandField here may not give the correct result in all cases, // but is better than nothing
, m_aExpand()
, m_pTextNode( nullptr )
{
SwFormatField& rSwFormatField(static_cast<SwFormatField&>(GetAttr()));
m_aExpand = rSwFormatField.GetField()->ExpandField(bInClipboard, nullptr);
rSwFormatField.SetTextField( *this );
SetHasDummyChar(true);
}
SwTextField::~SwTextField( )
{
SwFormatField & rFormatField( static_cast<SwFormatField &>(GetAttr()) ); if ( this == rFormatField.GetTextField() )
{
rFormatField.ClearTextField();
}
}
void SwTextField::ExpandTextField(constbool bForceNotify) const
{
OSL_ENSURE( m_pTextNode, "SwTextField: where is my TextNode?" );
const SwField* pField = GetFormatField().GetField(); const OUString aNewExpand( pField->ExpandField(m_pTextNode->GetDoc().IsClipBoard(), // can't do any better than this here...
m_pTextNode->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout()) );
const SwFieldIds nWhich = pField->GetTyp()->Which(); constbool bSameExpandSimpleNotification
= SwFieldIds::Chapter != nWhich && SwFieldIds::PageNumber != nWhich
&& SwFieldIds::RefPageGet != nWhich // Page count fields to not use aExpand during formatting, // therefore an invalidation of the text frame has to be triggered even if aNewExpand == aExpand:
&& (SwFieldIds::DocStat != nWhich
|| DS_PAGE != static_cast<const SwDocStatField*>(pField)->GetSubType())
&& (SwFieldIds::GetExp != nWhich
|| static_cast<const SwGetExpField*>(pField)->IsInBodyText());
void SwTextField::CopyTextField( SwTextField *pDest ) const
{
OSL_ENSURE( m_pTextNode, "SwTextField: where is my TextNode?" );
OSL_ENSURE( pDest->m_pTextNode, "SwTextField: where is pDest's TextNode?" );
// DDE fields need special treatment if( SwFieldIds::Dde == nFieldWhich )
{ if( rDestFormatField.GetTextField() )
{ static_cast<SwDDEFieldType*>(rDestFormatField.GetField()->GetTyp())->DecRefCnt();
} static_cast<SwDDEFieldType*>(pFieldType)->IncRefCnt();
}
OSL_ENSURE( pFieldType, "unknown FieldType" );
pFieldType->Add(rDestFormatField); // register at the field type
rDestFormatField.GetField()->ChgTyp( pFieldType );
}
void SwTextField::NotifyContentChange(SwFormatField& rFormatField)
{ //if not in undo section notify the change if (m_pTextNode && m_pTextNode->GetNodes().IsDocNodes())
m_pTextNode->TriggerNodeUpdate(sw::LegacyModifyHint(nullptr, &rFormatField));
}
// trigger update of fields for scenarios in which the Input Field's content is part of e.g. a table formula
GetTextNode().GetDoc().getIDocumentFieldsAccess().GetUpdateFields().SetFieldsDirty(true);
}
void SwTextInputField::UpdateTextNodeContent( const OUString& rNewContent )
{
assert(IsFieldInDoc() && "<SwTextInputField::UpdateTextNodeContent(..)> - misusage as Input Field is not in document content.");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.