sw/inc/PostItMgr.hxx                 |    6 +-
 sw/source/uibase/docvw/PostItMgr.cxx |   60 +++++++++++++++++++++-----
 sw/source/uibase/docvw/edtwin.cxx    |   79 +++++++++++++++++++++++++++++++++--
 sw/source/uibase/inc/edtwin.hxx      |    6 ++
 sw/source/uibase/inc/swruler.hxx     |    4 +
 sw/source/uibase/misc/swruler.cxx    |   33 +++++++++++++-
 6 files changed, 169 insertions(+), 19 deletions(-)

New commits:
commit 25399d65d4d6f2217c4389ec82d35ccbce0c6f3e
Author:     Rafael Lima <rafael.palma.l...@gmail.com>
AuthorDate: Sun Sep 8 15:12:51 2024 +0200
Commit:     Rafael Lima <rafael.palma.l...@gmail.com>
CommitDate: Fri Sep 27 19:44:17 2024 +0200

    tdf#162855 Draw a guide line while resizing the comment sidebar
    
    This patch draws a guide line while the user is dragging the comment 
sidebar edge, to provide a better feedback of the size that will be applied.
    
    Thanks to Jim Raykowski for his comments and contributions. It should be 
noted that he authored much of this patch.
    
    Change-Id: I08d4761a25c021c3ddda563a70fc0324000e4e62
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173017
    Tested-by: Jenkins
    Reviewed-by: Jim Raykowski <rayk...@gmail.com>
    Reviewed-by: Rafael Lima <rafael.palma.l...@gmail.com>

diff --git a/sw/inc/PostItMgr.hxx b/sw/inc/PostItMgr.hxx
index 05cc25baa032..30ae1296b62f 100644
--- a/sw/inc/PostItMgr.hxx
+++ b/sw/inc/PostItMgr.hxx
@@ -67,7 +67,7 @@ struct SwPostItPageItem
     tools::Long lOffset;
     SwRect mPageRect;
     std::vector<SwSidebarItem*> mvSidebarItems;
-    SwPostItPageItem(): bScrollbar(false), eSidebarPosition( 
sw::sidebarwindows::SidebarPosition::RIGHT ), lOffset(0)
+    SwPostItPageItem(): bScrollbar(false), eSidebarPosition( 
sw::sidebarwindows::SidebarPosition::NONE ), lOffset(0)
     {
     }
 };
@@ -155,7 +155,7 @@ class SAL_DLLPUBLIC_RTTI SwPostItMgr final : public 
SfxListener,
         bool ShowScrollbar(const tools::ULong aPage) const;
         bool HasNotes() const ;
         bool ShowNotes() const;
-        void SetSidebarWidth(Point aPoint);
+        void SetSidebarWidth(const Point& rPointLogic);
         tools::Rectangle GetSidebarRect(const Point& rPointLogic);
         tools::ULong GetSidebarWidth(bool bPx = false) const;
         tools::ULong GetSidebarBorderWidth(bool bPx = false) const;
@@ -252,6 +252,8 @@ class SAL_DLLPUBLIC_RTTI SwPostItMgr final : public 
SfxListener,
 
         void DrawNotesForPage(OutputDevice *pOutDev, sal_uInt32 nPage);
         void PaintTile(OutputDevice& rRenderContext);
+
+        sw::sidebarwindows::SidebarPosition GetSidebarPos(const Point& 
rPointLogic);
 };
 
 #endif
diff --git a/sw/source/uibase/docvw/PostItMgr.cxx 
b/sw/source/uibase/docvw/PostItMgr.cxx
index c50ffd06485a..03e2b9db6997 100644
--- a/sw/source/uibase/docvw/PostItMgr.cxx
+++ b/sw/source/uibase/docvw/PostItMgr.cxx
@@ -81,6 +81,7 @@
 
 #include <annotsh.hxx>
 #include <swabstdlg.hxx>
+#include <pagefrm.hxx>
 #include <memory>
 
 // distance between Anchor Y and initial note position
@@ -2134,8 +2135,7 @@ tools::Rectangle SwPostItMgr::GetSidebarRect(const Point& 
rPointLogic)
     if (!nPageNum)
         return tools::Rectangle();
 
