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 <sfx2/dispatch.hxx>
11 #include <svx/svdograf.hxx>
12 #include <svx/svdpage.hxx>
13 #include <test/calc_unoapi_test.hxx>
15 #include <com/sun/star/sheet/XSpreadsheet.hpp>
16 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
17 #include <com/sun/star/text/XText.hpp>
20 #include <drwlayer.hxx>
21 #include <scitems.hxx>
22 #include <svx/svdocirc.hxx>
23 #include <vcl/scheduler.hxx>
24 #include <tabvwsh.hxx>
32 class ScAnchorTest
: public CalcUnoApiTest
37 virtual void tearDown() override
;
39 void testUndoAnchor();
41 void testODFAnchorTypes();
42 void testCopyColumnWithImages();
43 void testCutWithImages();
46 CPPUNIT_TEST_SUITE(ScAnchorTest
);
47 CPPUNIT_TEST(testUndoAnchor
);
48 CPPUNIT_TEST(testTdf76183
);
49 CPPUNIT_TEST(testODFAnchorTypes
);
50 CPPUNIT_TEST(testCopyColumnWithImages
);
51 CPPUNIT_TEST(testCutWithImages
);
52 CPPUNIT_TEST(testTdf129552
);
53 CPPUNIT_TEST_SUITE_END();
56 uno::Reference
<lang::XComponent
> mxComponent
;
59 ScAnchorTest::ScAnchorTest()
60 : CalcUnoApiTest("sc/qa/unit/data/ods")
64 void ScAnchorTest::testUndoAnchor()
67 createFileURL("document_with_linked_graphic.ods", aFileURL
);
68 // open the document with graphic included
69 uno::Reference
<css::lang::XComponent
> xComponent
= loadFromDesktop(aFileURL
);
70 CPPUNIT_ASSERT(xComponent
.is());
72 // Get the document model
73 SfxObjectShell
* pFoundShell
= SfxObjectShell::GetShellFromComponent(xComponent
);
74 CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell
);
76 ScDocShell
* pDocSh
= dynamic_cast<ScDocShell
*>(pFoundShell
);
77 CPPUNIT_ASSERT(pDocSh
);
79 // Check whether graphic imported well
80 ScDocument
& rDoc
= pDocSh
->GetDocument();
81 ScDrawLayer
* pDrawLayer
= rDoc
.GetDrawLayer();
82 CPPUNIT_ASSERT(pDrawLayer
);
84 const SdrPage
* pPage
= pDrawLayer
->GetPage(0);
85 CPPUNIT_ASSERT(pPage
);
87 SdrGrafObj
* pObject
= dynamic_cast<SdrGrafObj
*>(pPage
->GetObj(0));
88 CPPUNIT_ASSERT(pObject
);
89 CPPUNIT_ASSERT(pObject
->IsLinkedGraphic());
91 const GraphicObject
& rGraphicObj
= pObject
->GetGraphicObject(true);
92 CPPUNIT_ASSERT_EQUAL(int(GraphicType::Bitmap
), int(rGraphicObj
.GetGraphic().GetType()));
93 CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj
.GetGraphic().GetSizeBytes());
95 // Get the document controller
96 ScTabViewShell
* pViewShell
= pDocSh
->GetBestViewShell(false);
97 CPPUNIT_ASSERT(pViewShell
);
99 // Get the draw view of the document
100 ScDrawView
* pDrawView
= pViewShell
->GetViewData().GetScDrawView();
101 CPPUNIT_ASSERT(pDrawView
);
103 // Select graphic object
104 pDrawView
->MarkNextObj();
105 CPPUNIT_ASSERT(pDrawView
->AreObjectsMarked());
108 ScDrawLayer::SetCellAnchoredFromPosition(*pObject
, rDoc
, 0, false);
110 ScAnchorType oldType
= ScDrawLayer::GetAnchorType(*pObject
);
111 CPPUNIT_ASSERT_EQUAL(SCA_CELL
, oldType
);
113 // Change all selected objects to page anchor
114 pViewShell
->GetViewData().GetDispatcher().Execute(SID_ANCHOR_PAGE
);
116 ScAnchorType newType
= ScDrawLayer::GetAnchorType(*pObject
);
117 CPPUNIT_ASSERT_EQUAL(SCA_PAGE
, newType
);
119 // Undo and check its result.
120 SfxUndoManager
* pUndoMgr
= rDoc
.GetUndoManager();
121 CPPUNIT_ASSERT(pUndoMgr
);
125 CPPUNIT_ASSERT_EQUAL(oldType
, ScDrawLayer::GetAnchorType(*pObject
));
126 CPPUNIT_ASSERT_EQUAL(int(GraphicType::Bitmap
), int(rGraphicObj
.GetGraphic().GetType()));
127 CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj
.GetGraphic().GetSizeBytes());
132 CPPUNIT_ASSERT_EQUAL(newType
, ScDrawLayer::GetAnchorType(*pObject
));
133 CPPUNIT_ASSERT_EQUAL(int(GraphicType::Bitmap
), int(rGraphicObj
.GetGraphic().GetType()));
134 CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj
.GetGraphic().GetSizeBytes());
136 ScDrawLayer::SetPageAnchored(*pObject
);
138 oldType
= ScDrawLayer::GetAnchorType(*pObject
);
139 CPPUNIT_ASSERT_EQUAL(SCA_PAGE
, oldType
);
141 // Change all selected objects to cell anchor
142 pViewShell
->GetViewData().GetDispatcher().Execute(SID_ANCHOR_CELL
);
144 newType
= ScDrawLayer::GetAnchorType(*pObject
);
145 CPPUNIT_ASSERT_EQUAL(SCA_CELL
, newType
);
150 CPPUNIT_ASSERT_EQUAL(oldType
, ScDrawLayer::GetAnchorType(*pObject
));
151 CPPUNIT_ASSERT_EQUAL(int(GraphicType::Bitmap
), int(rGraphicObj
.GetGraphic().GetType()));
152 CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj
.GetGraphic().GetSizeBytes());
157 CPPUNIT_ASSERT_EQUAL(newType
, ScDrawLayer::GetAnchorType(*pObject
));
158 CPPUNIT_ASSERT_EQUAL(int(GraphicType::Bitmap
), int(rGraphicObj
.GetGraphic().GetType()));
159 CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj
.GetGraphic().GetSizeBytes());
161 xComponent
->dispose();
164 void ScAnchorTest::testTdf76183()
166 uno::Reference
<lang::XComponent
> xComponent
= loadFromDesktop("private:factory/scalc");
167 SfxObjectShell
* pFoundShell
= SfxObjectShell::GetShellFromComponent(xComponent
);
168 ScDocShell
* pDocSh
= dynamic_cast<ScDocShell
*>(pFoundShell
);
169 ScDocument
& rDoc
= pDocSh
->GetDocument();
170 ScDrawLayer
* pDrawLayer
= rDoc
.GetDrawLayer();
171 SdrPage
* pPage
= pDrawLayer
->GetPage(0);
173 // Add a circle somewhere below first row.
174 const tools::Rectangle
aOrigRect(1000, 1000, 1200, 1200);
175 SdrCircObj
* pObj
= new SdrCircObj(*pDrawLayer
, SdrCircKind::Full
, aOrigRect
);
176 pPage
->InsertObject(pObj
);
178 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, rDoc
, 0, false);
179 const tools::Rectangle
& rNewRect
= pObj
->GetLogicRect();
181 // Set word wrap to true
182 rDoc
.ApplyAttr(0, 0, 0, SfxBoolItem(ATTR_LINEBREAK
, true));
183 // Add multi-line text to cell to initiate optimal height change
184 uno::Reference
<sheet::XSpreadsheetDocument
> xDoc(xComponent
, uno::UNO_QUERY_THROW
);
185 uno::Reference
<container::XIndexAccess
> xIA(xDoc
->getSheets(), uno::UNO_QUERY_THROW
);
186 uno::Reference
<sheet::XSpreadsheet
> xSheet(xIA
->getByIndex(0), uno::UNO_QUERY_THROW
);
187 uno::Reference
<text::XText
> xText(xSheet
->getCellByPosition(0, 0), uno::UNO_QUERY_THROW
);
188 xText
->setString("first\nsecond\nthird");
190 // The resize of first row must have moved the object down after its anchor cell
191 CPPUNIT_ASSERT(aOrigRect
.Top() < rNewRect
.Top());
196 void ScAnchorTest::testODFAnchorTypes()
199 createFileURL("3AnchorTypes.ods", aFileURL
);
200 // open the document with graphic included
201 uno::Reference
<css::lang::XComponent
> xComponent
= loadFromDesktop(aFileURL
);
202 CPPUNIT_ASSERT(xComponent
.is());
204 // Get the document model
205 SfxObjectShell
* pFoundShell
= SfxObjectShell::GetShellFromComponent(xComponent
);
206 CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell
);
208 ScDocShell
* pDocSh
= dynamic_cast<ScDocShell
*>(pFoundShell
);
209 CPPUNIT_ASSERT(pDocSh
);
211 // Check whether graphic imported well
212 ScDocument
& rDoc
= pDocSh
->GetDocument();
213 ScDrawLayer
* pDrawLayer
= rDoc
.GetDrawLayer();
214 CPPUNIT_ASSERT(pDrawLayer
);
216 const SdrPage
* pPage
= pDrawLayer
->GetPage(0);
217 CPPUNIT_ASSERT(pPage
);
219 // Check 1st object: Page anchored
220 SdrGrafObj
* pObject
= dynamic_cast<SdrGrafObj
*>(pPage
->GetObj(0));
221 CPPUNIT_ASSERT(pObject
);
222 ScAnchorType anchorType
= ScDrawLayer::GetAnchorType(*pObject
);
223 CPPUNIT_ASSERT_EQUAL(SCA_PAGE
, anchorType
);
225 // Check 2nd object: Cell anchored, resize with cell
226 pObject
= dynamic_cast<SdrGrafObj
*>(pPage
->GetObj(1));
227 CPPUNIT_ASSERT(pObject
);
228 anchorType
= ScDrawLayer::GetAnchorType(*pObject
);
229 CPPUNIT_ASSERT_EQUAL(SCA_CELL_RESIZE
, anchorType
);
231 // Check 3rd object: Cell anchored
232 pObject
= dynamic_cast<SdrGrafObj
*>(pPage
->GetObj(2));
233 CPPUNIT_ASSERT(pObject
);
234 anchorType
= ScDrawLayer::GetAnchorType(*pObject
);
235 CPPUNIT_ASSERT_EQUAL(SCA_CELL
, anchorType
);
240 /// Test that copying a column with an image anchored to it also copies the image
241 void ScAnchorTest::testCopyColumnWithImages()
244 createFileURL("3AnchorTypes.ods", aFileURL
);
245 // open the document with graphic included
246 uno::Reference
<css::lang::XComponent
> xComponent
= loadFromDesktop(aFileURL
);
247 CPPUNIT_ASSERT(xComponent
.is());
249 // Get the document model
250 SfxObjectShell
* pFoundShell
= SfxObjectShell::GetShellFromComponent(xComponent
);
251 CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell
);
253 ScDocShell
* pDocSh
= dynamic_cast<ScDocShell
*>(pFoundShell
);
254 CPPUNIT_ASSERT(pDocSh
);
256 ScDocument
* pDoc
= &(pDocSh
->GetDocument());
257 ScDrawLayer
* pDrawLayer
= pDoc
->GetDrawLayer();
258 CPPUNIT_ASSERT(pDrawLayer
);
260 // Get the document controller
261 ScTabViewShell
* pViewShell
= pDocSh
->GetBestViewShell(false);
262 CPPUNIT_ASSERT(pViewShell
!= nullptr);
264 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
268 // 1. Copy source range
270 aSrcRange
.Parse("A1:A11", pDoc
, pDoc
->GetAddressConvention());
271 pViewShell
->GetViewData().GetMarkData().SetMarkArea(aSrcRange
);
272 pViewShell
->GetViewData().GetView()->CopyToClip(&aClipDoc
, false, false, true, false);
274 // 2. Paste to target range
276 aDstRange
.Parse("D1:D11", pDoc
, pDoc
->GetAddressConvention());
277 pViewShell
->GetViewData().GetMarkData().SetMarkArea(aDstRange
);
278 pViewShell
->GetViewData().GetView()->PasteFromClip(InsertDeleteFlags::ALL
, &aClipDoc
);
280 // 3. Make sure the images have been copied too
281 std::map
<SCROW
, std::vector
<SdrObject
*>> aRowObjects
282 = pDrawLayer
->GetObjectsAnchoredToRange(0, 3, 0, 11);
283 CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be an image anchored to D3", 1,
284 static_cast<int>(aRowObjects
[2].size()));
285 CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be an image anchored to D11", 1,
286 static_cast<int>(aRowObjects
[10].size()));
289 // Copy individual cells
291 // 1. Copy source cells
293 aSrcRange
.Parse("A3:B3", pDoc
, pDoc
->GetAddressConvention());
294 pViewShell
->GetViewData().GetMarkData().SetMarkArea(aSrcRange
);
295 pViewShell
->GetViewData().GetView()->CopyToClip(&aClipDoc
, false, false, true, false);
297 // 2. Paste to target cells
299 aDstRange
.Parse("G3:H3", pDoc
, pDoc
->GetAddressConvention());
300 pViewShell
->GetViewData().GetMarkData().SetMarkArea(aDstRange
);
301 pViewShell
->GetViewData().GetView()->PasteFromClip(InsertDeleteFlags::ALL
, &aClipDoc
);
303 // 3. Make sure the image has been copied too
304 std::map
<SCROW
, std::vector
<SdrObject
*>> aRowObjects
305 = pDrawLayer
->GetObjectsAnchoredToRange(0, 6, 2, 2);
306 CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be an image anchored to G3", 1,
307 static_cast<int>(aRowObjects
[2].size()));
313 void ScAnchorTest::testCutWithImages()
316 createFileURL("3AnchorTypes.ods", aFileURL
);
317 // open the document with graphic included
318 uno::Reference
<css::lang::XComponent
> xComponent
= loadFromDesktop(aFileURL
);
319 CPPUNIT_ASSERT(xComponent
.is());
321 // Get the document model
322 SfxObjectShell
* pFoundShell
= SfxObjectShell::GetShellFromComponent(xComponent
);
323 CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell
);
325 ScDocShell
* pDocSh
= dynamic_cast<ScDocShell
*>(pFoundShell
);
326 CPPUNIT_ASSERT(pDocSh
);
328 ScDocument
* pDoc
= &(pDocSh
->GetDocument());
329 ScDrawLayer
* pDrawLayer
= pDoc
->GetDrawLayer();
330 CPPUNIT_ASSERT(pDrawLayer
);
332 // Get the document controller
333 ScTabViewShell
* pViewShell
= pDocSh
->GetBestViewShell(false);
334 CPPUNIT_ASSERT(pViewShell
!= nullptr);
340 aSrcRange
.Parse("A1:A11", pDoc
, pDoc
->GetAddressConvention());
341 pViewShell
->GetViewData().GetMarkData().SetMarkArea(aSrcRange
);
342 pViewShell
->GetViewData().GetView()->CutToClip();
344 std::map
<SCROW
, std::vector
<SdrObject
*>> aRowObjects
345 = pDrawLayer
->GetObjectsAnchoredToRange(0, 0, 0, 11);
347 // Images should have been removed from the cells
348 CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no image anchored to A3", 0,
349 static_cast<int>(aRowObjects
[2].size()));
350 CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no image anchored to A11", 0,
351 static_cast<int>(aRowObjects
[10].size()));
354 // Cut individual cells
358 aSrcRange
.Parse("A3:B3", pDoc
, pDoc
->GetAddressConvention());
359 pViewShell
->GetViewData().GetMarkData().SetMarkArea(aSrcRange
);
360 pViewShell
->GetViewData().GetView()->CutToClip();
362 // Image should have been removed from the cell
363 std::map
<SCROW
, std::vector
<SdrObject
*>> aRowObjects
364 = pDrawLayer
->GetObjectsAnchoredToRange(0, 0, 2, 2);
365 CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no image anchored to A3", 0,
366 static_cast<int>(aRowObjects
[2].size()));
372 void ScAnchorTest::testTdf129552()
375 createFileURL("tdf129552.fods", aFileURL
);
376 uno::Reference
<css::lang::XComponent
> xComponent
= loadFromDesktop(aFileURL
);
377 CPPUNIT_ASSERT(xComponent
.is());
379 // Without the accompanying fix in place, this test would have never returned due to an infinite
380 // invalidation loop, where ScGridWindow::Paint() invalidated itself.
381 Scheduler::ProcessEventsToIdle();
383 xComponent
->dispose();
386 void ScAnchorTest::tearDown()
388 if (mxComponent
.is())
390 closeDocument(mxComponent
);
393 CalcUnoApiTest::tearDown();
396 CPPUNIT_TEST_SUITE_REGISTRATION(ScAnchorTest
);
399 CPPUNIT_PLUGIN_IMPLEMENT();
401 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */