sw/source/core/inc/frmtool.hxx | 11 +++++ sw/source/core/layout/frmtool.cxx | 42 ++++++++++++++++++- sw/source/core/layout/wsfrm.cxx | 80 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 125 insertions(+), 8 deletions(-)
New commits: commit b0e300c54a1ebb0c7ea02f64e16d8b3bf394d9d7 Author: Michael Stahl <[email protected]> AuthorDate: Thu Aug 2 17:09:53 2018 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Thu Aug 2 17:10:25 2018 +0200 sw_redlinehide_2: show/hide flys in redlines The old implementation would not actually hide at-char flys but move the anchor, which is clearly not ideal; better to hide them. Change-Id: If21d0360e04857752a2c84f5329eadfad7818ac8 diff --git a/sw/source/core/inc/frmtool.hxx b/sw/source/core/inc/frmtool.hxx index 0ffe4a75c0f6..e692bb900ef6 100644 --- a/sw/source/core/inc/frmtool.hxx +++ b/sw/source/core/inc/frmtool.hxx @@ -45,6 +45,8 @@ class GraphicAttr; class SwPageDesc; class SwFrameFormats; class SwRegionRects; +class SwTextNode; +namespace sw { struct Extent; } #define FAR_AWAY (SAL_MAX_INT32 - 20000) // initial position of a Fly #define BROWSE_HEIGHT (56700L * 10L) // 10 Meters @@ -55,6 +57,15 @@ class SwRegionRects; void AppendObjs( const SwFrameFormats *pTable, sal_uLong nIndex, SwFrame *pFrame, SwPageFrame *pPage, SwDoc* doc ); +void AppendObjsOfNode(SwFrameFormats const* pTable, sal_uLong nIndex, + SwFrame * pFrame, SwPageFrame * pPage, SwDoc * pDoc, + std::vector<sw::Extent>::const_iterator * pIter, + std::vector<sw::Extent>::const_iterator const* pEnd); + +void RemoveHiddenObjsOfNode(SwTextNode const& rNode, + std::vector<sw::Extent>::const_iterator * pIter, + std::vector<sw::Extent>::const_iterator const* pEnd); + // draw background with brush or graphics // The 6th parameter indicates that the method should consider background // transparency, saved in the color of the brush item. diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx index ad8d07e2cc2f..9581aacb8e9d 100644 --- a/sw/source/core/layout/frmtool.cxx +++ b/sw/source/core/layout/frmtool.cxx @@ -1039,9 +1039,13 @@ static bool IsShown(sal_uLong const nIndex, std::vector<sw::Extent>::const_iterator const*const pEnd) { SwPosition const& rAnchor(*rAnch.GetContentAnchor()); + if (rAnchor.nNode.GetIndex() != nIndex) + { + return false; + } if (pIter && rAnch.GetAnchorId() != RndStdIds::FLY_AT_PARA) { - // TODO are frames sorted by anchor positions perhaps? + // note: frames are not sorted by anchor position. assert(pEnd); assert(rAnch.GetAnchorId() != RndStdIds::FLY_AT_FLY); for ( ; *pIter != *pEnd; ++*pIter) @@ -1049,8 +1053,13 @@ static bool IsShown(sal_uLong const nIndex, assert((**pIter).pNode->GetIndex() == nIndex); if ((**pIter).nStart <= rAnchor.nContent.GetIndex()) { - // TODO off by one? need < for AS_CHAR but what for AT_CHAR? - if (rAnchor.nContent.GetIndex() < (**pIter).nEnd) + // for AS_CHAR obviously must be < + // for AT_CHAR it is questionable whether < or <= should be used + // and there is the additional corner case of Len() to consider + // prefer < for now for symmetry (and inverted usage with + // "hidden") and handle special case explicitly + if (rAnchor.nContent.GetIndex() < (**pIter).nEnd + || (**pIter).nEnd == (**pIter).pNode->Len()) { return true; } @@ -1064,7 +1073,32 @@ static bool IsShown(sal_uLong const nIndex, } else { - return rAnch.GetContentAnchor()->nNode.GetIndex() == nIndex; + return true; + } +} + +void RemoveHiddenObjsOfNode(SwTextNode const& rNode, + std::vector<sw::Extent>::const_iterator *const pIter, + std::vector<sw::Extent>::const_iterator const*const pEnd) +{ + std::vector<SwFrameFormat*> const*const pFlys(rNode.GetAnchoredFlys()); + if (!pFlys) + { + return; + } + for (SwFrameFormat * pFrameFormat : *pFlys) + { + SwFormatAnchor const& rAnchor = pFrameFormat->GetAnchor(); + if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR + || (rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR + && RES_DRAWFRMFMT == pFrameFormat->Which())) + { + assert(rAnchor.GetContentAnchor()->nNode.GetIndex() == rNode.GetIndex()); + if (!IsShown(rNode.GetIndex(), rAnchor, pIter, pEnd)) + { + pFrameFormat->DelFrames(); + } + } } } diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index 68d9e1e418f1..acb2f34f28c5 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -4193,9 +4193,47 @@ static void UnHideRedlines(SwRootFrame & rLayout, rNode.GetRedlineMergeFlag() == SwNode::Merge::NonFirst); if (rNode.IsCreateFrameWhenHidingRedlines()) { - pFrame->SetMergedPara(CheckParaRedlineMerge(*pFrame, - rTextNode, sw::FrameMode::Existing)); - // ??? TODO flys etc. + { + auto pMerged(CheckParaRedlineMerge(*pFrame, + rTextNode, sw::FrameMode::Existing)); + pFrame->SetMergedPara(std::move(pMerged)); + } + if (auto const& pMerged = pFrame->GetMergedPara()) + { + // add visible flys in non-first node to merged frame + // (hidden flys remain and are deleted via DelFrames()) + SwFrameFormats& rTable(*rTextNode.GetDoc()->GetSpzFrameFormats()); + SwPageFrame *const pPage(pFrame->FindPageFrame()); + std::vector<sw::Extent>::const_iterator iterFirst(pMerged->extents.begin()); + std::vector<sw::Extent>::const_iterator iter(iterFirst); + SwTextNode const* pNode(&rTextNode); + for ( ; ; ++iter) + { + if (iter == pMerged->extents.end() + || iter->pNode != pNode) + { + if (pNode == &rTextNode) + { // remove existing hidden at-char anchored flys + RemoveHiddenObjsOfNode( + rTextNode, &iterFirst, &iter); + } + else + { + // pNode's frame has been deleted by CheckParaRedlineMerge() + AppendObjsOfNode(&rTable, + pNode->GetIndex(), pFrame, pPage, + rTextNode.GetDoc(), + &iterFirst, &iter); + } + if (iter == pMerged->extents.end()) + { + break; + } + pNode = iter->pNode; + iterFirst = iter; + } + } + } } } else @@ -4211,11 +4249,45 @@ static void UnHideRedlines(SwRootFrame & rLayout, if (rExtent.pNode != pNode) { sw::RemoveFootnotesForNode(*pFrame, *rExtent.pNode, nullptr); + // similarly, remove the anchored flys + if (auto const pFlys = rExtent.pNode->GetAnchoredFlys()) + { + for (SwFrameFormat * pFormat : *pFlys) + { + pFormat->DelFrames(/*&rLayout*/); + } + } pNode = rExtent.pNode; } } + // add all flys in first node that are hidden + std::vector<sw::Extent> hidden; + sal_Int32 nLast(0); + for (auto const& rExtent : pMergedPara->extents) + { + if (rExtent.pNode != &rTextNode) + { + break; + } + if (rExtent.nStart != 0) + { + assert(rExtent.nStart != nLast); + + hidden.emplace_back(&rTextNode, nLast, rExtent.nStart); + } + nLast = rExtent.nEnd; + } + if (nLast != rTextNode.Len()) + { + hidden.emplace_back(&rTextNode, nLast, rTextNode.Len()); + } + SwFrameFormats& rTable(*rTextNode.GetDoc()->GetSpzFrameFormats()); + auto iterBegin(hidden.cbegin()); + auto const iterEnd(hidden.cend()); + AppendObjsOfNode(&rTable, rTextNode.GetIndex(), pFrame, + pFrame->FindPageFrame(), rTextNode.GetDoc(), + &iterBegin, &iterEnd); pFrame->SetMergedPara(nullptr); - // ??? TODO flys etc. // ??? TODO recreate? or is invalidate enough? } } _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