-    OSL_ENSURE(mPages.size() > nPageNum - 1, "SwPostitMgr:: page container 
size wrong");
-    return mPages[nPageNum - 1]->eSidebarPosition == 
sw::sidebarwindows::SidebarPosition::LEFT
+    return GetSidebarPos(rPointLogic) == 
sw::sidebarwindows::SidebarPosition::LEFT
                ? tools::Rectangle(
                      Point(aPageFrame.Left() - GetSidebarWidth() - 
GetSidebarBorderWidth(),
                            aPageFrame.Top()),
@@ -2149,13 +2149,23 @@ bool SwPostItMgr::IsHitSidebarDragArea(const Point& 
rPointPx)
 {
     if (!HasNotes() || !ShowNotes())
         return false;
-    const Point aPoint = mpEditWin->PixelToLogic(rPointPx);
-    tools::Rectangle aDragArea(GetSidebarRect(aPoint));
-    aDragArea.SetPos(Point(aDragArea.TopRight().X() - 50, 
aDragArea.TopRight().Y()));
+
+    const Point aPointLogic = mpEditWin->PixelToLogic(rPointPx);
+    sw::sidebarwindows::SidebarPosition eSidebarPosition = 
GetSidebarPos(aPointLogic);
+    if (eSidebarPosition == sw::sidebarwindows::SidebarPosition::NONE)
+        return false;
+
+    tools::Rectangle aDragArea(GetSidebarRect(aPointLogic));
+    aDragArea.SetTop(aPointLogic.Y());
+    if (eSidebarPosition == sw::sidebarwindows::SidebarPosition::RIGHT)
+        aDragArea.SetPos(Point(aDragArea.Right() - 50, aDragArea.Top()));
+    else
+        aDragArea.SetPos(Point(aDragArea.Left() - 50, aDragArea.Top()));
+
     Size aS(aDragArea.GetSize());
     aS.setWidth(100);
     aDragArea.SetSize(aS);
-    return aDragArea.Contains(aPoint);
+    return aDragArea.Contains(aPointLogic);
 }
 
 tools::Rectangle SwPostItMgr::GetBottomScrollRect(const tools::ULong aPage) 
const
@@ -2271,12 +2281,28 @@ bool SwPostItMgr::HasNotes() const
     return !mvPostItFields.empty();
 }
 
-void SwPostItMgr::SetSidebarWidth(Point aMousePos)
+void SwPostItMgr::SetSidebarWidth(const Point& rPointLogic)
 {
-    sal_uInt16 nZoom = mpWrtShell->GetViewOptions()->GetZoom();
-    tools::Long nPxWidth
-        = aMousePos.X() - 
mpEditWin->LogicToPixel(GetSidebarRect(aMousePos).TopLeft()).X();
-    double nFactor = static_cast<double>(nPxWidth) / 
static_cast<double>(nZoom);
+    tools::Rectangle nSidebarRect = GetSidebarRect(rPointLogic);
+    if (nSidebarRect.IsEmpty())
+        return;
+
+    sw::sidebarwindows::SidebarPosition eSidebarPosition = 
GetSidebarPos(rPointLogic);
+    if (eSidebarPosition == sw::sidebarwindows::SidebarPosition::NONE)
+        return;
+
+    // Calculate the width to be applied in logic units
+    tools::Long nLogicWidth;
+    if (eSidebarPosition == sw::sidebarwindows::SidebarPosition::RIGHT)
+        nLogicWidth = rPointLogic.X() - nSidebarRect.Left();
+    else
+        nLogicWidth = nSidebarRect.Right() - rPointLogic.X();
+
+    // The zoom level is conveniently used as reference to define the minimum 
width
+    const sal_uInt16 nZoom = mpWrtShell->GetViewOptions()->GetZoom();
+    double nFactor = 
static_cast<double>(mpEditWin->LogicToPixel(Point(nLogicWidth, 0)).X())
+                     / static_cast<double>(nZoom);
+    // The width may vary from 1x to 8x the zoom factor
     nFactor = std::clamp(nFactor, 1.0, 8.0);
     std::shared_ptr<comphelper::ConfigurationChanges> xChanges(
         comphelper::ConfigurationChanges::create());
@@ -2286,6 +2312,7 @@ void SwPostItMgr::SetSidebarWidth(Point aMousePos)
     // tdf#159146 After resizing the sidebar the layout and the ruler needs to 
be updated
     mpWrtShell->InvalidateLayout(true);
     mpView->GetHRuler().Invalidate();
+    mpView->InvalidateRulerPos();
 
     LayoutPostIts();
 }
@@ -2682,4 +2709,15 @@ void SwPostItMgr::UpdateResolvedStatus(const 
sw::annotation::SwAnnotationWin* to
     }
 }
 
+sw::sidebarwindows::SidebarPosition SwPostItMgr::GetSidebarPos(const Point& 
rPointLogic)
+{
+    if (const SwRootFrame* pLayout = mpWrtShell->GetLayout())
+    {
+        const SwPageFrame* pPageFrame = pLayout->GetPageAtPos(rPointLogic, 
nullptr, true);
+        if (pPageFrame)
+            return pPageFrame->SidebarPosition();
+    }
+    return sw::sidebarwindows::SidebarPosition::NONE;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/docvw/edtwin.cxx 
b/sw/source/uibase/docvw/edtwin.cxx
index daf39ec6446b..71ef81ca9d24 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -163,6 +163,9 @@ using namespace ::com::sun::star;
  */
 static bool g_bInputLanguageSwitched = false;
 
+// Used to draw the guide line while resizing the comment sidebar width
+static tools::Rectangle aLastCommentSidebarPos;
+
 // Usually in MouseButtonUp a selection is revoked when the selection is
 // not currently being pulled open. Unfortunately in MouseButtonDown there
 // is being selected at double/triple click. That selection is completely
@@ -2992,9 +2995,11 @@ void SwEditWin::MouseButtonDown(const MouseEvent& _rMEvt)
         }
     }
 
-    if (m_rView.GetPostItMgr()->IsHitSidebarDragArea(aMEvt.GetPosPixel()))
+    if (aMEvt.GetButtons() == MOUSE_LEFT && 
m_rView.GetPostItMgr()->IsHitSidebarDragArea(aMEvt.GetPosPixel()))
     {
         mbIsDragSidebar = true;
+        // Capture mouse to keep tracking even if the mouse leaves the 
document window
+        CaptureMouse();
         return;
     }
 
@@ -4000,6 +4005,14 @@ void SwEditWin::MouseButtonDown(const MouseEvent& _rMEvt)
     }
     else if (MOUSE_RIGHT == aMEvt.GetButtons())
     {
+        // If right-click while dragging to resize the comment width, stop 
resizing
+        if (mbIsDragSidebar)
+        {
+            ReleaseCommentGuideLine();
+            ReleaseMouse();
+            return;
+        }
+
         if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton()
             && aMEvt.GetModifier() == KEY_MOD1)
         {
@@ -4129,12 +4142,19 @@ void SwEditWin::MouseMove(const MouseEvent& _rMEvt)
             return;
         }
     }
+
     if (m_rView.GetPostItMgr()->IsHitSidebarDragArea(rMEvt.GetPosPixel()))
     {
         SetPointer(PointerStyle::HSizeBar);
         return;
     }
 
+    if (mbIsDragSidebar)
+    {
+        DrawCommentGuideLine(rMEvt.GetPosPixel());
+        return;
+    }
+
     //ignore key modifiers for format paintbrush
     {
         bool bExecFormatPaintbrush = m_pApplyTempl && 
m_pApplyTempl->m_pFormatClipboard
@@ -4688,8 +4708,10 @@ void SwEditWin::MouseButtonUp(const MouseEvent& rMEvt)
 
     if (mbIsDragSidebar)
     {
-        m_rView.GetPostItMgr()->SetSidebarWidth(rMEvt.GetPosPixel());
-        mbIsDragSidebar = false;
+        SetSidebarWidth(rMEvt.GetPosPixel());
+        // While dragging the mouse is captured, so we need to release it here
+        ReleaseMouse();
+        ReleaseCommentGuideLine();
         return;
     }
 
@@ -6302,6 +6324,57 @@ void SwEditWin::SelectMenuPosition(SwWrtShell& rSh, 
const Point& rMousePos )
     }
 }
 
