[Libreoffice-commits] core.git: sc/qa sc/source
Regina Henschel (via logerrit)
logerrit at kemper.freedesktop.org
Wed Dec 2 18:07:31 UTC 2020
sc/qa/unit/data/ods/ManualColWidthRowHeight.ods |binary
sc/qa/unit/scshapetest.cxx | 121 ++++++++++++++++++++++++
sc/source/core/data/drwlayer.cxx | 22 ++--
3 files changed, 135 insertions(+), 8 deletions(-)
New commits:
commit d0921aa753c43600272865602df3c7c2a8f13196
Author: Regina Henschel <rb.henschel at t-online.de>
AuthorDate: Tue Dec 1 00:05:43 2020 +0100
Commit: Regina Henschel <rb.henschel at t-online.de>
CommitDate: Wed Dec 2 19:06:43 2020 +0100
tdf#137576 Improve cell anchored measure line in Calc
Measure lines do not always have a logic rectangle. It might be empty
or the 1cm x 1cm default square. But Calc needs it to calculate
NonRotatedAnchor. The latter is needed for cell anchored shapes when
saving in ODF. Always generating a logic rectangle in class
SdrMeasureObj is difficult (I got crashes in Draw) and not necessary.
Calc now forces the calculation of the logic rectangle where it is
needed by Calc.
Change-Id: I8689bc95985db1619eb5e72df99901bd52086cb2
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106990
Tested-by: Jenkins
Reviewed-by: Regina Henschel <rb.henschel at t-online.de>
diff --git a/sc/qa/unit/data/ods/ManualColWidthRowHeight.ods b/sc/qa/unit/data/ods/ManualColWidthRowHeight.ods
new file mode 100644
index 000000000000..1cc738e05244
Binary files /dev/null and b/sc/qa/unit/data/ods/ManualColWidthRowHeight.ods differ
diff --git a/sc/qa/unit/scshapetest.cxx b/sc/qa/unit/scshapetest.cxx
index 236cbc0879b4..c13ec7189622 100644
--- a/sc/qa/unit/scshapetest.cxx
+++ b/sc/qa/unit/scshapetest.cxx
@@ -13,10 +13,12 @@
#include <comphelper/propertyvalue.hxx>
#include <sfx2/dispatch.hxx>
+#include <sfx2/request.hxx>
#include <svx/svdoashp.hxx>
#include <svx/svdomeas.hxx>
#include <svx/svdpage.hxx>
#include <unotools/tempfile.hxx>
+#include <vcl/keycodes.hxx>
#include <docsh.hxx>
#include <drwlayer.hxx>
@@ -35,6 +37,8 @@ public:
ScShapeTest();
void saveAndReload(css::uno::Reference<css::lang::XComponent>& xComponent,
const OUString& rFilter);
+ void testTdf137576_LogicRectInDefaultMeasureline();
+ void testTdf137576_LogicRectInNewMeasureline();
void testMeasurelineHideColSave();
void testHideColsShow();
void testTdf138138_MoveCellWithRotatedShape();
@@ -46,6 +50,8 @@ public:
void testCustomShapeCellAnchoredRotatedShape();
CPPUNIT_TEST_SUITE(ScShapeTest);
+ CPPUNIT_TEST(testTdf137576_LogicRectInDefaultMeasureline);
+ CPPUNIT_TEST(testTdf137576_LogicRectInNewMeasureline);
CPPUNIT_TEST(testMeasurelineHideColSave);
CPPUNIT_TEST(testHideColsShow);
CPPUNIT_TEST(testTdf138138_MoveCellWithRotatedShape);
@@ -121,6 +127,121 @@ static void lcl_AssertPointEqualWithTolerance(const OString& sInfo, const Point
CPPUNIT_ASSERT_MESSAGE(sMsg.getStr(), std::abs(rExpected.Y() - rActual.Y()) <= nTolerance);
}
+void ScShapeTest::testTdf137576_LogicRectInDefaultMeasureline()
+{
+ // Error was, that the empty logical rectangle of a default measure line (Ctrl+Click)
+ // resulted in zeros in NonRotatedAnchor and a wrong position when reloading.
+
+ // Load an empty document.
+ OUString aFileURL;
+ createFileURL("ManualColWidthRowHeight.ods", aFileURL);
+ uno::Reference<css::lang::XComponent> xComponent = loadFromDesktop(aFileURL);
+ CPPUNIT_ASSERT(xComponent.is());
+
+ // Get ScDocShell
+ SfxObjectShell* pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);
+ CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
+ ScDocShell* pDocSh = dynamic_cast<ScDocShell*>(pFoundShell);
+ CPPUNIT_ASSERT_MESSAGE("No ScDocShell", pDocSh);
+
+ // Create default measureline by SfxRequest that corresponds to Ctrl+Click
+ ScTabViewShell* pTabViewShell = pDocSh->GetBestViewShell(false);
+ CPPUNIT_ASSERT_MESSAGE("No ScTabViewShell", pTabViewShell);
+ SfxRequest aReq(pTabViewShell->GetViewFrame(), SID_DRAW_MEASURELINE);
+ aReq.SetModifier(KEY_MOD1); // Ctrl
+ pTabViewShell->ExecDraw(aReq);
+
+ // Get document and newly created measure line.
+ ScDocument& rDoc = pDocSh->GetDocument();
+ ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
+ CPPUNIT_ASSERT_MESSAGE("No ScDrawLayer", pDrawLayer);
+ const SdrPage* pPage = pDrawLayer->GetPage(0);
+ CPPUNIT_ASSERT_MESSAGE("No draw page", pPage);
+ SdrObject* pObj = pPage->GetObj(0);
+ CPPUNIT_ASSERT_MESSAGE("No object found", pObj);
+
+ // Anchor "to Cell (resize with cell)"
+ ScDrawLayer::SetCellAnchoredFromPosition(*pObj, rDoc, 0 /*SCTAB*/, true /*bResizeWithCell*/);
+ // Deselect shape and switch to object selection type "Cell".
+ pTabViewShell->SetDrawShell(false);
+
+ // Hide column A.
+ uno::Sequence<beans::PropertyValue> aPropertyValues = {
+ comphelper::makePropertyValue("ToPoint", OUString("$A$1")),
+ };
+ dispatchCommand(xComponent, ".uno:GoToCell", aPropertyValues);
+ dispatchCommand(xComponent, ".uno:HideColumn", {});
+
+ // Get current position. I will not use absolute values for comparison, because document is loaded
+ // in full screen mode of unknown size and default object is placed in center of window.
+ Point aOldPos = pObj->GetRelativePos();
+
+ // Save and reload, get ScDocShell
+ saveAndReload(xComponent, "calc8");
+ CPPUNIT_ASSERT(xComponent);
+ pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);
+ CPPUNIT_ASSERT_MESSAGE("Reload: Failed to access document shell", pFoundShell);
+ pDocSh = dynamic_cast<ScDocShell*>(pFoundShell);
+ CPPUNIT_ASSERT(pDocSh);
+
+ // Get document and object
+ ScDocument& rDoc2 = pDocSh->GetDocument();
+ pDrawLayer = rDoc2.GetDrawLayer();
+ CPPUNIT_ASSERT_MESSAGE("Reload: No ScDrawLayer", pDrawLayer);
+ pPage = pDrawLayer->GetPage(0);
+ CPPUNIT_ASSERT_MESSAGE("Reload: No draw page", pPage);
+ pObj = pPage->GetObj(0);
+ CPPUNIT_ASSERT_MESSAGE("Measure line lost", pObj);
+
+ // Assert object position is unchanged, besides Twips<->Hmm inaccuracy.
+ Point aNewPos = pObj->GetRelativePos();
+ lcl_AssertPointEqualWithTolerance("after reload", aOldPos, aNewPos, 1);
+
+ pDocSh->DoClose();
+}
+
+void ScShapeTest::testTdf137576_LogicRectInNewMeasureline()
+{
+ // Error was, that a new measure line had no logical rectangle. This resulted in zeros in
+ // NonRotatedAnchor. As a result the position was wrong when reloading.
+
+ // Load an empty document
+ OUString aFileURL;
+ createFileURL("ManualColWidthRowHeight.ods", aFileURL);
+ uno::Reference<css::lang::XComponent> xComponent = loadFromDesktop(aFileURL);
+ CPPUNIT_ASSERT(xComponent.is());
+
+ // Get ScDocShell
+ SfxObjectShell* pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);
+ CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
+ ScDocShell* pDocSh = dynamic_cast<ScDocShell*>(pFoundShell);
+ CPPUNIT_ASSERT(pDocSh);
+
+ // Get SdrPage
+ ScDocument& rDoc = pDocSh->GetDocument();
+ ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
+ CPPUNIT_ASSERT_MESSAGE("No ScDrawLayer", pDrawLayer);
+ SdrPage* pPage = pDrawLayer->GetPage(0);
+ CPPUNIT_ASSERT_MESSAGE("No draw page", pPage);
+
+ // Create a new measure line and insert it
+ Point aStartPoint(5000, 5500);
+ Point aEndPoint(13000, 8000);
+ SdrMeasureObj* pObj = new SdrMeasureObj(*pDrawLayer, aStartPoint, aEndPoint);
+ CPPUNIT_ASSERT_MESSAGE("Could not create measure line", pObj);
+ pPage->InsertObject(pObj);
+
+ // Anchor "to cell (resize with cell)" and examine NonRotatedAnchor
+ ScDrawLayer::SetCellAnchoredFromPosition(*pObj, rDoc, 0 /*SCTAB*/, true /*bResizeWithCell*/);
+ ScDrawObjData* pNData = ScDrawLayer::GetNonRotatedObjData(pObj);
+ CPPUNIT_ASSERT_MESSAGE("Failed to get NonRotatedAnchor", pNData);
+ // Without the fix all four values would be zero.
+ CPPUNIT_ASSERT(pNData->maStart.Col() == 1 && pNData->maStart.Row() == 2);
+ CPPUNIT_ASSERT(pNData->maEnd.Col() == 7 && pNData->maEnd.Row() == 2);
+
+ pDocSh->DoClose();
+}
+
void ScShapeTest::testMeasurelineHideColSave()
{
// The document contains a SdrMeasureObj anchored "To Cell (resive with cell)" with start in cell
diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx
index 16fbe9c7f51c..eb329379398a 100644
--- a/sc/source/core/data/drwlayer.cxx
+++ b/sc/source/core/data/drwlayer.cxx
@@ -35,6 +35,7 @@
#include <svx/svdoashp.hxx>
#include <svx/svdobj.hxx>
#include <svx/svdocapt.hxx>
+#include <svx/svdomeas.hxx>
#include <svx/svdoole2.hxx>
#include <svx/svdopath.hxx>
#include <svx/svdundo.hxx>
@@ -932,14 +933,13 @@ void ScDrawLayer::InitializeCellAnchoredObj(SdrObject* pObj, ScDrawObjData& rDat
else if (pObj->GetObjIdentifier() == OBJ_MEASURE)
{
// Measure lines might have got wrong start and end anchor from XML import. Recreate
- // them from start and end point.
- const Point aPoint0(pObj->GetPoint(0));
- const Point aPoint1(pObj->GetPoint(1));
- const Point aPointLT(std::min(aPoint0.X(), aPoint1.X()),
- std::min(aPoint0.Y(), aPoint1.Y()));
- const Point aPointRB(std::max(aPoint0.X(), aPoint1.X()),
- std::max(aPoint0.Y(), aPoint1.Y()));
- const tools::Rectangle aObjRect(aPointLT, aPointRB);
+ // anchor from start and end point.
+ SdrMeasureObj* pMeasureObj = dynamic_cast<SdrMeasureObj*>(pObj);
+ // tdf#137576. The logic rectangle has likely no current values here, but only the
+ // 1cm x 1cm default size. The call of TakeUnrotatedSnapRect is currently (LO 7.2)
+ // the only way to force a recalc of the logic rectangle.
+ tools::Rectangle aObjRect;
+ pMeasureObj->TakeUnrotatedSnapRect(aObjRect);
GetCellAnchorFromPosition(aObjRect, rNoRotatedAnchor, *pDoc, rData.maStart.Tab(),
false /*bHiddenAsZero*/);
}
@@ -2227,6 +2227,12 @@ void ScDrawLayer::SetCellAnchoredFromPosition( SdrObject &rObj, const ScDocument
aObjRect2 = rObj.GetLogicRect();
rObj.NbcMirror(aLeft, aRight);
}
+ else if (rObj.GetObjIdentifier() == OBJ_MEASURE)
+ {
+ // tdf#137576. A SdrMeasureObj might have a wrong logic rect here. TakeUnrotatedSnapRect
+ // calculates the current unrotated snap rectangle, sets logic rectangle and returns it.
+ static_cast<SdrObjCustomShape*>(&rObj)->TakeUnrotatedSnapRect(aObjRect2);
+ }
else
aObjRect2 = rObj.GetLogicRect();
More information about the Libreoffice-commits
mailing list