diff options
-rw-r--r-- | sw/inc/HandleAnchorNodeChg.hxx | 5 | ||||
-rw-r--r-- | sw/qa/extras/uiwriter/data2/image-comment-at-char.odt | bin | 9777 -> 9985 bytes | |||
-rw-r--r-- | sw/qa/extras/uiwriter/uiwriter2.cxx | 29 | ||||
-rw-r--r-- | sw/source/core/layout/atrfrm.cxx | 69 |
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 Binary files differindex 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 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 |