sw/inc/postithelper.hxx | 3 sw/qa/extras/uiwriter/data2/image-comment-at-char.odt |binary sw/qa/extras/uiwriter/uiwriter2.cxx | 30 ++++++ sw/qa/extras/unowriter/unowriter.cxx | 16 +++ sw/source/core/fields/postithelper.cxx | 88 ++++++++++++++++-- sw/source/uibase/docvw/PostItMgr.cxx | 2 sw/source/uibase/fldui/fldmgr.cxx | 2 sw/source/uibase/inc/fldmgr.hxx | 2 sw/source/uibase/inc/wrtsh.hxx | 2 sw/source/uibase/wrtsh/wrtsh1.cxx | 18 +++ sw/source/uibase/wrtsh/wrtsh2.cxx | 18 +++ 11 files changed, 171 insertions(+), 10 deletions(-)
New commits: commit 4e05e2f11ad1328d46289bda57d8ac784e31da1f Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon Jul 1 16:08:10 2019 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu Jul 4 09:02:30 2019 +0200 sw comments on frames: fix UI to be able to annotate with at-char anchors We used to just comment the doc model position at the end of the paragraph of the image anchor. Change this, so that in case an at-char anchored image is commented, first we insert the comment (which creates a placeholder character), and then we set the annotation range to cover exactly that placeholder character. This results in a layout that shows a commented image. (cherry picked from commit 5cb34f1c38be72047be1c4ed8357c5e87134c6a2) Conflicts: sw/qa/extras/uiwriter/uiwriter2.cxx sw/source/uibase/inc/fldmgr.hxx Change-Id: Ie21d62ddb9f55f3e06ee39d9eccfaa0446ce7845 Reviewed-on: https://gerrit.libreoffice.org/75038 Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Tested-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/qa/extras/uiwriter/data2/image-comment-at-char.odt b/sw/qa/extras/uiwriter/data2/image-comment-at-char.odt new file mode 100644 index 000000000000..a3638ffe7276 Binary files /dev/null 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 cc64ae74c37f..daa813247bf4 100644 --- a/sw/qa/extras/uiwriter/uiwriter2.cxx +++ b/sw/qa/extras/uiwriter/uiwriter2.cxx @@ -50,6 +50,7 @@ public: void testMixedFormFieldInsertion(); void testTdf122942(); void testImageComment(); + void testImageCommentAtChar(); CPPUNIT_TEST_SUITE(SwUiWriterTest2); CPPUNIT_TEST(testTdf101534); @@ -63,6 +64,7 @@ public: CPPUNIT_TEST(testMixedFormFieldInsertion); CPPUNIT_TEST(testTdf122942); CPPUNIT_TEST(testImageComment); + CPPUNIT_TEST(testImageCommentAtChar); CPPUNIT_TEST_SUITE_END(); private: @@ -511,6 +513,34 @@ void SwUiWriterTest2::testImageComment() getProperty<OUString>(getRun(xPara, 5), "TextPortionType")); } +void SwUiWriterTest2::testImageCommentAtChar() +{ + // Load a document with an at-char image in it. + SwDoc* pDoc = createDoc("image-comment-at-char.odt"); + SwView* pView = pDoc->GetDocShell()->GetView(); + + // Select the image. + pView->GetViewFrame()->GetDispatcher()->Execute(FN_CNTNT_TO_NEXT_FRAME, SfxCallMode::SYNCHRON); + + // Insert a comment while the image is selected. + pView->GetViewFrame()->GetDispatcher()->Execute(FN_POSTIT, SfxCallMode::SYNCHRON); + + // Verify that the comment is around the image. + // Without the accompanying fix in place, this test would have failed, as the comment was + // anchored at the end of the paragraph, it was not around the image. + uno::Reference<text::XTextRange> xPara = getParagraph(1); + CPPUNIT_ASSERT_EQUAL(OUString("Text"), + getProperty<OUString>(getRun(xPara, 1), "TextPortionType")); + CPPUNIT_ASSERT_EQUAL(OUString("Annotation"), + getProperty<OUString>(getRun(xPara, 2), "TextPortionType")); + CPPUNIT_ASSERT_EQUAL(OUString("Frame"), + getProperty<OUString>(getRun(xPara, 3), "TextPortionType")); + CPPUNIT_ASSERT_EQUAL(OUString("AnnotationEnd"), + getProperty<OUString>(getRun(xPara, 4), "TextPortionType")); + CPPUNIT_ASSERT_EQUAL(OUString("Text"), + getProperty<OUString>(getRun(xPara, 5), "TextPortionType")); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest2); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/fldui/fldmgr.cxx b/sw/source/uibase/fldui/fldmgr.cxx index 687e4d84cd25..375958956593 100644 --- a/sw/source/uibase/fldui/fldmgr.cxx +++ b/sw/source/uibase/fldui/fldmgr.cxx @@ -1489,7 +1489,7 @@ bool SwFieldMgr::InsertField( // insert pCurShell->StartAllAction(); - pCurShell->Insert( *pField ); + pCurShell->Insert(*pField, rData.m_pAnnotationRange.get()); if (TYP_INPUTFLD == rData.m_nTypeId) { diff --git a/sw/source/uibase/inc/fldmgr.hxx b/sw/source/uibase/inc/fldmgr.hxx index 21153ab96823..64495e7d4215 100644 --- a/sw/source/uibase/inc/fldmgr.hxx +++ b/sw/source/uibase/inc/fldmgr.hxx @@ -78,6 +78,8 @@ struct SwInsertField_Data css::uno::Any m_aDBConnection; css::uno::Any m_aDBColumn; VclPtr<vcl::Window> m_pParent; // parent dialog used for SwWrtShell::StartInputFieldDlg() + /// Marks the PostIt field's annotation start/end if it differs from the cursor selection. + std::unique_ptr<SwPaM> m_pAnnotationRange; SwInsertField_Data(sal_uInt16 nType, sal_uInt16 nSub, const OUString& rPar1, const OUString& rPar2, sal_uInt32 nFormatId, SwWrtShell* pShell = nullptr, sal_Unicode cSep = ' ', bool bIsAutoLanguage = true) : diff --git a/sw/source/uibase/inc/wrtsh.hxx b/sw/source/uibase/inc/wrtsh.hxx index 10d652aadd9a..646ffd975fce 100644 --- a/sw/source/uibase/inc/wrtsh.hxx +++ b/sw/source/uibase/inc/wrtsh.hxx @@ -292,7 +292,7 @@ typedef bool (SwWrtShell:: *FNSimpleMove)(); int IntelligentCut(SelectionType nSelectionType, bool bCut = true); // edit - void Insert(SwField const &); + void Insert(SwField const &, SwPaM* pAnnotationRange = nullptr); void Insert(const OUString &); // graphic void Insert( const OUString &rPath, const OUString &rFilter, diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx b/sw/source/uibase/wrtsh/wrtsh1.cxx index 40d07646592b..88fcc174dab8 100644 --- a/sw/source/uibase/wrtsh/wrtsh1.cxx +++ b/sw/source/uibase/wrtsh/wrtsh1.cxx @@ -1898,6 +1898,24 @@ void SwWrtShell::InsertPostIt(SwFieldMgr& rFieldMgr, SfxRequest& rReq) { Right(CRSR_SKIP_CELLS, /*bSelect=*/true, 1, /*bBasicCall=*/false, /*bVisual=*/true); } + else if (pFormat && pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_CHAR) + { + // Ending the frame selection positions the cursor at the end of the paragraph, + // move it to the anchor position. + sal_Int32 nCursor = GetCurrentShellCursor().GetPoint()->nContent.GetIndex(); + const SwPosition* pAnchor = pFormat->GetAnchor().GetContentAnchor(); + if (pAnchor) + { + sal_Int32 nDiff = nCursor - pAnchor->nContent.GetIndex(); + if (nDiff > 0) + { + Left(CRSR_SKIP_CELLS, /*bSelect=*/false, nDiff, /*bBasicCall=*/false, + /*bVisual=*/true); + aData.m_pAnnotationRange.reset(new SwPaM( + *GetCurrentShellCursor().Start(), *GetCurrentShellCursor().End())); + } + } + } } } diff --git a/sw/source/uibase/wrtsh/wrtsh2.cxx b/sw/source/uibase/wrtsh/wrtsh2.cxx index 95249b6e40f1..b4efb8d6492d 100644 --- a/sw/source/uibase/wrtsh/wrtsh2.cxx +++ b/sw/source/uibase/wrtsh/wrtsh2.cxx @@ -65,7 +65,7 @@ #include <LibreOfficeKit/LibreOfficeKitEnums.h> #include <comphelper/lok.hxx> -void SwWrtShell::Insert(SwField const &rField) +void SwWrtShell::Insert(SwField const& rField, SwPaM* pAnnotationRange) { ResetCursorStack(); if(!CanInsert()) @@ -79,6 +79,11 @@ void SwWrtShell::Insert(SwField const &rField) bool bDeleted = false; std::unique_ptr<SwPaM> pAnnotationTextRange; + if (pAnnotationRange) + { + pAnnotationTextRange.reset(new SwPaM(*pAnnotationRange->Start(), *pAnnotationRange->End())); + } + if ( HasSelection() ) { if ( rField.GetTyp()->Which() == SwFieldIds::Postit ) @@ -118,6 +123,17 @@ void SwWrtShell::Insert(SwField const &rField) { if ( GetDoc() != nullptr ) { + const SwPaM& rCurrPaM = GetCurrentShellCursor(); + if (*rCurrPaM.Start() == *pAnnotationTextRange->Start() + && *rCurrPaM.End() == *pAnnotationTextRange->End()) + { + // Annotation range was passed in externally, and inserting the postit field shifted + // its start/end positions right by one. Restore the original position for the range + // start. This allows commenting on the placeholder character of the field. + SwIndex& rRangeStart = pAnnotationTextRange->Start()->nContent; + if (rRangeStart.GetIndex() > 0) + --rRangeStart; + } IDocumentMarkAccess* pMarksAccess = GetDoc()->getIDocumentMarkAccess(); pMarksAccess->makeAnnotationMark( *pAnnotationTextRange, OUString() ); } commit 5cb21bb555e208645c95871aa11d6fd748735354 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Jun 21 17:55:01 2019 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu Jul 4 09:02:21 2019 +0200 sw comments on frames: fix layout to place anchor next to the image With this, if you load sw/qa/extras/unowriter/data/image-comment-at-char.odt, the comment anchor leads to the commented image, not to the anchor of the image (between "aaa" and "bbb"). (cherry picked from commit ac246d6ea1bc43bfc82c9b4c69c9c0f1fd678129) Conflicts: sw/qa/extras/unowriter/unowriter.cxx sw/source/core/fields/postithelper.cxx Also squash in: Adapt new test to actual values observed on macOS The test against 5892 was introduced with ac246d6ea1bc43bfc82c9b4c69c9c0f1fd678129 "sw comments on frames: fix layout to place anchor next to the image", causing various macOS builds (<https://ci.libreoffice.org//job/lo_tb_master_mac/30338/> and <https://ci.libreoffice.org//job/lo_tb_master_mac_dbg/26914/> as well as my own local build) to consistently fail with 6283 instead, for whatever reason. So, at least for now, adapt the test to check for >= 5892. (cherry picked from commit cf5a3cb687a502e7f71cefb5f7001a73925bee56) Change-Id: I99389c9fc849269eb20d0266f8f604db89faec12 Reviewed-on: https://gerrit.libreoffice.org/75037 Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Tested-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/inc/postithelper.hxx b/sw/inc/postithelper.hxx index 982faa671569..2a4d5699e426 100644 --- a/sw/inc/postithelper.hxx +++ b/sw/inc/postithelper.hxx @@ -34,6 +34,7 @@ class SwEditWin; namespace sw { namespace annotation { class SwAnnotationWin; } } +namespace sw::mark { class IMark; } struct SwPosition; @@ -77,7 +78,7 @@ namespace SwPostItHelper SwLayoutStatus getLayoutInfos( SwLayoutInfo& o_rInfo, const SwPosition& rAnchorPos, - const SwPosition* pAnnotationStartPos = nullptr ); + const sw::mark::IMark* pAnnotationMark = nullptr ); long getLayoutHeight( const SwRootFrame* pRoot ); void setSidebarChanged( SwRootFrame* pRoot, bool bBrowseMode ); diff --git a/sw/qa/extras/unowriter/unowriter.cxx b/sw/qa/extras/unowriter/unowriter.cxx index 464b150dadfa..8a9e1565b0ab 100644 --- a/sw/qa/extras/unowriter/unowriter.cxx +++ b/sw/qa/extras/unowriter/unowriter.cxx @@ -20,6 +20,9 @@ #include <toolkit/helper/vclunohelper.hxx> #include <wrtsh.hxx> #include <ndtxt.hxx> +#include <PostItMgr.hxx> +#include <postithelper.hxx> +#include <AnnotationWin.hxx> using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -151,6 +154,19 @@ DECLARE_UNOAPI_TEST(testImageCommentAtChar) getProperty<OUString>(getRun(xPara, 4), "TextPortionType")); CPPUNIT_ASSERT_EQUAL(OUString("Text"), getProperty<OUString>(getRun(xPara, 5), "TextPortionType")); + + // Without the accompanying fix in place, this test would have failed with 'Expected: + // 5892; Actual: 1738', i.e. the anchor pos was between the "aaa" and "bbb" portions, not at the + // center of the page (horizontally) where the image is. On macOS, though, with the fix in + // place the actual value consistently is even greater with 6283 now instead of 5892, for + // whatever reason. + SwView* pView = pDoc->GetDocShell()->GetView(); + SwPostItMgr* pPostItMgr = pView->GetPostItMgr(); + for (const auto& pItem : *pPostItMgr) + { + const SwRect& rAnchor = pItem->pPostIt->GetAnchorRect(); + CPPUNIT_ASSERT_GREATEREQUAL(static_cast<long>(5892), rAnchor.Left()); + } } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/core/fields/postithelper.cxx b/sw/source/core/fields/postithelper.cxx index 6261e0ebc609..28db040ace8c 100644 --- a/sw/source/core/fields/postithelper.cxx +++ b/sw/source/core/fields/postithelper.cxx @@ -35,13 +35,76 @@ #include <scriptinfo.hxx> #include <editeng/charhiddenitem.hxx> #include <calbck.hxx> +#include <IMark.hxx> +#include <sortedobjs.hxx> +#include <anchoredobject.hxx> +#include <fmtanchr.hxx> class Point; +namespace +{ +/// Checks if pAnnotationMark covers exactly rAnchorPos (the comment anchor). +bool AnnotationMarkCoversCommentAnchor(const sw::mark::IMark* pAnnotationMark, + const SwPosition& rAnchorPos) +{ + if (!pAnnotationMark) + { + return false; + } + + const SwPosition& rMarkStart = pAnnotationMark->GetMarkStart(); + const SwPosition& rMarkEnd = pAnnotationMark->GetMarkEnd(); + + if (rMarkStart != rAnchorPos) + { + return false; + } + + if (rMarkStart.nNode != rMarkEnd.nNode) + { + return false; + } + + return rMarkEnd.nContent.GetIndex() == rMarkStart.nContent.GetIndex() + 1; +} + +/** + * Finds the first draw object of rTextFrame which has the same anchor position as the start of + * rAnnotationMark. + */ +SwAnchoredObject* GetAnchoredObjectOfAnnotationMark(const sw::mark::IMark& rAnnotationMark, + const SwTextFrame& rTextFrame) +{ + const SwSortedObjs* pAnchored = rTextFrame.GetDrawObjs(); + if (!pAnchored) + { + return nullptr; + } + + for (SwAnchoredObject* pObject : *pAnchored) + { + SwFrameFormat& rFrameFormat = pObject->GetFrameFormat(); + const SwPosition* pFrameAnchor = rFrameFormat.GetAnchor().GetContentAnchor(); + if (!pFrameAnchor) + { + continue; + } + + if (rAnnotationMark.GetMarkStart() == *pFrameAnchor) + { + return pObject; + } + } + + return nullptr; +} +} + SwPostItHelper::SwLayoutStatus SwPostItHelper::getLayoutInfos( SwLayoutInfo& o_rInfo, const SwPosition& rAnchorPos, - const SwPosition* pAnnotationStartPos ) + const sw::mark::IMark* pAnnotationMark ) { SwLayoutStatus aRet = INVISIBLE; SwTextNode* pTextNode = rAnchorPos.nNode.GetNode().GetTextNode(); @@ -62,12 +125,27 @@ SwPostItHelper::SwLayoutStatus SwPostItHelper::getLayoutInfos( o_rInfo.mpAnchorFrame = pTextFrame; { DisableCallbackAction a(*pTextFrame->getRootFrame()); - pTextFrame->GetCharRect(o_rInfo.mPosition, rAnchorPos, nullptr, false); + bool bPositionFromCommentAnchor = true; + if (AnnotationMarkCoversCommentAnchor(pAnnotationMark, rAnchorPos)) + { + SwAnchoredObject* pFrame + = GetAnchoredObjectOfAnnotationMark(*pAnnotationMark, *pTextFrame); + if (pFrame) + { + o_rInfo.mPosition = pFrame->GetObjRect(); + bPositionFromCommentAnchor = false; + } + } + if (bPositionFromCommentAnchor) + { + pTextFrame->GetCharRect(o_rInfo.mPosition, rAnchorPos, nullptr, false); + } } - if ( pAnnotationStartPos != nullptr ) + if (pAnnotationMark != nullptr) { - o_rInfo.mnStartNodeIdx = pAnnotationStartPos->nNode.GetIndex(); - o_rInfo.mnStartContent = pAnnotationStartPos->nContent.GetIndex(); + const SwPosition& rAnnotationStartPos = pAnnotationMark->GetMarkStart(); + o_rInfo.mnStartNodeIdx = rAnnotationStartPos.nNode.GetIndex(); + o_rInfo.mnStartContent = rAnnotationStartPos.nContent.GetIndex(); } else { diff --git a/sw/source/uibase/docvw/PostItMgr.cxx b/sw/source/uibase/docvw/PostItMgr.cxx index 4e024c731b33..473978dd1689 100644 --- a/sw/source/uibase/docvw/PostItMgr.cxx +++ b/sw/source/uibase/docvw/PostItMgr.cxx @@ -555,7 +555,7 @@ bool SwPostItMgr::CalcRects() SwPostItHelper::getLayoutInfos( pItem->maLayoutInfo, pItem->GetAnchorPosition(), - &pAnnotationMark->GetMarkStart() ); + pAnnotationMark ); } else { _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits