sw/qa/core/layout/flycnt.cxx       |   33 +++++++++++++++++++++++++++++++++
 sw/source/core/frmedt/feshview.cxx |   22 ++++++++++++++++++++++
 sw/source/core/inc/dflyobj.hxx     |    4 +++-
 3 files changed, 58 insertions(+), 1 deletion(-)

New commits:
commit 17367a67cd39109006060176b04bc2b174a17e48
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Apr 13 08:12:29 2023 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Thu Apr 13 09:22:03 2023 +0200

    sw floattable: restrict selection of follow flys
    
    Select a follow flys that is at the top of the page, drag it towards the
    bottom of the page, release it, it'll jump back to its original
    position, which is frustrating.
    
    The reason for this is that the layout ignores the vertical offset for
    follow flys on purpose, but this is communicated to the user poorly.
    
    Fix the problem by selecting the master fly on fly selection (for split
    flys), this allows changing the horizontal position for all flys in the
    chain and changing the vertical position for the master flys. This is
    now less confusing, since the indicator of the new position is also
    drawn for the master fly.
    
    This is somewhat similar to what
    7596e26fd259ce5445212949403e7cd32303b2bd (Add
    SwTextBoxHelper::findShapes, 2014-06-24) did for textboxes, but there we
    selected the owning draw shape of the fly frame.
    
    Change-Id: Ie8171d32a306bfb5d28cc750db5bbae6021ef72f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150310
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx
index c72f9fff0459..72591730bfb2 100644
--- a/sw/qa/core/layout/flycnt.cxx
+++ b/sw/qa/core/layout/flycnt.cxx
@@ -9,6 +9,8 @@
 
 #include <swmodeltestbase.hxx>
 
+#include <svx/svdview.hxx>
+
 #include <IDocumentLayoutAccess.hxx>
 #include <anchoredobject.hxx>
 #include <flyfrms.hxx>
@@ -26,6 +28,7 @@
 #include <frameformats.hxx>
 #include <cellfrm.hxx>
 #include <ndtxt.hxx>
+#include <dflyobj.hxx>
 
 namespace
 {
@@ -654,6 +657,36 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFly3rdRowDelete)
     // Without the accompanying fix in place, this test would have failed, 
page 3 was not deleted.
     CPPUNIT_ASSERT(!pPage2->GetNext());
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testSplitFly2ndRowSelect)
+{
+    // Given a document with a multi-page floating table:
+    createSwDoc("floattable.docx");
+
+    // When selecting the second row:
+    SwDoc* pDoc = getSwDoc();
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    auto pPage1 = dynamic_cast<SwPageFrame*>(pLayout->Lower());
+    CPPUNIT_ASSERT(pPage1);
+    auto pPage2 = dynamic_cast<SwPageFrame*>(pPage1->GetNext());
+    SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs();
+    auto pPage2Fly = dynamic_cast<SwFlyAtContentFrame*>(rPage2Objs[0]);
+    const SwRect& aFollowArea = pPage2Fly->getFrameArea();
+    Point aTopCenter((aFollowArea.Left() + aFollowArea.Right()) / 2, 
aFollowArea.Top());
+    SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
+    pWrtShell->SelectObj(aTopCenter);
+
+    // Then make sure the first row is selected:
+    const SdrMarkList& rMarkList = 
pWrtShell->GetDrawView()->GetMarkedObjectList();
+    SdrObject* pSelectedObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+    auto pSelectedVirtObj = dynamic_cast<SwVirtFlyDrawObj*>(pSelectedObj);
+    auto pSelected = 
static_cast<SwFlyAtContentFrame*>(pSelectedVirtObj->GetFlyFrame());
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 5
+    // - Actual  : 17
+    // i.e. a follow fly was possible to select (instead of its master)
+    CPPUNIT_ASSERT_EQUAL(pPage2Fly->GetPrecede()->GetFrameId(), 
pSelected->GetFrameId());
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/frmedt/feshview.cxx 
b/sw/source/core/frmedt/feshview.cxx
index be160057093e..ef9497b53f38 100644
--- a/sw/source/core/frmedt/feshview.cxx
+++ b/sw/source/core/frmedt/feshview.cxx
@@ -90,6 +90,7 @@
 #include <sfx2/lokhelper.hxx>
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
 #include <calbck.hxx>
+#include <flyfrms.hxx>
 #include <basegfx/polygon/b2dpolygontools.hxx>
 #include <svx/svxids.hrc>
 #include <osl/diagnose.h>
@@ -277,6 +278,27 @@ bool SwFEShell::SelectObj( const Point& rPt, sal_uInt8 
nFlag, SdrObject *pObj )
         }
     }
 
+    if (rMrkList.GetMarkCount() == 1)
+    {
+        SwFlyFrame* pSelFly = ::GetFlyFromMarked(&rMrkList, this);
+        if (pSelFly && pSelFly->IsFlySplitAllowed())
+        {
+            auto pMaster = static_cast<SwFlyAtContentFrame*>(pSelFly);
+            while (pMaster->IsFollow())
+            {
+                pMaster = pMaster->GetPrecede();
+            }
+            if (pMaster != pSelFly)
+            {
+                // A follow fly frame is selected, select the master instead. 
Selection of a follow
+                // would not be ideal, since one can't customize its vertical 
position (always
+                // starts at the top of the page).
+                pDView->UnmarkAll();
+                pDView->MarkObj(pMaster->DrawObj(), Imp()->GetPageView(), 
bAddSelect, bEnterGroup);
+            }
+        }
+    }
+
     if ( rMrkList.GetMarkCount() == 1 )
     {
         SwFlyFrame *pSelFly = ::GetFlyFromMarked( &rMrkList, this );
diff --git a/sw/source/core/inc/dflyobj.hxx b/sw/source/core/inc/dflyobj.hxx
index 96b12dcf49f8..fe43f24c9045 100644
--- a/sw/source/core/inc/dflyobj.hxx
+++ b/sw/source/core/inc/dflyobj.hxx
@@ -23,6 +23,8 @@
 #include <svx/svdovirt.hxx>
 #include <svx/svdobj.hxx>
 
+#include <swdllapi.h>
+
 namespace drawinglayer::geometry { class ViewInformation2D; }
 
 class SwFlyFrame;
@@ -62,7 +64,7 @@ public:
 // shown multiple times if needed (header/footer).
 // For example, if an SwFlyFrameFormat is anchored in a header, then all pages 
will have a separate
 // SwVirtFlyDrawObj in their headers.
-class SwVirtFlyDrawObj final : public SdrVirtObj
+class SW_DLLPUBLIC SwVirtFlyDrawObj final : public SdrVirtObj
 {
 private:
     SwFlyFrame *m_pFlyFrame;

Reply via email to