diff options
author | Michael Stahl <Michael.Stahl@cib.de> | 2018-07-27 18:25:59 +0200 |
---|---|---|
committer | Michael Stahl <Michael.Stahl@cib.de> | 2018-09-19 10:18:22 +0200 |
commit | b9067209c2aa3213ca7ef19161137bba77130707 (patch) | |
tree | 8f4ab33efbdcef68728a7b4827dffb3296eb6aa1 /sw/source/core/layout/wsfrm.cxx | |
parent | 2d3fa051ada34bc0267736a80e72b7731eb2b07f (diff) |
sw_redlinehide_2: improve SwRootFrame::SetHideRedlines()
Change-Id: If54585d20bbe0fbf5c071e3a96737015d7d62c05
Diffstat (limited to 'sw/source/core/layout/wsfrm.cxx')
-rw-r--r-- | sw/source/core/layout/wsfrm.cxx | 162 |
1 files changed, 135 insertions, 27 deletions
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index e1b388914bc9..b12817a4760e 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -30,6 +30,7 @@ #include <viewopt.hxx> #include <IDocumentSettingAccess.hxx> #include <IDocumentFieldsAccess.hxx> +#include <IDocumentRedlineAccess.hxx> #include <fesh.hxx> #include <docsh.hxx> #include <ftninfo.hxx> @@ -4154,37 +4155,23 @@ void SwRootFrame::InvalidateAllObjPos() } } -void SwRootFrame::SetHideRedlines(bool const bHideRedlines) +static void UnHideRedlines(SwRootFrame & rLayout, + SwNodes & rNodes, SwNode const& rEndOfSectionNode) { - if (bHideRedlines == mbHideRedlines) - { - return; - } - mbHideRedlines = bHideRedlines; - SwNodes const& rNodes(GetFormat()->GetDoc()->GetNodes()); - // Hide->Show: clear MergedPara, create frames - // Show->Hide: call CheckParaRedlineMerge, delete frames - // TODO how to traverse - // * via layout - // - but that won't find nodes that don't have frames in ->Show case - // * via nodes - // - what about special sections before content? flys? footnotes? - // is order of these predictable? flys not anchored in content? - // * ideally should call something existing that tries to create everything? - // - is that done automatically somewhere already? - // * other direction ->Hide - delete frames! - // in-order traversal should init flags in nodes *before* the nodes are found - for (sal_uLong i = 0; i < rNodes.Count(); ++i) + assert(rEndOfSectionNode.IsEndNode()); + assert(rNodes[rEndOfSectionNode.StartOfSectionNode()->GetIndex() + 1]->IsCreateFrameWhenHidingRedlines()); // first node is never hidden + for (sal_uLong i = rEndOfSectionNode.StartOfSectionNode()->GetIndex() + 1; + i < rEndOfSectionNode.GetIndex(); ++i) { - SwNode *const pNode(rNodes[i]); - if (pNode->IsTextNode()) + SwNode & rNode(*rNodes[i]); + if (rNode.IsTextNode()) // only text nodes are 1st node of a merge { - SwTextNode & rTextNode(*pNode->GetTextNode()); + SwTextNode & rTextNode(*rNode.GetTextNode()); SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(rTextNode); std::vector<SwTextFrame*> frames; for (SwTextFrame * pFrame = aIter.First(); pFrame; pFrame = aIter.Next()) { - if (pFrame->getRootFrame() == this) + if (pFrame->getRootFrame() == &rLayout) { frames.push_back(pFrame); } @@ -4192,21 +4179,142 @@ void SwRootFrame::SetHideRedlines(bool const bHideRedlines) // this messes with pRegisteredIn so do it outside SwIterator for (SwTextFrame * pFrame : frames) { - if (mbHideRedlines && pNode->IsCreateFrameWhenHidingRedlines()) + if (rLayout.IsHideRedlines()) { - pFrame->SetMergedPara(CheckParaRedlineMerge(*pFrame, rTextNode)); + assert(!pFrame->GetMergedPara() || + rNode.GetRedlineMergeFlag() == SwNode::Merge::NonFirst); + if (rNode.IsCreateFrameWhenHidingRedlines()) + { + pFrame->SetMergedPara(CheckParaRedlineMerge(*pFrame, rTextNode)); + // ??? TODO flys etc. + } } else { if (pFrame->GetMergedPara()) { pFrame->SetMergedPara(nullptr); - rTextNode.DelFrames(); // FIXME only those in this layout? + // ??? TODO flys etc. + // ??? TODO recreate? or is invalidate enough? + } + } + } + } + if (!rNode.IsCreateFrameWhenHidingRedlines()) + { + if (rLayout.IsHideRedlines()) + { + if (rNode.IsContentNode()) + { + static_cast<SwContentNode&>(rNode).DelFrames(); // FIXME only those in this layout? + } + else if (rNode.IsTableNode()) + { + static_cast<SwTableNode&>(rNode).DelFrames(); // FIXME only those in this layout? + } + else if (rNode.IsSectionNode()) + { + static_cast<SwSectionNode&>(rNode).DelFrames(); // FIXME only those in this layout? + } + } + else + { + sal_uLong j = i + 1; + for ( ; j < rEndOfSectionNode.GetIndex(); ++j) + { + if (rNodes[j]->IsCreateFrameWhenHidingRedlines()) + { + break; } } + // call MakeFrames once, because sections/tables + // InsertCnt_ also checks for hidden sections + SwNodeIndex const start(rNodes, i); + SwNodeIndex const end(rNodes, j); + ::MakeFrames(rLayout.GetFormat()->GetDoc(), start, end); + i = j - 1; // will be incremented again + } + } + } +} + +static void UnHideRedlinesExtras(SwRootFrame & rLayout, + SwNodes & rNodes, SwNode const& rEndOfExtraSectionNode) +{ + assert(rEndOfExtraSectionNode.IsEndNode()); + for (sal_uLong i = rEndOfExtraSectionNode.StartOfSectionNode()->GetIndex() + + 1; i < rEndOfExtraSectionNode.GetIndex(); ++i) + { + SwNode const& rStartNode(*rNodes[i]); + assert(rStartNode.IsStartNode()); + assert(rStartNode.GetRedlineMergeFlag() == SwNode::Merge::None); + SwNode const& rEndNode(*rStartNode.EndOfSectionNode()); + i = rEndNode.GetIndex(); + bool bSkip(false); + for (sal_uLong j = rStartNode.GetIndex() + 1; j < i; ++j) + { + // note: SwStartNode has no way to access the frames, so check + // whether the first content-node inside the section has frames + SwNode const& rNode(*rNodes[j]); + if (rNode.IsSectionNode() && + static_cast<SwSectionNode const&>(rNode).GetSection().IsHiddenFlag()) + { // skip hidden sections - they can be inserted in fly-frames :( + j = rNode.EndOfSectionNode()->GetIndex(); + continue; + } + if (rNode.IsContentNode()) + { + SwContentNode const& rCNode(static_cast<SwContentNode const&>(rNode)); + if (!rCNode.getLayoutFrame(&rLayout)) + { // ignore footnote/fly/header/footer with no layout frame + bSkip = true; // they will be created from scratch later if needed + } + break; } } + if (!bSkip) + { + UnHideRedlines(rLayout, rNodes, rEndNode); + } + } +} + +void SwRootFrame::SetHideRedlines(bool const bHideRedlines) +{ + if (bHideRedlines == mbHideRedlines) + { + return; } + mbHideRedlines = bHideRedlines; + SwDoc & rDoc(*GetFormat()->GetDoc()); + if (rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty()) + { + return; + } + // Hide->Show: clear MergedPara, create frames + // Show->Hide: call CheckParaRedlineMerge, delete frames + // Traverse the document via the nodes-array; traversing via the layout + // wouldn't find the nodes that don't have frames in the ->Show case. + // In-order traversal of each nodes array section should init the flags + // in nodes before they are iterated. + // Actual creation of frames should be done with existing functions + // if possible, particularly InsertCnt_() or its wrapper ::MakeFrames(). + SwNodes /*const*/& rNodes(rDoc.GetNodes()); + // Flys/footnotes: must iterate and find all the ones that already exist + // with frames and have redlines inside them; if any don't have frames at + // all, they will be created (if necessary) from scratch and completely by + // MakeFrames(). + // + // Flys before footnotes: because footnotes may contain flys but not + // vice-versa; alas flys may contain flys, so we skip some of them + // if they have already been created from scratch via their anchor flys. + UnHideRedlinesExtras(*this, rNodes, rNodes.GetEndOfAutotext()); + // Footnotes are created automatically (after invalidation etc.) by + // ConnectFootnote(), but need to be deleted manually. Footnotes do not + // occur in flys or headers/footers. + UnHideRedlinesExtras(*this, rNodes, rNodes.GetEndOfInserts()); + UnHideRedlines(*this, rNodes, rNodes.GetEndOfContent()); + InvalidateAllContent(SwInvalidateFlags::Size); // ??? TODO what to invalidate? } |