summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/vcl/weld.hxx4
-rw-r--r--sw/source/uibase/inc/conttree.hxx10
-rw-r--r--sw/source/uibase/utlui/content.cxx170
-rw-r--r--vcl/inc/salvtables.hxx4
-rw-r--r--vcl/inc/treeglue.hxx25
-rw-r--r--vcl/source/app/salvtables.cxx6
-rw-r--r--vcl/unx/gtk3/gtkinst.cxx41
7 files changed, 224 insertions, 36 deletions
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 4b4ea74f13b3..3bcbc0a7a08d 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -1352,7 +1352,9 @@ public:
* after the row
* b) dnd highlight the dest row
*/
- virtual bool get_dest_row_at_pos(const Point& rPos, weld::TreeIter* pResult, bool bDnDMode) = 0;
+ virtual bool get_dest_row_at_pos(const Point& rPos, weld::TreeIter* pResult, bool bDnDMode,
+ bool bAutoScroll = true)
+ = 0;
virtual void unset_drag_dest_row() = 0;
virtual tools::Rectangle get_row_area(const weld::TreeIter& rIter) const = 0;
// for dragging and dropping between TreeViews, return the active source
diff --git a/sw/source/uibase/inc/conttree.hxx b/sw/source/uibase/inc/conttree.hxx
index cf7c383f81e4..77358b9edb30 100644
--- a/sw/source/uibase/inc/conttree.hxx
+++ b/sw/source/uibase/inc/conttree.hxx
@@ -32,6 +32,8 @@
#include <o3tl/enumarray.hxx>
#include <o3tl/typed_flags_set.hxx>
+#include <svx/sdr/overlay/overlayobject.hxx>
+
class SwWrtShell;
class SwContentType;
class SwNavigationPI;
@@ -91,6 +93,7 @@ class SwContentTree final : public SfxListener
SwNavigationPI* m_pDialog;
OUString m_sSpace;
AutoTimer m_aUpdTimer;
+ AutoTimer m_aOverlayObjectDelayTimer;
o3tl::enumarray<ContentTypeId,std::unique_ptr<SwContentType>> m_aActiveContentArr;
o3tl::enumarray<ContentTypeId,std::unique_ptr<SwContentType>> m_aHiddenContentArr;
@@ -129,6 +132,11 @@ class SwContentTree final : public SfxListener
bool m_bDocHasChanged = true;
bool m_bIgnoreDocChange = false; // used to prevent tracking update
+ std::unique_ptr<weld::TreeIter> m_xOverlayCompareEntry;
+ std::unique_ptr<sdr::overlay::OverlayObject> m_xOverlayObject;
+
+ void BringBookmarksToAttention(const std::vector<OUString>& rNames);
+
/**
* Before any data will be deleted, the last active entry has to be found.
* After this the UserData will be deleted
@@ -183,6 +191,8 @@ class SwContentTree final : public SfxListener
DECL_LINK(QueryTooltipHdl, const weld::TreeIter&, OUString);
DECL_LINK(DragBeginHdl, bool&, bool);
DECL_LINK(TimerUpdate, Timer *, void);
+ DECL_LINK(m_aOverlayObjectDelayTimerHdl, Timer *, void);
+ DECL_LINK(MouseMoveHdl, 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 32a9e8ab63ce..cb7f96ec3b23 100644
--- a/sw/source/uibase/utlui/content.cxx
+++ b/sw/source/uibase/utlui/content.cxx
@@ -102,6 +102,12 @@
#include <txtftn.hxx>
#include <fmtftn.hxx>
+#include <txtfrm.hxx>
+#include <svx/sdr/overlay/overlayselection.hxx>
+#include <svx/sdr/overlay/overlayobject.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <svx/sdrpaintwindow.hxx>
+
#define CTYPE_CNT 0
#define CTYPE_CTT 1
@@ -1066,6 +1072,7 @@ SwContentTree::SwContentTree(std::unique_ptr<weld::TreeView> xTreeView, SwNaviga
, m_pDialog(pDialog)
, m_sSpace(OUString(" "))
, m_aUpdTimer("SwContentTree m_aUpdTimer")
+ , m_aOverlayObjectDelayTimer("SwContentTree m_aOverlayObjectDelayTimer")
, m_sInvisible(SwResId(STR_INVISIBLE))
, m_pHiddenShell(nullptr)
, m_pActiveShell(nullptr)
@@ -1082,6 +1089,7 @@ SwContentTree::SwContentTree(std::unique_ptr<weld::TreeView> xTreeView, SwNaviga
, m_bIsLastReadOnly(false)
, m_bIsOutlineMoveable(true)
, m_bViewHasChanged(false)
+ , m_xOverlayCompareEntry(m_xTreeView->make_iterator())
{
m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 30,
m_xTreeView->get_text_height() * 14);
@@ -1097,6 +1105,7 @@ SwContentTree::SwContentTree(std::unique_ptr<weld::TreeView> xTreeView, SwNaviga
m_xTreeView->connect_popup_menu(LINK(this, SwContentTree, CommandHdl));
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));
for (ContentTypeId i : o3tl::enumrange<ContentTypeId>())
{
@@ -1121,6 +1130,8 @@ SwContentTree::SwContentTree(std::unique_ptr<weld::TreeView> xTreeView, SwNaviga
m_aUpdTimer.SetInvokeHandler(LINK(this, SwContentTree, TimerUpdate));
m_aUpdTimer.SetTimeout(1000);
+ m_aOverlayObjectDelayTimer.SetInvokeHandler(LINK(this, SwContentTree, m_aOverlayObjectDelayTimerHdl));
+ m_aOverlayObjectDelayTimer.SetTimeout(500);
}
SwContentTree::~SwContentTree()
@@ -1135,6 +1146,74 @@ SwContentTree::~SwContentTree()
SetActiveShell(nullptr);
}
+IMPL_LINK(SwContentTree, MouseMoveHdl, const MouseEvent&, rMEvt, bool)
+{
+ if (rMEvt.IsEnterWindow())
+ {
+ m_xTreeView->get_iter_first(*m_xOverlayCompareEntry);
+ return false;
+ }
+ bool bRemoveOverlayObject = false;
+ if (rMEvt.IsLeaveWindow())
+ {
+ bRemoveOverlayObject = true;
+ }
+ else if (std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
+ m_xTreeView->get_dest_row_at_pos(rMEvt.GetPosPixel(), xEntry.get(), false, false))
+ {
+ if (lcl_IsContent(*xEntry, *m_xTreeView)) // content entry
+ {
+ SwContent* pCnt = weld::fromId<SwContent*>(m_xTreeView->get_id(*xEntry));
+ const ContentTypeId nType = pCnt->GetParent()->GetType();
+ bRemoveOverlayObject = nType != ContentTypeId::BOOKMARK;
+ if (!bRemoveOverlayObject &&
+ m_xTreeView->iter_compare(*xEntry, *m_xOverlayCompareEntry) != 0)
+ {
+ m_xTreeView->copy_iterator(*xEntry, *m_xOverlayCompareEntry);
+ if (nType == ContentTypeId::BOOKMARK)
+ {
+ BringBookmarksToAttention(std::vector<OUString> {pCnt->GetName()});
+ }
+ }
+ }
+ else // content type entry
+ {
+ const ContentTypeId nType =
+ weld::fromId<SwContentType*>(m_xTreeView->get_id(*xEntry))->GetType();
+ bRemoveOverlayObject = nType != ContentTypeId::BOOKMARK;
+ if (!bRemoveOverlayObject &&
+ m_xTreeView->iter_compare(*xEntry, *m_xOverlayCompareEntry) != 0)
+ {
+ m_xTreeView->copy_iterator(*xEntry, *m_xOverlayCompareEntry);
+ if (nType == ContentTypeId::BOOKMARK)
+ {
+ Reference<frame::XModel> xModel =
+ m_pActiveShell->GetView().GetDocShell()->GetBaseModel();
+ Reference<text::XBookmarksSupplier> xBkms(xModel, uno::UNO_QUERY);
+ Reference<container::XNameAccess> xNames = xBkms->getBookmarks();
+ if (xNames.is())
+ {
+ auto aNames(comphelper::sequenceToContainer<std::vector<OUString>>(
+ xNames->getElementNames()));
+ BringBookmarksToAttention(aNames);
+ }
+ }
+ }
+ }
+ }
+ if (bRemoveOverlayObject)
+ {
+ m_aOverlayObjectDelayTimer.Stop();
+ if (m_xOverlayObject && m_xOverlayObject->getOverlayManager())
+ {
+ m_xOverlayObject->getOverlayManager()->remove(*m_xOverlayObject);
+ m_xOverlayObject.reset();
+ }
+ m_xTreeView->get_iter_first(*m_xOverlayCompareEntry);
+ }
+ return false;
+}
+
// Drag&Drop methods
IMPL_LINK(SwContentTree, DragBeginHdl, bool&, rUnsetDragIcon, bool)
{
@@ -4836,6 +4915,23 @@ void SwContentTree::ShowActualView()
GetParentWindow()->UpdateListBox();
}
+IMPL_LINK_NOARG(SwContentTree, m_aOverlayObjectDelayTimerHdl, Timer *, void)
+{
+ m_aOverlayObjectDelayTimer.Stop();
+ if (m_xOverlayObject)
+ {
+ if (SdrView* pView = m_pActiveShell->GetDrawView())
+ {
+ if (SdrPaintWindow* pPaintWindow = pView->GetPaintWindow(0))
+ {
+ const rtl::Reference<sdr::overlay::OverlayManager>& xOverlayManager =
+ pPaintWindow->GetOverlayManager();
+ xOverlayManager->add(*m_xOverlayObject);
+ }
+ }
+ }
+}
+
IMPL_LINK_NOARG(SwContentTree, SelectHdl, weld::TreeView&, void)
{
if (m_pConfig->IsNavigateOnSelect())
@@ -5407,4 +5503,78 @@ void SwContentTree::SelectContentType(std::u16string_view rContentTypeName)
} while (m_xTreeView->iter_next_sibling(*xIter));
}
+void SwContentTree::BringBookmarksToAttention(const std::vector<OUString>& rNames)
+{
+ std::vector<basegfx::B2DRange> aRanges;
+ IDocumentMarkAccess* const pMarkAccess = m_pActiveShell->getIDocumentMarkAccess();
+ for (const auto& rName : rNames)
+ {
+ IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findBookmark(rName);
+ if (ppBkmk != pMarkAccess->getBookmarksEnd())
+ {
+ SwPosition aMarkStart = (*ppBkmk)->GetMarkStart();
+ if (const SwTextNode* pMarkStartTextNode = aMarkStart.GetNode().GetTextNode())
+ {
+ if (const SwTextFrame* pMarkStartFrame = static_cast<const SwTextFrame*>(
+ pMarkStartTextNode->getLayoutFrame(m_pActiveShell->GetLayout())))
+ {
+ SwPosition aMarkEnd = (*ppBkmk)->GetMarkEnd();
+ if (const SwTextNode* pMarkEndTextNode = aMarkEnd.GetNode().GetTextNode())
+ {
+ if (const SwTextFrame* pMarkEndFrame = static_cast<const SwTextFrame*>(
+ pMarkEndTextNode->getLayoutFrame(
+ m_pActiveShell->GetLayout())))
+ {
+ // adjust span when mark start equals mark end
+ if (aMarkStart == aMarkEnd)
+ {
+ if (aMarkEnd.GetContentIndex() < pMarkEndTextNode->Len() - 1)
+ aMarkEnd.AdjustContent(+1);
+ else if (aMarkStart.GetContentIndex() > 0)
+ aMarkStart.AdjustContent(-1);
+ }
+ SwRect aStartCharRect;
+ pMarkStartFrame->GetCharRect(aStartCharRect, aMarkStart);
+ SwRect aEndCharRect;
+ pMarkEndFrame->GetCharRect(aEndCharRect, aMarkEnd);
+ if (aStartCharRect.Top() == aEndCharRect.Top())
+ {
+ // single line range
+ aRanges.emplace_back(aStartCharRect.Left(),
+ aStartCharRect.Top(),
+ aEndCharRect.Right() + 1,
+ aEndCharRect.Bottom() + 1);
+ }
+ else
+ {
+ // multi line range
+ SwRect aMarkStartFrameRect = pMarkStartFrame->getFrameArea();
+ aRanges.emplace_back(aStartCharRect.Left(),
+ aStartCharRect.Top(),
+ aMarkStartFrameRect.Right(),
+ aStartCharRect.Bottom() + 1);
+ if (aStartCharRect.Bottom() + 1 != aEndCharRect.Top())
+ aRanges.emplace_back(aMarkStartFrameRect.Left(),
+ aStartCharRect.Bottom() + 1,
+ aMarkStartFrameRect.Right(),
+ aEndCharRect.Top() + 1);
+ aRanges.emplace_back(aMarkStartFrameRect.Left(),
+ aEndCharRect.Top() + 1,
+ aEndCharRect.Right() + 1,
+ aEndCharRect.Bottom() + 1);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (m_xOverlayObject && m_xOverlayObject->getOverlayManager())
+ m_xOverlayObject->getOverlayManager()->remove(*m_xOverlayObject);
+ m_xOverlayObject.reset(new sdr::overlay::OverlaySelection(sdr::overlay::OverlayType::Invert,
+ Color(), std::move(aRanges),
+ true /*unused for Invert type*/));
+ m_aOverlayObjectDelayTimer.Start();
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx
index 7ad7a145e8af..d6968e36d00c 100644
--- a/vcl/inc/salvtables.hxx
+++ b/vcl/inc/salvtables.hxx
@@ -1716,8 +1716,8 @@ public:
SvTabListBox& getTreeView();
- virtual bool get_dest_row_at_pos(const Point& rPos, weld::TreeIter* pResult,
- bool bDnDMode) override;
+ virtual bool get_dest_row_at_pos(const Point& rPos, weld::TreeIter* pResult, bool bDnDMode,
+ bool bAutoScroll = true) override;
virtual void unset_drag_dest_row() override;
diff --git a/vcl/inc/treeglue.hxx b/vcl/inc/treeglue.hxx
index 4cb120d81f7f..d445a533b43f 100644
--- a/vcl/inc/treeglue.hxx
+++ b/vcl/inc/treeglue.hxx
@@ -121,26 +121,29 @@ public:
m_aModelChangedHdl.Call(this);
}
- SvTreeListEntry* GetTargetAtPoint(const Point& rPos, bool bHighLightTarget)
+ SvTreeListEntry* GetTargetAtPoint(const Point& rPos, bool bHighLightTarget, bool bScroll = true)
{
SvTreeListEntry* pOldTargetEntry = pTargetEntry;
pTargetEntry = PosOverBody(rPos) ? pImpl->GetEntry(rPos) : nullptr;
if (pOldTargetEntry != pTargetEntry)
ImplShowTargetEmphasis(pOldTargetEntry, false);
- // scroll
- if (rPos.Y() < 12)
+ if (bScroll)
{
- ImplShowTargetEmphasis(pTargetEntry, false);
- ScrollOutputArea(+1);
- }
- else
- {
- Size aSize(pImpl->GetOutputSize());
- if (rPos.Y() > aSize.Height() - 12)
+ // scroll
+ if (rPos.Y() < 12)
{
ImplShowTargetEmphasis(pTargetEntry, false);
- ScrollOutputArea(-1);
+ ScrollOutputArea(+1);
+ }
+ else
+ {
+ Size aSize(pImpl->GetOutputSize());
+ if (rPos.Y() > aSize.Height() - 12)
+ {
+ ImplShowTargetEmphasis(pTargetEntry, false);
+ ScrollOutputArea(-1);
+ }
}
}
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 39ee33de947f..733d78179500 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -5154,12 +5154,12 @@ void SalInstanceTreeView::set_sort_column(int nColumn)
SvTabListBox& SalInstanceTreeView::getTreeView() { return *m_xTreeView; }
bool SalInstanceTreeView::get_dest_row_at_pos(const Point& rPos, weld::TreeIter* pResult,
- bool bDnDMode)
+ bool bDnDMode, bool bAutoScroll)
{
LclTabListBox* pTreeView
= !bDnDMode ? dynamic_cast<LclTabListBox*>(m_xTreeView.get()) : nullptr;
- SvTreeListEntry* pTarget
- = pTreeView ? pTreeView->GetTargetAtPoint(rPos, false) : m_xTreeView->GetDropTarget(rPos);
+ SvTreeListEntry* pTarget = pTreeView ? pTreeView->GetTargetAtPoint(rPos, false, bAutoScroll)
+ : m_xTreeView->GetDropTarget(rPos);
if (pTarget && pResult)
{
diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx
index e523e871290d..61d3f001c6d5 100644
--- a/vcl/unx/gtk3/gtkinst.cxx
+++ b/vcl/unx/gtk3/gtkinst.cxx
@@ -16240,7 +16240,7 @@ public:
weld::TreeView::connect_popup_menu(rLink);
}
- virtual bool get_dest_row_at_pos(const Point &rPos, weld::TreeIter* pResult, bool bDnDMode) override
+ virtual bool get_dest_row_at_pos(const Point &rPos, weld::TreeIter* pResult, bool bDnDMode, bool bAutoScroll) override
{
if (rPos.X() < 0 || rPos.Y() < 0)
{
@@ -16311,28 +16311,31 @@ public:
gtk_tree_path_free(path);
gtk_tree_path_free(lastpath);
- // auto scroll if we're close to the edges
- GtkAdjustment* pVAdjustment = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(m_pTreeView));
- double fStep = gtk_adjustment_get_step_increment(pVAdjustment);
- if (rPos.Y() < fStep)
+ if (bAutoScroll)
{
- double fValue = gtk_adjustment_get_value(pVAdjustment) - fStep;
- if (fValue < 0)
- fValue = 0.0;
- gtk_adjustment_set_value(pVAdjustment, fValue);
- }
- else
- {
- GdkRectangle aRect;
- gtk_tree_view_get_visible_rect(m_pTreeView, &aRect);
- if (rPos.Y() > aRect.height - fStep)
+ // auto scroll if we're close to the edges
+ GtkAdjustment* pVAdjustment = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(m_pTreeView));
+ double fStep = gtk_adjustment_get_step_increment(pVAdjustment);
+ if (rPos.Y() < fStep)
{
- double fValue = gtk_adjustment_get_value(pVAdjustment) + fStep;
- double fMax = gtk_adjustment_get_upper(pVAdjustment);
- if (fValue > fMax)
- fValue = fMax;
+ double fValue = gtk_adjustment_get_value(pVAdjustment) - fStep;
+ if (fValue < 0)
+ fValue = 0.0;
gtk_adjustment_set_value(pVAdjustment, fValue);
}
+ else
+ {
+ GdkRectangle aRect;
+ gtk_tree_view_get_visible_rect(m_pTreeView, &aRect);
+ if (rPos.Y() > aRect.height - fStep)
+ {
+ double fValue = gtk_adjustment_get_value(pVAdjustment) + fStep;
+ double fMax = gtk_adjustment_get_upper(pVAdjustment);
+ if (fValue > fMax)
+ fValue = fMax;
+ gtk_adjustment_set_value(pVAdjustment, fValue);
+ }
+ }
}
return ret;