summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2019-07-09 17:48:14 +0200
committerMiklos Vajna <vmiklos@collabora.com>2019-07-09 20:01:55 +0200
commit5da29a31903e0c11802548327b41511519e61d7d (patch)
tree57817a7435f8bdba3883a8854829d22cfeb2c731
parent44a6335f49a64ac77207d3aa46c267503c65c5ff (diff)
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@collabora.com> Tested-by: Jenkins
-rw-r--r--sw/inc/HandleAnchorNodeChg.hxx5
-rw-r--r--sw/qa/extras/uiwriter/data2/image-comment-at-char.odtbin9777 -> 9985 bytes
-rw-r--r--sw/qa/extras/uiwriter/uiwriter2.cxx29
-rw-r--r--sw/source/core/layout/atrfrm.cxx69
4 files changed, 99 insertions, 4 deletions
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
--- a/sw/qa/extras/uiwriter/data2/image-comment-at-char.odt
+++ b/sw/qa/extras/uiwriter/data2/image-comment-at-char.odt
Binary files 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