summaryrefslogtreecommitdiff
path: root/sw/source/uibase/wrtsh
diff options
context:
space:
mode:
authorJim Raykowski <raykowj@gmail.com>2021-04-18 23:00:38 -0800
committerJim Raykowski <raykowj@gmail.com>2021-05-14 06:14:35 +0200
commit6b09276d157abada74e1a4989700139167207778 (patch)
treed90e2036f47b3acc5caa777a33847e4096731fb6 /sw/source/uibase/wrtsh
parent6c8ca02c5935a800cff70f3c173319b454b63c41 (diff)
Outline folding experimental feature rehack
* Changes the way the outline content visibility button is shown to similiar how the table un-float button is shown. * Toggle function is replaced by an invalidate function that makes outline content visible or not visible only if needed. * Removes the left and right arrow keys restrictions of cursor movement in and out of an outline node paragraph having outline content visibility attribute set false (folded outline content). These were prevented due to causing an assert in txtfrm.cxx SwTextFrame::MapModelToView but seems to do no harm here if allowed. * Makes a selection read-only if it spans an outline node that has folded content and disallows actions that would cause loss of folded content. * Adds RestoreSavePos when Move fails in SwCursor::LeftRight to fix a bug 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 the added RestoreSavePos. * Addresses tdf#141390 concerning position of view when feature is turned off and on. Change-Id: I0430f73643201aa08ffc347c1597b44b1de290e8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114255 Tested-by: Jenkins Reviewed-by: Jim Raykowski <raykowj@gmail.com>
Diffstat (limited to 'sw/source/uibase/wrtsh')
-rw-r--r--sw/source/uibase/wrtsh/wrtsh1.cxx285
1 files changed, 207 insertions, 78 deletions
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: */