diff options
Diffstat (limited to 'sw')
27 files changed, 518 insertions, 525 deletions
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx index 64a9d34906e2..a7d4d2474613 100644 --- a/sw/source/core/crsr/crsrsh.cxx +++ b/sw/source/core/crsr/crsrsh.cxx @@ -3344,6 +3344,31 @@ void SwCursorShell::SetReadOnlyAvailable( bool bFlag ) bool SwCursorShell::HasReadonlySel() const { + if (GetViewOptions()->IsShowOutlineContentVisibilityButton()) + { + // Treat selections that span over start or end of paragraph of an outline node + // with folded outline content as read-only. + SwWrtShell* pWrtSh = GetDoc()->GetDocShell()->GetWrtShell(); + if (pWrtSh) + { + for(SwPaM& rPaM : GetCursor()->GetRingContainer()) + { + rPaM.Normalize(); + SwNodeIndex aPointIdx(rPaM.GetPoint()->nNode.GetNode()); + SwNodeIndex aMarkIdx(rPaM.GetMark()->nNode.GetNode()); + if (aPointIdx == aMarkIdx) + continue; + // If any nodes in PaM are folded outline content nodes, then set read-only. + SwOutlineNodes::size_type nPos; + for (SwNodeIndex aIdx = aPointIdx; aIdx <= aMarkIdx; aIdx++) + { + if (GetDoc()->GetNodes().GetOutLineNds().Seek_Entry(&(aIdx.GetNode()), &nPos) && + !pWrtSh->GetAttrOutlineContentVisible(nPos)) + return true; + } + } + } + } bool bRet = false; // If protected area is to be ignored, then selections are never read-only. if ((IsReadOnlyAvailable() || GetViewOptions()->IsFormView() || diff --git a/sw/source/core/crsr/swcrsr.cxx b/sw/source/core/crsr/swcrsr.cxx index a2c4264f6301..69388177ab28 100644 --- a/sw/source/core/crsr/swcrsr.cxx +++ b/sw/source/core/crsr/swcrsr.cxx @@ -57,6 +57,8 @@ #include <comphelper/lok.hxx> #include <editsh.hxx> +#include <viewopt.hxx> + using namespace ::com::sun::star::i18n; const sal_uInt16 coSrchRplcThreshold = 60000; @@ -1798,7 +1800,19 @@ bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, } if ( !Move( fnMove, fnGo ) ) + { + SwEditShell* rSh = GetDoc().GetEditShell(); + if (rSh && rSh->GetViewOptions() && + rSh->GetViewOptions()->IsShowOutlineContentVisibilityButton()) + // Fixes crash that occurs in documents with outline content folded at the end of + // the document. When the cursor is at the end of the visible document and + // right arrow key is pressed Move fails after moving the cursor to the + // end of the document model, which doesn't have a node frame and causes + // wierd numbers to be displayed in the statusbar page number count. Left + // arrow, when in this state, causes a crash without RestoredSavePos() added here. + RestoreSavePos(); break; + } if (pFrame) { diff --git a/sw/source/core/doc/docnum.cxx b/sw/source/core/doc/docnum.cxx index b0bffd31c205..5e287e84f19d 100644 --- a/sw/source/core/doc/docnum.cxx +++ b/sw/source/core/doc/docnum.cxx @@ -55,6 +55,7 @@ #include <map> #include <stdlib.h> +#include <wrtsh.hxx> namespace { void lcl_ResetIndentAttrs(SwDoc *pDoc, const SwPaM &rPam, sal_uInt16 marker, @@ -1825,6 +1826,8 @@ bool SwDoc::NumUpDown(const SwPaM& rPam, bool bDown, SwRootFrame const*const pLa // it will expand its selection to include full SwTextFrames. bool SwDoc::MoveParagraph(SwPaM& rPam, tools::Long nOffset, bool const bIsOutlMv) { + MakeAllOutlineContentTemporarilyVisible a(this); + // sw_redlinehide: as long as a layout with Hide mode exists, only // move nodes that have merged frames *completely* SwRootFrame const* pLayout(nullptr); diff --git a/sw/source/core/edit/ednumber.cxx b/sw/source/core/edit/ednumber.cxx index 38582a4143e3..af7ec8178e41 100644 --- a/sw/source/core/edit/ednumber.cxx +++ b/sw/source/core/edit/ednumber.cxx @@ -394,55 +394,8 @@ void SwEditShell::SetIndent(short nIndent, const SwPosition & rPos) EndAllAction(); } -namespace -{ -class MakeAllOutlineContentTemporarilyVisibile -{ -private: - SwWrtShell* pWrtShell; - std::vector<SwNode*> aOutlineNdsArray; -public: - MakeAllOutlineContentTemporarilyVisibile(SwWrtShell* pShell) - : pWrtShell(pShell) - { - if (!(pWrtShell && pWrtShell->GetViewOptions() && pWrtShell->GetViewOptions()->IsShowOutlineContentVisibilityButton())) - return; - - // make all outlines content visible and store outline nodes having - // content visible attribute value false - SwOutlineNodes rOutlineNds = pWrtShell->GetNodes().GetOutLineNds(); - for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNds.size(); ++nPos) - { - SwNode* pNd = rOutlineNds[nPos]; - if (pNd->IsTextNode()) // should always be true - { - bool bOutlineContentVisibleAttr = true; - pNd->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr); - if (!bOutlineContentVisibleAttr) - { - aOutlineNdsArray.push_back(pNd); - pWrtShell->ToggleOutlineContentVisibility(nPos); - } - } - } - } - - ~MakeAllOutlineContentTemporarilyVisibile() COVERITY_NOEXCEPT_FALSE - { - if (!pWrtShell) - return; - // restore outlines content visibility - for (SwNode* pNd : aOutlineNdsArray) - pWrtShell->ToggleOutlineContentVisibility(pNd, true); - } -}; -} - bool SwEditShell::MoveParagraph( tools::Long nOffset ) { - // make all outline nodes content temporarily visible for paragraph move - MakeAllOutlineContentTemporarilyVisibile a(dynamic_cast<SwWrtShell*>(this)); - StartAllAction(); SwPaM *pCursor = GetCursor(); diff --git a/sw/source/core/edit/edundo.cxx b/sw/source/core/edit/edundo.cxx index a55f45651fba..bfadd01aaffd 100644 --- a/sw/source/core/edit/edundo.cxx +++ b/sw/source/core/edit/edundo.cxx @@ -35,6 +35,8 @@ #include <docsh.hxx> #include <pagefrm.hxx> +#include <wrtsh.hxx> + /** helper function to select all objects in an SdrMarkList; * implementation: see below */ static void lcl_SelectSdrMarkList( SwEditShell* pShell, @@ -96,6 +98,8 @@ void SwEditShell::HandleUndoRedoContext(::sw::UndoRedoContext & rContext) void SwEditShell::Undo(sal_uInt16 const nCount) { + MakeAllOutlineContentTemporarilyVisible a(GetDoc()); + CurrShell aCurr( this ); // current undo state was not saved @@ -152,6 +156,8 @@ void SwEditShell::Undo(sal_uInt16 const nCount) void SwEditShell::Redo(sal_uInt16 const nCount) { + MakeAllOutlineContentTemporarilyVisible a(GetDoc()); + CurrShell aCurr( this ); bool bRet = false; diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx index 1473697a07ad..abef52f448aa 100644 --- a/sw/source/core/inc/txtfrm.hxx +++ b/sw/source/core/inc/txtfrm.hxx @@ -46,6 +46,7 @@ class SwPortionHandler; class SwScriptInfo; enum class ExpandMode; class SwTextAttr; +class SwWrtShell; #define NON_PRINTING_CHARACTER_COLOR Color(0x26, 0x8b, 0xd2) @@ -319,6 +320,9 @@ class SW_DLLPUBLIC SwTextFrame: public SwContentFrame virtual void DestroyImpl() override; virtual ~SwTextFrame() override; + void UpdateOutlineContentVisibilityButton(SwWrtShell* pWrtSh) const; + void PaintOutlineContentVisibilityButton() const; + protected: virtual void SwClientNotify(SwModify const& rModify, SfxHint const& rHint) override; diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx index 557bc2414e63..14a73d4d5869 100644 --- a/sw/source/core/layout/frmtool.cxx +++ b/sw/source/core/layout/frmtool.cxx @@ -3827,7 +3827,9 @@ bool IsExtraData( const SwDoc *pDoc ) return rInf.IsPaintLineNumbers() || rInf.IsCountInFlys() || (static_cast<sal_Int16>(SW_MOD()->GetRedlineMarkPos()) != text::HoriOrientation::NONE && - !pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty()); + !pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty()) || + (pDoc->GetEditShell() && pDoc->GetEditShell()->GetViewOptions() && + pDoc->GetEditShell()->GetViewOptions()->IsShowOutlineContentVisibilityButton()); } // OD 22.09.2003 #110978# diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index 9e5cd3a16c05..27cbf1b4a997 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -4247,6 +4247,14 @@ void SwFlyFrame::PaintDecorators() const } } +void SwTextFrame::PaintOutlineContentVisibilityButton() const +{ + SwWrtShell* pWrtSh = dynamic_cast<SwWrtShell*>(gProp.pSGlobalShell); + if (pWrtSh && pWrtSh->GetViewOptions()->IsShowOutlineContentVisibilityButton()) + UpdateOutlineContentVisibilityButton(pWrtSh); +} + + void SwTabFrame::PaintSwFrame(vcl::RenderContext& rRenderContext, SwRect const& rRect, SwPrintData const*const) const { const SwViewOption* pViewOption = gProp.pSGlobalShell->GetViewOptions(); diff --git a/sw/source/core/text/frmpaint.cxx b/sw/source/core/text/frmpaint.cxx index 6f1d1fc12ad1..7f35ea7633b6 100644 --- a/sw/source/core/text/frmpaint.cxx +++ b/sw/source/core/text/frmpaint.cxx @@ -305,6 +305,8 @@ void SwTextFrame::PaintExtraData( const SwRect &rRect ) const if( getFrameArea().Top() > rRect.Bottom() || getFrameArea().Bottom() < rRect.Top() ) return; + PaintOutlineContentVisibilityButton(); + SwDoc const& rDoc(GetDoc()); const IDocumentRedlineAccess& rIDRA = rDoc.getIDocumentRedlineAccess(); const SwLineNumberInfo &rLineInf = rDoc.GetLineNumberInfo(); diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx index acd1b1b4f5be..6a91cfd36a3d 100644 --- a/sw/source/core/text/txtfrm.cxx +++ b/sw/source/core/text/txtfrm.cxx @@ -71,6 +71,10 @@ #include <ftnidx.hxx> #include <ftnfrm.hxx> +#include <wrtsh.hxx> +#include <view.hxx> +#include <edtwin.hxx> +#include <FrameControlsManager.hxx> namespace sw { @@ -878,6 +882,12 @@ void SwTextFrame::DestroyImpl() } } + if (!GetDoc().IsInDtor()) + { + if (SwView* pView = GetActiveView()) + pView->GetEditWin().GetFrameControlsManager().RemoveControls(this); + } + SwContentFrame::DestroyImpl(); } @@ -4024,4 +4034,15 @@ void SwTextFrame::repaintTextFrames( const SwTextNode& rNode ) } } +void SwTextFrame::UpdateOutlineContentVisibilityButton(SwWrtShell* pWrtSh) const +{ + if (pWrtSh && pWrtSh->GetViewOptions()->IsShowOutlineContentVisibilityButton() && + GetTextNodeFirst()->IsOutline()) + { + SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin(); + SwFrameControlsManager& rMngr = rEditWin.GetFrameControlsManager(); + rMngr.SetOutlineContentVisibilityButton(this); + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/appopt.cxx b/sw/source/uibase/app/appopt.cxx index 9862da388021..1b22068ebe7f 100644 --- a/sw/source/uibase/app/appopt.cxx +++ b/sw/source/uibase/app/appopt.cxx @@ -261,51 +261,23 @@ void SwModule::ApplyItemSet( sal_uInt16 nId, const SfxItemSet& rSet ) } // Elements - interpret Item - std::vector<SwNode*> aFoldedOutlineNdsArray; - bool bShow = false; + bool bFlag = true; if( SfxItemState::SET == rSet.GetItemState( FN_PARAM_ELEM, false, &pItem ) ) { const SwElemItem* pElemItem = static_cast<const SwElemItem*>(pItem); pElemItem->FillViewOptions( aViewOpt ); SwWrtShell* pWrtShell = GetActiveWrtShell(); - bShow = pWrtShell->GetViewOptions()->IsShowOutlineContentVisibilityButton(); + bFlag = pWrtShell->GetViewOptions()->IsShowOutlineContentVisibilityButton(); bool bTreatSubsChanged = aViewOpt.IsTreatSubOutlineLevelsAsContent() != pWrtShell->GetViewOptions()->IsTreatSubOutlineLevelsAsContent(); - - // move cursor to top if something with the outline mode changed - if ((bShow != aViewOpt.IsShowOutlineContentVisibilityButton()) || - (pWrtShell->GetViewOptions()->IsTreatSubOutlineLevelsAsContent() != - aViewOpt.IsTreatSubOutlineLevelsAsContent())) - { - // move cursor to top of document - if (pWrtShell->IsSelFrameMode()) - { - pWrtShell->UnSelectFrame(); - pWrtShell->LeaveSelFrameMode(); - } - pWrtShell->EnterStdMode(); - pWrtShell->SttEndDoc(true); - } - - if (bShow && (!aViewOpt.IsShowOutlineContentVisibilityButton() || bTreatSubsChanged)) + if (bFlag && (!aViewOpt.IsShowOutlineContentVisibilityButton() || bTreatSubsChanged)) { // outline mode options have change which require to show all content - const SwOutlineNodes& rOutlineNds = pWrtShell->GetNodes().GetOutLineNds(); - for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNds.size(); ++nPos) - { - SwNode* pNd = rOutlineNds[nPos]; - if (pNd->IsTextNode()) // should always be true - { - bool bOutlineContentVisibleAttr = true; - pNd->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr); - if (!bOutlineContentVisibleAttr) - { - aFoldedOutlineNdsArray.push_back(pNd); - pWrtShell->ToggleOutlineContentVisibility(nPos); - } - } - } + pWrtShell->MakeAllFoldedOutlineContentVisible(); + + if (bTreatSubsChanged) + bFlag = false; // folding method changed, set bFlag false to refold below } } @@ -429,21 +401,8 @@ void SwModule::ApplyItemSet( sal_uInt16 nId, const SfxItemSet& rSet ) if (SfxItemState::SET != rSet.GetItemState(FN_PARAM_ELEM, false)) return; - if (!GetActiveWrtShell()->GetViewOptions()->IsShowOutlineContentVisibilityButton()) - { - // outline mode is no longer active - // set outline content visible attribute to false for nodes in the array - for (SwNode* pNd : aFoldedOutlineNdsArray) - pNd->GetTextNode()->SetAttrOutlineContentVisible(false); - } - else if (bShow) - { - // outline mode remained active - // sub level treatment might have changed - // ToggleOutlineContentVisibility only knows sub level treatment after ApplyUserPref - for (SwNode* pNd : aFoldedOutlineNdsArray) - GetActiveWrtShell()->ToggleOutlineContentVisibility(pNd, true); - } + if (!bFlag) + GetActiveWrtShell()->MakeAllFoldedOutlineContentVisible(false); } std::unique_ptr<SfxTabPage> SwModule::CreateTabPage( sal_uInt16 nId, weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet ) diff --git a/sw/source/uibase/app/docst.cxx b/sw/source/uibase/app/docst.cxx index aceb1c548ded..654ff05a0650 100644 --- a/sw/source/uibase/app/docst.cxx +++ b/sw/source/uibase/app/docst.cxx @@ -1108,6 +1108,8 @@ void SwDocShell::Hide(const OUString &rName, SfxStyleFamily nFamily, bool bHidde SfxStyleFamily SwDocShell::ApplyStyles(const OUString &rName, SfxStyleFamily nFamily, SwWrtShell* pShell, const sal_uInt16 nMode ) { + MakeAllOutlineContentTemporarilyVisible a(GetDoc()); + SwDocStyleSheet* pStyle = static_cast<SwDocStyleSheet*>( m_xBasePool->Find( rName, nFamily ) ); SAL_WARN_IF( !pStyle, "sw.ui", "Style not found" ); diff --git a/sw/source/uibase/docvw/FrameControlsManager.cxx b/sw/source/uibase/docvw/FrameControlsManager.cxx index 622d5fced30b..9b6cbdf2a8db 100644 --- a/sw/source/uibase/docvw/FrameControlsManager.cxx +++ b/sw/source/uibase/docvw/FrameControlsManager.cxx @@ -40,7 +40,6 @@ SwFrameControlsManager::~SwFrameControlsManager() void SwFrameControlsManager::dispose() { m_aControls.clear(); - m_aTextNodeContentFrameMap.clear(); } SwFrameControlPtr SwFrameControlsManager::GetControl( FrameControlType eType, const SwFrame* pFrame ) @@ -188,64 +187,8 @@ SwFrameMenuButtonBase::SwFrameMenuButtonBase(SwEditWin* pEditWin, const SwFrame* { } -void SwFrameControlsManager::SetOutlineContentVisibilityButtons() +void SwFrameControlsManager::SetOutlineContentVisibilityButton(const SwContentFrame* pContentFrame) { - // remove entries with outline node keys that are not in the outline nodes list - IDocumentOutlineNodes::tSortedOutlineNodeList aOutlineNodes; - m_pEditWin->GetView().GetWrtShell().getIDocumentOutlineNodesAccess()->getOutlineNodes(aOutlineNodes); - std::map<const SwTextNode*, const SwContentFrame*>::iterator it = m_aTextNodeContentFrameMap.begin(); - while(it != m_aTextNodeContentFrameMap.end()) - { - const SwNode* pNd = it->first; - IDocumentOutlineNodes::tSortedOutlineNodeList::iterator i = std::find(aOutlineNodes.begin(), aOutlineNodes.end(), pNd); - if (i == aOutlineNodes.end()) - { - RemoveControlsByType(FrameControlType::Outline, it->second); - it = m_aTextNodeContentFrameMap.erase(it); - } - else - ++it; - } - for (SwNode* pNd : m_pEditWin->GetView().GetWrtShell().GetNodes().GetOutLineNds()) - { - bool bOutlineContentVisibleAttr = true; - pNd->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr); - if (!bOutlineContentVisibleAttr) - SetOutlineContentVisibilityButton(pNd->GetTextNode()); - } -} - -void SwFrameControlsManager::SetOutlineContentVisibilityButton(const SwTextNode* pTextNd) -{ - const SwContentFrame* pContentFrame = pTextNd->getLayoutFrame(nullptr); - - // has node frame changed or been deleted? - std::map<const SwTextNode*, const SwContentFrame*>::iterator iter = m_aTextNodeContentFrameMap.find(pTextNd); - if (iter != m_aTextNodeContentFrameMap.end()) - { - const SwContentFrame* pFrameWas = iter->second; - if (pContentFrame != pFrameWas) - { - // frame does not match frame in map for node - RemoveControlsByType(FrameControlType::Outline, pFrameWas); - m_aTextNodeContentFrameMap.erase(iter); - } - } - if (pContentFrame && !pContentFrame->IsInDtor()) - { - // frame is not being destroyed and isn't in map - m_aTextNodeContentFrameMap.insert(make_pair(pTextNd, pContentFrame)); - } - else - { - if (pContentFrame) - { - // frame is being destroyed - RemoveControlsByType(FrameControlType::Outline, pContentFrame); - } - return; - } - // Check if we already have the control SwFrameControlPtr pControl; @@ -266,48 +209,10 @@ void SwFrameControlsManager::SetOutlineContentVisibilityButton(const SwTextNode* } SwOutlineContentVisibilityWin* pWin = dynamic_cast<SwOutlineContentVisibilityWin *>(pControl->GetWindow()); - assert(pWin != nullptr) ; pWin->Set(); if (pWin->GetSymbol() == ButtonSymbol::SHOW) - { - // show expand button immediately - pWin->Show(); - /* - The outline content might be visible here. This happens on document load, - undo outline moves, and show of outline content that itself has outline nodes - having outline content visibility attribute false, for example tables and text - frames containing outline nodes. - */ - SwOutlineNodes::size_type nPos; - SwOutlineNodes rOutlineNds = m_pEditWin->GetView().GetWrtShell().GetNodes().GetOutLineNds(); - if (rOutlineNds.Seek_Entry(const_cast<SwTextNode*>(pTextNd), &nPos)) - { - SwNodeIndex aIdx(*pTextNd, +1); - // there shouldn't be a layout frame - // if there is then force visibility false - if (!m_pEditWin->GetView().GetWrtShell().GetViewOptions()->IsTreatSubOutlineLevelsAsContent()) - { - if (!(aIdx.GetNode().IsEndNode() || - (nPos + 1 < rOutlineNds.size() && &aIdx.GetNode() == rOutlineNds[nPos +1])) - && aIdx.GetNode().IsContentNode() - // this determines if the content is really visible - && aIdx.GetNode().GetContentNode()->getLayoutFrame(nullptr)) - { - // force outline content visibility false - m_pEditWin->GetView().GetWrtShell().ToggleOutlineContentVisibility(nPos, true); - } - } - else if (!aIdx.GetNode().IsEndNode() - && aIdx.GetNode().IsContentNode() - // this determines if the content is really visible - && aIdx.GetNode().GetContentNode()->getLayoutFrame(nullptr)) - { - // force outline content visibility false - m_pEditWin->GetView().GetWrtShell().ToggleOutlineContentVisibility(nPos, true); - } - } - } + pWin->Show(); // show the SHOW button immediately else if (!pWin->IsVisible() && pWin->GetSymbol() == ButtonSymbol::HIDE) pWin->ShowAll(true); } diff --git a/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx b/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx index a50832c3385f..d511812f4278 100644 --- a/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx +++ b/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx @@ -107,28 +107,17 @@ void SwOutlineContentVisibilityWin::SetSymbol(ButtonSymbol eStyle) void SwOutlineContentVisibilityWin::Set() { const SwTextFrame* pTextFrame = static_cast<const SwTextFrame*>(GetFrame()); - - // outline node frame containing folded outline node content might be folded so need to hide it - if (!pTextFrame || pTextFrame->IsInDtor()) - { - SetSymbol(ButtonSymbol::NONE); - Hide(); - return; - } const SwTextNode* pTextNode = pTextFrame->GetTextNodeFirst(); SwWrtShell& rSh = GetEditWin()->GetView().GetWrtShell(); const SwOutlineNodes& rOutlineNodes = rSh.GetNodes().GetOutLineNds(); - if (!pTextNode - || !rOutlineNodes.Seek_Entry(static_cast<SwNode*>(const_cast<SwTextNode*>(pTextNode)), - &m_nOutlinePos) - || m_nOutlinePos == SwOutlineNodes::npos) - { - assert(false); // should never get here - return; - } + + rOutlineNodes.Seek_Entry(static_cast<SwNode*>(const_cast<SwTextNode*>(pTextNode)), + &m_nOutlinePos); // set symbol displayed on button - SetSymbol(rSh.IsOutlineContentVisible(m_nOutlinePos) ? ButtonSymbol::HIDE : ButtonSymbol::SHOW); + bool bVisible = true; + const_cast<SwTextNode*>(pTextNode)->GetAttrOutlineContentVisible(bVisible); + SetSymbol(bVisible ? ButtonSymbol::HIDE : ButtonSymbol::SHOW); // set quick help SwOutlineNodes::size_type nOutlineNodesCount @@ -147,11 +136,11 @@ void SwOutlineContentVisibilityWin::Set() SwRect aCharRect; GetFrame()->GetCharRect(aCharRect, SwPosition(*pTextNode)); Point aPxPt(GetEditWin()->GetOutDev()->LogicToPixel( - Point(aCharRect.Right(), aFrameAreaRect.Center().getY()))); + Point(aCharRect.Left(), aFrameAreaRect.Center().getY()))); if (GetFrame()->IsRightToLeft()) - aPxPt.AdjustX(5); + aPxPt.AdjustX(2); else - aPxPt.AdjustX(-(GetSizePixel().getWidth() + 5)); + aPxPt.AdjustX(-(GetSizePixel().getWidth() + 2)); aPxPt.AdjustY(-GetSizePixel().getHeight() / 2); SetPosPixel(aPxPt); } @@ -178,39 +167,6 @@ bool SwOutlineContentVisibilityWin::Contains(const Point& rDocPt) const return false; } -void SwOutlineContentVisibilityWin::ToggleOutlineContentVisibility(const bool bSubs) -{ - SwWrtShell& rSh = GetEditWin()->GetView().GetWrtShell(); - rSh.LockView(true); - if (GetEditWin()->GetView().GetDrawView()->IsTextEdit()) - rSh.EndTextEdit(); - if (GetEditWin()->GetView().IsDrawMode()) - GetEditWin()->GetView().LeaveDrawCreate(); - rSh.EnterStdMode(); - if (rSh.GetViewOptions()->IsTreatSubOutlineLevelsAsContent()) - rSh.ToggleOutlineContentVisibility(m_nOutlinePos); - else if (bSubs) - { - // toggle including sub levels - SwOutlineNodes::size_type nPos = m_nOutlinePos; - SwOutlineNodes::size_type nOutlineNodesCount - = rSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount(); - int nLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(m_nOutlinePos); - bool bVisible = rSh.IsOutlineContentVisible(m_nOutlinePos); - do - { - if (rSh.IsOutlineContentVisible(nPos) == bVisible) - rSh.ToggleOutlineContentVisibility(nPos); - } while (++nPos < nOutlineNodesCount - && rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nLevel); - } - else - rSh.ToggleOutlineContentVisibility(m_nOutlinePos); - // set cursor position to the toggled outline node - rSh.GotoOutline(m_nOutlinePos); - rSh.LockView(false); -} - IMPL_LINK(SwOutlineContentVisibilityWin, MouseMoveHdl, const MouseEvent&, rMEvt, bool) { if (rMEvt.IsLeaveWindow()) @@ -264,27 +220,17 @@ IMPL_LINK(SwOutlineContentVisibilityWin, MouseMoveHdl, const MouseEvent&, rMEvt, return false; } +// Toggle the outline content visibility on mouse press IMPL_LINK(SwOutlineContentVisibilityWin, MousePressHdl, const MouseEvent&, rMEvt, bool) { Hide(); - // Crash occurs if control does not have focus when toggling from hidden to shown. - // Seems to happen due to the control being disposed in the toggle process. - // Does NOT crash in debugger with GrabFocus and GrabFocusToDocument commented out. - // DOES crash in debugger on GrabFocusToDocument when GrabFocus is commented out. - // Until light is shed on why this happens, prevent crash by doing the following: - // 1) grab focus to the control - // 2) toggle content visibility - // 3) grab focus to the document - if (!ControlHasFocus()) - GrabFocus(); - ToggleOutlineContentVisibility(rMEvt.IsRight()); - GrabFocusToDocument(); + GetEditWin()->ToggleOutlineContentVisibility(m_nOutlinePos, rMEvt.IsRight()); return false; } IMPL_LINK_NOARG(SwOutlineContentVisibilityWin, DelayAppearHandler, Timer*, void) { - const int TICKS_BEFORE_WE_APPEAR = 5; + const int TICKS_BEFORE_WE_APPEAR = 3; if (m_nDelayAppearing < TICKS_BEFORE_WE_APPEAR) { ++m_nDelayAppearing; diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx index ea0cf5c23e0f..752de942539b 100644 --- a/sw/source/uibase/docvw/edtwin.cxx +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -1366,32 +1366,6 @@ void SwEditWin::KeyInput(const KeyEvent &rKEvt) } } - if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton()) - { - // not allowed if outline content visibility is false - sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode(); - if ((rSh.IsSttPara() && (nKey == KEY_BACKSPACE || nKey == KEY_LEFT)) - || (rSh.IsEndOfPara() && (nKey == KEY_DELETE || nKey == KEY_RETURN || nKey == KEY_RIGHT))) - { - SwContentNode* pContentNode = rSh.GetCurrentShellCursor().GetContentNode(); - SwOutlineNodes::size_type nPos; - if (rSh.GetDoc()->GetNodes().GetOutLineNds().Seek_Entry(pContentNode, &nPos)) - { - bool bOutlineContentVisibleAttr = true; - pContentNode->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr); - if (!bOutlineContentVisibleAttr) - return; // outline content visibility is false - if (rSh.IsSttPara() && (nKey == KEY_BACKSPACE || nKey == KEY_LEFT) && (nPos-1 != SwOutlineNodes::npos)) - { - bOutlineContentVisibleAttr = true; - rSh.GetDoc()->GetNodes().GetOutLineNds()[nPos-1]->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr); - if (!bOutlineContentVisibleAttr) - return; // previous outline node has content visibility false - } - } - } - } - if( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE && m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard ) { @@ -2704,10 +2678,6 @@ KEYINPUT_CHECKTABLE_INSDEL: } } - // x11 backend doesn't like not having this - if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton()) - GetFrameControlsManager().SetOutlineContentVisibilityButtons(); - // update the page number in the statusbar sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode(); if( KEY_UP == nKey || KEY_DOWN == nKey || KEY_PAGEUP == nKey || KEY_PAGEDOWN == nKey ) @@ -3536,16 +3506,16 @@ void SwEditWin::MouseButtonDown(const MouseEvent& _rMEvt) { if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton()) { + // ctrl+left-click on outline node frame SwContentAtPos aContentAtPos(IsAttrAtPos::Outline); if(rSh.GetContentAtPos(aDocPos, aContentAtPos)) { - // move cursor to outline para start and toggle outline content visibility - MoveCursor(rSh, aDocPos, bOnlyText, bLockView); - SwPaM aPam(*rSh.GetCurrentShellCursor().GetPoint()); SwOutlineNodes::size_type nPos; - if (rSh.GetNodes().GetOutLineNds().Seek_Entry(&aPam.GetPoint()->nNode.GetNode(), &nPos)) - rSh.ToggleOutlineContentVisibility(nPos); - return; + if (rSh.GetNodes().GetOutLineNds().Seek_Entry(aContentAtPos.aFnd.pNode, &nPos)) + { + ToggleOutlineContentVisibility(nPos, false); + return; + } } } if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) && !lcl_urlOverBackground( rSh, aDocPos ) ) @@ -3784,29 +3754,14 @@ void SwEditWin::MouseButtonDown(const MouseEvent& _rMEvt) if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton() && aMEvt.GetModifier() == KEY_MOD1) { + // ctrl+right-click on outline node frame SwContentAtPos aContentAtPos(IsAttrAtPos::Outline); if(rSh.GetContentAtPos(aDocPos, aContentAtPos)) { - // move cursor to para start toggle outline content visibility and set the same visibility for subs - MoveCursor(rSh, aDocPos, false, true); - SwPaM aPam(*rSh.GetCurrentShellCursor().GetPoint()); SwOutlineNodes::size_type nPos; - if (rSh.GetNodes().GetOutLineNds().Seek_Entry(&aPam.GetPoint()->nNode.GetNode(), &nPos)) + if (rSh.GetNodes().GetOutLineNds().Seek_Entry(aContentAtPos.aFnd.pNode, &nPos)) { - if (rSh.GetViewOptions()->IsTreatSubOutlineLevelsAsContent()) - rSh.ToggleOutlineContentVisibility(nPos); - else - { - SwOutlineNodes::size_type nOutlineNodesCount = rSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount(); - int nLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos); - bool bVisible = rSh.IsOutlineContentVisible(nPos); - do - { - if (rSh.IsOutlineContentVisible(nPos) == bVisible) - rSh.ToggleOutlineContentVisibility(nPos); - } while (++nPos < nOutlineNodesCount - && rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nLevel); - } + ToggleOutlineContentVisibility(nPos, !rSh.GetViewOptions()->IsTreatSubOutlineLevelsAsContent()); return; } } @@ -3940,48 +3895,37 @@ void SwEditWin::MouseMove(const MouseEvent& _rMEvt) if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton()) { - // add/remove outline collapse button + // add/remove outline content hide button + const SwNodes& rNds = rSh.GetDoc()->GetNodes(); + SwOutlineNodes::size_type nPos; SwContentAtPos aSwContentAtPos(IsAttrAtPos::Outline); if (rSh.GetContentAtPos(PixelToLogic(rMEvt.GetPosPixel()), aSwContentAtPos)) { if(aSwContentAtPos.aFnd.pNode && aSwContentAtPos.aFnd.pNode->IsTextNode()) { - const SwNodes& rNds = rSh.GetDoc()->GetNodes(); - SwOutlineNodes::size_type nPos; SwContentFrame* pContentFrame = aSwContentAtPos.aFnd.pNode->GetTextNode()->getLayoutFrame(nullptr); if (pContentFrame != m_pSavedOutlineFrame) { - // remove collapse button when saved frame is not frame at mouse position - if (m_pSavedOutlineFrame && /* is it possible that m_pSavedOutlineFrame is removed? */ !m_pSavedOutlineFrame->IsInDtor() && + if (m_pSavedOutlineFrame && !m_pSavedOutlineFrame->IsInDtor() && rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos) && - rSh.IsOutlineContentVisible(nPos)) - { + rSh.GetAttrOutlineContentVisible(nPos)) GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame); - } m_pSavedOutlineFrame = pContentFrame; } - // show collapse button - if (rNds.GetOutLineNds().Seek_Entry(aSwContentAtPos.aFnd.pNode->GetTextNode(), - &nPos) && rSh.IsOutlineContentVisible(nPos)) - { - GetFrameControlsManager().SetOutlineContentVisibilityButton(aSwContentAtPos.aFnd.pNode->GetTextNode()); - } + // show button + if (rNds.GetOutLineNds().Seek_Entry(aSwContentAtPos.aFnd.pNode->GetTextNode(), &nPos) && + rSh.GetAttrOutlineContentVisible(nPos)) + GetFrameControlsManager().SetOutlineContentVisibilityButton(pContentFrame); } } else if (m_pSavedOutlineFrame && !m_pSavedOutlineFrame->IsInDtor()) { // current pointer pos is not over an outline frame // previous frame was an outline frame - // remove collapse button if showing - const SwNodes& rNds = rSh.GetDoc()->GetNodes(); - SwOutlineNodes::size_type nPos; - if (rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)-> - GetTextNodeFirst(), &nPos) && - rSh.IsOutlineContentVisible(nPos)) - { - GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, - m_pSavedOutlineFrame); - } + // remove outline content visibility button if showing + if (rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos) && + rSh.GetAttrOutlineContentVisible(nPos)) + GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame); m_pSavedOutlineFrame = nullptr; } } @@ -4025,11 +3969,11 @@ void SwEditWin::MouseMove(const MouseEvent& _rMEvt) if (m_pSavedOutlineFrame && !bInsWin) { // the mouse pointer has left the building - // 86 the collapse button if showing + // remove the outline content visibility button if showing const SwNodes& rNds = rSh.GetDoc()->GetNodes(); SwOutlineNodes::size_type nPos; - rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos); - if (rSh.IsOutlineContentVisible(nPos)) + if (rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos) && + rSh.GetAttrOutlineContentVisible(nPos)) GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame); m_pSavedOutlineFrame = nullptr; } @@ -6668,4 +6612,41 @@ SwFrameControlsManager& SwEditWin::GetFrameControlsManager() return *m_pFrameControlsManager; } +void SwEditWin::ToggleOutlineContentVisibility(const size_t nOutlinePos, const bool bSubs) +{ + SwWrtShell& rSh = GetView().GetWrtShell(); + + if (GetView().GetDrawView()->IsTextEdit()) + rSh.EndTextEdit(); + if (GetView().IsDrawMode()) + GetView().LeaveDrawCreate(); + rSh.EnterStdMode(); + + if (!bSubs || rSh.GetViewOptions()->IsTreatSubOutlineLevelsAsContent()) + { + SwNode* pNode = rSh.GetNodes().GetOutLineNds()[nOutlinePos]; + bool bVisible = true; + pNode->GetTextNode()->GetAttrOutlineContentVisible(bVisible); + pNode->GetTextNode()->SetAttrOutlineContentVisible(!bVisible); + } + else if (bSubs) + { + // toggle including sub levels + SwOutlineNodes::size_type nPos = nOutlinePos; + SwOutlineNodes::size_type nOutlineNodesCount + = rSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount(); + int nLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nOutlinePos); + bool bVisible = rSh.IsOutlineContentVisible(nOutlinePos); + do + { + if (rSh.IsOutlineContentVisible(nPos) == bVisible) + rSh.GetNodes().GetOutLineNds()[nPos]->GetTextNode()->SetAttrOutlineContentVisible(!bVisible); + } while (++nPos < nOutlineNodesCount + && rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nLevel); + } + + rSh.InvalidateOutlineContentVisibility(); + rSh.GotoOutline(nOutlinePos); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/edtwin2.cxx b/sw/source/uibase/docvw/edtwin2.cxx index a72554202f2e..0f4a2e1250d8 100644 --- a/sw/source/uibase/docvw/edtwin2.cxx +++ b/sw/source/uibase/docvw/edtwin2.cxx @@ -467,9 +467,6 @@ void SwEditWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle if( bPaintShadowCursor ) m_pShadCursor->Paint(); - - if (pWrtShell->GetViewOptions()->IsShowOutlineContentVisibilityButton()) - GetFrameControlsManager().SetOutlineContentVisibilityButtons(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/inc/FrameControlsManager.hxx b/sw/source/uibase/inc/FrameControlsManager.hxx index cb51be62f860..f73f226b36d7 100644 --- a/sw/source/uibase/inc/FrameControlsManager.hxx +++ b/sw/source/uibase/inc/FrameControlsManager.hxx @@ -25,14 +25,13 @@ typedef std::shared_ptr< SwFrameControl > SwFrameControlPtr; typedef std::map<const SwFrame*, SwFrameControlPtr> SwFrameControlPtrMap; -/** A container for the Header/Footer, or PageBreak controls. +/** A container for the Header/Footer, PageBreak, and Outline Content Visibility controls. */ class SwFrameControlsManager { private: VclPtr<SwEditWin> m_pEditWin; std::map< FrameControlType, SwFrameControlPtrMap > m_aControls; - std::map<const SwTextNode*, const SwContentFrame*> m_aTextNodeContentFrameMap; public: SwFrameControlsManager( SwEditWin* pEditWin ); @@ -49,8 +48,7 @@ class SwFrameControlsManager void SetHeaderFooterControl( const SwPageFrame* pPageFrame, FrameControlType eType, Point aOffset ); void SetPageBreakControl( const SwPageFrame* pPageFrame ); void SetUnfloatTableButton( const SwFlyFrame* pFlyFrame, bool bShow, Point aTopRightPixel = Point() ); - void SetOutlineContentVisibilityButton(const SwTextNode* pTextNd); - void SetOutlineContentVisibilityButtons(); + void SetOutlineContentVisibilityButton(const SwContentFrame* pContentFrame); }; #endif diff --git a/sw/source/uibase/inc/OutlineContentVisibilityWin.hxx b/sw/source/uibase/inc/OutlineContentVisibilityWin.hxx index 96c0c0500ac4..db993021aa11 100644 --- a/sw/source/uibase/inc/OutlineContentVisibilityWin.hxx +++ b/sw/source/uibase/inc/OutlineContentVisibilityWin.hxx @@ -32,8 +32,6 @@ private: bool m_bDestroyed; size_t m_nOutlinePos; - void ToggleOutlineContentVisibility(const bool bSubs); - public: SwOutlineContentVisibilityWin(SwEditWin* pEditWin, const SwFrame* pFrame); virtual ~SwOutlineContentVisibilityWin() override { disposeOnce(); } diff --git a/sw/source/uibase/inc/edtwin.hxx b/sw/source/uibase/inc/edtwin.hxx index cb736bdf562f..44985f903c86 100644 --- a/sw/source/uibase/inc/edtwin.hxx +++ b/sw/source/uibase/inc/edtwin.hxx @@ -293,6 +293,7 @@ public: const SwFrame* GetSavedOutlineFrame() const { return m_pSavedOutlineFrame; } void SetSavedOutlineFrame(SwFrame* pFrame) { m_pSavedOutlineFrame = pFrame; } + void ToggleOutlineContentVisibility(const size_t nOutlinePos, const bool bSubs); virtual FactoryFunction GetUITestFactory() const override; }; diff --git a/sw/source/uibase/inc/wrtsh.hxx b/sw/source/uibase/inc/wrtsh.hxx index 67b626dc70bc..3e7b5d7eaf89 100644 --- a/sw/source/uibase/inc/wrtsh.hxx +++ b/sw/source/uibase/inc/wrtsh.hxx @@ -30,10 +30,12 @@ #include <svx/swframetypes.hxx> #include <vcl/weld.hxx> +#include <doc.hxx> +#include <docsh.hxx> +#include <viewopt.hxx> + namespace vcl { class Window; } class SbxArray; -class SwDoc; -class SwViewOption; class SwFlyFrameAttrMgr; class SwField; class SwTOXBase; @@ -492,8 +494,10 @@ typedef bool (SwWrtShell::*FNSimpleMove)(); void InsertPostIt(SwFieldMgr& rFieldMgr, const SfxRequest& rReq); bool IsOutlineContentVisible(const size_t nPos); - void ToggleOutlineContentVisibility(SwNode* pNd, const bool bForceNotVisible = false); - void ToggleOutlineContentVisibility(const size_t nPos, const bool bForceNotVisible = false); + void MakeOutlineContentVisible(const size_t nPos, bool bMakeVisible = true); + void MakeAllFoldedOutlineContentVisible(bool bMakeVisible = true); + void InvalidateOutlineContentVisibility(); + bool GetAttrOutlineContentVisible(const size_t nPos); private: @@ -653,4 +657,39 @@ inline bool SwWrtShell::Is_FnDragEQBeginDrag() const #endif } +class MakeAllOutlineContentTemporarilyVisible +{ +private: + SwWrtShell* m_pWrtSh; + bool m_bDone = false; +public: + static sal_uInt32 nLock; + MakeAllOutlineContentTemporarilyVisible(SwDoc* pDoc) + { + ++nLock; + if (nLock > 1) + return; + if (SwDocShell* pDocSh = pDoc->GetDocShell()) + if ((m_pWrtSh = pDocSh->GetWrtShell()) && m_pWrtSh->GetViewOptions() && + m_pWrtSh->GetViewOptions()->IsShowOutlineContentVisibilityButton()) + { + m_pWrtSh->StartAllAction(); + m_pWrtSh->MakeAllFoldedOutlineContentVisible(); + m_bDone = true; + } + } + + ~MakeAllOutlineContentTemporarilyVisible() COVERITY_NOEXCEPT_FALSE + { + --nLock; + if (nLock > 0) + return; + if (m_bDone && m_pWrtSh) + { + m_pWrtSh->MakeAllFoldedOutlineContentVisible(false); + m_pWrtSh->EndAllAction(); + } + } +}; + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/shells/basesh.cxx b/sw/source/uibase/shells/basesh.cxx index d8b4c3210547..5942e7cc7340 100644 --- a/sw/source/uibase/shells/basesh.cxx +++ b/sw/source/uibase/shells/basesh.cxx @@ -99,6 +99,8 @@ #include <shellres.hxx> #include <UndoTable.hxx> +#include <ndtxt.hxx> + FlyMode SwBaseShell::eFrameMode = FLY_DRAG_END; // These variables keep the state of Gallery (slot SID_GALLERY_BG_BRUSH) @@ -195,11 +197,53 @@ void SwBaseShell::ExecDelete(SfxRequest &rReq) switch(rReq.GetSlot()) { case SID_DELETE: + if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton()) + { + if (rSh.IsEndPara()) + { + SwNodeIndex aIdx(rSh.GetCursor()->GetNode()); + // disallow if this is am outline node having folded content + bool bVisible = true; + aIdx.GetNode().GetTextNode()->GetAttrOutlineContentVisible(bVisible); + if (!bVisible) + return; + // disallow if the next text node is an outline node having folded content + ++aIdx; + SwNodeType aNodeType; + while ((aNodeType = aIdx.GetNode().GetNodeType()) != SwNodeType::Text) + ++aIdx; + if (aIdx.GetNode().IsTextNode()) + { + bVisible = true; + aIdx.GetNode().GetTextNode()->GetAttrOutlineContentVisible(bVisible); + if (!bVisible) + return; + } + } + } rSh.DelRight(); break; case FN_BACKSPACE: - + if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton()) + { + if (rSh.IsSttPara()) + { + SwNodeIndex aIdx(rSh.GetCursor()->GetNode()); + // disallow if this is a folded outline node + bool bVisible = true; + aIdx.GetNode().GetTextNode()->GetAttrOutlineContentVisible(bVisible); + if (!bVisible) + return; + // disallow if previous text node does not have a layout frame + --aIdx; + SwNodeType aNodeType; + while ((aNodeType = aIdx.GetNode().GetNodeType()) != SwNodeType::Text) + --aIdx; + if (aIdx.GetNode().IsContentNode() && !aIdx.GetNode().GetContentNode()->getLayoutFrame(nullptr)) + return; + } + } if( rSh.IsNoNum() ) { rSh.SttCursorMove(); @@ -234,6 +278,8 @@ void SwBaseShell::ExecDelete(SfxRequest &rReq) void SwBaseShell::ExecClpbrd(SfxRequest &rReq) { + MakeAllOutlineContentTemporarilyVisible a(GetShell().GetDoc()); + // Attention: At risk of suicide! // After paste, paste special the shell can be destroy. @@ -523,6 +569,8 @@ void SwBaseShell::StateClpbrd(SfxItemSet &rSet) void SwBaseShell::ExecUndo(SfxRequest &rReq) { + MakeAllOutlineContentTemporarilyVisible a(GetShell().GetDoc()); + SwWrtShell &rWrtShell = GetShell(); SwUndoId nUndoId(SwUndoId::EMPTY); diff --git a/sw/source/uibase/uiview/view.cxx b/sw/source/uibase/uiview/view.cxx index 58012edabf60..3091e5af3bc6 100644 --- a/sw/source/uibase/uiview/view.cxx +++ b/sw/source/uibase/uiview/view.cxx @@ -1051,6 +1051,9 @@ SwView::SwView( SfxViewFrame *_pFrame, SfxViewShell* pOldSh ) if( !m_pVScrollbar->IsVisible( true ) ) ShowVScrollbar( false ); + if (m_pWrtShell && m_pWrtShell->GetViewOptions()->IsShowOutlineContentVisibilityButton()) + m_pWrtShell->InvalidateOutlineContentVisibility(); + GetViewFrame()->GetWindow().AddChildEventListener( LINK( this, SwView, WindowChildEventListener ) ); } diff --git a/sw/source/uibase/uiview/view0.cxx b/sw/source/uibase/uiview/view0.cxx index 8d7e8521664e..01bed0a3f35b 100644 --- a/sw/source/uibase/uiview/view0.cxx +++ b/sw/source/uibase/uiview/view0.cxx @@ -603,33 +603,20 @@ void SwView::ExecViewOptions(SfxRequest &rReq) SwWrtShell &rSh = GetWrtShell(); - // move cursor to top of document - if (rSh.IsSelFrameMode()) - { - rSh.UnSelectFrame(); - rSh.LeaveSelFrameMode(); - } - rSh.EnterStdMode(); - rSh.SttEndDoc(true); - - if (!bFlag) - { - // make all content visible - const SwOutlineNodes& rOutlineNds = rSh.GetNodes().GetOutLineNds(); - for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNds.size(); ++nPos) - { - SwNode* pNd = rOutlineNds[nPos]; - bool bOutlineContentVisibleAttr = true; - pNd->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr); - if (!bOutlineContentVisibleAttr) - { - rSh.ToggleOutlineContentVisibility(nPos); - pNd->GetTextNode()->SetAttrOutlineContentVisible(false); - } - } - } + if (!bFlag) // Outline folding is being turned ON! + rSh.MakeAllFoldedOutlineContentVisible(); pOpt->SetShowOutlineContentVisibilityButton(bFlag); + + // Apply option change here so if toggling the outline folding feature ON + // the invalidate function will see this. + rSh.StartAction(); + rSh.ApplyViewOptions(*pOpt); + rSh.EndAction(); + + if (bFlag) // Outline folding is being turned OFF! + rSh.MakeAllFoldedOutlineContentVisible(false); + break; } diff --git a/sw/source/uibase/uiview/view2.cxx b/sw/source/uibase/uiview/view2.cxx index 49d04147f063..7a30c9e8db0c 100644 --- a/sw/source/uibase/uiview/view2.cxx +++ b/sw/source/uibase/uiview/view2.cxx @@ -146,6 +146,8 @@ #include <basegfx/utils/zoomtools.hxx> +#include <ndtxt.hxx> + const char sStatusDelim[] = " : "; using namespace sfx2; @@ -1185,8 +1187,14 @@ void SwView::Execute(SfxRequest &rReq) { m_pWrtShell->EnterStdMode(); size_t nPos(m_pWrtShell->GetOutlinePos()); - m_pWrtShell->ToggleOutlineContentVisibility(nPos); - m_pWrtShell->GotoOutline(nPos); + if (nPos != SwOutlineNodes::npos) + { + SwNode* pNode = m_pWrtShell->GetNodes().GetOutLineNds()[nPos]; + pNode->GetTextNode()->SetAttrOutlineContentVisible( + !m_pWrtShell->GetAttrOutlineContentVisible(nPos)); + m_pWrtShell->InvalidateOutlineContentVisibility(); + m_pWrtShell->GotoOutline(nPos); + } } break; case FN_NAV_ELEMENT: diff --git a/sw/source/uibase/uiview/viewport.cxx b/sw/source/uibase/uiview/viewport.cxx index b5ebbb258187..6e20aaedf7f6 100644 --- a/sw/source/uibase/uiview/viewport.cxx +++ b/sw/source/uibase/uiview/viewport.cxx @@ -43,6 +43,8 @@ #include "viewfunc.hxx" +#include <FrameControlsManager.hxx> + // The SetVisArea of the DocShell must not be called from InnerResizePixel. // But our adjustments must take place. static bool bProtectDocShellVisArea = false; @@ -301,6 +303,9 @@ void SwView::SetVisArea( const Point &rPt, bool bUpdateScrollbar ) if ( aPt == m_aVisArea.TopLeft() ) return; + if (m_pWrtShell && m_pWrtShell->GetViewOptions()->IsShowOutlineContentVisibilityButton()) + GetEditWin().GetFrameControlsManager().HideControls(FrameControlType::Outline); + const tools::Long lXDiff = m_aVisArea.Left() - aPt.X(); const tools::Long lYDiff = m_aVisArea.Top() - aPt.Y(); SetVisArea( tools::Rectangle( aPt, diff --git a/sw/source/uibase/utlui/content.cxx b/sw/source/uibase/utlui/content.cxx index f1264d026f9a..bfdf00e7aff9 100644 --- a/sw/source/uibase/utlui/content.cxx +++ b/sw/source/uibase/utlui/content.cxx @@ -2923,6 +2923,8 @@ void SwContentTree::Notify(SfxBroadcaster & rBC, SfxHint const& rHint) void SwContentTree::ExecCommand(std::string_view rCmd, bool bOutlineWithChildren) { + MakeAllOutlineContentTemporarilyVisible a(GetWrtShell()->GetDoc()); + const bool bUp = rCmd == "chapterup"; const bool bUpDown = bUp || rCmd == "chapterdown"; const bool bLeft = rCmd == "promote"; @@ -2987,7 +2989,6 @@ void SwContentTree::ExecCommand(std::string_view rCmd, bool bOutlineWithChildren SwOutlineNodes::difference_type nDirLast = bUp ? -1 : 1; bool bStartedAction = false; - std::vector<SwNode*> aOutlineNdsArray; for (auto const& pCurrentEntry : selected) { assert(pCurrentEntry && lcl_IsContent(*pCurrentEntry, *m_xTreeView)); @@ -3009,29 +3010,6 @@ void SwContentTree::ExecCommand(std::string_view rCmd, bool bOutlineWithChildren if (!bStartedAction) { pShell->StartAllAction(); - if (bUpDown) - { - if (pShell->GetViewOptions()->IsShowOutlineContentVisibilityButton()) - { - // make all outline nodes content visible before move - // restore outline nodes content visible state after move - SwOutlineNodes rOutlineNds = pShell->GetDoc()->GetNodes().GetOutLineNds(); - for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNds.size(); ++nPos) - { - SwNode* pNd = rOutlineNds[nPos]; - if (pNd->IsTextNode()) // should always be true - { - bool bOutlineContentVisibleAttr = true; - pNd->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr); - if (!bOutlineContentVisibleAttr) - { - aOutlineNdsArray.push_back(pNd); - pShell->ToggleOutlineContentVisibility(nPos); - } - } - } - } - } pShell->StartUndo(bLeftRight ? SwUndoId::OUTLINE_LR : SwUndoId::OUTLINE_UD); bStartedAction = true; } @@ -3203,15 +3181,6 @@ void SwContentTree::ExecCommand(std::string_view rCmd, bool bOutlineWithChildren if (bStartedAction) { pShell->EndUndo(); - if (bUpDown) - { - if (pShell->GetViewOptions()->IsShowOutlineContentVisibilityButton()) - { - // restore state of outline content visibility to before move - for (SwNode* pNd : aOutlineNdsArray) - pShell->ToggleOutlineContentVisibility(pNd, true); - } - } pShell->EndAllAction(); if (m_aActiveContentArr[ContentTypeId::OUTLINE]) m_aActiveContentArr[ContentTypeId::OUTLINE]->Invalidate(); @@ -3637,30 +3606,10 @@ void SwContentTree::SelectOutlinesWithSelection() void SwContentTree::MoveOutline(SwOutlineNodes::size_type nTargetPos) { + MakeAllOutlineContentTemporarilyVisible a(GetWrtShell()->GetDoc()); + SwWrtShell *const pShell = GetWrtShell(); pShell->StartAllAction(); - std::vector<SwNode*> aOutlineNdsArray; - - if (pShell->GetViewOptions()->IsShowOutlineContentVisibilityButton()) - { - // make all outline nodes content visible before move - // restore outline nodes content visible state after move - SwOutlineNodes rOutlineNds = pShell->GetDoc()->GetNodes().GetOutLineNds(); - for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNds.size(); ++nPos) - { - SwNode* pNd = rOutlineNds[nPos]; - if (pNd->IsTextNode()) // should always be true - { - bool bOutlineContentVisibleAttr = true; - pNd->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr); - if (!bOutlineContentVisibleAttr) - { - aOutlineNdsArray.push_back(pNd); - pShell->ToggleOutlineContentVisibility(nPos); - } - } - } - } pShell->StartUndo(SwUndoId::OUTLINE_UD); SwOutlineNodes::size_type nPrevSourcePos = SwOutlineNodes::npos; @@ -3711,12 +3660,6 @@ void SwContentTree::MoveOutline(SwOutlineNodes::size_type nTargetPos) } pShell->EndUndo(); - if (pShell->GetViewOptions()->IsShowOutlineContentVisibilityButton()) - { - // restore state of outline content visibility to before move - for (SwNode* pNd : aOutlineNdsArray) - pShell->ToggleOutlineContentVisibility(pNd, true); - } pShell->EndAllAction(); m_aActiveContentArr[ContentTypeId::OUTLINE]->Invalidate(); Display(true); @@ -4028,9 +3971,13 @@ void SwContentTree::ExecuteContextMenuAction(const OString& rSelectedPopupEntry) m_pActiveShell->EnterStdMode(); m_bIgnoreViewChange = true; SwOutlineContent* pCntFirst = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xFirst).toInt64()); + + // toggle the outline node outline content visible attribute if (nSelectedPopupEntry == TOGGLE_OUTLINE_CONTENT_VISIBILITY) { - m_pActiveShell->ToggleOutlineContentVisibility(pCntFirst->GetOutlinePos()); + SwNode* pNode = m_pActiveShell->GetDoc()->GetNodes().GetOutLineNds()[pCntFirst->GetOutlinePos()]; + pNode->GetTextNode()->SetAttrOutlineContentVisible( + !m_pActiveShell->GetAttrOutlineContentVisible(pCntFirst->GetOutlinePos())); } else { @@ -4048,15 +3995,16 @@ void SwContentTree::ExecuteContextMenuAction(const OString& rSelectedPopupEntry) do { if (m_pActiveShell->IsOutlineContentVisible(nPos) != bShow) - m_pActiveShell->ToggleOutlineContentVisibility(nPos); + m_pActiveShell->GetDoc()->GetNodes().GetOutLineNds()[nPos]->GetTextNode()->SetAttrOutlineContentVisible(bShow); } while (++nPos < nOutlineNodesCount && (nLevel == -1 || m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nLevel)); } + m_pActiveShell->InvalidateOutlineContentVisibility(); // show in the document what was toggled if (lcl_IsContentType(*xFirst, *m_xTreeView)) // Headings root entry m_pActiveShell->GotoPage(1, true); else - GotoContent(pCntFirst); + m_pActiveShell->GotoOutline(pCntFirst->GetOutlinePos()); grab_focus(); m_bIgnoreViewChange = false; } @@ -4314,6 +4262,7 @@ void SwContentTree::Select() } } } + SwNavigationPI* pNavi = GetParentWindow(); pNavi->m_xContent6ToolBox->set_item_sensitive("chapterup", bEnable); pNavi->m_xContent6ToolBox->set_item_sensitive("chapterdown", bEnable); diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx b/sw/source/uibase/wrtsh/wrtsh1.cxx index b8c36c76eda4..98e41e16299e 100644 --- a/sw/source/uibase/wrtsh/wrtsh1.cxx +++ b/sw/source/uibase/wrtsh/wrtsh1.cxx @@ -121,6 +121,25 @@ void collectUIInformation(const OUString& rAction, const OUString& aParameters) } +sal_uInt32 MakeAllOutlineContentTemporarilyVisible::nLock = 0; + +static bool lcl_IsAllowed(const SwWrtShell* rSh) +{ + if (rSh->GetViewOptions()->IsShowOutlineContentVisibilityButton() && rSh->IsEndPara()) + { + SwTextNode* pTextNode = rSh->GetCursor()->GetNode().GetTextNode(); + if (pTextNode && pTextNode->IsOutline()) + { + // disallow if this is am outline node having folded content + bool bVisible = true; + pTextNode->GetAttrOutlineContentVisible(bVisible); + if (!bVisible) + return false; + } + } + return true; +} + #define BITFLD_INI_LIST \ m_bClearMark = \ m_bIns = true;\ @@ -876,6 +895,9 @@ void SwWrtShell::ConnectObj( svt::EmbeddedObjectRef& xObj, const SwRect &rPrt, // Selections will be overwritten void SwWrtShell::InsertPageBreak(const OUString *pPageDesc, const ::std::optional<sal_uInt16>& oPgNum ) { + if (!lcl_IsAllowed(this)) + return; + ResetCursorStack(); if( CanInsert() ) { @@ -911,6 +933,9 @@ void SwWrtShell::InsertPageBreak(const OUString *pPageDesc, const ::std::optiona void SwWrtShell::InsertLineBreak() { + if (!lcl_IsAllowed(this)) + return; + ResetCursorStack(); if( CanInsert() ) { @@ -931,6 +956,9 @@ void SwWrtShell::InsertLineBreak() void SwWrtShell::InsertColumnBreak() { + if (!lcl_IsAllowed(this)) + return; + SwActContext aActContext(this); ResetCursorStack(); if( !CanInsert() ) @@ -987,6 +1015,9 @@ void SwWrtShell::InsertFootnote(const OUString &rStr, bool bEndNote, bool bEdit void SwWrtShell::SplitNode( bool bAutoFormat ) { + if (!lcl_IsAllowed(this)) + return; + ResetCursorStack(); if( !CanInsert() ) return; @@ -1994,64 +2025,53 @@ void SwWrtShell::InsertPostIt(SwFieldMgr& rFieldMgr, const SfxRequest& rReq) } bool SwWrtShell::IsOutlineContentVisible(const size_t nPos) { - const SwNodes& rNodes = GetDoc()->GetNodes(); - const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds(); + const SwOutlineNodes& rOutlineNodes = GetDoc()->GetNodes().GetOutLineNds(); + const SwNode* pOutlineNode = rOutlineNodes[nPos]; - SwNode* pOutlineNode = rOutlineNodes[nPos]; - if (pOutlineNode->IsEndNode()) - return true; + // no layout frame means outline folding is set to include sub levels and the outline node has + // a parent outline node with outline content visible attribute false (folded outline content) + if (!pOutlineNode->GetTextNode()->getLayoutFrame(nullptr)) + return false; + + // try the next node to determine if this outline node has visible content + SwNodeIndex aIdx(*pOutlineNode, +1); + if (&aIdx.GetNode() == &aIdx.GetNodes().GetEndOfContent()) // end of regular content + return false; - bool bOutlineContentVisibleAttr = false; - if (pOutlineNode->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr)) - return bOutlineContentVisibleAttr; + if (aIdx.GetNode().IsTextNode()) + { + // sublevels treated as outline content + // If next node (aIdx) doesn't have a layout frame + // then this outline node does not have visible outline content. + // sublevels NOT treated as outline content + // If the next node (aIdx) is the next outline node + // then return the outline content visible attribute value. + if (!GetViewOptions()->IsTreatSubOutlineLevelsAsContent() && + nPos + 1 < rOutlineNodes.size() && + rOutlineNodes[nPos + 1] == &aIdx.GetNode()) + return GetAttrOutlineContentVisible(nPos); - return true; -} + return aIdx.GetNode().GetTextNode()->getLayoutFrame(nullptr); + } -void SwWrtShell::ToggleOutlineContentVisibility(SwNode* pNd, const bool bForceNotVisible) -{ - SwOutlineNodes::size_type nPos; - if (GetNodes().GetOutLineNds().Seek_Entry(pNd, &nPos)) - ToggleOutlineContentVisibility(nPos, bForceNotVisible); + return true; } -void SwWrtShell::ToggleOutlineContentVisibility(const size_t nPos, const bool bForceNotVisible) +void SwWrtShell::MakeOutlineContentVisible(const size_t nPos, bool bMakeVisible) { const SwNodes& rNodes = GetNodes(); const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds(); - assert(nPos < rOutlineNodes.size()); - SwNode* pSttNd = rOutlineNodes[nPos]; - if (pSttNd->IsEndNode()) - return; + // determine end node SwNode* pEndNd = &rNodes.GetEndOfContent(); if (rOutlineNodes.size() > nPos + 1) pEndNd = rOutlineNodes[nPos + 1]; - if (pSttNd->GetTableBox() || pSttNd->GetIndex() < rNodes.GetEndOfExtras().GetIndex()) - { - // limit toggle to within table box - if (pSttNd->EndOfSectionIndex() < pEndNd->GetIndex() ) - pEndNd = pSttNd->EndOfSectionNode(); - } - // if pSttNd isn't in table but pEndNd is, skip over all outline nodes in table - else if (pEndNd->GetTableBox()) - { - pEndNd = &rNodes.GetEndOfContent(); - for (size_t nOutlinePos = nPos + 2; nOutlinePos < rOutlineNodes.size(); nOutlinePos++) - { - if (!(rOutlineNodes[nOutlinePos]->GetTableBox())) - { - pEndNd = rOutlineNodes[nOutlinePos]; - break; - } - } - } - if (GetViewOptions()->IsTreatSubOutlineLevelsAsContent()) { + // get the last outline node to include (iPos) int nLevel = pSttNd->GetTextNode()->GetAttrOutlineLevel(); SwOutlineNodes::size_type iPos = nPos; while (++iPos < rOutlineNodes.size() && @@ -2080,64 +2100,173 @@ void SwWrtShell::ToggleOutlineContentVisibility(const size_t nPos, const bool bF } } - SwNodeIndex aIdx(*pSttNd, +1); // the next node after pSttdNd in the doc model SwNodes - if (!IsOutlineContentVisible(nPos) && !bForceNotVisible) + // table, text box, header, footer + if (pSttNd->GetTableBox() || pSttNd->GetIndex() < rNodes.GetEndOfExtras().GetIndex()) { - // make visible + // limit to within section + if (pSttNd->EndOfSectionIndex() < pEndNd->GetIndex()) + pEndNd = pSttNd->EndOfSectionNode(); + } + // if pSttNd isn't in table but pEndNd is, skip over all outline nodes in table + else if (pEndNd->GetTableBox()) + { + pEndNd = &rNodes.GetEndOfContent(); + for (size_t nOutlinePos = nPos + 2; nOutlinePos < rOutlineNodes.size(); nOutlinePos++) + { + if (!(rOutlineNodes[nOutlinePos]->GetTableBox())) + { + pEndNd = rOutlineNodes[nOutlinePos]; + break; + } + } + } + // end node determined + + // Remove content frames from the next node after the starting outline node to + // the determined ending node. Always do this to prevent the chance of duplicate + // frames being made. They will be remade below if needed. + SwNodeIndex aIdx(*pSttNd, +1); + while (aIdx != *pEndNd) + { + SwNode* pNd = &aIdx.GetNode(); + if (pNd->IsContentNode()) + pNd->GetContentNode()->DelFrames(nullptr); + else if (pNd->IsTableNode()) + pNd->GetTableNode()->DelFrames(nullptr); + aIdx++; + } + + if (bMakeVisible) // make outline nodes outline content visible + { + // reset the index marker and make frames + aIdx.Assign(*pSttNd, +1); MakeFrames(GetDoc(), aIdx, *pEndNd); pSttNd->GetTextNode()->SetAttrOutlineContentVisible(true); - if (GetViewOptions()->IsShowOutlineContentVisibilityButton()) + // make outline content made visible that have outline visible attribute false not visible + while (aIdx != *pEndNd) { - // remove button if focus is not on outline frame control window - SwContentFrame* pFrame = pSttNd->GetTextNode()->getLayoutFrame(nullptr); - if (pFrame && !pFrame->IsInDtor()) - { - SwFrameControlPtr pOutlineFrameControl = GetView().GetEditWin().GetFrameControlsManager().GetControl(FrameControlType::Outline, pFrame); - if (pOutlineFrameControl && pOutlineFrameControl->GetWindow() && !pOutlineFrameControl->HasFocus()) - GetView().GetEditWin().GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, pFrame); - } - - // toggle outline content made visible that have outline visible attribute false - while (aIdx != *pEndNd) + SwNode* pNd = &aIdx.GetNode(); + if (pNd->IsTextNode() && pNd->GetTextNode()->IsOutline()) { - SwNode* pTmpNd = &aIdx.GetNode(); - if (pTmpNd->IsTextNode() && pTmpNd->GetTextNode()->IsOutline()) + SwTextNode* pTextNd = pNd->GetTextNode(); + bool bOutlineContentVisibleAttr = true; + pTextNd->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr); + if (!bOutlineContentVisibleAttr) { - SwTextNode* pTmpTextNd = pTmpNd->GetTextNode(); - bool bOutlineContentVisibleAttr = true; - if (pTmpTextNd->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr) && - !bOutlineContentVisibleAttr) + SwOutlineNodes::size_type iPos; + if (rOutlineNodes.Seek_Entry(pTextNd, &iPos)) { - SwOutlineNodes::size_type iPos; - if (rOutlineNodes.Seek_Entry(pTmpTextNd, &iPos)) - { - if (pTmpTextNd->getLayoutFrame(nullptr)) - ToggleOutlineContentVisibility(iPos, true); // force not visible - } + if (pTextNd->getLayoutFrame(nullptr)) + MakeOutlineContentVisible(iPos, false); } } - aIdx++; } + aIdx++; } } else + pSttNd->GetTextNode()->SetAttrOutlineContentVisible(false); +} + +// make content visible or not visible only if needed +void SwWrtShell::InvalidateOutlineContentVisibility() +{ + GetView().GetEditWin().GetFrameControlsManager().HideControls(FrameControlType::Outline); + + const SwOutlineNodes& rOutlineNds = GetNodes().GetOutLineNds(); + for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNds.size(); ++nPos) { - // remove content frames - while (aIdx != *pEndNd) + bool bIsOutlineContentVisible = IsOutlineContentVisible(nPos); + bool bOutlineContentVisibleAttr = true; + rOutlineNds[nPos]->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr); + if (!bIsOutlineContentVisible && bOutlineContentVisibleAttr) + MakeOutlineContentVisible(nPos); + else if (bIsOutlineContentVisible && !bOutlineContentVisibleAttr) + MakeOutlineContentVisible(nPos, false); + } +} + +void SwWrtShell::MakeAllFoldedOutlineContentVisible(bool bMakeVisible) +{ + // deselect any drawing or frame and leave editing mode + SdrView* pSdrView = GetDrawView(); + if (pSdrView && pSdrView->IsTextEdit() ) + { + bool bLockView = IsViewLocked(); + LockView(true); + EndTextEdit(); + LockView(bLockView); + } + + if (IsSelFrameMode() || IsObjSelected()) + { + UnSelectFrame(); + LeaveSelFrameMode(); + GetView().LeaveDrawCreate(); + EnterStdMode(); + DrawSelChanged(); + GetView().StopShellTimer(); + } + else + EnterStdMode(); + + SwOutlineNodes::size_type nPos = GetOutlinePos(); + + if (bMakeVisible) + { + // make all content visible + + // When shortcut is assigned to the show outline content visibility button and used to + // toggle the feature and the mouse pointer is on an outline frame the button will not + // be removed. An easy way to make sure the button does not remain shown is to use the + // HideControls function. + GetView().GetEditWin().GetFrameControlsManager().HideControls(FrameControlType::Outline); + + // temporarily set outline content visibile attribute true for folded outline nodes + std::vector<SwNode*> aFoldedOutlineNodeArray; + for (SwNode* pNd: GetNodes().GetOutLineNds()) { - SwNode* pNd = &aIdx.GetNode(); - if (pNd->IsContentNode()) - pNd->GetContentNode()->DelFrames(nullptr); - else if (pNd->IsTableNode()) - pNd->GetTableNode()->DelFrames(nullptr); - aIdx++; + bool bOutlineContentVisibleAttr = true; + pNd->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr); + if (!bOutlineContentVisibleAttr) + { + aFoldedOutlineNodeArray.push_back(pNd); + pNd->GetTextNode()->SetAttrOutlineContentVisible(true); + } } - pSttNd->GetTextNode()->SetAttrOutlineContentVisible(false); + + StartAction(); + InvalidateOutlineContentVisibility(); + EndAction(); + + // restore outline content visible attribute for folded outline nodes + for (SwNode* pNd: aFoldedOutlineNodeArray) + pNd->GetTextNode()->SetAttrOutlineContentVisible(false); } + else + { + StartAction(); + InvalidateOutlineContentVisibility(); + EndAction(); - GetDoc()->GetDocShell()->Broadcast(SfxHint(SfxHintId::DocChanged)); + // If needed, find visible outline node to place cursor. + if (nPos != SwOutlineNodes::npos && !IsOutlineContentVisible(nPos)) + { + while (nPos != SwOutlineNodes::npos && !GetNodes().GetOutLineNds()[nPos]->GetTextNode()->getLayoutFrame(nullptr)) + --nPos; + if (nPos != SwOutlineNodes::npos) + GotoOutline(nPos); + } + } +} + +bool SwWrtShell::GetAttrOutlineContentVisible(const size_t nPos) +{ + bool bVisibleAttr = true; + GetNodes().GetOutLineNds()[nPos]->GetTextNode()->GetAttrOutlineContentVisible(bVisibleAttr); + return bVisibleAttr; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |