summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2019-08-01 15:31:10 +0200
committerMiklos Vajna <vmiklos@collabora.com>2019-08-01 18:37:25 +0200
commit27c46ecf34b32bae1806d3fc0e1684179301feb8 (patch)
treee14f8c60d2e8790dfc7fda985e8c24792878472d
parentc9d6de20d9a64481ca3dd0f099b752a4ef11a46e (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
-rw-r--r--sw/qa/extras/layout/data/image-comment.odtbin0 -> 10445 bytes
-rw-r--r--sw/qa/extras/layout/layout.cxx40
-rw-r--r--sw/source/core/text/itrcrsr.cxx30
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
new file mode 100644
index 000000000000..d861d3a9aa03
--- /dev/null
+++ b/sw/qa/extras/layout/data/image-comment.odt
Binary files differ
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() )