+void SwEditWin::DrawCommentGuideLine(Point aPointPixel)
+{
+    const Point aPointLogic = PixelToLogic(aPointPixel);
+
+    sw::sidebarwindows::SidebarPosition eSidebarPosition
+        = m_rView.GetPostItMgr()->GetSidebarPos(aPointLogic);
+    if (eSidebarPosition == sw::sidebarwindows::SidebarPosition::NONE) // 
should never happen
+        return;
+
+    tools::Long nPosX;
+    sal_uInt16 nZoom = m_rView.GetWrtShell().GetViewOptions()->GetZoom();
+    if (eSidebarPosition == sw::sidebarwindows::SidebarPosition::RIGHT)
+    {
+        tools::Long nSidebarRectLeft
+            = 
LogicToPixel(m_rView.GetPostItMgr()->GetSidebarRect(aPointLogic).TopLeft()).X();
+        tools::Long nPxWidth = aPointPixel.X() - nSidebarRectLeft;
+        nPosX = nSidebarRectLeft + std::clamp<tools::Long>(nPxWidth, 1 * 
nZoom, 8 * nZoom);
+    }
+    else
+    {
+        tools::Long nSidebarRectRight
+            = 
LogicToPixel(m_rView.GetPostItMgr()->GetSidebarRect(aPointLogic).TopRight()).X();
+        tools::Long nPxWidth = nSidebarRectRight - aPointPixel.X();
+        nPosX = nSidebarRectRight - std::clamp<tools::Long>(nPxWidth, 1 * 
nZoom, 8 * nZoom);
+    }
+
+
+    // We need two InvertTracking calls here to "erase" the previous and draw 
the new position at each mouse move
+    InvertTracking(aLastCommentSidebarPos, ShowTrackFlags::Clip | 
ShowTrackFlags::Split);
+    const tools::Long nHeight = GetOutDev()->GetOutputSizePixel().Height();
+    aLastCommentSidebarPos
+        = tools::Rectangle(PixelToLogic(Point(nPosX, 0)), 
PixelToLogic(Point(nPosX, nHeight)));
+    InvertTracking(aLastCommentSidebarPos, ShowTrackFlags::Clip | 
ShowTrackFlags::Split);
+}
+
+void SwEditWin::ReleaseCommentGuideLine()
+{
+    InvertTracking(aLastCommentSidebarPos, ShowTrackFlags::Clip | 
ShowTrackFlags::Split);
+    aLastCommentSidebarPos = tools::Rectangle();
+    mbIsDragSidebar = false;
+}
+
+void SwEditWin::SetSidebarWidth(const Point& rPointPixel)
+{
+    if (aLastCommentSidebarPos.IsEmpty())
+        return;
+    // aLastCommentSidebarPos right and left positions are the same so either 
can be used here
+    m_rView.GetPostItMgr()->SetSidebarWidth(
+        Point(aLastCommentSidebarPos.Right(), PixelToLogic(rPointPixel).Y()));
+}
+
 static SfxShell* lcl_GetTextShellFromDispatcher( SwView const & rView )
 {
     // determine Shell
diff --git a/sw/source/uibase/inc/edtwin.hxx b/sw/source/uibase/inc/edtwin.hxx
index ac6bbaeeeeff..53e7ddf16568 100644
--- a/sw/source/uibase/inc/edtwin.hxx
+++ b/sw/source/uibase/inc/edtwin.hxx
@@ -298,6 +298,12 @@ public:
     void ToggleOutlineContentVisibility(const size_t nOutlinePos, const bool 
bSubs);
 
     virtual FactoryFunction GetUITestFactory() const override;
+
+    // Draws a guide line at the specified position
+    void DrawCommentGuideLine(Point aPointPixel);
+    // Stops drawing the guide line
+    void ReleaseCommentGuideLine();
+    void SetSidebarWidth(const Point& rPointPixel);
 };
 
 extern bool g_bModePushed;
diff --git a/sw/source/uibase/inc/swruler.hxx b/sw/source/uibase/inc/swruler.hxx
index 6a9b9f27e92d..13435972a1f3 100644
--- a/sw/source/uibase/inc/swruler.hxx
+++ b/sw/source/uibase/inc/swruler.hxx
@@ -14,6 +14,8 @@
 #include <vcl/timer.hxx>
 #include <vcl/virdev.hxx>
 
+#include <SidebarWindowsTypes.hxx>
+
 class SwViewShell;
 class View;
 namespace vcl { class Window; }
@@ -81,6 +83,8 @@ private:
      */
     virtual void Update() override;
 
