summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorJim Raykowski <raykowj@gmail.com>2023-04-27 20:32:03 -0800
committerJim Raykowski <raykowj@gmail.com>2023-05-07 01:23:20 +0200
commit50deb478e97aa9cfd023c5fa2f9d567b0b5797c2 (patch)
tree2f1adf74f4be9764d3d0262756bd11d4078f4cda /sw
parent45646542a638ec452b00c0c36a8a65d7194defcc (diff)
tdf#154211 SwNavigator: select range of content by shift + double-
click or shift + enter key Enhancement to make a selection from the current cursor position in the document to the position in the document that is navigated to when a content entry in the Navigator tree is double clicked or the enter key is pressed. No selection is made when the current cursor position is in a table, header, footer, footnote, or frame. To make shift + double-click behavior for x11 and qt5 the same as gtk3, FunctionSet::SetCursorAtPoint is added to the Shift case for SelectionMode::Single in SelectionEngine::SelMouseButtonDown. Change-Id: Id845dad8011ff7777a24f9b2730f10c62271c368 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151157 Tested-by: Jenkins Reviewed-by: Jim Raykowski <raykowj@gmail.com>
Diffstat (limited to 'sw')
-rw-r--r--sw/source/uibase/inc/conttree.hxx5
-rw-r--r--sw/source/uibase/utlui/content.cxx132
2 files changed, 112 insertions, 25 deletions
diff --git a/sw/source/uibase/inc/conttree.hxx b/sw/source/uibase/inc/conttree.hxx
index 5bcdc9013e89..ee04aeabac40 100644
--- a/sw/source/uibase/inc/conttree.hxx
+++ b/sw/source/uibase/inc/conttree.hxx
@@ -134,6 +134,9 @@ class SwContentTree final : public SfxListener
bool m_bDocHasChanged = true;
bool m_bIgnoreDocChange = false; // used to prevent tracking update
+ ImplSVEvent* m_nRowActivateEventId = nullptr;
+ bool m_bSelectTo = false;
+
std::unique_ptr<weld::TreeIter> m_xOverlayCompareEntry;
std::unique_ptr<sdr::overlay::OverlayObject> m_xOverlayObject;
@@ -199,6 +202,7 @@ class SwContentTree final : public SfxListener
/** Collapse - Remember the state for content types. */
DECL_LINK(CollapseHdl, const weld::TreeIter&, bool);
DECL_LINK(ContentDoubleClickHdl, weld::TreeView&, bool);
+ DECL_LINK(AsyncContentDoubleClickHdl, void*, void);
DECL_LINK(SelectHdl, weld::TreeView&, void);
DECL_LINK(FocusInHdl, weld::Widget&, void);
DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
@@ -208,6 +212,7 @@ class SwContentTree final : public SfxListener
DECL_LINK(TimerUpdate, Timer *, void);
DECL_LINK(OverlayObjectDelayTimerHdl, Timer *, void);
DECL_LINK(MouseMoveHdl, const MouseEvent&, bool);
+ DECL_LINK(MousePressHdl, const MouseEvent&, bool);
public:
SwContentTree(std::unique_ptr<weld::TreeView> xTreeView, SwNavigationPI* pDialog);
diff --git a/sw/source/uibase/utlui/content.cxx b/sw/source/uibase/utlui/content.cxx
index 86975a413004..05721ad4e348 100644
--- a/sw/source/uibase/utlui/content.cxx
+++ b/sw/source/uibase/utlui/content.cxx
@@ -1102,6 +1102,7 @@ SwContentTree::SwContentTree(std::unique_ptr<weld::TreeView> xTreeView, SwNaviga
m_xTreeView->connect_query_tooltip(LINK(this, SwContentTree, QueryTooltipHdl));
m_xTreeView->connect_drag_begin(LINK(this, SwContentTree, DragBeginHdl));
m_xTreeView->connect_mouse_move(LINK(this, SwContentTree, MouseMoveHdl));
+ m_xTreeView->connect_mouse_press(LINK(this, SwContentTree, MousePressHdl));
for (ContentTypeId i : o3tl::enumrange<ContentTypeId>())
{
@@ -1142,6 +1143,12 @@ SwContentTree::~SwContentTree()
SetActiveShell(nullptr);
}
+IMPL_LINK(SwContentTree, MousePressHdl, const MouseEvent&, rMEvt, bool)
+{
+ m_bSelectTo = rMEvt.IsShift() && (m_pConfig->IsNavigateOnSelect() || rMEvt.GetClicks() == 2);
+ return false;
+}
+
IMPL_LINK(SwContentTree, MouseMoveHdl, const MouseEvent&, rMEvt, bool)
{
if (m_eState == State::HIDDEN)
@@ -2332,9 +2339,36 @@ IMPL_LINK(SwContentTree, CollapseHdl, const weld::TreeIter&, rParent, bool)
// Also on double click will be initially opened only.
IMPL_LINK_NOARG(SwContentTree, ContentDoubleClickHdl, weld::TreeView&, bool)
{
+ if (m_nRowActivateEventId)
+ Application::RemoveUserEvent(m_nRowActivateEventId);
+ // post the event to process row activate after mouse press event to be able to set key
+ // modifier for selection feature (tdf#154211)
+ m_nRowActivateEventId
+ = Application::PostUserEvent(LINK(this, SwContentTree, AsyncContentDoubleClickHdl));
+
bool bConsumed = false;
std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ if (m_xTreeView->get_cursor(xEntry.get()) && lcl_IsContent(*xEntry, *m_xTreeView) &&
+ (State::HIDDEN != m_eState))
+ {
+ SwContent* pCnt = weld::fromId<SwContent*>(m_xTreeView->get_id(*xEntry));
+ assert(pCnt && "no UserData");
+ if (pCnt && !pCnt->IsInvisible())
+ {
+ // fdo#36308 don't expand outlines on double-click
+ bConsumed = pCnt->GetParent()->GetType() == ContentTypeId::OUTLINE;
+ }
+ }
+
+ return bConsumed; // false/true == allow/disallow more to be done, i.e. expand/collapse children
+}
+
+IMPL_LINK_NOARG(SwContentTree, AsyncContentDoubleClickHdl, void*, void)
+{
+ m_nRowActivateEventId = nullptr;
+
+ std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
bool bEntry = m_xTreeView->get_cursor(xEntry.get());
// Is it a content type?
OSL_ENSURE(bEntry, "no current entry!");
@@ -2358,13 +2392,9 @@ IMPL_LINK_NOARG(SwContentTree, ContentDoubleClickHdl, weld::TreeView&, bool)
}
//Jump to content type:
GotoContent(pCnt);
- // fdo#36308 don't expand outlines on double-click
- bConsumed = pCnt->GetParent()->GetType() == ContentTypeId::OUTLINE;
}
}
}
-
- return bConsumed; // false/true == allow/disallow more to be done, i.e. expand/collapse children
}
namespace
@@ -4191,6 +4221,10 @@ IMPL_LINK(SwContentTree, KeyInputHdl, const KeyEvent&, rEvent, bool)
else
ContentDoubleClickHdl(*m_xTreeView);
break;
+ case KEY_SHIFT:
+ m_bSelectTo = true;
+ ContentDoubleClickHdl(*m_xTreeView);
+ break;
}
}
}
@@ -5169,13 +5203,18 @@ void SwContentTree::EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode)
static void lcl_AssureStdModeAtShell(SwWrtShell* pWrtShell)
{
// deselect any drawing or frame and leave editing mode
- SdrView* pSdrView = pWrtShell->GetDrawView();
- if (pSdrView && pSdrView->IsTextEdit() )
+ if (SdrView* pSdrView = pWrtShell->GetDrawView())
{
- bool bLockView = pWrtShell->IsViewLocked();
- pWrtShell->LockView(true);
- pWrtShell->EndTextEdit();
- pWrtShell->LockView(bLockView);
+ if (pSdrView->IsTextEdit())
+ {
+ bool bLockView = pWrtShell->IsViewLocked();
+ pWrtShell->LockView(true);
+ pWrtShell->EndTextEdit();
+ pWrtShell->LockView(bLockView);
+ }
+ // go out of the frame
+ Point aPt(LONG_MIN, LONG_MIN);
+ pWrtShell->SelectObj(aPt, SW_LEAVE_FRAME);
}
if (pWrtShell->IsSelFrameMode() || pWrtShell->IsObjSelected())
@@ -5219,9 +5258,27 @@ void SwContentTree::CopyOutlineSelections()
void SwContentTree::GotoContent(const SwContent* pCnt)
{
+ if (m_bSelectTo)
+ {
+ if (m_pActiveShell->IsCursorInTable() ||
+ (m_pActiveShell->GetCursor()->GetPoint()->nNode.GetIndex() <=
+ m_pActiveShell->GetDoc()->GetNodes().GetEndOfExtras().GetIndex()))
+ {
+ m_bSelectTo = false;
+ m_pActiveShell->GetView().GetEditWin().GrabFocus();
+ return;
+ }
+ }
+
m_nLastGotoContentWasOutlinePos = SwOutlineNodes::npos;
m_sSelectedItem = "";
lcl_AssureStdModeAtShell(m_pActiveShell);
+
+ std::optional<std::unique_ptr<SwPosition>> oPosition;
+ if (m_bSelectTo)
+ oPosition.emplace(new SwPosition(m_pActiveShell->GetCursor()->GetPoint()->nNode,
+ m_pActiveShell->GetCursor()->GetPoint()->nContent));
+
switch(m_nLastSelType = pCnt->GetParent()->GetType())
{
case ContentTypeId::TEXTFIELD:
@@ -5306,25 +5363,50 @@ void SwContentTree::GotoContent(const SwContent* pCnt)
default: break;
}
- if (m_pActiveShell->IsFrameSelected() || m_pActiveShell->IsObjSelected())
+ if (m_bSelectTo)
{
- m_pActiveShell->HideCursor();
- m_pActiveShell->EnterSelFrameMode();
- }
+ m_pActiveShell->SttCursorMove();
+ while (m_pActiveShell->IsCursorInTable())
+ {
+ m_pActiveShell->MoveTable(GotoCurrTable, fnTableStart);
+ if (!m_pActiveShell->Left(SwCursorSkipMode::Chars, false, 1, false))
+ break; // Table is at the beginning of the document. It can't be selected this way.
+ }
+ m_pActiveShell->EndCursorMove();
- SwView& rView = m_pActiveShell->GetView();
- rView.StopShellTimer();
- rView.GetPostItMgr()->SetActiveSidebarWin(nullptr);
- rView.GetEditWin().GrabFocus();
+ lcl_AssureStdModeAtShell(m_pActiveShell);
+
+ m_pActiveShell->SetMark();
+ m_pActiveShell->GetCursor()->GetMark()->nNode = oPosition.value()->nNode;
+ m_pActiveShell->GetCursor()->GetMark()->nContent = oPosition.value()->nContent;
+ m_pActiveShell->UpdateCursor();
+
+ m_pActiveShell->GetView().GetEditWin().GrabFocus();
- // Assure cursor is in visible view area.
- // (tdf#147041) Always show the navigated outline at the top of the visible view area.
- if (pCnt->GetParent()->GetType() == ContentTypeId::OUTLINE ||
- (!m_pActiveShell->IsCursorVisible() && !m_pActiveShell->IsFrameSelected() &&
- !m_pActiveShell->IsObjSelected()))
+ m_bSelectTo = false;
+ }
+ else
{
- Point aPoint(rView.GetVisArea().getX(), m_pActiveShell->GetCursorDocPos().getY());
- rView.SetVisArea(aPoint);
+ if (m_pActiveShell->IsFrameSelected() || m_pActiveShell->IsObjSelected())
+ {
+ m_pActiveShell->HideCursor();
+ m_pActiveShell->EnterSelFrameMode();
+ }
+
+ SwView& rView = m_pActiveShell->GetView();
+ rView.StopShellTimer();
+ rView.GetPostItMgr()->SetActiveSidebarWin(nullptr);
+ rView.GetEditWin().GrabFocus();
+
+ // Assure cursor is in visible view area.
+ // (tdf#147041) Always show the navigated outline at the top of the visible view area.
+ if (pCnt->GetParent()->GetType() == ContentTypeId::OUTLINE ||
+ (!m_pActiveShell->IsCursorVisible() && !m_pActiveShell->IsFrameSelected() &&
+ !m_pActiveShell->IsObjSelected()))
+ {
+ Point aPoint(rView.GetVisArea().getX(), m_pActiveShell->GetCursorDocPos().getY());
+ rView.SetVisArea(aPoint);
+ }
}
}