diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2019-08-01 15:31:10 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2019-08-01 18:37:25 +0200 |
commit | 27c46ecf34b32bae1806d3fc0e1684179301feb8 (patch) | |
tree | e14f8c60d2e8790dfc7fda985e8c24792878472d /sw | |
parent | c9d6de20d9a64481ca3dd0f099b752a4ef11a46e (diff) |
sw comments on frames: improve doc coordinates -> doc model pos conversion
In case an as-char image at the end of a paragraph was commented and the
user clicked past the end of the paragraph, we defaulted to extending
that comment, rather appending content. (The cursor was placed between
the as-char image and the comment anchor, not past the comment anchor.)
This doesn't seem to be useful, probably the expectation is that if the
user clicks before the comment anchor then we extend the comment range,
and if the click is after the comment anchor, then we don't. In both
cases we used to *select* the comment anchor, so typing a character
deleted the comment instead.
This commit is a step in the direction of never selecting the comment
anchor: now if you click past the comment anchor, then we place the
cursor after the comment anchor.
(But clicking before the comment anchor results in unchanged behavior
for now.)
Change-Id: I6c36ec4344591fdf330a73bcd3cdd6fd0610e339
Reviewed-on: https://gerrit.libreoffice.org/76803
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'sw')
-rw-r--r-- | sw/qa/extras/layout/data/image-comment.odt | bin | 0 -> 10445 bytes | |||
-rw-r--r-- | sw/qa/extras/layout/layout.cxx | 40 | ||||
-rw-r--r-- | sw/source/core/text/itrcrsr.cxx | 30 |
3 files changed, 69 insertions, 1 deletions
diff --git a/sw/qa/extras/layout/data/image-comment.odt b/sw/qa/extras/layout/data/image-comment.odt Binary files differnew file mode 100644 index 000000000000..d861d3a9aa03 --- /dev/null +++ b/sw/qa/extras/layout/data/image-comment.odt diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index 2f69230849e1..1de7bba9d926 100644 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -25,6 +25,11 @@ #include <edtwin.hxx> #include <view.hxx> #include <txtfrm.hxx> +#include <pagefrm.hxx> +#include <bodyfrm.hxx> +#include <sortedobjs.hxx> +#include <anchoredobject.hxx> +#include <ndtxt.hxx> static char const DATA_DIRECTORY[] = "/sw/qa/extras/layout/data/"; @@ -2978,6 +2983,41 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTabOverMargin) assertXPath(pXmlDoc, "/root/page/body/txt[2]/LineBreak", 1); } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testImageComment) +{ + // Load a document that has "aaa" in it, then a commented image (4th char is the as-char image, + // 5th char is the comment anchor). + SwDoc* pDoc = createDoc("image-comment.odt"); + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + + // Look up a layout position which is on the right of the image. + SwRootFrame* pRoot = pWrtShell->GetLayout(); + CPPUNIT_ASSERT(pRoot->GetLower()->IsPageFrame()); + SwPageFrame* pPage = static_cast<SwPageFrame*>(pRoot->GetLower()); + CPPUNIT_ASSERT(pPage->GetLower()->IsBodyFrame()); + SwBodyFrame* pBody = static_cast<SwBodyFrame*>(pPage->GetLower()); + CPPUNIT_ASSERT(pBody->GetLower()->IsTextFrame()); + SwTextFrame* pTextFrame = static_cast<SwTextFrame*>(pBody->GetLower()); + CPPUNIT_ASSERT(pTextFrame->GetDrawObjs()); + SwSortedObjs& rDrawObjs = *pTextFrame->GetDrawObjs(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rDrawObjs.size()); + SwAnchoredObject* pDrawObj = rDrawObjs[0]; + const SwRect& rDrawObjRect = pDrawObj->GetObjRect(); + Point aPoint = rDrawObjRect.Center(); + aPoint.setX(aPoint.getX() + rDrawObjRect.Width() / 2); + + // Ask for the doc model pos of this layout point. + SwPosition aPosition(*pTextFrame->GetTextNodeForFirstText()); + pTextFrame->GetCursorOfst(&aPosition, aPoint); + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 5 + // - Actual : 4 + // i.e. the cursor got positioned between the image and its comment, so typing extended the + // comment, instead of adding content after the commented image. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(5), aPosition.nContent.GetIndex()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/text/itrcrsr.cxx b/sw/source/core/text/itrcrsr.cxx index 84effe8b49c1..cc5b21cd0b0e 100644 --- a/sw/source/core/text/itrcrsr.cxx +++ b/sw/source/core/text/itrcrsr.cxx @@ -1254,6 +1254,27 @@ void SwTextCursor::GetCharRect( SwRect* pOrig, TextFrameIndex const nOfst, } } +/** + * Determines if SwTextCursor::GetCursorOfst() should consider the next portion when calculating the + * doc model position from a Point. + */ +static bool ConsiderNextPortionForCursorOffset(SwLinePortion* pPor, sal_uInt16 nWidth30, sal_uInt16 nX) +{ + if (!pPor->GetNextPortion()) + { + return false; + } + + // If we're poast the target position, stop the iteration in general. + // Exception: don't stop the iteration between as-char fly portions and their comments. + if (nWidth30 >= nX && (!pPor->IsFlyCntPortion() || !pPor->GetNextPortion()->IsPostItsPortion())) + { + return false; + } + + return !pPor->IsBreakPortion(); +} + // Return: Offset in String TextFrameIndex SwTextCursor::GetCursorOfst( SwPosition *pPos, const Point &rPoint, bool bChgNode, SwCursorMoveState* pCMS ) const @@ -1341,7 +1362,7 @@ TextFrameIndex SwTextCursor::GetCursorOfst( SwPosition *pPos, const Point &rPoin 30 : nWidth; - while( pPor->GetNextPortion() && nWidth30 < nX && !pPor->IsBreakPortion() ) + while (ConsiderNextPortionForCursorOffset(pPor, nWidth30, nX)) { nX = nX - nWidth; nCurrStart = nCurrStart + pPor->GetLen(); @@ -1512,7 +1533,14 @@ TextFrameIndex SwTextCursor::GetCursorOfst( SwPosition *pPos, const Point &rPoin { if ( pPor->IsPostItsPortion() || pPor->IsBreakPortion() || pPor->InToxRefGrp() ) + { + if (pPor->IsPostItsPortion()) + { + // Offset would be nCurrStart + nLength below, do the same for post-it portions. + nCurrStart += pPor->GetLen(); + } return nCurrStart; + } if ( pPor->InFieldGrp() ) { if( bRightOver && !static_cast<SwFieldPortion*>(pPor)->HasFollow() ) |