[Libreoffice-commits] core.git: sw/inc sw/qa sw/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Tue Jul 9 18:03:04 UTC 2019


 sw/inc/HandleAnchorNodeChg.hxx                        |    5 +
 sw/qa/extras/uiwriter/data2/image-comment-at-char.odt |binary
 sw/qa/extras/uiwriter/uiwriter2.cxx                   |   29 +++++++
 sw/source/core/layout/atrfrm.cxx                      |   69 ++++++++++++++++--
 4 files changed, 99 insertions(+), 4 deletions(-)

New commits:
commit 5da29a31903e0c11802548327b41511519e61d7d
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Tue Jul 9 17:48:14 2019 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Tue Jul 9 20:01:55 2019 +0200

    sw comments on frames: fix comment handling when changing at-char anchor
    
    If the user drags the at-char image and the anchor changes, then need to
    update the comment anchor (and its annotation range) as well. Use the
    same API that's used by SwTransferable::PrivateDrop(), except work with
    doc model positions, not with screen coordinates, like drag&drop does.
    
    Change-Id: Ib9610b3eddc77f9973b68a1c5c8cdbe1f7079ab9
    Reviewed-on: https://gerrit.libreoffice.org/75312
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    Tested-by: Jenkins

diff --git a/sw/inc/HandleAnchorNodeChg.hxx b/sw/inc/HandleAnchorNodeChg.hxx
index 7453e4e6b9be..e01da4c932a6 100644
--- a/sw/inc/HandleAnchorNodeChg.hxx
+++ b/sw/inc/HandleAnchorNodeChg.hxx
@@ -59,6 +59,11 @@ private:
     // and that re-creation of fly frames is necessary.
     bool mbAnchorNodeChanged;
 
+    /// If the fly frame has a comment, this points to the old comment anchor.
+    std::unique_ptr<SwPosition> mpCommentAnchor;
+
+    SwWrtShell* mpWrtShell;
+
     SwHandleAnchorNodeChg( const SwHandleAnchorNodeChg& ) = delete;
     void operator=( const SwHandleAnchorNodeChg ) = delete;
 };
diff --git a/sw/qa/extras/uiwriter/data2/image-comment-at-char.odt b/sw/qa/extras/uiwriter/data2/image-comment-at-char.odt
index a3638ffe7276..ac6a06780a81 100644
Binary files a/sw/qa/extras/uiwriter/data2/image-comment-at-char.odt and b/sw/qa/extras/uiwriter/data2/image-comment-at-char.odt differ
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index b0c08917e787..83a49883dbc6 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -1647,6 +1647,35 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testImageCommentAtChar)
     // 1', i.e. the comment of the image was not deleted when the image was deleted.
     CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0),
                          pDoc->getIDocumentMarkAccess()->getAnnotationMarksCount());
+
+    // Undo the deletion and move the image down, so the anchor changes.
+    pView->GetViewFrame()->GetDispatcher()->Execute(SID_UNDO, SfxCallMode::SYNCHRON);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1),
+                         pDoc->getIDocumentMarkAccess()->getAnnotationMarksCount());
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    Point aNewAnchor = pWrtShell->GetFlyRect().TopLeft();
+    aNewAnchor.Move(0, 600);
+    pWrtShell->SetFlyPos(aNewAnchor);
+
+    // Get the image anchor doc model position.
+    SwFlyFrame* pFly = pWrtShell->GetCurrFlyFrame(false);
+    CPPUNIT_ASSERT(pFly);
+    SwFrameFormat& rFlyFormat = pFly->GetFrameFormat();
+    const SwPosition* pImageAnchor = rFlyFormat.GetAnchor().GetContentAnchor();
+    CPPUNIT_ASSERT(pImageAnchor);
+
+    // Get the annotation mark doc model start.
+    auto it = pDoc->getIDocumentMarkAccess()->getAnnotationMarksBegin();
+    CPPUNIT_ASSERT(it != pDoc->getIDocumentMarkAccess()->getAnnotationMarksEnd());
+    const sw::mark::IMark* pMark = *it;
+    const SwPosition& rAnnotationMarkStart = pMark->GetMarkPos();
+
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: SwPosition (node 14, offset 15)
+    // - Actual  : SwPosition (node 12, offset 3)
+    // This means moving the image anchor did not move the comment anchor / annotation mark, so the
+    // image and its comment got out of sync.
+    CPPUNIT_ASSERT_EQUAL(*pImageAnchor, rAnnotationMarkStart);
 }
 
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf120338)
diff --git a/sw/source/core/layout/atrfrm.cxx b/sw/source/core/layout/atrfrm.cxx
index 0cbb44249644..4969bdc54599 100644
--- a/sw/source/core/layout/atrfrm.cxx
+++ b/sw/source/core/layout/atrfrm.cxx
@@ -87,13 +87,13 @@
 #include <drawdoc.hxx>
 #include <hints.hxx>
 
