summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <mstahl@redhat.com>2016-11-30 14:54:14 +0100
committerMichael Stahl <mstahl@redhat.com>2016-11-30 19:31:07 +0000
commit946684ab33e51140f257cf497ad8c26ff4156669 (patch)
tree5b6d432b88b2407ab181ae3426f25a5580b3a17e
parent86484b74b5c27b6ce3a3cb03e46524f2e8c35568 (diff)
rhbz#1122096 tdf#54834: sw navigator: multi-selection of outline entries
* SwContentTree::ToggleToRoot(): allow multi-selection iff outline root is displayed * SwContentTree::ExecCommand(): handle outline operations for multiple selected entries; since it's not possible to prevent selecting both parent & child, try to ignore selected children in that case * add Undo bracketing * rename misleading "bModifier" variable which was actually true without the Ctrl key * regarding SwContentTree::KeyInput(), the KEY_RETURN causes the view to jump to the entry, and KEY_DELETE is not possible for outline entries, and KEY_SPACE is only for drawing objects, so no need for handling multi-selection here * it probably doesn't make sense to handle multi selection in the context menu but it appears that the context menu for outline entries is already quite borked even going back to OOo times Change-Id: Ib324065e5fe827796e0f202f01ab9c3e33c47ec5 (cherry picked from commit bf7b5ee0c8a552625b80a7a57c32fe05ee756f7a) Reviewed-on: https://gerrit.libreoffice.org/31432 Reviewed-by: Michael Stahl <mstahl@redhat.com> Tested-by: Michael Stahl <mstahl@redhat.com>
-rw-r--r--sw/source/uibase/utlui/content.cxx86
1 files changed, 69 insertions, 17 deletions
diff --git a/sw/source/uibase/utlui/content.cxx b/sw/source/uibase/utlui/content.cxx
index 16756002ed89..0d241c773789 100644
--- a/sw/source/uibase/utlui/content.cxx
+++ b/sw/source/uibase/utlui/content.cxx
@@ -1867,10 +1867,15 @@ void SwContentTree::ToggleToRoot()
m_nRootType = pCntType->GetType();
m_bIsRoot = true;
Display(State::HIDDEN != m_eState);
+ if (m_nRootType == ContentTypeId::OUTLINE)
+ {
+ SetSelectionMode(SelectionMode::Multiple);
+ }
}
}
else
{
+ SetSelectionMode(SelectionMode::Single);
m_nRootType = ContentTypeId::UNKNOWN;
m_bIsRoot = false;
FindActiveTypeAndRemoveUserData();
@@ -2203,7 +2208,9 @@ void SwContentTree::Notify(SfxBroadcaster & rBC, SfxHint const& rHint)
}
}
-void SwContentTree::ExecCommand(const OUString& rCmd, bool bModifier)
+
+
+void SwContentTree::ExecCommand(const OUString& rCmd, bool bOutlineWithChildren)
{
const bool bUp = rCmd == "up";
const bool bUpDown = bUp || rCmd == "down";
@@ -2221,40 +2228,80 @@ void SwContentTree::ExecCommand(const OUString& rCmd, bool bModifier)
SwWrtShell *const pShell = GetWrtShell();
sal_Int8 nActOutlineLevel = m_nOutlineLevel;
sal_uInt16 nActPos = pShell->GetOutlinePos(nActOutlineLevel);
- SvTreeListEntry* pFirstEntry = FirstSelected();
- if (pFirstEntry && lcl_IsContent(pFirstEntry))
+
+ std::vector<SvTreeListEntry*> selected;
+ for (SvTreeListEntry * pEntry = FirstSelected(); pEntry; pEntry = NextSelected(pEntry))
{
- assert(dynamic_cast<SwContent*>(static_cast<SwTypeNumber*>(pFirstEntry->GetUserData())));
- if ((m_bIsRoot && m_nRootType == ContentTypeId::OUTLINE) ||
- static_cast<SwContent*>(pFirstEntry->GetUserData())->GetParent()->GetType()
- == ContentTypeId::OUTLINE)
+ // it's possible to select the root node too which is a really bad idea
+ bool bSkip = lcl_IsContentType(pEntry);
+ // filter out children of selected parents so they don't get promoted
+ // or moved twice (except if there is Ctrl modifier, since in that
+ // case children are re-parented)
+ if ((bLeftRight || bOutlineWithChildren) && !selected.empty())
+ {
+ for (auto pParent = GetParent(pEntry); pParent; pParent = GetParent(pParent))
+ {
+ if (selected.back() == pParent)
+ {
+ bSkip = true;
+ break;
+ }
+ }
+ }
+ if (!bSkip)
{
- nActPos = static_cast<SwOutlineContent*>(pFirstEntry->GetUserData())->GetPos();
+ selected.push_back(pEntry);
}
}
- if (nActPos < USHRT_MAX && (!bUpDown || pShell->IsOutlineMovable(nActPos)))
+ if (bUpDown && !bUp)
+ { // to move down, start at the end!
+ std::reverse(selected.begin(), selected.end());
+ }
+
+ bool bStartedAction = false;
+ for (auto pCurrentEntry : selected)
{
- pShell->StartAllAction();
+ if (pCurrentEntry && lcl_IsContent(pCurrentEntry))
+ {
+ assert(dynamic_cast<SwContent*>(static_cast<SwTypeNumber*>(pCurrentEntry->GetUserData())));
+ if ((m_bIsRoot && m_nRootType == ContentTypeId::OUTLINE) ||
+ static_cast<SwContent*>(pCurrentEntry->GetUserData())->GetParent()->GetType()
+ == ContentTypeId::OUTLINE)
+ {
+ nActPos = static_cast<SwOutlineContent*>(pCurrentEntry->GetUserData())->GetPos();
+ }
+ }
+ if (nActPos == USHRT_MAX || (bUpDown && !pShell->IsOutlineMovable(nActPos)))
+ {
+ continue;
+ }
+
+ if (!bStartedAction)
+ {
+ pShell->StartAllAction();
+ pShell->StartUndo(bLeftRight ? UNDO_OUTLINE_LR : UNDO_OUTLINE_UD);
+ bStartedAction = true;
+ }
pShell->GotoOutline( nActPos); // If text selection != box selection
pShell->Push();
- pShell->MakeOutlineSel(nActPos, nActPos, bModifier);
+ pShell->MakeOutlineSel(nActPos, nActPos, bOutlineWithChildren);
if (bUpDown)
{
short nDir = bUp ? -1 : 1;
- if (!bModifier && ((nDir == -1 && nActPos > 0) ||
+ if (!bOutlineWithChildren && ((nDir == -1 && nActPos > 0) ||
(nDir == 1 && nActPos < GetEntryCount() - 2)))
{
pShell->MoveOutlinePara( nDir );
// Set cursor back to the current position
pShell->GotoOutline( nActPos + nDir);
}
- else if (bModifier && pFirstEntry)
+ else if (bOutlineWithChildren && pCurrentEntry)
{
sal_uInt16 nActEndPos = nActPos;
- SvTreeListEntry* pEntry = pFirstEntry;
- assert(dynamic_cast<SwOutlineContent*>(static_cast<SwTypeNumber*>(pFirstEntry->GetUserData())));
+ SvTreeListEntry* pEntry = pCurrentEntry;
+ assert(dynamic_cast<SwOutlineContent*>(static_cast<SwTypeNumber*>(pCurrentEntry->GetUserData())));
const auto nActLevel = static_cast<SwOutlineContent*>(
- pFirstEntry->GetUserData())->GetOutlineLevel();
+ pCurrentEntry->GetUserData())->GetOutlineLevel();
pEntry = Next(pEntry);
while (pEntry && CTYPE_CNT ==
static_cast<SwTypeNumber*>(pEntry->GetUserData())->GetTypeId())
@@ -2300,7 +2347,7 @@ void SwContentTree::ExecCommand(const OUString& rCmd, bool bModifier)
else
{
sal_uInt16 nDest = nActPos;
- pEntry = pFirstEntry;
+ pEntry = pCurrentEntry;
while (pEntry && nDest)
{
nDest--;
@@ -2331,6 +2378,11 @@ void SwContentTree::ExecCommand(const OUString& rCmd, bool bModifier)
pShell->ClearMark();
pShell->Pop(false); // Cursor is now back at the current heading.
+ }
+
+ if (bStartedAction)
+ {
+ pShell->EndUndo();
pShell->EndAllAction();
if (m_aActiveContentArr[ContentTypeId::OUTLINE])
m_aActiveContentArr[ContentTypeId::OUTLINE]->Invalidate();