summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw/inc/strings.hrc4
-rw-r--r--sw/source/uibase/inc/conttree.hxx2
-rw-r--r--sw/source/uibase/utlui/content.cxx178
-rw-r--r--sw/uiconfig/swriter/ui/navigatorcontextmenu.ui20
4 files changed, 199 insertions, 5 deletions
diff --git a/sw/inc/strings.hrc b/sw/inc/strings.hrc
index 20d45f5cc19b..a9b2ab36d587 100644
--- a/sw/inc/strings.hrc
+++ b/sw/inc/strings.hrc
@@ -647,6 +647,10 @@
#define STR_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT NC_("STR_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT", "hold Ctrl or right-click to include sub levels")
#define STR_ClICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY NC_("STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY", "Click to Toggle Outline Content Visibility")
#define STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT NC_("STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT", "right-click to include sub levels")
+#define STR_OUTLINE_CONTENT_VISIBILITY NC_("STR_OUTLINE_CONTENT", "Outline Content Visibility")
+#define STR_OUTLINE_CONTENT_VISIBILITY_TOGGLE NC_("STR_OUTLINE_CONTENT_VISIBILITY_TOGGLE", "Toggle")
+#define STR_OUTLINE_CONTENT_VISIBILITY_SHOW_ALL NC_("STR_OUTLINE_CONTENT_VISIBILITY_SHOW_ALL", "Show All")
+#define STR_OUTLINE_CONTENT_VISIBILITY_HIDE_ALL NC_("STR_OUTLINE_CONTENT_VISIBILITY_HIDE_ALL", "Hide All")
#define STR_EXPANDALL NC_("STR_EXPANDALL", "Expand All")
#define STR_COLLAPSEALL NC_("STR_COLLAPSEALL", "Collapse All")
diff --git a/sw/source/uibase/inc/conttree.hxx b/sw/source/uibase/inc/conttree.hxx
index 0a090a1d18f0..6f65b1984523 100644
--- a/sw/source/uibase/inc/conttree.hxx
+++ b/sw/source/uibase/inc/conttree.hxx
@@ -121,7 +121,7 @@ class SwContentTree final : public SfxListener
// outline root mode drag & drop
std::vector<std::unique_ptr<weld::TreeIter>> m_aDndOutlinesSelected;
- bool m_bIsInPromoteDemote = false;
+ bool m_bIgnoreViewChange = false;
/**
* Before any data will be deleted, the last active entry has to be found.
diff --git a/sw/source/uibase/utlui/content.cxx b/sw/source/uibase/utlui/content.cxx
index 1fcd1873d8f3..e92cddc641ef 100644
--- a/sw/source/uibase/utlui/content.cxx
+++ b/sw/source/uibase/utlui/content.cxx
@@ -1152,6 +1152,122 @@ static bool lcl_InsertExpandCollapseAllItem(weld::TreeView& rContentTree, weld::
return true;
}
+static void lcl_SetOutlineContentEntriesSensitivities(SwContentTree* pThis, weld::TreeView& rContentTree, weld::TreeIter& rEntry, weld::Menu& rPop)
+{
+ rPop.set_sensitive(OString::number(1512), false);
+ rPop.set_sensitive(OString::number(1513), false);
+ rPop.set_sensitive(OString::number(1514), false);
+
+ if (!pThis->GetActiveWrtShell()->GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ return;
+
+ // todo: multi selection
+ if (rContentTree.count_selected_rows() > 1)
+ return;
+
+ const SwNodes& rNodes = pThis->GetWrtShell()->GetNodes();
+ const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds();
+ size_t nOutlinePos = weld::GetAbsPos(rContentTree, rEntry);
+
+ bool bIsRoot = lcl_IsContentType(rEntry, rContentTree);
+
+ if (!bIsRoot)
+ --nOutlinePos;
+
+ if (nOutlinePos >= rOutlineNodes.size())
+ return;
+
+ int nFirstLevel = pThis->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineLevel(nOutlinePos);
+ {
+ // determine if any concerned outline node has content
+ bool bHasContent(false);
+ size_t nPos = nOutlinePos;
+ SwNode* pSttNd = rOutlineNodes[nPos];
+ SwNode* pEndNd = &rNodes.GetEndOfContent();
+ if (rOutlineNodes.size() > nPos + 1)
+ pEndNd = rOutlineNodes[nPos + 1];
+
+ // selected
+ SwNodeIndex aIdx(*pSttNd);
+ if (rNodes.GoNext(&aIdx) != pEndNd)
+ bHasContent = true;
+
+ // decendants
+ if (!bHasContent && (rContentTree.iter_has_child(rEntry) || rContentTree.get_children_on_demand(rEntry)))
+ {
+ while (++nPos < rOutlineNodes.size() &&
+ (bIsRoot || pThis->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nFirstLevel))
+ {
+ pSttNd = rOutlineNodes[nPos];
+ pEndNd = &rNodes.GetEndOfContent();
+ if (rOutlineNodes.size() > nPos + 1)
+ pEndNd = rOutlineNodes[nPos + 1];
+
+ // test for content in outline node
+ aIdx.Assign(*pSttNd);
+ if (rNodes.GoNext(&aIdx) != pEndNd)
+ {
+ bHasContent = true;
+ break;
+ }
+ }
+ }
+
+ if (!bHasContent)
+ return; // no content in any of the concerned outline nodes
+ }
+
+ // determine for subs if all are folded or unfolded or if they are mixed
+ if (rContentTree.iter_has_child(rEntry) || rContentTree.get_children_on_demand(rEntry))
+ {
+ // skip no content nodes
+ // we know there is content from results above so this is presumably safe
+ size_t nPos = nOutlinePos;
+ while (true)
+ {
+ SwNode* pSttNd = rOutlineNodes[nPos];
+ SwNode* pEndNd = rOutlineNodes.back();
+ if (!bIsRoot && rOutlineNodes.size() > nPos + 1)
+ pEndNd = rOutlineNodes[nPos + 1];
+
+ SwNodeIndex aIdx(*pSttNd);
+ if (rNodes.GoNext(&aIdx) != pEndNd)
+ break;
+ nPos++;
+ }
+
+ bool bHasFolded(pThis->GetWrtShell()->IsOutlineContentFolded(nPos));
+ bool bHasUnfolded(!bHasFolded);
+
+ while ((++nPos < pThis->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineNodesCount()) &&
+ (bIsRoot || pThis->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nFirstLevel))
+ {
+
+ SwNode* pSttNd = rOutlineNodes[nPos];
+ SwNode* pEndNd = &rNodes.GetEndOfContent();
+ if (rOutlineNodes.size() > nPos + 1)
+ pEndNd = rOutlineNodes[nPos + 1];
+
+ SwNodeIndex aIdx(*pSttNd);
+ if (rNodes.GoNext(&aIdx) == pEndNd)
+ continue; // skip if no content
+
+ if (pThis->GetWrtShell()->IsOutlineContentFolded(nPos))
+ bHasFolded = true;
+ else
+ bHasUnfolded = true;
+
+ if (bHasFolded && bHasUnfolded)
+ break; // mixed so no need to continue
+ }
+
+ rPop.set_sensitive(OString::number(1513), bHasUnfolded);
+ rPop.set_sensitive(OString::number(1514), bHasFolded);
+ }
+
+ bIsRoot ? rPop.remove(OString::number(1512)) : rPop.set_sensitive(OString::number(1512), true);
+}
+
IMPL_LINK(SwContentTree, CommandHdl, const CommandEvent&, rCEvt, bool)
{
if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
@@ -1166,6 +1282,11 @@ IMPL_LINK(SwContentTree, CommandHdl, const CommandEvent&, rCEvt, bool)
std::unique_ptr<weld::Menu> xSubPop3 = xBuilder->weld_menu("displaymenu");
std::unique_ptr<weld::Menu> xSubPopOutlineTracking = xBuilder->weld_menu("outlinetracking");
+ std::unique_ptr<weld::Menu> xSubPopOutlineContent = xBuilder->weld_menu("outlinecontent");
+ xSubPopOutlineContent->append(OUString::number(1512), SwResId(STR_OUTLINE_CONTENT_VISIBILITY_TOGGLE));
+ xSubPopOutlineContent->append(OUString::number(1513), SwResId(STR_OUTLINE_CONTENT_VISIBILITY_HIDE_ALL));
+ xSubPopOutlineContent->append(OUString::number(1514), SwResId(STR_OUTLINE_CONTENT_VISIBILITY_SHOW_ALL));
+
for(int i = 1; i <= 3; ++i)
xSubPopOutlineTracking->append_radio(OUString::number(i + 10), m_aContextStrings[IDX_STR_OUTLINE_TRACKING + i]);
xSubPopOutlineTracking->set_active(OString::number(10 + m_nOutlineTracking), true);
@@ -1259,6 +1380,7 @@ IMPL_LINK(SwContentTree, CommandHdl, const CommandEvent&, rCEvt, bool)
if(ContentTypeId::OUTLINE == nContentType)
{
bOutline = true;
+ lcl_SetOutlineContentEntriesSensitivities(this, *m_xTreeView, *xEntry, *xSubPopOutlineContent);
bRemoveToggleExpandEntry = lcl_InsertExpandCollapseAllItem(*m_xTreeView, *xEntry, *xPop);
if (!bReadonly)
{
@@ -1326,6 +1448,7 @@ IMPL_LINK(SwContentTree, CommandHdl, const CommandEvent&, rCEvt, bool)
if (ContentTypeId::OUTLINE == pType->GetType())
{
bOutline = true;
+ lcl_SetOutlineContentEntriesSensitivities(this, *m_xTreeView, *xEntry, *xSubPopOutlineContent);
bRemoveToggleExpandEntry = lcl_InsertExpandCollapseAllItem(*m_xTreeView, *xEntry, *xPop);
bRemoveSendOutlineEntry = false;
}
@@ -1402,6 +1525,14 @@ IMPL_LINK(SwContentTree, CommandHdl, const CommandEvent&, rCEvt, bool)
xSubPopOutlineTracking.reset();
xPop->remove(OString::number(4)); // outline tracking menu
}
+ if (!bOutline
+ || !m_pActiveShell->GetViewOptions()->IsShowOutlineContentVisibilityButton()
+ || m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineNodesCount() == 0)
+ {
+ xSubPopOutlineContent.reset();
+ xPop->remove(OString::number(5)); // outline content menu
+ xPop->remove("separator1511");
+ }
OString sCommand = xPop->popup_at_rect(m_xTreeView.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)));
if (!sCommand.isEmpty())
@@ -2036,7 +2167,7 @@ void SwContentTree::Display( bool bActive )
}
}
- if (!m_bIsInPromoteDemote && GetEntryCount() == nOldEntryCount)
+ if (!m_bIgnoreViewChange && GetEntryCount() == nOldEntryCount)
{
m_xTreeView->vadjustment_set_value(nOldScrollPos);
}
@@ -2545,7 +2676,7 @@ void SwContentTree::Notify(SfxBroadcaster & rBC, SfxHint const& rHint)
switch (rHint.GetId())
{
case SfxHintId::DocChanged:
- if (!m_bIsInPromoteDemote)
+ if (!m_bIgnoreViewChange)
{
m_bViewHasChanged = true;
TimerUpdate(&m_aUpdTimer);
@@ -2590,7 +2721,7 @@ void SwContentTree::ExecCommand(const OString& rCmd, bool bOutlineWithChildren)
return;
}
- m_bIsInPromoteDemote = true;
+ m_bIgnoreViewChange = true;
SwWrtShell *const pShell = GetWrtShell();
sal_Int8 nActOutlineLevel = m_nOutlineLevel;
@@ -2911,7 +3042,7 @@ void SwContentTree::ExecCommand(const OString& rCmd, bool bOutlineWithChildren)
}
}
}
- m_bIsInPromoteDemote = false;
+ m_bIgnoreViewChange = false;
}
void SwContentTree::ShowTree()
@@ -3421,6 +3552,45 @@ void SwContentTree::ExecuteContextMenuAction(const OString& rSelectedPopupEntry)
auto nSelectedPopupEntry = rSelectedPopupEntry.toUInt32();
switch (nSelectedPopupEntry)
{
+ case 1512: // fold or unfold outline content of selected entry
+ case 1513: // fold outline content of selected entry and decendents
+ case 1514: // unfold outline content of selected entry and decendents
+ {
+ m_pActiveShell->EnterStdMode();
+ m_bIgnoreViewChange = true;
+ SwOutlineContent* pCntFirst = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xFirst).toInt64());
+ if (nSelectedPopupEntry == 1512)
+ {
+ m_pActiveShell->ToggleOutlineContentVisibility(pCntFirst->GetOutlinePos());
+ }
+ else
+ {
+ // with subs
+ SwOutlineNodes::size_type nPos = pCntFirst->GetOutlinePos();
+ if (lcl_IsContentType(*xFirst, *m_xTreeView)) // Headings root entry
+ nPos = SwOutlineNodes::npos;
+ SwOutlineNodes::size_type nOutlineNodesCount = m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineNodesCount();
+ int nLevel = -1;
+ if (nPos != SwOutlineNodes::npos) // not root
+ nLevel = m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos);
+ else
+ nPos = 0;
+ bool bFold(nSelectedPopupEntry == 1514);
+ do
+ {
+ if (m_pActiveShell->IsOutlineContentFolded(nPos) == bFold)
+ m_pActiveShell->ToggleOutlineContentVisibility(nPos);
+ } while (++nPos < nOutlineNodesCount
+ && (nLevel == -1 || m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nLevel));
+ }
+ if (lcl_IsContentType(*xFirst, *m_xTreeView)) // Headings root entry
+ m_pActiveShell->GotoPage(1, true);
+ else
+ GotoContent(pCntFirst);
+ grab_focus();
+ m_bIgnoreViewChange = false;
+ }
+ break;
case 11:
case 12:
case 13:
diff --git a/sw/uiconfig/swriter/ui/navigatorcontextmenu.ui b/sw/uiconfig/swriter/ui/navigatorcontextmenu.ui
index b324c1a26c74..aecbc2cb1852 100644
--- a/sw/uiconfig/swriter/ui/navigatorcontextmenu.ui
+++ b/sw/uiconfig/swriter/ui/navigatorcontextmenu.ui
@@ -183,6 +183,26 @@
</object>
</child>
<child>
+ <object class="GtkMenuItem" id="5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="navigatorcontextmenu|STR_OUTLINE_CONTENT">Outline Content Visibility</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="outlinecontent">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem" id="separator1511">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ <child>
<object class="GtkMenuItem" id="4">
<property name="visible">True</property>
<property name="can_focus">False</property>