-#ifndef NDEBUG
 #include <ndtxt.hxx>
-#endif
 
 #include <svx/sdr/attribute/sdrallfillattributeshelper.hxx>
 #include <svx/xfillit0.hxx>
 #include <svl/itemiter.hxx>
+#include <wrtsh.hxx>
+#include <txtfld.hxx>
 
 using namespace ::com::sun::star;
 
@@ -3224,15 +3224,16 @@ SwHandleAnchorNodeChg::SwHandleAnchorNodeChg( SwFlyFrameFormat& _rFlyFrameFormat
                                               const SwFormatAnchor& _rNewAnchorFormat,
                                               SwFlyFrame const * _pKeepThisFlyFrame )
     : mrFlyFrameFormat( _rFlyFrameFormat ),
-      mbAnchorNodeChanged( false )
+      mbAnchorNodeChanged( false ),
+      mpWrtShell(nullptr)
 {
+    const SwFormatAnchor& aOldAnchorFormat(_rFlyFrameFormat.GetAnchor());
     const RndStdIds nNewAnchorType( _rNewAnchorFormat.GetAnchorId() );
     if ( ((nNewAnchorType == RndStdIds::FLY_AT_PARA) ||
           (nNewAnchorType == RndStdIds::FLY_AT_CHAR)) &&
          _rNewAnchorFormat.GetContentAnchor() &&
          _rNewAnchorFormat.GetContentAnchor()->nNode.GetNode().GetContentNode() )
     {
-        const SwFormatAnchor& aOldAnchorFormat( _rFlyFrameFormat.GetAnchor() );
         if ( aOldAnchorFormat.GetAnchorId() == nNewAnchorType &&
              aOldAnchorFormat.GetContentAnchor() &&
              aOldAnchorFormat.GetContentAnchor()->nNode.GetNode().GetContentNode() &&
@@ -3275,6 +3276,18 @@ SwHandleAnchorNodeChg::SwHandleAnchorNodeChg( SwFlyFrameFormat& _rFlyFrameFormat
             }
         }
     }
+
+    if (aOldAnchorFormat.GetContentAnchor()
+        && aOldAnchorFormat.GetAnchorId() == RndStdIds::FLY_AT_CHAR)
+    {
+        mpCommentAnchor.reset(new SwPosition(*aOldAnchorFormat.GetContentAnchor()));
+    }
+
+    if (_pKeepThisFlyFrame)
+    {
+        SwViewShell* pViewShell = _pKeepThisFlyFrame->getRootFrame()->GetCurrShell();
+        mpWrtShell = dynamic_cast<SwWrtShell*>(pViewShell);
+    }
 }
 
 SwHandleAnchorNodeChg::~SwHandleAnchorNodeChg()
@@ -3283,6 +3296,54 @@ SwHandleAnchorNodeChg::~SwHandleAnchorNodeChg()
     {
         mrFlyFrameFormat.MakeFrames();
     }
+
+    // See if the fly frame had a comment: if so, move it to the new anchor as well.
+    if (!mpCommentAnchor)
+    {
+        return;
+    }
+
+    SwTextNode* pTextNode = mpCommentAnchor->nNode.GetNode().GetTextNode();
+    if (!pTextNode)
+    {
+        return;
+    }
+
+    const SwTextField* pField = pTextNode->GetFieldTextAttrAt(mpCommentAnchor->nContent.GetIndex());
+    if (!pField || pField->GetFormatField().GetField()->GetTyp()->Which() != SwFieldIds::Postit)
+    {
+        return;
+    }
+
+    if (!mpWrtShell)
+    {
+        return;
+    }
+
+    // Save current cursor position, so we can restore it later.
+    mpWrtShell->Push();
+
+    // Set up the source of the move: the old comment anchor.
+    {
+        SwPaM& rCursor = mpWrtShell->GetCurrentShellCursor();
+        *rCursor.GetPoint() = *mpCommentAnchor;
+        rCursor.SetMark();
+        *rCursor.GetMark() = *mpCommentAnchor;
+        ++rCursor.GetMark()->nContent;
+    }
+
+    // Set up the target of the move: the new comment anchor.
+    const SwFormatAnchor& rNewAnchorFormat = mrFlyFrameFormat.GetAnchor();
+    mpWrtShell->CreateCursor();
+    *mpWrtShell->GetCurrentShellCursor().GetPoint() = *rNewAnchorFormat.GetContentAnchor();
+
+    // Move by copying and deleting.
+    mpWrtShell->SwEditShell::Copy(mpWrtShell);
+    mpWrtShell->DestroyCursor();
+
+    mpWrtShell->Delete();
+
+    mpWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
 }
 
 namespace sw


More information about the Libreoffice-commits mailing list