/* -*- 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 .
*/
/** An overview of how a new SwTextFlyCnt is created: * MakeTextAttr() is called e.g. by SwTextNode::CopyText(). * The following steps are required to clone: * 1) copying the pFormat with content, attributes etc. * 2) setting the anchor * 3) notification * Because not all required information is available at all times, * the steps are distributed variously: * ad 1) MakeTextAttr() calls DocumentLayoutManager::CopyLayoutFormat() * which creates the new SwFlyFrameFormat and copies the content of the * fly frame. * ad 2) SetAnchor() is called by SwTextNode::InsertHint() and sets the anchor * position in the SwFlyFrameFormat to the SwPosition of the dummy * CH_TXTATR_BREAKWORD. This cannot be done in MakeTextAttr() because it * doesn't know the target text node. * ad 3) GetFlyFrame_() is called during text formatting by SwTextFormatter * and searches for the SwFlyFrame for the dummy char of the current * SwTextFrame. If none is found, a new SwFlyInContentFrame is created. * Important: pTextFrame->AppendFly() immediately triggers a reformat * of pTextFrame. However, the recursion is blocked by the lock mechanism * in SwTextFrame::Format(). * The advantage of all this is that it's not necessary to explicitly iterate * over all SwTextFrames that depend on the SwTextNode to create the * SwFlyInContentFrame - this is done automatically already.
*/
void SwTextFlyCnt::CopyFlyFormat( SwDoc& rDoc )
{
SwFrameFormat* pFormat = GetFlyCnt().GetFrameFormat();
assert(pFormat); // The FlyFrameFormat must be copied - CopyLayoutFormat // (DocumentLayoutManager.cxx) creates the FlyFrameFormat and copies the // content.
// disable undo while copying attribute
::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
SwFormatAnchor aAnchor( pFormat->GetAnchor() ); if ((RndStdIds::FLY_AT_PAGE != aAnchor.GetAnchorId()) &&
(&rDoc != &pFormat->GetDoc())) // different documents?
{ // JP 03.06.96: ensure that the copied anchor points to valid content! // setting it to the correct position is done later.
SwNodeIndex aIdx( rDoc.GetNodes().GetEndOfExtras(), +2 );
SwContentNode* pCNd = aIdx.GetNode().GetContentNode(); if( !pCNd )
pCNd = SwNodes::GoNext(&aIdx);
/** SetAnchor() is called by SwTextNode::InsertHint() and sets the anchor * position in the SwFlyFrameFormat to the SwPosition of the dummy * CH_TXTATR_BREAKWORD. This cannot be done in MakeTextAttr() because it * doesn't know the target text node.
*/ void SwTextFlyCnt::SetAnchor( const SwTextNode *pNode )
{ // for Undo, the new anchor must be known already!
// in case of anchor change, delete all FlyFrames // JP 25.04.95: if the Frames can be moved within SplitNode, they don't // need to be deleted if( ( !pNode->GetpSwpHints() || !pNode->GetpSwpHints()->IsInSplitNode() )
&& RES_DRAWFRMFMT != pFormat->Which() )
pFormat->DelFrames();
// copy into a different document? if( &rDoc != &pFormat->GetDoc() )
{ // disable undo while copying attribute
::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
SwFrameFormat* pNew = rDoc.getIDocumentLayoutAccess().CopyLayoutFormat( *pFormat, aAnchor, false, false );
::sw::UndoGuard const undoGuardFormat(
pFormat->GetDoc().GetIDocumentUndoRedo());
pFormat->GetDoc().getIDocumentLayoutAccess().DelLayoutFormat( pFormat ); const_cast<SwFormatFlyCnt&>(GetFlyCnt()).SetFlyFormat( pNew );
} elseif( pNode->GetpSwpHints() &&
pNode->GetpSwpHints()->IsInSplitNode() &&
RES_DRAWFRMFMT != pFormat->Which() )
{
pFormat->LockModify();
pFormat->SetFormatAttr( aAnchor ); // only set the anchor // tdf#91228 must notify the anchor nodes despite LockModify
assert(pOldNode);
pOldNode->RemoveAnchoredFly(pFormat);
oPos->GetNode().AddAnchoredFly(pFormat);
pFormat->UnlockModify();
} else
{
assert(!pFormat->IsModifyLocked()); // need to notify anchor node if (RES_DRAWFRMFMT == pFormat->Which())
{ if (SdrObject const*const pObj = pFormat->FindSdrObject())
{ // tdf#123259 disconnect with *old* anchor position if (SwDrawContact* pContact = static_cast<SwDrawContact*>(::GetUserCall( pObj )))
pContact->DisconnectFromLayout(false);
}
}
pFormat->SetFormatAttr( aAnchor ); // only set the anchor
// If the draw format has a TextBox, then set its anchor as well. if (SwFrameFormat* pTextBox
= SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT))
{
SwFormatAnchor aTextBoxAnchor(pTextBox->GetAnchor());
aTextBoxAnchor.SetAnchor(aAnchor.GetContentAnchor());
// SwFlyAtContentFrame::SwClientNotify() assumes the anchor has a matching layout frame, which // may not be the case when we're in the process of a node split, so block // notifications. bool bIsInSplitNode = pNode->GetpSwpHints() && pNode->GetpSwpHints()->IsInSplitNode(); if (bIsInSplitNode)
{
pTextBox->LockModify();
} else
{ // Otherwise delete fly frames on anchor change.
pTextBox->DelFrames();
}
// The node may have several SwTextFrames - for every SwTextFrame a // SwFlyInContentFrame is created.
}
/** GetFlyFrame_() is called during text formatting by SwTextFormatter * and searches for the SwFlyFrame for the dummy char of the current * SwTextFrame. If none is found, a new SwFlyInContentFrame is created.
*/
SwFlyInContentFrame *SwTextFlyCnt::GetFlyFrame_( const SwFrame *pCurrFrame )
{
SwFrameFormat* pFrameFormat = GetFlyCnt().GetFrameFormat(); if( RES_DRAWFRMFMT == pFrameFormat->Which() )
{
OSL_ENSURE( false, "SwTextFlyCnt::GetFlyFrame_: DrawInCnt-under construction!" ); return nullptr;
}
// We did not find a matching FlyFrame, so create a new one. // AppendFly() triggers a reformat of pCurrentFrame. However, the // recursion is blocked by the lock mechanism in SwTextFrame::Format().
SwFrame* pCurrentFrame = const_cast<SwFrame*>(pCurrFrame);
SwFlyInContentFrame *pFly = new SwFlyInContentFrame(static_cast<SwFlyFrameFormat*>(pFrameFormat), pCurrentFrame, pCurrentFrame);
pCurrentFrame->AppendFly(pFly);
pFly->RegistFlys();
// We must ensure that the content of the FlyInCnt is fully formatted // right after construction. // #i26945# - Use new object formatter to format Writer // fly frame and its content.
SwObjectFormatter::FormatObj( *pFly, const_cast<SwFrame*>(pCurrFrame),
pCurrFrame->FindPageFrame() );
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.