1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <sal/config.h>
12 #include <string_view>
14 #include "helper/qahelper.hxx"
16 #include <comphelper/propertyvalue.hxx>
17 #include <sfx2/dispatch.hxx>
18 #include <sfx2/request.hxx>
19 #include <svl/intitem.hxx>
20 #include <svx/svdoashp.hxx>
21 #include <svx/svdomeas.hxx>
22 #include <svx/svdorect.hxx>
23 #include <svx/svdouno.hxx>
24 #include <svx/svdpage.hxx>
25 #include <unotools/tempfile.hxx>
26 #include <vcl/keycodes.hxx>
29 #include <drwlayer.hxx>
30 #include <fuconcustomshape.hxx>
31 #include <fuconuno.hxx>
32 #include <tabvwsh.hxx>
33 #include <userdat.hxx>
35 #include <sc.hrc> // defines of slot-IDs
39 class ScShapeTest
: public ScModelTestBase
43 : ScModelTestBase("sc/qa/unit/data")
48 static SdrPage
* lcl_getSdrPageWithAssert(ScDocument
& rDoc
)
50 ScDrawLayer
* pDrawLayer
= rDoc
.GetDrawLayer();
51 CPPUNIT_ASSERT_MESSAGE("No ScDrawLayer", pDrawLayer
);
52 SdrPage
* pPage
= pDrawLayer
->GetPage(0);
53 CPPUNIT_ASSERT_MESSAGE("No draw page", pPage
);
57 static SdrObject
* lcl_getSdrObjectWithAssert(ScDocument
& rDoc
, sal_uInt16 nObjNumber
)
59 ScDrawLayer
* pDrawLayer
= rDoc
.GetDrawLayer();
60 CPPUNIT_ASSERT_MESSAGE("No ScDrawLayer", pDrawLayer
);
61 const SdrPage
* pPage
= pDrawLayer
->GetPage(0);
62 CPPUNIT_ASSERT_MESSAGE("No draw page", pPage
);
63 SdrObject
* pObj
= pPage
->GetObj(nObjNumber
);
64 OString sMsg
= "no Object " + OString::number(nObjNumber
);
65 CPPUNIT_ASSERT_MESSAGE(sMsg
.getStr(), pObj
);
69 static SdrObject
* lcl_getSdrObjectbyName(ScDocument
& rDoc
, std::u16string_view rName
)
71 ScDrawLayer
* pDrawLayer
= rDoc
.GetDrawLayer();
72 const SdrPage
* pPage
= pDrawLayer
->GetPage(0);
73 SdrObject
* pObj
= pPage
->GetObjByName(rName
);
77 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf144242_OpenBezier_noSwapWH
)
79 // Shapes, which have rotation incorporated in their points, got erroneously width-height
80 // swapped, because they report a rotation. (Rotation was introduced to align text with curve.)
82 // Create a spreadsheet document with default row height and col width
85 // Insert default open Bezier curve
86 ScTabViewShell
* pTabViewShell
= getViewShell();
87 SfxRequest
aReq(pTabViewShell
->GetViewFrame(), SID_DRAW_BEZIER_NOFILL
);
88 aReq
.SetModifier(KEY_MOD1
); // Ctrl
89 pTabViewShell
->ExecDraw(aReq
);
90 pTabViewShell
->SetDrawShell(false);
92 // Get document and newly created object
93 ScDocument
* pDoc
= getScDoc();
94 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
96 // Rotate object by 300deg
97 pObj
->Rotate(pObj
->GetSnapRect().Center(), 30000_deg100
, sin(toRadians(30000_deg100
)),
98 cos(toRadians(30000_deg100
)));
99 tools::Rectangle
aExpectRect(pObj
->GetSnapRect());
101 // Save, reload and compare
102 saveAndReload("Calc Office Open XML");
104 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
105 tools::Rectangle
aSnapRect(pObj
->GetSnapRect());
106 // Without fix in place width and height were swapped
107 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectRect
, aSnapRect
, 40);
110 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf144242_Line_noSwapWH
)
112 // Shapes, which have rotation incorporated in their points, got erroneously width-height
113 // swapped, because they report a rotation. (Rotation was introduced to align text with line.)
115 // Create a spreadsheet document with default row height and col width
118 // Insert default line
119 ScTabViewShell
* pTabViewShell
= getViewShell();
120 SfxRequest
aReq(pTabViewShell
->GetViewFrame(), SID_DRAW_LINE
);
121 aReq
.SetModifier(KEY_MOD1
); // Ctrl
122 pTabViewShell
->ExecDraw(aReq
);
123 pTabViewShell
->SetDrawShell(false);
125 // Get document and newly created object
126 ScDocument
* pDoc
= getScDoc();
127 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
129 // Rotate object by 300deg
130 pObj
->Rotate(pObj
->GetSnapRect().Center(), 30000_deg100
, sin(toRadians(30000_deg100
)),
131 cos(toRadians(30000_deg100
)));
132 tools::Rectangle
aExpectRect(pObj
->GetSnapRect());
134 // Save, reload and compare
135 saveAndReload("Calc Office Open XML");
137 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
138 tools::Rectangle
aSnapRect(pObj
->GetSnapRect());
139 // Without fix in place width and height were swapped
140 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectRect
, aSnapRect
, 40);
143 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf143619_validation_circle_pos
)
145 // Load a document, which has validation circle around cell E6.
146 createScDoc("ods/tdf143619_validationCirclePos.ods");
149 ScDocument
* pDoc
= getScDoc();
151 // Get shape. That is the validation circle.
152 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
154 // Error was, that deleting row and col before E6 does not move circle to D5, but to B3.
155 // Delete first row and first column.
157 dispatchCommand(mxComponent
, ".uno:DeleteRows", {});
159 dispatchCommand(mxComponent
, ".uno:DeleteColumns", {});
161 // Without fix in place the position was (2007, 833)
162 Point aPos
= pObj
->GetSnapRect().TopLeft();
163 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(Point(6523, 1736), aPos
, 1);
166 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf140252_DragCreateFormControl
)
168 // Error was, that drag-created form controls were initially not on layer 'controls' and thus
169 // other shapes could be placed in front of form controls.
170 // Load an empty document.
171 createScDoc("ods/ManualColWidthRowHeight.ods");
173 // Get ScTabViewShell
174 ScTabViewShell
* pTabViewShell
= getViewShell();
176 // drag-create a push button as example of form control
177 SfxUInt16Item
aIdentifierItem(SID_FM_CONTROL_IDENTIFIER
,
178 static_cast<sal_uInt16
>(SdrObjKind::FormButton
));
179 SfxUInt32Item
aInventorItem(SID_FM_CONTROL_INVENTOR
, sal_uInt32(SdrInventor::FmForm
));
180 const SfxPoolItem
* pArgs
[] = { &aIdentifierItem
, &aInventorItem
, nullptr };
181 pTabViewShell
->GetViewData().GetDispatcher().Execute(SID_FM_CREATE_CONTROL
,
182 SfxCallMode::SYNCHRON
, pArgs
);
183 // above includes creation of FuConstUnoControl and call of its Activate() method
185 // get FuConstUnoControl
186 ScTabView
* pTabView
= pTabViewShell
->GetViewData().GetView();
187 CPPUNIT_ASSERT(pTabView
);
188 FuConstUnoControl
* pFuConstUC
= static_cast<FuConstUnoControl
*>(pTabView
->GetDrawFuncPtr());
189 CPPUNIT_ASSERT(pFuConstUC
);
191 // drag-create shape, points are in pixel
192 MouseEvent
aMouseEvent(Point(50, 100), 1, MouseEventModifiers::NONE
, MOUSE_LEFT
, 0);
193 pFuConstUC
->MouseButtonDown(aMouseEvent
);
194 aMouseEvent
= MouseEvent(Point(200, 250), 1, MouseEventModifiers::DRAGMOVE
, MOUSE_LEFT
, 0);
195 pFuConstUC
->MouseMove(aMouseEvent
);
196 aMouseEvent
= MouseEvent(Point(200, 250), 1, MouseEventModifiers::NONE
, MOUSE_LEFT
, 0);
197 pFuConstUC
->MouseButtonUp(aMouseEvent
);
198 pFuConstUC
->Deactivate();
199 pTabViewShell
->SetDrawShell(false);
201 // Get document and newly created push button.
202 ScDocument
* pDoc
= getScDoc();
203 SdrUnoObj
* pObj
= static_cast<SdrUnoObj
*>(lcl_getSdrObjectWithAssert(*pDoc
, 0));
205 // Without the fix in place, the shape would be on layer SC_LAYER_FRONT (0)
206 sal_Int16 nExpectedID
= SC_LAYER_CONTROLS
.get();
207 sal_Int16 nActualID
= pObj
->GetLayer().get();
208 CPPUNIT_ASSERT_EQUAL(nExpectedID
, nActualID
);
211 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf134355_DragCreateCustomShape
)
213 // Error was, that drag-created custom shapes were initially on layer "controls", although that
214 // layer is exclusively for form controls. Effect was, that other shapes could not be brought in
215 // front of custom shapes.
216 // Load an empty document.
217 createScDoc("ods/ManualColWidthRowHeight.ods");
220 ScTabViewShell
* pTabViewShell
= getViewShell();
221 ScTabView
* pTabView
= pTabViewShell
->GetViewData().GetView();
223 // drag-create custom shape
224 uno::Sequence
<beans::PropertyValue
> aPropertyValues
= {
225 comphelper::makePropertyValue("SymbolShapes", OUString("smiley")),
227 dispatchCommand(mxComponent
, ".uno:SymbolShapes", aPropertyValues
);
228 // above includes creation of FuConstCustomShape and call of its Activate() method
229 FuConstCustomShape
* pFuConstCS
= static_cast<FuConstCustomShape
*>(pTabView
->GetDrawFuncPtr());
230 CPPUNIT_ASSERT(pFuConstCS
);
231 // points are in pixel
232 MouseEvent
aMouseEvent(Point(50, 100), 1, MouseEventModifiers::NONE
, MOUSE_LEFT
, 0);
233 pFuConstCS
->MouseButtonDown(aMouseEvent
);
234 aMouseEvent
= MouseEvent(Point(200, 250), 1, MouseEventModifiers::DRAGMOVE
, MOUSE_LEFT
, 0);
235 pFuConstCS
->MouseMove(aMouseEvent
);
236 aMouseEvent
= MouseEvent(Point(200, 250), 1, MouseEventModifiers::NONE
, MOUSE_LEFT
, 0);
237 pFuConstCS
->MouseButtonUp(aMouseEvent
);
238 pFuConstCS
->Deactivate();
239 pTabViewShell
->SetDrawShell(false);
241 // Get document and newly created custom shape.
242 ScDocument
* pDoc
= getScDoc();
243 SdrObjCustomShape
* pObj
= static_cast<SdrObjCustomShape
*>(lcl_getSdrObjectWithAssert(*pDoc
, 0));
245 // Without the fix in place, the shape would be on layer SC_LAYER_CONTROLS (3)
246 sal_Int16 nExpectedID
= SC_LAYER_FRONT
.get();
247 sal_Int16 nActualID
= pObj
->GetLayer().get();
248 CPPUNIT_ASSERT_EQUAL(nExpectedID
, nActualID
);
251 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf140252_LayerOfControl
)
253 // Error was, that a newly inserted control shape was put on layer
254 // "vorne" instead of layer "control".
255 // Load an empty document.
256 createScDoc("ods/ManualColWidthRowHeight.ods");
258 // Create default push button
259 SfxUInt16Item
aIdentifierItem(SID_FM_CONTROL_IDENTIFIER
,
260 static_cast<sal_uInt16
>(SdrObjKind::FormButton
));
261 SfxUInt32Item
aInventorItem(SID_FM_CONTROL_INVENTOR
, sal_uInt32(SdrInventor::FmForm
));
262 const SfxPoolItem
* pArgs
[] = { &aIdentifierItem
, &aInventorItem
, nullptr };
263 const SfxPoolItem
* pInternalArgs
[] = { nullptr };
264 ScTabViewShell
* pTabViewShell
= getViewShell();
265 pTabViewShell
->GetViewData().GetDispatcher().Execute(
266 SID_FM_CREATE_CONTROL
, SfxCallMode::SYNCHRON
, pArgs
, KEY_MOD1
, pInternalArgs
);
268 // Get document and newly created push button.
269 ScDocument
* pDoc
= getScDoc();
270 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
272 // Check LayerID of object. Without the fix in place it was 0.
273 sal_Int16 nExpectedID
= SC_LAYER_CONTROLS
.get();
274 sal_Int16 nActualID
= pObj
->GetLayer().get();
275 CPPUNIT_ASSERT_EQUAL(nExpectedID
, nActualID
);
278 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf137082_LTR_to_RTL
)
280 // Before the fix for tdf137081 and tdf137082, when flipping sheet from LTR to RTL, page anchored
281 // shapes were mirrored, but cell anchored shapes not. This was changed so, that shapes are always
282 // mirrored. Graphics are still not mirrored but shifted. This test makes sure a shape is mirrored
283 // and an image is not mirrored.
285 createScDoc("ods/tdf137082_LTR_arrow_image.ods");
288 ScDocument
* pDoc
= getScDoc();
290 // Get objects and their transformation angles
291 SdrObject
* pObjCS
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
292 const Degree100 nRotateLTR
= pObjCS
->GetRotateAngle();
293 SdrObject
* pObjImage
= lcl_getSdrObjectWithAssert(*pDoc
, 1);
294 const Degree100 nShearLTR
= pObjImage
->GetShearAngle();
297 ScTabViewShell
* pViewShell
= getViewShell();
298 pViewShell
->GetViewData().GetDispatcher().Execute(FID_TAB_RTL
);
300 // Check custom shape is mirrored, image not.
301 const Degree100 nShearRTLActual
= pObjImage
->GetShearAngle();
302 CPPUNIT_ASSERT_EQUAL_MESSAGE("image should not be mirrored", nShearLTR
.get(),
303 nShearRTLActual
.get());
304 const Degree100 nRotateRTLExpected
= 36000_deg100
- nRotateLTR
;
305 const Degree100 nRotateRTLActual
= pObjCS
->GetRotateAngle();
306 CPPUNIT_ASSERT_EQUAL_MESSAGE("custom shape should be mirrored", nRotateRTLExpected
.get(),
307 nRotateRTLActual
.get());
310 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf137082_RTL_cell_anchored
)
312 // Error was, that cell anchored custom shapes wrote wrong offsets to file and thus were wrong on
313 // reloading. The file contains one custom shape with "resize" and another one without.
314 createScDoc("ods/tdf137082_RTL_cell_anchored.ods");
317 ScDocument
* pDoc
= getScDoc();
320 const Point
aTopLeftA(-20500, 3500); // shape A without "resize"
321 const Point
aTopLeftB(-9500, 3500); // shape B with "resize"
322 const Size
aSize(2278, 5545); // both
323 const tools::Rectangle
aSnapRectA(aTopLeftA
, aSize
);
324 const tools::Rectangle
aSnapRectB(aTopLeftB
, aSize
);
326 // Test reading was correct
327 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
328 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aSnapRectA
, pObj
->GetSnapRect(), 1);
329 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 1);
330 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aSnapRectB
, pObj
->GetSnapRect(), 1);
333 saveAndReload("calc8");
339 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
340 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aSnapRectA
, pObj
->GetSnapRect(), 1);
341 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 1);
342 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aSnapRectB
, pObj
->GetSnapRect(), 1);
345 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf137081_RTL_page_anchored
)
347 // Error was, that page anchored lines and custom shapes were mirrored on opening. The document
348 // contains measure line, polyline and transformed custom shape.
349 createScDoc("ods/tdf137081_RTL_page_anchored.ods");
352 ScDocument
* pDoc
= getScDoc();
356 const Point
aStart(-3998, 2490);
357 const Point
aEnd(-8488, 5490);
359 const Point
aFirst(-10010, 2500);
360 const Point
aSecond(-14032, 5543);
361 const Point
aThird(-14500, 3500);
363 const Point
aTopLeft(-20500, 4583);
365 // Test reading was correct
366 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
368 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aStart
, pObj
->GetPoint(0), 1);
369 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aEnd
, pObj
->GetPoint(1), 1);
371 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 1);
372 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aFirst
, pObj
->GetPoint(0), 1);
373 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aSecond
, pObj
->GetPoint(1), 1);
374 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aThird
, pObj
->GetPoint(2), 1);
376 SdrObjCustomShape
* pObjCS
377 = static_cast<SdrObjCustomShape
*>(lcl_getSdrObjectWithAssert(*pDoc
, 2));
378 CPPUNIT_ASSERT(!pObjCS
->IsMirroredX());
379 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aTopLeft
, pObjCS
->GetLogicRect().TopLeft(), 1);
382 saveAndReload("calc8");
388 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
390 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aStart
, pObj
->GetPoint(0), 1);
391 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aEnd
, pObj
->GetPoint(1), 1);
393 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 1);
394 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aFirst
, pObj
->GetPoint(0), 1);
395 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aSecond
, pObj
->GetPoint(1), 1);
396 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aThird
, pObj
->GetPoint(2), 1);
398 pObjCS
= static_cast<SdrObjCustomShape
*>(lcl_getSdrObjectWithAssert(*pDoc
, 2));
399 CPPUNIT_ASSERT(!pObjCS
->IsMirroredX());
400 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aTopLeft
, pObjCS
->GetLogicRect().TopLeft(), 1);
403 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf139583_Rotate180deg
)
405 // Load an empty document.
406 createScDoc("ods/ManualColWidthRowHeight.ods");
408 // Get document and draw page
409 ScDocument
* pDoc
= getScDoc();
410 SdrPage
* pPage
= lcl_getSdrPageWithAssert(*pDoc
);
413 const tools::Rectangle
aRect(Point(3000, 4000), Size(5000, 2000));
414 ScDrawLayer
* pDrawLayer
= pDoc
->GetDrawLayer();
415 CPPUNIT_ASSERT_MESSAGE("No ScDrawLayer", pDrawLayer
);
416 rtl::Reference
<SdrRectObj
> pObj
= new SdrRectObj(*pDrawLayer
, aRect
);
417 CPPUNIT_ASSERT_MESSAGE("Could not create rectangle", pObj
);
418 pPage
->InsertObject(pObj
.get());
420 // Anchor "to cell (resize with cell)" and then rotate it by 180deg around center
421 // The order is important here.
422 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, *pDoc
, 0 /*SCTAB*/, true /*bResizeWithCell*/);
423 pObj
->Rotate(aRect
.Center(), Degree100(18000), 0.0, -1.0);
427 saveAndReload("calc8");
429 // Get document and object
431 pObj
= static_cast<SdrRectObj
*>(lcl_getSdrObjectWithAssert(*pDoc
, 0));
433 // Without the fix in place, the shape would have nearly zero size.
434 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aRect
, pObj
->GetSnapRect(), 1);
437 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf137033_FlipHori_Resize
)
439 // Load a document, which has a rotated custom shape, which is horizontal flipped. Error was, that
440 // if such shape was anchored "resize with cell", then after save and reload it was distorted.
441 createScDoc("ods/tdf137033_FlipHoriRotCustomShape.ods");
443 // Get document and shape
444 ScDocument
* pDoc
= getScDoc();
445 SdrObjCustomShape
* pObj
= static_cast<SdrObjCustomShape
*>(lcl_getSdrObjectWithAssert(*pDoc
, 0));
447 // Verify shape is correctly loaded. Then set shape to "resize with cell".
448 tools::Rectangle
aSnapRect(pObj
->GetSnapRect());
449 const tools::Rectangle
aExpectRect(Point(4998, 7000), Size(9644, 6723));
450 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectRect
, aSnapRect
, 1);
451 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, *pDoc
, 0 /*SCTAB*/, true /*bResizeWithCell*/);
454 saveAndReload("calc8");
456 // Get document and shape
458 pObj
= static_cast<SdrObjCustomShape
*>(lcl_getSdrObjectWithAssert(*pDoc
, 0));
460 // Check shape has the original geometry, besides rounding and unit conversion errors
461 aSnapRect
= pObj
->GetSnapRect();
462 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectRect
, aSnapRect
, 1);
465 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf137033_RotShear_ResizeHide
)
467 // For rotated or sheared shapes anchored "To Cell (resize with cell) hiding rows or columns will
468 // not only change size but rotation and shear angle too. Error was, that not the original angles
469 // of the full sized shape were written to file but the changed one.
471 // Load a document, which has a rotated and sheared shape, anchored to cell with resize.
472 createScDoc("ods/tdf137033_RotShearResizeAnchor.ods");
475 ScDocument
* pDoc
= getScDoc();
477 // Hide rows 4 and 5 (UI number), which are inside the shape and thus change shape geometry
478 pDoc
->SetRowHidden(3, 4, 0, true);
479 pDoc
->SetDrawPageSize(0); // trigger recalcpos, otherwise shapes are not changed
482 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
484 // Verify hiding has changed shape geometry as expected
485 tools::Rectangle
aSnapRect(pObj
->GetSnapRect());
486 Degree100
aRotateAngle(pObj
->GetRotateAngle());
487 Degree100
aShearAngle(pObj
->GetShearAngle());
488 // mathematical exact would be Point(3868, 4795), Size(9763, 1909)
489 // current values as of LO 7.2
490 const tools::Rectangle
aExpectRect(Point(3875, 4796), Size(9760, 1911));
491 const Degree100
aExpectRotateAngle(20925_deg100
);
492 const Degree100
aExpectShearAngle(-6570_deg100
);
493 CPPUNIT_ASSERT_MESSAGE("Hide rows, shear angle: ",
494 abs(aShearAngle
- aExpectShearAngle
) <= 1_deg100
);
495 CPPUNIT_ASSERT_MESSAGE("Hide rows, rotate angle: ",
496 abs(aRotateAngle
- aExpectRotateAngle
) <= 1_deg100
);
497 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectRect
, aSnapRect
, 1);
500 saveAndReload("calc8");
502 // Get document and shape
504 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
506 // Check shape has the original geometry, besides heavy rounding and unit conversion errors
507 aSnapRect
= pObj
->GetSnapRect();
508 aRotateAngle
= pObj
->GetRotateAngle();
509 aShearAngle
= pObj
->GetShearAngle();
510 CPPUNIT_ASSERT_MESSAGE("Reload, shear angle: ",
511 abs(aShearAngle
- aExpectShearAngle
) <= 3_deg100
);
512 CPPUNIT_ASSERT_MESSAGE("Reload, rotate angle: ",
513 abs(aRotateAngle
- aExpectRotateAngle
) <= 3_deg100
);
514 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectRect
, aSnapRect
, 7);
517 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf137033_RotShear_Hide
)
519 // Hiding row or columns affect cell anchored shape based on their snap rectangle. The first
520 // attempt to fix lost position has used the logic rect instead. For rotated or sheared shape it
521 // makes a difference.
523 // Load a document, which has a rotated and sheared shape, anchored to cell, without resize.
524 createScDoc("ods/tdf137033_RotShearCellAnchor.ods");
527 ScDocument
* pDoc
= getScDoc();
529 // Hide column C, which is left from logic rect, but right from left edge of snap rect
530 pDoc
->SetColHidden(2, 2, 0, true);
531 pDoc
->SetDrawPageSize(0); // trigger recalcpos, otherwise shapes are not changed
534 saveAndReload("calc8");
536 // Get document and shape
538 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
540 // Check shape is visible. With the old version, the shape was moved to column C and
541 // thus hidden on reload.
542 CPPUNIT_ASSERT_MESSAGE("Reload: Shape has to be visible", pObj
->IsVisible());
543 // Verify position and size are unchanged besides rounding and unit conversion errors
544 // Values are manually taken from shape before hiding column C.
545 const tools::Rectangle
aExpectRect(Point(4500, 3500), Size(15143, 5187));
546 const tools::Rectangle aSnapRect
= pObj
->GetSnapRect();
547 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectRect
, aSnapRect
, 1);
550 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf137576_LogicRectInDefaultMeasureline
)
552 // Error was, that the empty logical rectangle of a default measure line (Ctrl+Click)
553 // resulted in zeros in NonRotatedAnchor and a wrong position when reloading.
555 // Load an empty document.
556 createScDoc("ods/ManualColWidthRowHeight.ods");
558 // Create default measureline by SfxRequest that corresponds to Ctrl+Click
559 ScTabViewShell
* pTabViewShell
= getViewShell();
560 SfxRequest
aReq(pTabViewShell
->GetViewFrame(), SID_DRAW_MEASURELINE
);
561 aReq
.SetModifier(KEY_MOD1
); // Ctrl
562 pTabViewShell
->ExecDraw(aReq
);
564 // Get document and newly created measure line.
565 ScDocument
* pDoc
= getScDoc();
566 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
568 // Anchor "to Cell (resize with cell)"
569 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, *pDoc
, 0 /*SCTAB*/, true /*bResizeWithCell*/);
570 // Deselect shape and switch to object selection type "Cell".
571 pTabViewShell
->SetDrawShell(false);
575 dispatchCommand(mxComponent
, ".uno:HideColumn", {});
577 // Get current position. I will not use absolute values for comparison, because document is loaded
578 // in full screen mode of unknown size and default object is placed in center of window.
579 Point aOldPos
= pObj
->GetRelativePos();
581 // Save and reload, get ScDocShell
582 saveAndReload("calc8");
584 // Get document and object
586 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
588 // Assert object position is unchanged, besides Twips<->Hmm inaccuracy.
589 Point aNewPos
= pObj
->GetRelativePos();
590 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aOldPos
, aNewPos
, 1);
593 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf137576_LogicRectInNewMeasureline
)
595 // Error was, that a new measure line had no logical rectangle. This resulted in zeros in
596 // NonRotatedAnchor. As a result the position was wrong when reloading.
598 // Load an empty document
599 createScDoc("ods/ManualColWidthRowHeight.ods");
601 // Get document and draw page
602 ScDocument
* pDoc
= getScDoc();
603 SdrPage
* pPage
= lcl_getSdrPageWithAssert(*pDoc
);
605 // Create a new measure line and insert it
606 Point
aStartPoint(5000, 5500);
607 Point
aEndPoint(13000, 8000);
608 ScDrawLayer
* pDrawLayer
= pDoc
->GetDrawLayer();
609 CPPUNIT_ASSERT_MESSAGE("No ScDrawLayer", pDrawLayer
);
610 rtl::Reference
<SdrMeasureObj
> pObj
= new SdrMeasureObj(*pDrawLayer
, aStartPoint
, aEndPoint
);
611 CPPUNIT_ASSERT_MESSAGE("Could not create measure line", pObj
);
612 pPage
->InsertObject(pObj
.get());
614 // Anchor "to cell (resize with cell)" and examine NonRotatedAnchor
615 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, *pDoc
, 0 /*SCTAB*/, true /*bResizeWithCell*/);
616 ScDrawObjData
* pNData
= ScDrawLayer::GetNonRotatedObjData(pObj
.get());
617 CPPUNIT_ASSERT_MESSAGE("Failed to get NonRotatedAnchor", pNData
);
618 // Without the fix all four values would be zero.
619 CPPUNIT_ASSERT_EQUAL(SCCOL(1), pNData
->maStart
.Col());
620 CPPUNIT_ASSERT_EQUAL(SCROW(2), pNData
->maStart
.Row());
621 CPPUNIT_ASSERT_EQUAL(SCCOL(7), pNData
->maEnd
.Col());
622 CPPUNIT_ASSERT_EQUAL(SCROW(2), pNData
->maEnd
.Row());
627 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testMeasurelineHideColSave
)
629 // The document contains a SdrMeasureObj anchored "To Cell (resize with cell)" with start in cell
630 // D11 and end in cell I5. Error was, that after hiding col A and saving, start and end point
631 // position were lost.
632 createScDoc("ods/measurelineHideColSave.ods");
634 // Get document and shape
635 ScDocument
* pDoc
= getScDoc();
636 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
638 // Make sure loading is correct
639 Point
aStartPoint(7500, 15000); // according UI
640 Point
aEndPoint(17500, 8000);
641 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aStartPoint
, pObj
->GetPoint(0), 1);
642 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aEndPoint
, pObj
->GetPoint(1), 1);
645 pDoc
->SetColHidden(0, 0, 0, true);
646 pDoc
->SetDrawPageSize(0); // trigger recalcpos, otherwise shapes are not changed
647 // Shape should move by column width, here 3000
648 aStartPoint
.Move(-3000, 0);
649 aEndPoint
.Move(-3000, 0);
650 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aStartPoint
, pObj
->GetPoint(0), 1);
651 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aEndPoint
, pObj
->GetPoint(1), 1);
654 saveAndReload("calc8");
656 // Get document and shape
658 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
660 // Check that start and end point are unchanged besides rounding and unit conversion errors
661 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aStartPoint
, pObj
->GetPoint(0), 2);
662 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aEndPoint
, pObj
->GetPoint(1), 2);
665 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testHideColsShow
)
667 // The document contains a shape anchored "To Cell (resize with cell)" with starts in cell C3 and
668 //ends in cell D5. Error was, that hiding cols C and D and then show them again extends the shape
671 createScDoc("ods/hideColsShow.ods");
673 // Get document and shape
674 ScDocument
* pDoc
= getScDoc();
675 SdrObjCustomShape
* pObj
= static_cast<SdrObjCustomShape
*>(lcl_getSdrObjectWithAssert(*pDoc
, 0));
677 CPPUNIT_ASSERT_MESSAGE("Load: Object should be visible", pObj
->IsVisible());
678 tools::Rectangle
aSnapRectOrig(pObj
->GetSnapRect());
680 // Hide cols C and D.
681 goToCell("$C$1:$D$1");
683 ScTabViewShell
* pViewShell
= getViewShell();
684 pViewShell
->GetViewData().GetDispatcher().Execute(FID_COL_HIDE
);
686 // Check object is invisible
687 CPPUNIT_ASSERT_MESSAGE("Hide: Object should be invisible", !pObj
->IsVisible());
690 goToCell("$C$1:$D$1");
691 pViewShell
->GetViewData().GetDispatcher().Execute(FID_COL_SHOW
);
693 // Check object is visible and has old size
694 CPPUNIT_ASSERT_MESSAGE("Show: Object should be visible", pObj
->IsVisible());
695 tools::Rectangle
aSnapRectShow(pObj
->GetSnapRect());
696 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aSnapRectOrig
, aSnapRectShow
, 1);
699 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testFormSizeWithHiddenCol
)
701 // The document contains a form (Listbox) shape anchored "To Cell (resize with cell)" with starts in cell B5 and
702 // ends in cell D5. The error was the form shape was resized if there was hidden col/row.
704 createScDoc("ods/tdf154005.ods");
706 // Get document and shape
707 ScDocument
* pDoc
= getScDoc();
708 SdrUnoObj
* pObj
= static_cast<SdrUnoObj
*>(lcl_getSdrObjectWithAssert(*pDoc
, 0));
710 // Check Position and Size
711 pDoc
->SetDrawPageSize(0); // trigger recalcpos
712 tools::Rectangle
aRect(2432, 3981, 4932, 4631); // expected snap rect from values in file
713 const tools::Rectangle
& rShapeRect(pObj
->GetSnapRect());
714 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aRect
, rShapeRect
, 1);
717 ScDrawObjData
* pData
= ScDrawLayer::GetObjData(pObj
);
718 CPPUNIT_ASSERT_MESSAGE("expected object meta data", pData
);
720 const OUString
sActual("start col " + OUString::number(pData
->maStart
.Col()) + " row "
721 + OUString::number(pData
->maStart
.Row()) + " end col "
722 + OUString::number(pData
->maEnd
.Col()) + " row "
723 + OUString::number(pData
->maEnd
.Row()));
724 CPPUNIT_ASSERT_EQUAL(OUString("start col 1 row 4 end col 3 row 4"), sActual
);
727 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf138138_MoveCellWithRotatedShape
)
729 // The document contains a 90deg rotated, cell-anchored rectangle in column D. Insert 2 columns
730 // after column B, save and reload. The shape was not correctly moved to column F.
731 createScDoc("ods/tdf138138_MoveCellWithRotatedShape.ods");
733 // Get document and shape
734 ScDocument
* pDoc
= getScDoc();
735 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
737 // Check anchor and position of shape. The expected values are taken from UI.
738 tools::Rectangle aSnapRect
= pObj
->GetSnapRect();
739 tools::Rectangle
aExpectedRect(Point(10000, 3000), Size(1000, 7500));
740 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectedRect
, aSnapRect
, 1);
742 // Insert two columns after column B
743 goToCell("$A$1:$B$1");
745 ScTabViewShell
* pViewShell
= getViewShell();
746 pViewShell
->GetViewData().GetDispatcher().Execute(FID_INS_COLUMNS_AFTER
);
747 aExpectedRect
= tools::Rectangle(Point(16000, 3000), Size(1000, 7500)); // col width 3000
748 aSnapRect
= pObj
->GetSnapRect();
749 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectedRect
, aSnapRect
, 1);
752 saveAndReload("calc8");
754 // Get document and shape
756 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
758 // Assert objects size is unchanged, position is shifted.
759 aSnapRect
= pObj
->GetSnapRect();
760 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectedRect
, aSnapRect
, 1);
763 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testLoadVerticalFlip
)
765 // The document has a cell anchored custom shape with vertical flip. Error was, that the
766 // flip was lost on loading.
767 createScDoc("ods/loadVerticalFlip.ods");
769 // Get document and shape
770 ScDocument
* pDoc
= getScDoc();
771 SdrObjCustomShape
* pObj
= static_cast<SdrObjCustomShape
*>(lcl_getSdrObjectWithAssert(*pDoc
, 0));
773 // Check that shape is flipped
774 CPPUNIT_ASSERT_MESSAGE("Load: Object should be vertically flipped", pObj
->IsMirroredY());
777 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf117948_CollapseBeforeShape
)
779 // The document contains a column group left from the image. The group is expanded. Collapse the
780 // group, save and reload. The original error was, that the line was on wrong position after reload.
781 // After the fix for 'resize with cell', the custom shape had wrong position and size too.
782 createScDoc("ods/tdf117948_CollapseBeforeShape.ods");
784 // Get document and objects
785 ScDocument
* pDoc
= getScDoc();
786 SdrObject
* pObj0
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
787 SdrObject
* pObj1
= lcl_getSdrObjectWithAssert(*pDoc
, 1);
789 // Collapse the group
790 ScTabViewShell
* pViewShell
= getViewShell();
791 pViewShell
->GetViewData().SetCurX(1);
792 pViewShell
->GetViewData().SetCurY(0);
793 pViewShell
->GetViewData().GetDispatcher().Execute(SID_OUTLINE_HIDE
);
795 // Check anchor and position of shape. The expected values are taken from UI before saving.
796 tools::Rectangle aSnapRect0Collapse
= pObj0
->GetSnapRect();
797 tools::Rectangle
aExpectedRect0(Point(4672, 1334), Size(1787, 1723));
798 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectedRect0
, aSnapRect0Collapse
, 1);
799 tools::Rectangle aSnapRect1Collapse
= pObj1
->GetSnapRect();
800 tools::Rectangle
aExpectedRect1(Point(5647, 4172), Size(21, 3441));
801 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectedRect1
, aSnapRect1Collapse
, 1);
804 saveAndReload("calc8");
806 // Get document and objects
808 pObj0
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
809 pObj1
= lcl_getSdrObjectWithAssert(*pDoc
, 1);
811 // Assert objects size and position are not changed. Actual values differ a little bit
812 // because of cumulated Twips-Hmm conversion errors.
813 tools::Rectangle aSnapRect0Reload
= pObj0
->GetSnapRect();
814 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectedRect0
, aSnapRect0Reload
, 2);
816 tools::Rectangle aSnapRect1Reload
= pObj1
->GetSnapRect();
817 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectedRect1
, aSnapRect1Reload
, 2);
820 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf137355_UndoHideRows
)
822 // The document contains a shape anchored "To Cell" with start in cell C3 and end in cell D6.
823 // Error was, that hiding rows 3 to 6 and undo that action "lost" the shape.
824 // Actually it was not lost but hidden.
825 createScDoc("ods/tdf137355_UndoHideRows.ods");
827 // Get document and shape
828 ScDocument
* pDoc
= getScDoc();
829 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
831 CPPUNIT_ASSERT_MESSAGE("Load: Object should be visible", pObj
->IsVisible());
832 tools::Rectangle
aSnapRectOrig(pObj
->GetSnapRect());
834 // Hide rows 3 to 6 in UI. [Note: Simple pDoc->SetRowHidden(2,5,0,true) does not work, because it
835 // does not produce the needed undo items.]
836 goToCell("$A$3:$A$6");
837 ScTabViewShell
* pViewShell
= getViewShell();
838 pViewShell
->GetViewData().GetDispatcher().Execute(FID_ROW_HIDE
);
840 // Check object is invisible
841 CPPUNIT_ASSERT_MESSAGE("Hide: Object should be invisible", !pObj
->IsVisible());
844 pViewShell
->GetViewData().GetDispatcher().Execute(SID_UNDO
);
846 // Check object is visible and has old size
847 CPPUNIT_ASSERT_MESSAGE("Undo: Object should exist", pObj
);
848 CPPUNIT_ASSERT_MESSAGE("Undo: Object should be visible", pObj
->IsVisible());
849 tools::Rectangle
aSnapRectUndo(pObj
->GetSnapRect());
850 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aSnapRectOrig
, aSnapRectUndo
, 1);
853 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf152081_UndoHideColsWithNotes
)
855 createScDoc("ods/tdf152081_UndoHideColsWithNotes.ods");
857 // Get document and shape
858 ScDocument
* pDoc
= getScDoc();
859 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
861 CPPUNIT_ASSERT_MESSAGE("Load: Note object should be visible", pObj
->IsVisible());
864 goToCell("$B$2:$B$2");
865 ScTabViewShell
* pViewShell
= getViewShell();
866 pViewShell
->GetViewData().GetDispatcher().Execute(FID_COL_HIDE
);
868 // Check object is invisible
869 CPPUNIT_ASSERT_MESSAGE("Hide: Note object should be invisible", !pObj
->IsVisible());
872 pViewShell
->GetViewData().GetDispatcher().Execute(SID_UNDO
);
874 // Check object is visible
875 CPPUNIT_ASSERT_MESSAGE("Undo: Note object should exist", pObj
);
876 CPPUNIT_ASSERT_MESSAGE("Undo: Note object should be visible", pObj
->IsVisible());
879 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf115655_HideDetail
)
881 // The document contains an image inside a cell anchored "To Cell (resize with cell)". The cell
882 // belongs to a group. On loading the group is expanded.
883 // Error was, that after collapsing the group, save and reload, and expanding the group, the image
884 // was "lost". Actually is was resized to zero height.
885 createScDoc("ods/tdf115655_HideDetail.ods");
887 // Get document and image
888 ScDocument
* pDoc
= getScDoc();
889 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
892 tools::Rectangle aSnapRectOrig
= pObj
->GetSnapRect();
894 // Collapse the group
895 ScTabViewShell
* pViewShell
= getViewShell();
896 pViewShell
->GetViewData().SetCurX(0);
897 pViewShell
->GetViewData().SetCurY(1);
898 pViewShell
->GetViewData().GetDispatcher().Execute(SID_OUTLINE_HIDE
);
899 CPPUNIT_ASSERT_MESSAGE("Collapse: Image should not be visible", !pObj
->IsVisible());
902 saveAndReload("calc8");
904 // Get document and image
906 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
909 pViewShell
= getViewShell();
910 pViewShell
->GetViewData().SetCurX(0);
911 pViewShell
->GetViewData().SetCurY(1);
912 pViewShell
->GetViewData().GetDispatcher().Execute(SID_OUTLINE_SHOW
);
913 CPPUNIT_ASSERT_MESSAGE("Expand: Image should be visible", pObj
->IsVisible());
915 // Assert image size is not changed
916 tools::Rectangle aSnapRectReload
= pObj
->GetSnapRect();
917 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aSnapRectOrig
, aSnapRectReload
, 1);
920 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testFitToCellSize
)
922 // The document has a cell anchored custom shape. Applying
923 // FitToCellSize should resize and position the shape so,
924 // that it fits into its anchor cell. That did not happened.
925 createScDoc("ods/tdf119191_FitToCellSize.ods");
927 // Get document and shape
928 ScDocument
* pDoc
= getScDoc();
929 SdrObjCustomShape
* pObj
930 = dynamic_cast<SdrObjCustomShape
*>(lcl_getSdrObjectWithAssert(*pDoc
, 0));
932 // Get the draw view of the document
933 ScTabViewShell
* pViewShell
= getViewShell();
934 ScDrawView
* pDrawView
= pViewShell
->GetViewData().GetScDrawView();
935 CPPUNIT_ASSERT(pDrawView
);
938 pDrawView
->MarkNextObj();
939 CPPUNIT_ASSERT(pDrawView
->AreObjectsMarked());
941 // Fit selected shape into cell
942 pViewShell
->GetViewData().GetDispatcher().Execute(SID_FITCELLSIZE
);
944 const tools::Rectangle
& rShapeRect(pObj
->GetSnapRect());
945 const tools::Rectangle aCellRect
= pDoc
->GetMMRect(1, 1, 1, 1, 0);
946 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aCellRect
, rShapeRect
, 2);
949 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testCustomShapeCellAnchoredRotatedShape
)
951 // The example doc contains a cell anchored custom shape that is rotated
952 // and sheared. Error was, that the shape lost position and size on
954 createScDoc("ods/tdf119191_transformedShape.ods");
956 // Get document and shape
957 ScDocument
* pDoc
= getScDoc();
958 SdrObjCustomShape
* pObj
959 = dynamic_cast<SdrObjCustomShape
*>(lcl_getSdrObjectWithAssert(*pDoc
, 0));
961 // Check Position and Size
962 pDoc
->SetDrawPageSize(0); // trigger recalcpos
963 tools::Rectangle
aRect(2400, 751, 5772, 3694); // expected snap rect from values in file
964 const tools::Rectangle
& rShapeRect(pObj
->GetSnapRect());
965 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aRect
, rShapeRect
, 1);
968 ScDrawObjData
* pData
= ScDrawLayer::GetObjData(pObj
);
969 CPPUNIT_ASSERT_MESSAGE("expected object meta data", pData
);
971 const OUString
sActual("start col " + OUString::number(pData
->maStart
.Col()) + " row "
972 + OUString::number(pData
->maStart
.Row()) + " end col "
973 + OUString::number(pData
->maEnd
.Col()) + " row "
974 + OUString::number(pData
->maEnd
.Row()));
975 CPPUNIT_ASSERT_EQUAL(OUString("start col 1 row 1 end col 2 row 8"), sActual
);
978 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testLargeAnchorOffset
)
980 // The example doc contains a resize-with-cell-anchored measure line
981 // with a large vertical offset that shifts the start point onto the
983 createScDoc("ods/LargeAnchorOffset.ods");
985 ScDocument
* pDoc
= getScDoc();
986 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
988 const Point aOldPos
= pObj
->GetRelativePos();
989 // Just to check that it imports correctly
990 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(Point(9504, 9089), aOldPos
, 1);
992 saveAndReload("calc8");
995 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
997 // Without the fix, this would fail:
998 // Test name: sc_apitest::ScShapeTest::testLargeAnchorOffset
1000 // - Expression: std::abs(rExpected.Y() - rActual.Y()) <= nTolerance
1001 // - after reload Y expected 9089 actual 9643 Tolerance 1
1002 const Point aNewPos
= pObj
->GetRelativePos();
1003 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(aOldPos
, aNewPos
, 1);
1006 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf139083_copy_without_resize
)
1008 // Load a document, which has a shape anchored to cell B2, but without 'resize with cell'.
1009 // When the range B2:B3 is copied and pasted to D5, then the copied shape should keep its size.
1010 createScDoc("ods/tdf139083_copy_without_resize.ods");
1013 ScDocument
* pDoc
= getScDoc();
1015 // Copy cells B2:B3. They have row height 2cm and column width 3cm.
1016 goToCell("$B$2:$B$3");
1017 dispatchCommand(mxComponent
, ".uno:Copy", {});
1019 // Paste to D5. There are row height 0.5cm and column width 1cm.
1021 dispatchCommand(mxComponent
, ".uno:Paste", {});
1023 // Make sure original and pasted shape have the same size.
1024 // Size of original shape is 2001x3002, without fix size of pasted shape was 668x750.
1025 SdrObject
* pObjOrig
= lcl_getSdrObjectWithAssert(*pDoc
, 0); // original shape
1026 SdrObject
* pObjPasted
= lcl_getSdrObjectWithAssert(*pDoc
, 1); // pasted shape
1027 CPPUNIT_ASSERT_DOUBLES_EQUAL(2001, pObjOrig
->GetSnapRect().GetWidth(), 1);
1028 CPPUNIT_ASSERT_DOUBLES_EQUAL(3002, pObjOrig
->GetSnapRect().GetHeight(), 1);
1029 CPPUNIT_ASSERT_DOUBLES_EQUAL(2001, pObjPasted
->GetSnapRect().GetWidth(), 1);
1030 CPPUNIT_ASSERT_DOUBLES_EQUAL(3002, pObjPasted
->GetSnapRect().GetHeight(), 1);
1033 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf155093_double_names
)
1035 // Load a document, which has a shape in range B6:C14 with name "myArrow". When the range was
1036 // copied and pasted, then the copied shape got the same name and thus was not accessible with
1038 createScDoc("ods/tdf155093_double_names.ods");
1039 ScDocument
* pDoc
= getScDoc();
1042 goToCell("$B$6:$C$14");
1043 dispatchCommand(mxComponent
, ".uno:Copy", {});
1045 dispatchCommand(mxComponent
, ".uno:Paste", {});
1047 // Make sure original and pasted shape have different names.
1048 SdrObject
* pObjOrig
= lcl_getSdrObjectWithAssert(*pDoc
, 0); // original shape
1049 SdrObject
* pObjPasted
= lcl_getSdrObjectWithAssert(*pDoc
, 1); // pasted shape
1050 CPPUNIT_ASSERT(pObjOrig
->GetName() != pObjPasted
->GetName());
1053 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf155095_shape_collapsed_group
)
1055 // Load a document, which has a shape in range C9:C16, anchored 'To cell (resize with cell)'.
1056 // The rows 11 to 14 are in a collapsed group. So the shape effectively spans 4 rows. When
1057 // copying the range B5:C19 and pasting it to B22, the group is expanded and the shape should
1058 // increase its height so that it spans 8 rows.
1059 createScDoc("ods/tdf155095_shape_over_collapsed_group.ods");
1060 ScDocument
* pDoc
= getScDoc();
1063 goToCell("$B$5:$C$19");
1064 dispatchCommand(mxComponent
, ".uno:Copy", {});
1066 dispatchCommand(mxComponent
, ".uno:Paste", {});
1068 // Make sure the shape has the correct size and spans C26:C33
1069 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 1); // pasted shape
1070 // Without fix the shape had position(6708,11564) and size(407,2013).
1071 tools::Rectangle
aExpectedRect(tools::Rectangle(Point(6708, 10743), Size(407, 3473)));
1072 tools::Rectangle
aSnapRect(pObj
->GetSnapRect());
1073 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectedRect
, aSnapRect
, 1);
1075 // Without fix the shape spans C28:C32
1076 ScDrawObjData
* pObjData
= ScDrawLayer::GetObjData(pObj
);
1077 ScAddress
aExpectedStart(SCCOL(2), SCROW(25), SCTAB(0)); // zero based
1078 ScAddress
aExpectedEnd(SCCOL(2), SCROW(32), SCTAB(0));
1079 CPPUNIT_ASSERT_EQUAL(aExpectedStart
, (*pObjData
).maStart
);
1080 CPPUNIT_ASSERT_EQUAL(aExpectedEnd
, (*pObjData
).maEnd
);
1083 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf155094_paste_transposed
)
1085 // Load a document, which has a page anchored shape "Red" in C4, a cell anchored shape "Green" in
1086 // D4 and a cell anchored shape "Blue" with 'resize with cell' in E4. The range C3:E5 is copied
1087 // and pasted with 'Transpose all' to cell K6. The pasted content had these errors:
1088 // Pasted shape "Red" was missing.
1089 // Pasted shape "Green" was resized although 'resize with cell' was not set.
1090 // Pasted shape "Blue" was in cell K5 instead of L8.
1091 // The behavior of paste transposed is changed since LO 7.6 so that no shape is resized.
1092 createScDoc("ods/tdf155094_paste_transposed.ods");
1093 ScDocument
* pDoc
= getScDoc();
1096 goToCell("$C$3:$E$5");
1097 dispatchCommand(mxComponent
, ".uno:Copy", {});
1099 uno::Sequence
<beans::PropertyValue
> aPropertyValues
1100 = { comphelper::makePropertyValue("Flags", OUString("A")),
1101 comphelper::makePropertyValue("FormulaCommand", sal_uInt16(0)),
1102 comphelper::makePropertyValue("SkipEmptyCells", false),
1103 comphelper::makePropertyValue("Transpose", true),
1104 comphelper::makePropertyValue("AsLink", false),
1105 comphelper::makePropertyValue("MoveMode", sal_uInt16(4)) };
1106 dispatchCommand(mxComponent
, ".uno:InsertContents", aPropertyValues
);
1108 // Without fix there had been only 5 object.
1109 ScDrawLayer
* pDrawLayer
= pDoc
->GetDrawLayer();
1110 CPPUNIT_ASSERT_MESSAGE("No ScDrawLayer", pDrawLayer
);
1111 const SdrPage
* pPage
= pDrawLayer
->GetPage(0);
1112 CPPUNIT_ASSERT_MESSAGE("No draw page", pPage
);
1113 CPPUNIT_ASSERT_EQUAL(size_t(6), pPage
->GetObjCount());
1115 // Without fix pasted object had position(7972, 8616) and size(1805×801).
1116 SdrObject
* pObjGreen
= lcl_getSdrObjectWithAssert(*pDoc
, 4); // pasted shape "Green"
1117 tools::Rectangle
aExpectedRect(tools::Rectangle(Point(12489, 12609), Size(800, 800)));
1118 tools::Rectangle
aSnapRect(pObjGreen
->GetSnapRect());
1119 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectedRect
, aSnapRect
, 1);
1121 // Without fix the pasted object was at wrong position(10230,8616).
1122 // Since LO 7.6 the pasted object has the same size as the original shape "Blue".
1123 SdrObject
* pObjBlue
= lcl_getSdrObjectWithAssert(*pDoc
, 5);
1124 aExpectedRect
= tools::Rectangle(Point(12489, 14612), Size(800, 800));
1125 aSnapRect
= pObjBlue
->GetSnapRect();
1126 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aExpectedRect
, aSnapRect
, 1);
1129 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf155091_paste_duplicates
)
1131 // Load a document, which has a shape in range C6:C16, anchored 'To cell (resize with cell)'.
1132 // The rows 6 to 9 are filtered. When copying the range B5:C19 and paste it to B23, the
1133 // shape was pasted twice.
1134 createScDoc("ods/tdf155091_paste_duplicates.ods");
1135 ScDocument
* pDoc
= getScDoc();
1138 goToCell("$B$5:$C$19");
1139 dispatchCommand(mxComponent
, ".uno:Copy", {});
1141 dispatchCommand(mxComponent
, ".uno:Paste", {});
1143 // Make sure there is no third object but only original and pasted one.
1144 ScDrawLayer
* pDrawLayer
= pDoc
->GetDrawLayer();
1145 CPPUNIT_ASSERT_MESSAGE("No ScDrawLayer", pDrawLayer
);
1146 const SdrPage
* pPage
= pDrawLayer
->GetPage(0);
1147 CPPUNIT_ASSERT_MESSAGE("No draw page", pPage
);
1148 CPPUNIT_ASSERT_EQUAL(size_t(2), pPage
->GetObjCount());
1151 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf125938_anchor_after_copy_paste
)
1153 // Load a document, which has an image in cell $sheet1.$B$3, anchored to cell. When the range
1154 // A3:C3 was copied and pasted to D9:D11 in sheet2, the image was displayed in cell D10, but
1155 // its anchor was in B3.
1156 createScDoc("ods/tdf125938_anchor_after_copy_paste.ods");
1157 ScDocument
* pDoc
= getScDoc();
1160 goToCell("$Sheet1.$A$3:$C$3");
1161 dispatchCommand(mxComponent
, ".uno:Copy", {});
1162 goToCell("$Sheet2.$D$9");
1163 dispatchCommand(mxComponent
, ".uno:Paste", {});
1166 ScDrawLayer
* pDrawLayer
= pDoc
->GetDrawLayer();
1167 const SdrPage
* pPage
= pDrawLayer
->GetPage(1);
1168 SdrObject
* pObj
= pPage
->GetObj(0);
1170 // Make sure object is anchored to E9
1171 ScDrawObjData
* pObjData
= ScDrawLayer::GetObjData(pObj
);
1172 ScAddress
aExpectedAddress(SCCOL(4), SCROW(8), SCTAB(1)); // zero based
1173 CPPUNIT_ASSERT_EQUAL(aExpectedAddress
, (*pObjData
).maStart
);
1176 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf154821_shape_in_group
)
1178 // The document contains a shape in A7, a group spanning rows 2 to 4 and a second group spanning
1179 // rows 6 to 10. Error was, that when the document was saved with collapsed groups, the shape
1180 // lost its position.
1181 createScDoc("ods/tdf154821_shape_in_group.ods");
1183 // Get snap rectangle before collapse and save
1184 ScDocument
* pDoc
= getScDoc();
1185 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
1186 tools::Rectangle aRectOrig
= pObj
->GetSnapRect();
1188 // Collapse the lower group
1189 ScTabViewShell
* pViewShell
= getViewShell();
1190 pViewShell
->GetViewData().SetCurX(0);
1191 pViewShell
->GetViewData().SetCurY(5);
1192 pViewShell
->GetViewData().GetDispatcher().Execute(SID_OUTLINE_HIDE
);
1193 // Collapse the upper group
1194 pViewShell
->GetViewData().SetCurX(0);
1195 pViewShell
->GetViewData().SetCurY(1);
1196 pViewShell
->GetViewData().GetDispatcher().Execute(SID_OUTLINE_HIDE
);
1198 saveAndReload("calc8");
1200 // Expand the lower group
1201 pViewShell
= getViewShell();
1202 pViewShell
->GetViewData().SetCurX(0);
1203 pViewShell
->GetViewData().SetCurY(5);
1204 pViewShell
->GetViewData().GetDispatcher().Execute(SID_OUTLINE_SHOW
);
1205 // Expand the upper group
1206 pViewShell
= getViewShell();
1207 pViewShell
->GetViewData().SetCurX(0);
1208 pViewShell
->GetViewData().SetCurY(1);
1209 pViewShell
->GetViewData().GetDispatcher().Execute(SID_OUTLINE_SHOW
);
1211 // Verify shape position is not changed besides rounding errors from twips<->mm
1213 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
1214 tools::Rectangle aRectReload
= pObj
->GetSnapRect();
1215 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aRectOrig
, aRectReload
, 1);
1218 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf160003_copy_page_anchored
)
1220 // Load a document, which has a chart anchored to page on sheet2. Copy&paste to other document
1221 // had lost the chart object.
1222 createScDoc("ods/tdf160003_page_anchored_object.ods");
1224 // copy range with chart
1225 goToCell("$Sheet2.$A$1:$L$24");
1226 dispatchCommand(mxComponent
, ".uno:Copy", {});
1228 // close document and create new one
1232 goToCell("$Sheet1.$A$1");
1233 dispatchCommand(mxComponent
, ".uno:Paste", {});
1235 // Make sure the chart object exists.
1236 ScDocument
* pDoc
= getScDoc();
1237 ScDrawLayer
* pDrawLayer
= pDoc
->GetDrawLayer();
1238 const SdrPage
* pPage
= pDrawLayer
->GetPage(0);
1239 CPPUNIT_ASSERT_EQUAL(size_t(1), pPage
->GetObjCount());
1242 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf160369_groupshape
)
1244 // The document contains a group spanning range C5:F12. It is currently anchored to page to
1245 // make sure its position does not change. When the group was anchored 'To Cell' and rows or
1246 // columns were hidden before the group, saving changed the anchor position and anchor
1247 // offset. This happened both with using 'resize with cell' and not.
1248 createScDoc("ods/tdf160369_groupshape.ods");
1250 // Get document and group object
1251 ScDocument
* pDoc
= getScDoc();
1252 SdrObject
* pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
1254 // Anchor group 'To Cell (resize with cell)' to prepare the test.
1255 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, *pDoc
, 0 /*SCTAB*/, true /*bResizeWithCell*/);
1257 // Hide rows 3 and 4 (UI number), which are before the group
1258 // Hide column D, which is inside the group
1259 pDoc
->SetRowHidden(2, 3, 0, true);
1260 pDoc
->SetDrawPageSize(0); // trigger recalcpos, otherwise shapes are not changed
1261 pDoc
->SetColHidden(3, 3, 0, true);
1262 pDoc
->SetDrawPageSize(0);
1264 // Get geometry of the group
1265 ScDrawObjData
* pObjData
= ScDrawLayer::GetObjData(pObj
);
1266 ScAddress aOrigStart
= (*pObjData
).maStart
;
1267 ScAddress aOrigEnd
= (*pObjData
).maEnd
;
1268 tools::Rectangle aOrigRect
= pObj
->GetSnapRect();
1270 // Save document but do not reload. Saving alone had already caused the error.
1273 // Get geometry of the group again
1274 ScDrawObjData
* pAfterObjData
= ScDrawLayer::GetObjData(pObj
);
1275 ScAddress aAfterStart
= (*pAfterObjData
).maStart
;
1276 ScAddress aAfterEnd
= (*pAfterObjData
).maEnd
;
1277 tools::Rectangle aAfterRect
= pObj
->GetSnapRect();
1279 // verify Orig equals After
1280 CPPUNIT_ASSERT_EQUAL(aOrigStart
, aAfterStart
);
1281 CPPUNIT_ASSERT_EQUAL(aOrigEnd
, aAfterEnd
);
1282 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aOrigRect
, aAfterRect
, 1);
1284 // The same but with saveAndReload.
1285 createScDoc("ods/tdf160369_groupshape.ods");
1287 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
1288 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, *pDoc
, 0 /*SCTAB*/, true /*bResizeWithCell*/);
1289 pDoc
->SetRowHidden(2, 3, 0, true);
1290 pDoc
->SetDrawPageSize(0); // trigger recalcpos, otherwise shapes are not changed
1291 pDoc
->SetColHidden(3, 3, 0, true);
1292 pDoc
->SetDrawPageSize(0);
1294 saveAndReload("calc8");
1296 // Verify geometry is same as before save
1298 pObj
= lcl_getSdrObjectWithAssert(*pDoc
, 0);
1299 pAfterObjData
= ScDrawLayer::GetObjData(pObj
);
1300 aAfterStart
= (*pAfterObjData
).maStart
;
1301 aAfterEnd
= (*pAfterObjData
).maEnd
;
1302 aAfterRect
= pObj
->GetSnapRect();
1304 // verify Orig equals After
1305 CPPUNIT_ASSERT_EQUAL(aOrigStart
, aAfterStart
);
1306 CPPUNIT_ASSERT_EQUAL(aOrigEnd
, aAfterEnd
);
1307 CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aOrigRect
, aAfterRect
, 1);
1310 CPPUNIT_TEST_FIXTURE(ScShapeTest
, testTdf160329_sortWithHiddenRows
)
1312 // Load a document, which has images anchored to cell and rows hidden
1313 createScDoc("ods/tdf160329_sortWithHiddenRows.ods");
1314 ScDocument
* pDoc
= getScDoc();
1317 uno::Sequence
<beans::PropertyValue
> aArgs1
1318 = { comphelper::makePropertyValue("DbName", u
"myRange"_ustr
) };
1319 dispatchCommand(mxComponent
, ".uno:SelectDB", aArgs1
);
1320 uno::Sequence
<beans::PropertyValue
> aArgs2
1321 = { comphelper::makePropertyValue("ByRows", true),
1322 comphelper::makePropertyValue("HasHeader", true),
1323 comphelper::makePropertyValue("Col1", sal_Int32(1)),
1324 comphelper::makePropertyValue("Ascending1", false),
1325 comphelper::makePropertyValue("IncludeImages", true) };
1326 dispatchCommand(mxComponent
, ".uno:DataSort", aArgs2
);
1328 // Make sure objects are on correct position
1329 SdrObject
* pObj
= lcl_getSdrObjectbyName(*pDoc
, std::u16string_view(u
"ImageD"));
1330 Point aPos
= pObj
->GetSnapRect().TopLeft();
1331 // The position was (3000|2899) without fix.
1332 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(Point(3000, 5898), aPos
, 1);
1333 pObj
= lcl_getSdrObjectbyName(*pDoc
, std::u16string_view(u
"ImageE"));
1334 aPos
= pObj
->GetSnapRect().TopLeft();
1335 // The position was (2600|2499) without fix.
1336 CPPUNIT_ASSERT_POINT_EQUAL_WITH_TOLERANCE(Point(2600, 4399), aPos
, 1);
1339 CPPUNIT_PLUGIN_IMPLEMENT();
1341 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */