diff --git a/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx b/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx index 0253e8a93023..3e16a5e0997f 100644 --- a/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx +++ b/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx @@ -211,7 +211,8 @@ IMPL_LINK(SwOutlineContentVisibilityWin, MouseMoveHdl, const MouseEvent&, rMEvt, // for saved outline frame is now disposed. } } - GetEditWin()->SetSavedOutlineFrame(const_cast(GetFrame())); + GetEditWin()->SetSavedOutlineFrame( + static_cast(const_cast(GetFrame()))); } if (!m_bDestroyed && m_aDelayTimer.IsActive()) m_aDelayTimer.Stop(); diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx index 85a47603a971..a820f4731fe1 100644 --- a/sw/source/uibase/docvw/edtwin.cxx +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -3892,40 +3892,56 @@ void SwEditWin::MouseMove(const MouseEvent& _rMEvt) SwContentAtPos aSwContentAtPos(IsAttrAtPos::Outline); if (rSh.GetContentAtPos(PixelToLogic(rMEvt.GetPosPixel()), aSwContentAtPos)) { + // mouse pointer is on an outline paragraph node if(aSwContentAtPos.aFnd.pNode && aSwContentAtPos.aFnd.pNode->IsTextNode()) { - SwContentFrame* pContentFrame = aSwContentAtPos.aFnd.pNode->GetTextNode()->getLayoutFrame(nullptr); + // Get the outline paragraph frame and compare it to the saved ouline frame. If they + // are not the same, remove the fold button from the saved outline frame, if not + // already removed, and then add a fold button to the mouse over outline frame if + // the content is not folded. + SwContentFrame* pContentFrame = + aSwContentAtPos.aFnd.pNode->GetTextNode()->getLayoutFrame(rSh.GetLayout()); if (pContentFrame != m_pSavedOutlineFrame) { - if (m_pSavedOutlineFrame && !m_pSavedOutlineFrame->IsInDtor()) + if (m_pSavedOutlineFrame) { - SwTextNode* pTextNode = - static_cast(m_pSavedOutlineFrame)->GetTextNodeFirst(); - if (pTextNode && rNds.GetOutLineNds().Seek_Entry(pTextNode, &nPos) && - rSh.GetAttrOutlineContentVisible(nPos)) - GetFrameControlsManager().RemoveControlsByType( - FrameControlType::Outline, m_pSavedOutlineFrame); + if (m_pSavedOutlineFrame->isFrameAreaDefinitionValid()) + { + SwTextNode* pTextNode = m_pSavedOutlineFrame->GetTextNodeFirst(); + if (pTextNode && rNds.GetOutLineNds().Seek_Entry(pTextNode, &nPos) && + rSh.GetAttrOutlineContentVisible(nPos)) + { + GetFrameControlsManager().RemoveControlsByType( + FrameControlType::Outline, m_pSavedOutlineFrame); + } + } } - m_pSavedOutlineFrame = pContentFrame; + m_pSavedOutlineFrame = static_cast(pContentFrame); } - // show button + // show fold button if outline content is visible if (rNds.GetOutLineNds().Seek_Entry(aSwContentAtPos.aFnd.pNode->GetTextNode(), &nPos) && rSh.GetAttrOutlineContentVisible(nPos)) GetFrameControlsManager().SetOutlineContentVisibilityButton(pContentFrame); } } - else if (m_pSavedOutlineFrame && !m_pSavedOutlineFrame->IsInDtor()) + else if (m_pSavedOutlineFrame) { - // current pointer pos is not over an outline frame - // previous pointer pos was over an outline frame - // remove outline content visibility button if showing - if (m_pSavedOutlineFrame->isFrameAreaDefinitionValid() && - m_pSavedOutlineFrame->IsTextFrame() && - rNds.GetOutLineNds().Seek_Entry( - static_cast(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos) - && rSh.GetAttrOutlineContentVisible(nPos)) - GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, - m_pSavedOutlineFrame); + // The saved frame may not still be in the document, e.g., when an outline paragraph + // is deleted. This causes the call to GetTextNodeFirst to behave badly. Use + // isFrameAreaDefinitionValid to check if the frame is still in the document. + if (m_pSavedOutlineFrame->isFrameAreaDefinitionValid()) + { + // current pointer pos is not over an outline frame + // previous pointer pos was over an outline frame + // remove outline content visibility button if showing + SwTextNode* pTextNode = m_pSavedOutlineFrame->GetTextNodeFirst(); + if (pTextNode && rNds.GetOutLineNds().Seek_Entry(pTextNode, &nPos) && + rSh.GetAttrOutlineContentVisible(nPos)) + { + GetFrameControlsManager().RemoveControlsByType( + FrameControlType::Outline, m_pSavedOutlineFrame); + } + } m_pSavedOutlineFrame = nullptr; } } @@ -3968,13 +3984,20 @@ void SwEditWin::MouseMove(const MouseEvent& _rMEvt) { if (m_pSavedOutlineFrame && !bInsWin) { - // the mouse pointer has left the building + // the mouse pointer has left the building (edit window) // remove the outline content visibility button if showing - const SwNodes& rNds = rSh.GetDoc()->GetNodes(); - SwOutlineNodes::size_type nPos; - if (rNds.GetOutLineNds().Seek_Entry(static_cast(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos) && - rSh.GetAttrOutlineContentVisible(nPos)) - GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame); + if (m_pSavedOutlineFrame->isFrameAreaDefinitionValid()) + { + const SwNodes& rNds = rSh.GetDoc()->GetNodes(); + SwOutlineNodes::size_type nPos; + SwTextNode* pTextNode = m_pSavedOutlineFrame->GetTextNodeFirst(); + if (pTextNode && rNds.GetOutLineNds().Seek_Entry(pTextNode, &nPos) && + rSh.GetAttrOutlineContentVisible(nPos)) + { + GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, + m_pSavedOutlineFrame); + } + } m_pSavedOutlineFrame = nullptr; } } diff --git a/sw/source/uibase/inc/edtwin.hxx b/sw/source/uibase/inc/edtwin.hxx index 0db0e6d2b35a..108dbfb05307 100644 --- a/sw/source/uibase/inc/edtwin.hxx +++ b/sw/source/uibase/inc/edtwin.hxx @@ -45,6 +45,7 @@ struct QuickHelpData; class SdrDropMarkerOverlay; class SwFrameControlsManager; enum class SdrHitKind; +class SwTextFrame; // input window @@ -127,7 +128,7 @@ class SW_DLLPUBLIC SwEditWin final : public vcl::Window, std::unique_ptr m_pFrameControlsManager; - SwFrame* m_pSavedOutlineFrame = nullptr; + SwTextFrame* m_pSavedOutlineFrame = nullptr; void LeaveArea(const Point &); void JustifyAreaTimer(); @@ -291,8 +292,8 @@ public: /// Allows starting or ending a graphic move or resize action. void SetGraphicTwipPosition(bool bStart, const Point& rPosition); - const SwFrame* GetSavedOutlineFrame() const { return m_pSavedOutlineFrame; } - void SetSavedOutlineFrame(SwFrame* pFrame) { m_pSavedOutlineFrame = pFrame; } + const SwTextFrame* GetSavedOutlineFrame() const { return m_pSavedOutlineFrame; } + void SetSavedOutlineFrame(SwTextFrame* pFrame) { m_pSavedOutlineFrame = pFrame; } void ToggleOutlineContentVisibility(const size_t nOutlinePos, const bool bSubs); virtual FactoryFunction GetUITestFactory() const override;