sc/qa/unit/data/ods/tdf143619_validationCirclePos.ods |binary
 sc/qa/unit/scshapetest.cxx                            |   34 ++++++++++++++++++
 sc/source/core/data/drwlayer.cxx                      |    7 +++
 3 files changed, 41 insertions(+)

New commits:
commit 003b821b03474f048d993dc3cee240cf25b9a7ea
Author:     Regina Henschel <rb.hensc...@t-online.de>
AuthorDate: Fri Jul 30 23:18:39 2021 +0200
Commit:     Gabor Kelemen <kelemen.gab...@nisz.hu>
CommitDate: Thu Sep 2 10:27:14 2021 +0200

    tdf#143619 validation circle anchor is special
    
    For usual drawing objects, maStart in its Calc user data means the
    cell address of left/top of snapRect/logicRect. For validation circle
    it means 'address of cell to be validated'. Thus corrections might be
    needed, if a general method is used for validation circle.
    
    Here the method SetLogicRect() calls via broadcast
    ScDrawLayer::SetCellAnchoredFromPosition(), which calculates maStart
    from snapRect/logicRect. Because the circle is extended to cover a
    larger area than the to be validated cell, maStart got the cell address
    of the cell one left and one above of the to be validated cell.
    
    Now the old, correct address is backuped and restored.
    
    Change-Id: I9646da3f22fef45a6e47e59ef55a70307e2f9cc6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/119715
    Tested-by: Jenkins
    Reviewed-by: Regina Henschel <rb.hensc...@t-online.de>
    (cherry picked from commit 0cff1aa48453ee0c05bafcac5360329fb6bf9557)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120147
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120224
    Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com>
    (cherry picked from commit ee749af6d3c742efdfc28d245db6422d461ed51b)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121464
    Tested-by: Gabor Kelemen <kelemen.gab...@nisz.hu>
    Reviewed-by: Gabor Kelemen <kelemen.gab...@nisz.hu>

diff --git a/sc/qa/unit/data/ods/tdf143619_validationCirclePos.ods 
b/sc/qa/unit/data/ods/tdf143619_validationCirclePos.ods
new file mode 100644
index 000000000000..6470d6a1f430
Binary files /dev/null and 
b/sc/qa/unit/data/ods/tdf143619_validationCirclePos.ods differ
diff --git a/sc/qa/unit/scshapetest.cxx b/sc/qa/unit/scshapetest.cxx
index 11b7875c83ee..ff156cc65df3 100644
--- a/sc/qa/unit/scshapetest.cxx
+++ b/sc/qa/unit/scshapetest.cxx
@@ -41,6 +41,7 @@ public:
     ScShapeTest();
     void saveAndReload(css::uno::Reference<css::lang::XComponent>& xComponent,
                        const OUString& rFilter);
+    void testTdf143619_validation_circle_pos();
     void testTdf137082_LTR_to_RTL();
     void testTdf137082_RTL_cell_anchored();
     void testTdf137081_RTL_page_anchored();
@@ -64,6 +65,7 @@ public:
     void testCustomShapeCellAnchoredRotatedShape();
 
     CPPUNIT_TEST_SUITE(ScShapeTest);
+    CPPUNIT_TEST(testTdf143619_validation_circle_pos);
     CPPUNIT_TEST(testTdf137082_LTR_to_RTL);
     CPPUNIT_TEST(testTdf137082_RTL_cell_anchored);
     CPPUNIT_TEST(testTdf137081_RTL_page_anchored);
@@ -189,6 +191,38 @@ static SdrObject* lcl_getSdrObjectWithAssert(ScDocument& 
rDoc, sal_uInt16 nObjNu
     return pObj;
 }
 
+void ScShapeTest::testTdf143619_validation_circle_pos()
+{
+    // Load a document, which has validation circle around cell E6.
+
+    OUString aFileURL;
+    createFileURL(u"tdf143619_validationCirclePos.ods", aFileURL);
+    uno::Reference<css::lang::XComponent> xComponent = 
loadFromDesktop(aFileURL);
+
+    // Get document
+    ScDocShell* pDocSh = lcl_getScDocShellWithAssert(xComponent);
+    ScDocument& rDoc = pDocSh->GetDocument();
+
+    // Get shape. That is the validation circle.
+    SdrObject* pObj = lcl_getSdrObjectWithAssert(rDoc, 0);
+
+    // Error was, that deleting row and col before E6 does not move circle to 
D5, but to B3.
+    // Delete first row and first column.
+    uno::Sequence<beans::PropertyValue> aPropertyValues = {
+        comphelper::makePropertyValue("ToPoint", OUString("$A$1")),
+    };
+    dispatchCommand(xComponent, ".uno:GoToCell", aPropertyValues);
+    dispatchCommand(xComponent, ".uno:DeleteRows", {});
+    dispatchCommand(xComponent, ".uno:GoToCell", aPropertyValues);
+    dispatchCommand(xComponent, ".uno:DeleteColumns", {});
+
+    // Without fix in place the position was (2007, 833)
+    Point aPos = pObj->GetSnapRect().TopLeft();
+    lcl_AssertPointEqualWithTolerance("after row and col delete", Point(6523, 
1736), aPos, 1);
+
+    pDocSh->DoClose();
+}
+
 void ScShapeTest::testTdf137082_LTR_to_RTL()
 {
     // Before the fix for tdf137081 and tdf137082, when flipping sheet from 
LTR to RTL, page anchored
diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx
index 497ad478b146..15440fa3f94b 100644
--- a/sc/source/core/data/drwlayer.cxx
+++ b/sc/source/core/data/drwlayer.cxx
@@ -1061,6 +1061,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, 
ScDrawObjData& rData, bool bNegati
         // Validation circle for detective.
         rData.setShapeRect(GetDocument(), pObj->GetLogicRect());
 
+        // rData.maStart should contain the address of the be validated cell.
         tools::Rectangle aRect = GetCellRect(*GetDocument(), rData.maStart, 
true);
         aRect.AdjustLeft( -250 );
         aRect.AdjustRight(250 );
@@ -1074,7 +1075,13 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, 
ScDrawObjData& rData, bool bNegati
             if (bRecording)
                 AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *pObj ) );
             rData.setShapeRect(GetDocument(), lcl_makeSafeRectangle(aRect));
+            // maStart has the meaning of "to be validated cell" in a 
validation circle. For usual
+            // drawing objects it has the meaning "left/top of logic/snap 
rect". Because the rectangle
+            // is expanded above, SetLogicRect() will set maStart to one cell 
left and one cell above
+            // of the to be validated cell. We need to backup the old value 
and restore it.
+            ScAddress aBackup(rData.maStart);
             pObj->SetLogicRect(rData.getShapeRect());
+            rData.maStart = aBackup;
         }
     }
     else if (rData.meType == ScDrawObjData::DetectiveArrow)

Reply via email to