+    sw::sidebarwindows::SidebarPosition GetSidebarPosition();
+
     tools::Rectangle GetDragArea();
 
     /**
diff --git a/sw/source/uibase/misc/swruler.cxx 
b/sw/source/uibase/misc/swruler.cxx
index 2551bf1dc03e..4d6f5e5e64c2 100644
--- a/sw/source/uibase/misc/swruler.cxx
+++ b/sw/source/uibase/misc/swruler.cxx
@@ -16,6 +16,7 @@
 #include <edtwin.hxx>
 #include <PostItMgr.hxx>
 #include <view.hxx>
+#include <wrtsh.hxx>
 #include <cmdid.h>
 #include <sfx2/request.hxx>
 #include <vcl/commandevent.hxx>
@@ -106,6 +107,13 @@ void SwCommentRuler::dispose()
     SvxRuler::dispose();
 }
 
+sw::sidebarwindows::SidebarPosition SwCommentRuler::GetSidebarPosition()
+{
+    if (SwPostItMgr* pPostItMgr = mpViewShell->GetPostItMgr())
+        return 
pPostItMgr->GetSidebarPos(mpSwWin->GetView().GetWrtShell().GetCursorDocPos());
+    return sw::sidebarwindows::SidebarPosition::NONE;
+}
+
 void SwCommentRuler::Paint(vcl::RenderContext& rRenderContext, const 
tools::Rectangle& rRect)
 {
     if (comphelper::LibreOfficeKit::isActive())
@@ -200,7 +208,10 @@ void SwCommentRuler::Command(const CommandEvent& rCEvt)
 void SwCommentRuler::MouseMove(const MouseEvent& rMEvt)
 {
     if (mbIsDrag)
+    {
+        mpSwWin->DrawCommentGuideLine(rMEvt.GetPosPixel());
         return;
+    }
 
     SvxRuler::MouseMove(rMEvt);
     if (!mpViewShell->GetPostItMgr() || 
!mpViewShell->GetPostItMgr()->HasNotes())
@@ -221,6 +232,15 @@ void SwCommentRuler::MouseMove(const MouseEvent& rMEvt)
 
 void SwCommentRuler::MouseButtonDown(const MouseEvent& rMEvt)
 {
+    // If right-click while dragging to resize the comment width, stop resizing
+    if (mbIsDrag && rMEvt.GetButtons() == MOUSE_RIGHT)
+    {
+        ReleaseMouse();
+        mpSwWin->ReleaseCommentGuideLine();
+        mbIsDrag = false;
+        return;
+    }
+
     Point aMousePos = rMEvt.GetPosPixel();
     if (!rMEvt.IsLeft() || IsTracking()
         || (!GetCommentControlRegion().Contains(aMousePos) && 
!GetDragArea().Contains(aMousePos)))
@@ -232,6 +252,7 @@ void SwCommentRuler::MouseButtonDown(const MouseEvent& 
rMEvt)
     if (GetDragArea().Contains(aMousePos))
     {
         mbIsDrag = true;
+        CaptureMouse();
     }
     else
     {
@@ -254,7 +275,10 @@ void SwCommentRuler::MouseButtonUp(const MouseEvent& rMEvt)
         SvxRuler::MouseButtonUp(rMEvt);
         return;
     }
-    mpViewShell->GetPostItMgr()->SetSidebarWidth(rMEvt.GetPosPixel());
+
+    mpSwWin->SetSidebarWidth(rMEvt.GetPosPixel());
+    ReleaseMouse();
+    mpSwWin->ReleaseCommentGuideLine();
     mbIsDrag = false;
     Invalidate();
 }
@@ -280,7 +304,10 @@ void SwCommentRuler::UpdateCommentHelpText()
 tools::Rectangle SwCommentRuler::GetDragArea()
 {
     tools::Rectangle base(GetCommentControlRegion());
-    base.Move(Size(base.GetWidth() - 5, 0));
+    if (GetSidebarPosition() == sw::sidebarwindows::SidebarPosition::LEFT)
+        base.Move(-5, 0);
+    else
+        base.Move(Size(base.GetWidth() - 5, 0));
     base.SetWidth(10);
     return base;
 }
@@ -300,7 +327,7 @@ tools::Rectangle SwCommentRuler::GetCommentControlRegion()
 
     //FIXME When the page width is larger then screen, the ruler is misplaced 
by one pixel
     tools::Long nLeft = GetPageOffset();
-    if (GetTextRTL())
+    if (GetSidebarPosition() == sw::sidebarwindows::SidebarPosition::LEFT)
         nLeft += GetBorderOffset() - nSidebarWidth;
     else
         nLeft += GetWinOffset() + mpSwWin->LogicToPixel(Size(GetPageWidth(), 
0)).Width();

Reply via email to