From 57cbadcd84bff198811629470f0554396b041f40 Mon Sep 17 00:00:00 2001 From: Mike Kaganski Date: Tue, 9 Mar 2021 12:59:41 +0300 Subject: tdf#40427: use node index as position, not Y position on screen As mentioned in comment to SwContent::nYPosition in sw/source/uibase/inc/swcont.hxx: some subclasses appear to use this for a tools/gen.hxx-style geometric Y position, while e.g. SwOutlineContent wants to store the index in its subtree Abusing the nYPosition to store vertical position *on screen* gives wrong results when a following section is positioned on screen higher than a previous section - e.g., when multiple-page view is active. So just use the section's node as Y position of the Navigator entry. When the section is inside a fly frame, use the frame's anchor node. Change-Id: I6caf26aeb19d845129dc837138c37f42bbc18655 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112197 Tested-by: Jenkins Reviewed-by: Mike Kaganski Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112283 Tested-by: Jenkins CollaboraOffice --- sw/source/uibase/utlui/content.cxx | 61 ++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/sw/source/uibase/utlui/content.cxx b/sw/source/uibase/utlui/content.cxx index 85e6d4559608..06c4795a6531 100644 --- a/sw/source/uibase/utlui/content.cxx +++ b/sw/source/uibase/utlui/content.cxx @@ -268,6 +268,26 @@ namespace return false; } + +// Gets "YPos" for SwRegionContent, i.e. a number used to sort sections in Navigator's list +long getYPosForSection(const SwNodeIndex& rNodeIndex) +{ + sal_uLong nIndex = rNodeIndex.GetIndex(); + if (rNodeIndex.GetNodes().GetEndOfExtras().GetIndex() >= nIndex) + { + // Not a node of BodyText + // Are we in a fly? + if (const auto pFlyFormat = rNodeIndex.GetNode().GetFlyFormat()) + { + // Get node index of anchor + if (auto pSwPosition = pFlyFormat->GetAnchor().GetContentAnchor()) + { + nIndex = getYPosForSection(pSwPosition->nNode); + } + } + } + return static_cast(nIndex); +} } // end of anonymous namespace SwContentType::SwContentType(SwWrtShell* pShell, ContentTypeId nType, sal_uInt8 nLevel) : @@ -359,18 +379,20 @@ void SwContentType::Init(bool* pbInvalidateWindow) pOldMember = std::move(m_pMember); m_pMember.reset( new SwContentArr ); } - const Point aNullPt; m_nMemberCount = m_pWrtShell->GetSectionFormatCount(); for(size_t i = 0; i < m_nMemberCount; ++i) { - const SwSectionFormat* pFormat; - SectionType eTmpType; - if( (pFormat = &m_pWrtShell->GetSectionFormat(i))->IsInNodesArr() && - (eTmpType = pFormat->GetSection()->GetType()) != TOX_CONTENT_SECTION - && TOX_HEADER_SECTION != eTmpType ) + const SwSectionFormat* pFormat = &m_pWrtShell->GetSectionFormat(i); + if (!pFormat->IsInNodesArr()) + continue; + const SwSection* pSection = pFormat->GetSection(); + if (SectionType eTmpType = pSection->GetType(); + eTmpType == TOX_CONTENT_SECTION || eTmpType == TOX_HEADER_SECTION) + continue; + const SwNodeIndex* pNodeIndex = pFormat->GetContent().GetContentIdx(); + if (pNodeIndex) { - const OUString& rSectionName = - pFormat->GetSection()->GetSectionName(); + const OUString& rSectionName = pSection->GetSectionName(); sal_uInt8 nLevel = 0; SwSectionFormat* pParentFormat = pFormat->GetParent(); while(pParentFormat) @@ -380,8 +402,7 @@ void SwContentType::Init(bool* pbInvalidateWindow) } std::unique_ptr pCnt(new SwRegionContent(this, rSectionName, - nLevel, - pFormat->FindLayoutRect( false, &aNullPt ).Top())); + nLevel, getYPosForSection(*pNodeIndex))); SwPtrMsgPoolItem aAskItem( RES_CONTENT_VISIBLE, nullptr ); if( !pFormat->GetInfo( aAskItem ) && @@ -664,17 +685,20 @@ void SwContentType::FillMemberList(bool* pbLevelOrVisibilityChanged) break; case ContentTypeId::REGION : { - const Point aNullPt; m_nMemberCount = m_pWrtShell->GetSectionFormatCount(); for(size_t i = 0; i < m_nMemberCount; ++i) { - const SwSectionFormat* pFormat; - SectionType eTmpType; - if( (pFormat = &m_pWrtShell->GetSectionFormat(i))->IsInNodesArr() && - (eTmpType = pFormat->GetSection()->GetType()) != TOX_CONTENT_SECTION - && TOX_HEADER_SECTION != eTmpType ) + const SwSectionFormat* pFormat = &m_pWrtShell->GetSectionFormat(i); + if (!pFormat->IsInNodesArr()) + continue; + const SwSection* pSection = pFormat->GetSection(); + if (SectionType eTmpType = pSection->GetType(); + eTmpType == TOX_CONTENT_SECTION || eTmpType == TOX_HEADER_SECTION) + continue; + const SwNodeIndex* pNodeIndex = pFormat->GetContent().GetContentIdx(); + if (pNodeIndex) { - OUString sSectionName = pFormat->GetSection()->GetSectionName(); + const OUString& sSectionName = pSection->GetSectionName(); sal_uInt8 nLevel = 0; SwSectionFormat* pParentFormat = pFormat->GetParent(); @@ -685,8 +709,7 @@ void SwContentType::FillMemberList(bool* pbLevelOrVisibilityChanged) } std::unique_ptr pCnt(new SwRegionContent(this, sSectionName, - nLevel, - pFormat->FindLayoutRect( false, &aNullPt ).Top())); + nLevel, getYPosForSection(*pNodeIndex))); if( !pFormat->GetInfo( aAskItem ) && !aAskItem.pObject ) // not visible pCnt->SetInvisible(); -- cgit