sw/inc/HandleAnchorNodeChg.hxx | 5 + sw/inc/swrect.hxx | 3 sw/qa/extras/uiwriter/data2/image-comment-at-char.odt |binary sw/qa/extras/uiwriter/uiwriter2.cxx | 30 +++++++ sw/source/core/layout/atrfrm.cxx | 69 ++++++++++++++++-- 5 files changed, 102 insertions(+), 5 deletions(-)
New commits: commit c4b07455859c8ae7e5c3af12c36f03d52b7de4f8 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Tue Jul 9 17:48:14 2019 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Jul 10 16:06:19 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. (cherry picked from commit 5da29a31903e0c11802548327b41511519e61d7d) Change-Id: Ib9610b3eddc77f9973b68a1c5c8cdbe1f7079ab9 Reviewed-on: https://gerrit.libreoffice.org/75347 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/inc/HandleAnchorNodeChg.hxx b/sw/inc/HandleAnchorNodeChg.hxx index 576efa46890f..6cf907227de7 100644 --- a/sw/inc/HandleAnchorNodeChg.hxx +++ b/sw/inc/HandleAnchorNodeChg.hxx @@ -64,6 +64,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/inc/swrect.hxx b/sw/inc/swrect.hxx index 924e4adc2ebd..03d252d3101f 100644 --- a/sw/inc/swrect.hxx +++ b/sw/inc/swrect.hxx @@ -23,6 +23,7 @@ #include <sal/log.hxx> #include <tools/gen.hxx> +#include "swdllapi.h" class SvStream; @@ -30,7 +31,7 @@ class SvStream; /// This is half-open so m_Point.X() + m_Size.getWidth() is *not* included. /// Note the tools Rectangle is (usually? sometimes?) closed so there's a /// SVRect() to subtract 1 for the conversion. -class SAL_WARN_UNUSED SwRect +class SAL_WARN_UNUSED SW_DLLPUBLIC SwRect { Point m_Point; Size m_Size; 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 7f161e0d9369..954db3082ea1 100644 --- a/sw/qa/extras/uiwriter/uiwriter2.cxx +++ b/sw/qa/extras/uiwriter/uiwriter2.cxx @@ -29,6 +29,7 @@ #include <sfx2/dispatch.hxx> #include <view.hxx> #include <cmdid.h> +#include <fmtanchr.hxx> namespace { @@ -570,6 +571,35 @@ void 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 std::shared_ptr<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_SUITE_REGISTRATION(SwUiWriterTest2); diff --git a/sw/source/core/layout/atrfrm.cxx b/sw/source/core/layout/atrfrm.cxx index 118f551cbf4c..807816542d4b 100644 --- a/sw/source/core/layout/atrfrm.cxx +++ b/sw/source/core/layout/atrfrm.cxx @@ -80,13 +80,13 @@ #include <pagedeschint.hxx> #include <drawdoc.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; @@ -3237,15 +3237,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() && @@ -3286,6 +3287,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() @@ -3294,6 +3307,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); } // class SwDrawFrameFormat _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits