Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / sd / qa / unit / tiledrendering / tiledrendering.cxx
blobcfcf3241e2b9515e4d9c385f5ff1fd3c6e64ae94
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include "../sdmodeltestbase.hxx"
11 #include <app.hrc>
12 #include <test/bootstrapfixture.hxx>
13 #include <test/helper/transferable.hxx>
14 #include <test/xmltesttools.hxx>
15 #include <boost/property_tree/json_parser.hpp>
16 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
17 #include <sfx2/lokhelper.hxx>
18 #include <com/sun/star/frame/Desktop.hpp>
19 #include <comphelper/dispatchcommand.hxx>
20 #include <comphelper/processfactory.hxx>
21 #include <comphelper/propertysequence.hxx>
22 #include <comphelper/string.hxx>
23 #include <editeng/eeitem.hxx>
24 #include <editeng/editids.hrc>
25 #include <editeng/editobj.hxx>
26 #include <editeng/editview.hxx>
27 #include <editeng/outliner.hxx>
28 #include <editeng/fhgtitem.hxx>
29 #include <editeng/outlobj.hxx>
30 #include <osl/conditn.hxx>
31 #include <sfx2/dispatch.hxx>
32 #include <sfx2/viewfrm.hxx>
33 #include <svl/srchitem.hxx>
34 #include <svl/stritem.hxx>
35 #include <svl/intitem.hxx>
36 #include <comphelper/lok.hxx>
37 #include <svx/svdotable.hxx>
38 #include <svx/svdoutl.hxx>
39 #include <unotools/datetime.hxx>
41 #include <DrawDocShell.hxx>
42 #include <ViewShellBase.hxx>
43 #include <ViewShell.hxx>
44 #include <sdpage.hxx>
45 #include <unomodel.hxx>
46 #include <drawdoc.hxx>
47 #include <undo/undomanager.hxx>
48 #include <sfx2/request.hxx>
49 #include <svx/svxids.hrc>
50 #include <pres.hxx>
51 #include <navigatr.hxx>
52 #include <vcl/cursor.hxx>
53 #include <vcl/scheduler.hxx>
54 #include <vcl/vclevent.hxx>
56 #include <chrono>
57 #include <cstdlib>
59 using namespace css;
61 static char const DATA_DIRECTORY[] = "/sd/qa/unit/tiledrendering/data/";
63 static std::ostream& operator<<(std::ostream& os, ViewShellId id)
65 os << static_cast<sal_Int32>(id);
66 return os;
69 class SdTiledRenderingTest : public SdModelTestBase, public XmlTestTools
71 public:
72 SdTiledRenderingTest();
73 virtual void setUp() override;
74 virtual void tearDown() override;
76 void testCreateDestroy();
77 void testCreateView();
78 void testRegisterCallback();
79 void testPostKeyEvent();
80 void testPostMouseEvent();
81 void testSetTextSelection();
82 void testGetTextSelection();
83 void testSetGraphicSelection();
84 void testUndoShells();
85 void testResetSelection();
86 void testSearch();
87 void testSearchAll();
88 void testSearchAllSelections();
89 void testSearchAllNotifications();
90 void testSearchAllFollowedBySearch();
91 void testDontSearchInMasterPages();
92 void testInsertDeletePage();
93 void testInsertTable();
94 void testPartHash();
95 void testResizeTable();
96 void testResizeTableColumn();
97 void testViewCursors();
98 void testViewCursorParts();
99 void testCursorViews();
100 void testViewLock();
101 void testUndoLimiting();
102 void testCreateViewGraphicSelection();
103 void testCreateViewTextCursor();
104 void testTdf102223();
105 void testPostKeyEventInvalidation();
106 void testTdf103083();
107 void testTdf104405();
108 void testTdf81754();
109 void testTdf105502();
110 void testCommentCallbacks();
111 void testMultiViewInsertDeletePage();
112 void testDisableUndoRepair();
113 void testDocumentRepair();
114 void testLanguageStatus();
115 void testDefaultView();
116 void testIMESupport();
117 void testTdf115783();
118 void testPasteTextOnSlide();
119 void testTdf115873();
120 void testTdf115873Group();
121 void testCutSelectionChange();
122 void testRegenerateDiagram();
123 void testLanguageAllText();
124 void testInsertDeletePageInvalidation();
126 CPPUNIT_TEST_SUITE(SdTiledRenderingTest);
127 CPPUNIT_TEST(testCreateDestroy);
128 CPPUNIT_TEST(testCreateView);
129 CPPUNIT_TEST(testRegisterCallback);
130 CPPUNIT_TEST(testPostKeyEvent);
131 CPPUNIT_TEST(testPostMouseEvent);
132 CPPUNIT_TEST(testSetTextSelection);
133 CPPUNIT_TEST(testGetTextSelection);
134 CPPUNIT_TEST(testSetGraphicSelection);
135 CPPUNIT_TEST(testUndoShells);
136 CPPUNIT_TEST(testResetSelection);
137 CPPUNIT_TEST(testSearch);
138 CPPUNIT_TEST(testSearchAll);
139 CPPUNIT_TEST(testSearchAllSelections);
140 CPPUNIT_TEST(testSearchAllNotifications);
141 CPPUNIT_TEST(testSearchAllFollowedBySearch);
142 CPPUNIT_TEST(testDontSearchInMasterPages);
143 CPPUNIT_TEST(testInsertDeletePage);
144 CPPUNIT_TEST(testInsertTable);
145 CPPUNIT_TEST(testPartHash);
146 CPPUNIT_TEST(testResizeTable);
147 CPPUNIT_TEST(testResizeTableColumn);
148 CPPUNIT_TEST(testViewCursors);
149 CPPUNIT_TEST(testViewCursorParts);
150 CPPUNIT_TEST(testCursorViews);
151 CPPUNIT_TEST(testViewLock);
152 CPPUNIT_TEST(testUndoLimiting);
153 CPPUNIT_TEST(testCreateViewGraphicSelection);
154 CPPUNIT_TEST(testCreateViewTextCursor);
155 CPPUNIT_TEST(testTdf102223);
156 CPPUNIT_TEST(testPostKeyEventInvalidation);
157 CPPUNIT_TEST(testTdf103083);
158 CPPUNIT_TEST(testTdf104405);
159 CPPUNIT_TEST(testTdf81754);
160 CPPUNIT_TEST(testTdf105502);
161 CPPUNIT_TEST(testCommentCallbacks);
162 CPPUNIT_TEST(testMultiViewInsertDeletePage);
163 CPPUNIT_TEST(testDisableUndoRepair);
164 CPPUNIT_TEST(testDocumentRepair);
165 CPPUNIT_TEST(testLanguageStatus);
166 CPPUNIT_TEST(testDefaultView);
167 CPPUNIT_TEST(testIMESupport);
168 CPPUNIT_TEST(testTdf115783);
169 CPPUNIT_TEST(testPasteTextOnSlide);
170 CPPUNIT_TEST(testTdf115873);
171 CPPUNIT_TEST(testTdf115873Group);
172 CPPUNIT_TEST(testCutSelectionChange);
173 CPPUNIT_TEST(testRegenerateDiagram);
174 CPPUNIT_TEST(testLanguageAllText);
175 CPPUNIT_TEST(testInsertDeletePageInvalidation);
177 CPPUNIT_TEST_SUITE_END();
179 private:
180 SdXImpressDocument* createDoc(const char* pName, const uno::Sequence<beans::PropertyValue>& rArguments = uno::Sequence<beans::PropertyValue>());
181 static void callback(int nType, const char* pPayload, void* pData);
182 void callbackImpl(int nType, const char* pPayload);
183 xmlDocPtr parseXmlDump();
185 uno::Reference<lang::XComponent> mxComponent;
186 ::tools::Rectangle m_aInvalidation;
187 std::vector<::tools::Rectangle> m_aSelection;
188 bool m_bFound;
189 sal_Int32 m_nPart;
190 std::vector<OString> m_aSearchResultSelection;
191 std::vector<int> m_aSearchResultPart;
192 int m_nSelectionBeforeSearchResult;
193 int m_nSelectionAfterSearchResult;
195 /// For document size changed callback.
196 osl::Condition m_aDocumentSizeCondition;
197 xmlBufferPtr m_pXmlBuffer;
200 SdTiledRenderingTest::SdTiledRenderingTest()
201 : m_bFound(true),
202 m_nPart(0),
203 m_nSelectionBeforeSearchResult(0),
204 m_nSelectionAfterSearchResult(0),
205 m_pXmlBuffer(nullptr)
209 void SdTiledRenderingTest::setUp()
211 test::BootstrapFixture::setUp();
213 // prevent showing warning message box
214 setenv("OOX_NO_SMARTART_WARNING", "1", 1);
215 comphelper::LibreOfficeKit::setActive(true);
217 mxDesktop.set(css::frame::Desktop::create(comphelper::getComponentContext(getMultiServiceFactory())));
220 void SdTiledRenderingTest::tearDown()
222 if (mxComponent.is())
223 mxComponent->dispose();
225 if (m_pXmlBuffer)
226 xmlBufferFree(m_pXmlBuffer);
228 comphelper::LibreOfficeKit::setActive(false);
230 test::BootstrapFixture::tearDown();
233 SdXImpressDocument* SdTiledRenderingTest::createDoc(const char* pName, const uno::Sequence<beans::PropertyValue>& rArguments)
235 if (mxComponent.is())
236 mxComponent->dispose();
237 mxComponent = loadFromDesktop(m_directories.getURLFromSrc(DATA_DIRECTORY) + OUString::createFromAscii(pName), "com.sun.star.presentation.PresentationDocument");
238 SdXImpressDocument* pImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
239 CPPUNIT_ASSERT(pImpressDocument);
240 pImpressDocument->initializeForTiledRendering(rArguments);
241 return pImpressDocument;
244 void SdTiledRenderingTest::callback(int nType, const char* pPayload, void* pData)
246 static_cast<SdTiledRenderingTest*>(pData)->callbackImpl(nType, pPayload);
249 static std::vector<OUString> lcl_convertSeparated(const OUString& rString, sal_Unicode nSeparator)
251 std::vector<OUString> aRet;
253 sal_Int32 nIndex = 0;
256 OUString aToken = rString.getToken(0, nSeparator, nIndex);
257 aToken = aToken.trim();
258 if (!aToken.isEmpty())
259 aRet.push_back(aToken);
261 while (nIndex >= 0);
263 return aRet;
266 static void lcl_convertRectangle(const OUString& rString, ::tools::Rectangle& rRectangle)
268 uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated(rString);
269 CPPUNIT_ASSERT(aSeq.getLength() == 4 || aSeq.getLength() == 5);
270 rRectangle.setX(aSeq[0].toInt32());
271 rRectangle.setY(aSeq[1].toInt32());
272 rRectangle.setWidth(aSeq[2].toInt32());
273 rRectangle.setHeight(aSeq[3].toInt32());
276 void SdTiledRenderingTest::callbackImpl(int nType, const char* pPayload)
278 switch (nType)
280 case LOK_CALLBACK_INVALIDATE_TILES:
282 OUString aPayload = OUString::createFromAscii(pPayload);
283 if (aPayload != "EMPTY" && m_aInvalidation.IsEmpty())
284 lcl_convertRectangle(aPayload, m_aInvalidation);
286 break;
287 case LOK_CALLBACK_TEXT_SELECTION:
289 OUString aPayload = OUString::createFromAscii(pPayload);
290 m_aSelection.clear();
291 for (const OUString& rString : lcl_convertSeparated(aPayload, u';'))
293 ::tools::Rectangle aRectangle;
294 lcl_convertRectangle(rString, aRectangle);
295 m_aSelection.push_back(aRectangle);
297 if (m_aSearchResultSelection.empty())
298 ++m_nSelectionBeforeSearchResult;
299 else
300 ++m_nSelectionAfterSearchResult;
302 break;
303 case LOK_CALLBACK_SEARCH_NOT_FOUND:
305 m_bFound = false;
307 break;
308 case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED:
310 m_aDocumentSizeCondition.set();
312 break;
313 case LOK_CALLBACK_SET_PART:
315 OUString aPayload = OUString::createFromAscii(pPayload);
316 m_nPart = aPayload.toInt32();
318 break;
319 case LOK_CALLBACK_SEARCH_RESULT_SELECTION:
321 m_aSearchResultSelection.clear();
322 m_aSearchResultPart.clear();
323 boost::property_tree::ptree aTree;
324 std::stringstream aStream(pPayload);
325 boost::property_tree::read_json(aStream, aTree);
326 for (const boost::property_tree::ptree::value_type& rValue : aTree.get_child("searchResultSelection"))
328 m_aSearchResultSelection.emplace_back(rValue.second.get<std::string>("rectangles").c_str());
329 m_aSearchResultPart.push_back(std::atoi(rValue.second.get<std::string>("part").c_str()));
332 break;
336 xmlDocPtr SdTiledRenderingTest::parseXmlDump()
338 if (m_pXmlBuffer)
339 xmlBufferFree(m_pXmlBuffer);
341 // Create the xml writer.
342 m_pXmlBuffer = xmlBufferCreate();
343 xmlTextWriterPtr pXmlWriter = xmlNewTextWriterMemory(m_pXmlBuffer, 0);
344 xmlTextWriterStartDocument(pXmlWriter, nullptr, nullptr, nullptr);
346 // Create the dump.
347 SdXImpressDocument* pImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
348 CPPUNIT_ASSERT(pImpressDocument);
349 pImpressDocument->GetDoc()->dumpAsXml(pXmlWriter);
351 // Delete the xml writer.
352 xmlTextWriterEndDocument(pXmlWriter);
353 xmlFreeTextWriter(pXmlWriter);
355 return xmlParseMemory(reinterpret_cast<const char*>(xmlBufferContent(m_pXmlBuffer)), xmlBufferLength(m_pXmlBuffer));
358 void SdTiledRenderingTest::testCreateDestroy()
360 createDoc("dummy.odp");
361 // Nothing to do, the tearDown call should cleanup.
364 void SdTiledRenderingTest::testCreateView()
366 createDoc("dummy.odp");
368 SfxLokHelper::createView();
371 void SdTiledRenderingTest::testRegisterCallback()
373 SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
374 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
375 pViewShell->GetViewShellBase().registerLibreOfficeKitViewCallback(&SdTiledRenderingTest::callback, this);
377 // Start text edit of the empty title shape.
378 SdPage* pActualPage = pViewShell->GetActualPage();
379 SdrObject* pObject = pActualPage->GetObj(0);
380 SdrView* pView = pViewShell->GetView();
381 pView->SdrBeginTextEdit(pObject);
382 CPPUNIT_ASSERT(pView->GetTextEditObject());
384 // Check that the top left 256x256px tile would be invalidated.
385 CPPUNIT_ASSERT(!m_aInvalidation.IsEmpty());
386 ::tools::Rectangle aTopLeft(0, 0, 256*15, 256*15); // 1 px = 15 twips, assuming 96 DPI.
387 CPPUNIT_ASSERT(m_aInvalidation.IsOver(aTopLeft));
390 void SdTiledRenderingTest::testPostKeyEvent()
392 SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
393 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
394 SdPage* pActualPage = pViewShell->GetActualPage();
395 SdrObject* pObject = pActualPage->GetObj(0);
396 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(OBJ_TITLETEXT), pObject->GetObjIdentifier());
397 SdrTextObj* pTextObj = static_cast<SdrTextObj*>(pObject);
398 SdrView* pView = pViewShell->GetView();
399 pView->MarkObj(pTextObj, pView->GetSdrPageView());
400 SfxStringItem aInputString(SID_ATTR_CHAR, "x");
401 pViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR,
402 SfxCallMode::SYNCHRON, { &aInputString });
404 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
405 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
406 Scheduler::ProcessEventsToIdle();
408 CPPUNIT_ASSERT(pView->GetTextEditObject());
409 EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
410 // Did we manage to enter a second character?
411 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), rEditView.GetSelection().nStartPos);
412 ESelection aWordSelection(0, 0, 0, 2); // start para, start char, end para, end char.
413 rEditView.SetSelection(aWordSelection);
414 // Did we enter the expected character?
415 CPPUNIT_ASSERT_EQUAL(OUString("xx"), rEditView.GetSelected());
418 void SdTiledRenderingTest::testPostMouseEvent()
420 SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
421 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
422 SdPage* pActualPage = pViewShell->GetActualPage();
423 SdrObject* pObject = pActualPage->GetObj(0);
424 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(OBJ_TITLETEXT), pObject->GetObjIdentifier());
425 SdrTextObj* pTextObj = static_cast<SdrTextObj*>(pObject);
426 SdrView* pView = pViewShell->GetView();
427 pView->MarkObj(pTextObj, pView->GetSdrPageView());
428 SfxStringItem aInputString(SID_ATTR_CHAR, "x");
429 pViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR,
430 SfxCallMode::SYNCHRON, { &aInputString });
431 CPPUNIT_ASSERT(pView->GetTextEditObject());
432 EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
433 // Did we manage to go after the first character?
434 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), rEditView.GetSelection().nStartPos);
436 vcl::Cursor* pCursor = rEditView.GetCursor();
437 Point aPosition(pCursor->GetPos().getX(), pCursor->GetPos().getY() + pCursor->GetSize().Height() / 2);
438 aPosition.setX(aPosition.getX() - 1000);
439 pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
440 convertMm100ToTwip(aPosition.getX()), convertMm100ToTwip(aPosition.getY()),
441 1, MOUSE_LEFT, 0);
442 pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
443 convertMm100ToTwip(aPosition.getX()), convertMm100ToTwip(aPosition.getY()),
444 1, MOUSE_LEFT, 0);
445 Scheduler::ProcessEventsToIdle();
446 CPPUNIT_ASSERT(pView->GetTextEditObject());
447 // The new cursor position must be before the first word.
448 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), rEditView.GetSelection().nStartPos);
451 void SdTiledRenderingTest::testSetTextSelection()
453 SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
454 uno::Reference<container::XIndexAccess> xDrawPage(pXImpressDocument->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
455 uno::Reference<text::XTextRange> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
456 xShape->setString("Aaa bbb.");
457 // Create a selection on the second word.
458 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
459 SdPage* pActualPage = pViewShell->GetActualPage();
460 SdrObject* pObject = pActualPage->GetObj(0);
461 SdrView* pView = pViewShell->GetView();
462 pView->SdrBeginTextEdit(pObject);
463 CPPUNIT_ASSERT(pView->GetTextEditObject());
464 EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
465 ESelection aWordSelection(0, 4, 0, 7);
466 rEditView.SetSelection(aWordSelection);
467 // Did we indeed manage to select the second word?
468 CPPUNIT_ASSERT_EQUAL(OUString("bbb"), rEditView.GetSelected());
470 // Now use setTextSelection() to move the end of the selection 1000 twips right.
471 vcl::Cursor* pCursor = rEditView.GetCursor();
472 Point aEnd = pCursor->GetPos();
473 aEnd.setX(aEnd.getX() + 1000);
474 pXImpressDocument->setTextSelection(LOK_SETTEXTSELECTION_END, aEnd.getX(), aEnd.getY());
475 // The new selection must include the ending dot, too -- but not the first word.
476 CPPUNIT_ASSERT_EQUAL(OUString("bbb."), rEditView.GetSelected());
479 void SdTiledRenderingTest::testGetTextSelection()
481 SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
482 uno::Reference<container::XIndexAccess> xDrawPage(pXImpressDocument->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
483 uno::Reference<text::XTextRange> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
484 xShape->setString("Shape");
485 // Create a selection on the shape text.
486 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
487 SdPage* pActualPage = pViewShell->GetActualPage();
488 SdrObject* pObject = pActualPage->GetObj(0);
489 SdrView* pView = pViewShell->GetView();
490 pView->SdrBeginTextEdit(pObject);
491 CPPUNIT_ASSERT(pView->GetTextEditObject());
492 EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
493 ESelection aWordSelection(0, 0, 0, 5);
494 rEditView.SetSelection(aWordSelection);
495 // Did we indeed manage to copy the selected text?
496 CPPUNIT_ASSERT_EQUAL(OString("Shape"), apitest::helper::transferable::getTextSelection(pXImpressDocument->getSelection(), "text/plain;charset=utf-8"));
498 // Make sure returned RTF is not empty.
499 CPPUNIT_ASSERT(!apitest::helper::transferable::getTextSelection(pXImpressDocument->getSelection(), "text/rtf").isEmpty());
502 void SdTiledRenderingTest::testSetGraphicSelection()
504 SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
505 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
506 SdPage* pPage = pViewShell->GetActualPage();
507 SdrObject* pObject = pPage->GetObj(0);
508 SdrHdlList handleList(nullptr);
509 pObject->AddToHdlList(handleList);
510 // Make sure the rectangle has 8 handles: at each corner and at the center of each edge.
511 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(8), handleList.GetHdlCount());
512 // Take the bottom center one.
513 SdrHdl* pHdl = handleList.GetHdl(6);
514 CPPUNIT_ASSERT_EQUAL(int(SdrHdlKind::Lower), static_cast<int>(pHdl->GetKind()));
515 ::tools::Rectangle aShapeBefore = pObject->GetSnapRect();
516 // Resize.
517 pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_START, convertMm100ToTwip(pHdl->GetPos().getX()), convertMm100ToTwip(pHdl->GetPos().getY()));
518 pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_END, convertMm100ToTwip(pHdl->GetPos().getX()), convertMm100ToTwip(pHdl->GetPos().getY() + 1000));
520 // Assert that view shell ID tracking works.
521 sal_Int32 nView1 = SfxLokHelper::getView();
522 SdDrawDocument* pDocument = pXImpressDocument->GetDoc();
523 sd::UndoManager* pUndoManager = pDocument->GetUndoManager();
524 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pUndoManager->GetUndoActionCount());
525 auto pListAction = dynamic_cast<SfxListUndoAction*>(pUndoManager->GetUndoAction());
526 CPPUNIT_ASSERT(pListAction);
527 for (size_t i = 0; i < pListAction->maUndoActions.size(); ++i)
528 // The second item was -1 here, view shell ID wasn't known.
529 CPPUNIT_ASSERT_EQUAL(ViewShellId(nView1), pListAction->GetUndoAction(i)->GetViewShellId());
531 ::tools::Rectangle aShapeAfter = pObject->GetSnapRect();
532 // Check that a resize happened, but aspect ratio is not kept.
533 CPPUNIT_ASSERT_EQUAL(aShapeBefore.getWidth(), aShapeAfter.getWidth());
534 CPPUNIT_ASSERT(aShapeBefore.getHeight() < aShapeAfter.getHeight());
537 void SdTiledRenderingTest::testUndoShells()
539 // Load a document and set the page size.
540 SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
541 uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
543 {"AttributePageSize.Width", uno::makeAny(static_cast<sal_Int32>(10000))},
544 {"AttributePageSize.Height", uno::makeAny(static_cast<sal_Int32>(10000))},
545 }));
546 comphelper::dispatchCommand(".uno:AttributePageSize", aPropertyValues);
547 Scheduler::ProcessEventsToIdle();
549 // Assert that view shell ID tracking works for SdUndoAction subclasses.
550 SdDrawDocument* pDocument = pXImpressDocument->GetDoc();
551 sd::UndoManager* pUndoManager = pDocument->GetUndoManager();
552 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pUndoManager->GetUndoActionCount());
553 sal_Int32 nView1 = SfxLokHelper::getView();
554 // This was -1, SdUndoGroup did not track what view shell created it.
555 CPPUNIT_ASSERT_EQUAL(ViewShellId(nView1), pUndoManager->GetUndoAction()->GetViewShellId());
558 void SdTiledRenderingTest::testResetSelection()
560 SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
561 uno::Reference<container::XIndexAccess> xDrawPage(pXImpressDocument->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
562 uno::Reference<text::XTextRange> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
563 xShape->setString("Aaa bbb.");
564 // Create a selection on the second word.
565 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
566 SdPage* pActualPage = pViewShell->GetActualPage();
567 SdrObject* pObject = pActualPage->GetObj(0);
568 SdrView* pView = pViewShell->GetView();
569 pView->SdrBeginTextEdit(pObject);
570 CPPUNIT_ASSERT(pView->GetTextEditObject());
571 EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
572 ESelection aWordSelection(0, 4, 0, 7);
573 rEditView.SetSelection(aWordSelection);
574 // Did we indeed manage to select the second word?
575 CPPUNIT_ASSERT_EQUAL(OUString("bbb"), rEditView.GetSelected());
577 // Now use resetSelection() to reset the selection.
578 pXImpressDocument->resetSelection();
579 CPPUNIT_ASSERT(!pView->GetTextEditObject());
582 static void lcl_search(const OUString& rKey, bool bFindAll = false)
584 uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
586 {"SearchItem.SearchString", uno::makeAny(rKey)},
587 {"SearchItem.Backward", uno::makeAny(false)},
588 {"SearchItem.Command", uno::makeAny(static_cast<sal_uInt16>(bFindAll ? SvxSearchCmd::FIND_ALL : SvxSearchCmd::FIND))},
589 }));
590 comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues);
593 void SdTiledRenderingTest::testSearch()
595 SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
596 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
597 pViewShell->GetViewShellBase().registerLibreOfficeKitViewCallback(&SdTiledRenderingTest::callback, this);
598 uno::Reference<container::XIndexAccess> xDrawPage(pXImpressDocument->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
599 uno::Reference<text::XTextRange> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
600 xShape->setString("Aaa bbb.");
602 lcl_search("bbb");
604 SdrView* pView = pViewShell->GetView();
605 EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
606 // Did we indeed manage to select the second word?
607 CPPUNIT_ASSERT_EQUAL(OUString("bbb"), rEditView.GetSelected());
609 // Did the selection callback fire?
610 CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), m_aSelection.size());
612 // Search for something on the second slide, and make sure that the set-part callback fired.
613 lcl_search("bbb");
614 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), m_nPart);
615 CPPUNIT_ASSERT_EQUAL(true, m_bFound);
616 // This was 0; should be 1 match for "find".
617 CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), m_aSearchResultSelection.size());
618 // Result is on the second slide.
619 CPPUNIT_ASSERT_EQUAL(1, m_aSearchResultPart[0]);
621 // This should trigger the not-found callback.
622 lcl_search("ccc");
623 CPPUNIT_ASSERT_EQUAL(false, m_bFound);
626 void SdTiledRenderingTest::testSearchAll()
628 SdXImpressDocument* pXImpressDocument = createDoc("search-all.odp");
629 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
630 pViewShell->GetViewShellBase().registerLibreOfficeKitViewCallback(&SdTiledRenderingTest::callback, this);
632 lcl_search("match", /*bFindAll=*/true);
634 // This was empty: find-all did not highlight the first match.
635 CPPUNIT_ASSERT_EQUAL(OString("match"), apitest::helper::transferable::getTextSelection(pXImpressDocument->getSelection(), "text/plain;charset=utf-8"));
637 // We're on the first slide, search for something on the second slide and make sure we get a SET_PART.
638 m_nPart = 0;
639 lcl_search("second", /*bFindAll=*/true);
640 // This was 0: no SET_PART was emitted.
641 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), m_nPart);
644 void SdTiledRenderingTest::testSearchAllSelections()
646 SdXImpressDocument* pXImpressDocument = createDoc("search-all.odp");
647 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
648 pViewShell->GetViewShellBase().registerLibreOfficeKitViewCallback(&SdTiledRenderingTest::callback, this);
650 lcl_search("third", /*bFindAll=*/true);
651 // Make sure this is found on the 3rd slide.
652 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), m_nPart);
653 // This was 1: only the first match was highlighted.
654 CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), m_aSelection.size());
657 void SdTiledRenderingTest::testSearchAllNotifications()
659 SdXImpressDocument* pXImpressDocument = createDoc("search-all.odp");
660 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
661 pViewShell->GetViewShellBase().registerLibreOfficeKitViewCallback(&SdTiledRenderingTest::callback, this);
663 lcl_search("third", /*bFindAll=*/true);
664 // Make sure that we get no notifications about selection changes during search.
665 CPPUNIT_ASSERT_EQUAL(0, m_nSelectionBeforeSearchResult);
666 // But we do get the selection of the first hit.
667 CPPUNIT_ASSERT(m_nSelectionAfterSearchResult > 0);
670 void SdTiledRenderingTest::testSearchAllFollowedBySearch()
672 SdXImpressDocument* pXImpressDocument = createDoc("search-all.odp");
673 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
674 pViewShell->GetViewShellBase().registerLibreOfficeKitViewCallback(&SdTiledRenderingTest::callback, this);
676 lcl_search("third", /*bFindAll=*/true);
677 lcl_search("match" /*,bFindAll=false*/);
679 // This used to give wrong result: 'search' after 'search all' still
680 // returned 'third'
681 CPPUNIT_ASSERT_EQUAL(OString("match"), apitest::helper::transferable::getTextSelection(pXImpressDocument->getSelection(), "text/plain;charset=utf-8"));
684 void SdTiledRenderingTest::testDontSearchInMasterPages()
686 SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
687 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
688 pViewShell->GetViewShellBase().registerLibreOfficeKitViewCallback(&SdTiledRenderingTest::callback, this);
690 // This should trigger the not-found callback ("date" is present only on
691 // the master page)
692 lcl_search("date");
693 CPPUNIT_ASSERT_EQUAL(false, m_bFound);
696 namespace
699 std::vector<OUString> getCurrentParts(SdXImpressDocument* pDocument)
701 int parts = pDocument->getParts();
702 std::vector<OUString> result;
704 result.reserve(parts);
705 for (int i = 0; i < parts; i++)
707 result.push_back(pDocument->getPartName(i));
710 return result;
715 void SdTiledRenderingTest::testInsertDeletePage()
717 SdXImpressDocument* pXImpressDocument = createDoc("insert-delete.odp");
718 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
719 pViewShell->GetViewShellBase().registerLibreOfficeKitViewCallback(&SdTiledRenderingTest::callback, this);
721 SdDrawDocument* pDoc = pXImpressDocument->GetDocShell()->GetDoc();
722 CPPUNIT_ASSERT(pDoc);
724 std::vector<OUString> aInserted =
726 "Slide 1", "Slide 2", "Slide 3", "Slide 4", "Slide 5",
727 "Slide 6", "Slide 7", "Slide 8", "Slide 9", "Slide 10", "Slide 11"
730 std::vector<OUString> aDeleted =
732 "Slide 1"
735 // the document has 1 slide
736 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(1), pDoc->GetSdPageCount(PageKind::Standard));
738 uno::Sequence<beans::PropertyValue> aArgs;
740 // Insert slides
741 m_aDocumentSizeCondition.reset();
742 for (unsigned it = 1; it <= 10; it++)
743 comphelper::dispatchCommand(".uno:InsertPage", aArgs);
745 osl::Condition::Result aResult = m_aDocumentSizeCondition.wait(std::chrono::seconds(2));
746 CPPUNIT_ASSERT_EQUAL(osl::Condition::result_ok, aResult);
748 // Verify inserted slides
749 std::vector<OUString> aPageList(getCurrentParts(pXImpressDocument));
750 CPPUNIT_ASSERT_EQUAL(aPageList.size(), aInserted.size());
752 for (auto it1 = aPageList.begin(), it2 = aInserted.begin(); it1 != aPageList.end(); ++it1, ++it2)
754 CPPUNIT_ASSERT_EQUAL(*it1, *it2);
757 // Delete slides
758 m_aDocumentSizeCondition.reset();
759 for (unsigned it = 1; it <= 10; it++)
760 comphelper::dispatchCommand(".uno:DeletePage", aArgs);
762 aResult = m_aDocumentSizeCondition.wait(std::chrono::seconds(2));
763 CPPUNIT_ASSERT_EQUAL(osl::Condition::result_ok, aResult);
765 // Verify deleted slides
766 aPageList = getCurrentParts(pXImpressDocument);
767 CPPUNIT_ASSERT_EQUAL(aPageList.size(), aDeleted.size());
768 for (auto it1 = aPageList.begin(), it2 = aDeleted.begin(); it1 != aPageList.end(); ++it1, ++it2)
770 CPPUNIT_ASSERT_EQUAL(*it1, *it2);
773 // Undo deleted slides
774 m_aDocumentSizeCondition.reset();
775 for (unsigned it = 1; it <= 10; it++)
776 comphelper::dispatchCommand(".uno:Undo", aArgs);
778 aResult = m_aDocumentSizeCondition.wait(std::chrono::seconds(2));
779 CPPUNIT_ASSERT_EQUAL(osl::Condition::result_ok, aResult);
781 // Verify inserted slides
782 aPageList = getCurrentParts(pXImpressDocument);
783 CPPUNIT_ASSERT_EQUAL(aPageList.size(), aInserted.size());
784 for (auto it1 = aPageList.begin(), it2 = aInserted.begin(); it1 != aPageList.end(); ++it1, ++it2)
786 CPPUNIT_ASSERT_EQUAL(*it1, *it2);
789 // Redo deleted slides
790 m_aDocumentSizeCondition.reset();
791 for (unsigned it = 1; it <= 10; it++)
792 comphelper::dispatchCommand(".uno:Redo", aArgs);
794 aResult = m_aDocumentSizeCondition.wait(std::chrono::seconds(2));
795 CPPUNIT_ASSERT_EQUAL(osl::Condition::result_ok, aResult);
797 // Verify deleted slides
798 aPageList = getCurrentParts(pXImpressDocument);
799 CPPUNIT_ASSERT_EQUAL(aPageList.size(), aDeleted.size());
800 for (auto it1 = aPageList.begin(), it2 = aDeleted.begin(); it1 != aPageList.end(); ++it1, ++it2)
802 CPPUNIT_ASSERT_EQUAL(*it1, *it2);
805 // the document has 1 slide
806 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(1), pDoc->GetSdPageCount(PageKind::Standard));
809 void SdTiledRenderingTest::testInsertTable()
811 SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
813 uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
815 { "Rows", uno::makeAny(sal_Int32(3)) },
816 { "Columns", uno::makeAny(sal_Int32(5)) }
817 }));
819 comphelper::dispatchCommand(".uno:InsertTable", aArgs);
820 Scheduler::ProcessEventsToIdle();
822 // get the table
823 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
824 SdPage* pActualPage = pViewShell->GetActualPage();
825 SdrObject* pObject = pActualPage->GetObj(1);
826 CPPUNIT_ASSERT(pObject);
828 // check that the table is not in the top left corner
829 Point aPos(pObject->GetRelativePos());
831 CPPUNIT_ASSERT(aPos.X() != 0);
832 CPPUNIT_ASSERT(aPos.Y() != 0);
835 void SdTiledRenderingTest::testPartHash()
837 SdXImpressDocument* pDoc = createDoc("dummy.odp");
839 int nParts = pDoc->getParts();
840 for (int it = 0; it < nParts; it++)
842 CPPUNIT_ASSERT(!pDoc->getPartHash(it).isEmpty());
845 // check part that it does not exists
846 CPPUNIT_ASSERT(pDoc->getPartHash(100).isEmpty());
849 void SdTiledRenderingTest::testResizeTable()
851 // Load the document.
852 SdXImpressDocument* pXImpressDocument = createDoc("table.odp");
853 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
854 SdPage* pActualPage = pViewShell->GetActualPage();
855 SdrObject* pObject = pActualPage->GetObj(0);
856 auto pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pObject);
857 CPPUNIT_ASSERT(pTableObject);
859 // Select the table by marking it + starting and ending text edit.
860 SdrView* pView = pViewShell->GetView();
861 pView->MarkObj(pObject, pView->GetSdrPageView());
862 pView->SdrBeginTextEdit(pObject);
863 pView->SdrEndTextEdit();
865 // Remember the original row heights.
866 uno::Reference<table::XColumnRowRange> xTable = pTableObject->getTable();
867 uno::Reference<container::XIndexAccess> xRows = xTable->getRows();
868 uno::Reference<beans::XPropertySet> xRow1(xRows->getByIndex(0), uno::UNO_QUERY);
869 sal_Int32 nExpectedRow1 = xRow1->getPropertyValue("Size").get<sal_Int32>();
870 uno::Reference<beans::XPropertySet> xRow2(xRows->getByIndex(1), uno::UNO_QUERY);
871 sal_Int32 nExpectedRow2 = xRow2->getPropertyValue("Size").get<sal_Int32>();
873 // Resize the upper row, decrease its height by 1 cm.
874 Point aInnerRowEdge = pObject->GetSnapRect().Center();
875 pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_START, convertMm100ToTwip(aInnerRowEdge.getX()), convertMm100ToTwip(aInnerRowEdge.getY()));
876 pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_END, convertMm100ToTwip(aInnerRowEdge.getX()), convertMm100ToTwip(aInnerRowEdge.getY() - 1000));
878 // Remember the resized row heights.
879 sal_Int32 nResizedRow1 = xRow1->getPropertyValue("Size").get<sal_Int32>();
880 CPPUNIT_ASSERT(nResizedRow1 < nExpectedRow1);
881 sal_Int32 nResizedRow2 = xRow2->getPropertyValue("Size").get<sal_Int32>();
882 CPPUNIT_ASSERT_EQUAL(nExpectedRow2, nResizedRow2);
884 // Now undo the resize.
885 pXImpressDocument->GetDocShell()->GetUndoManager()->Undo();
887 // Check the undo result.
888 sal_Int32 nActualRow1 = xRow1->getPropertyValue("Size").get<sal_Int32>();
889 CPPUNIT_ASSERT_EQUAL(nExpectedRow1, nActualRow1);
890 sal_Int32 nActualRow2 = xRow2->getPropertyValue("Size").get<sal_Int32>();
891 // Expected was 4000, actual was 4572, i.e. the second row after undo was larger than expected.
892 CPPUNIT_ASSERT_EQUAL(nExpectedRow2, nActualRow2);
895 void SdTiledRenderingTest::testResizeTableColumn()
897 // Load the document.
898 SdXImpressDocument* pXImpressDocument = createDoc("table-column.odp");
899 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
900 SdPage* pActualPage = pViewShell->GetActualPage();
901 SdrObject* pObject = pActualPage->GetObj(0);
902 auto pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pObject);
903 CPPUNIT_ASSERT(pTableObject);
905 // Select the table by marking it + starting and ending text edit.
906 SdrView* pView = pViewShell->GetView();
907 pView->MarkObj(pObject, pView->GetSdrPageView());
908 pView->SdrBeginTextEdit(pObject);
909 pView->SdrEndTextEdit();
911 // Remember the original cell widths.
912 xmlDocPtr pXmlDoc = parseXmlDump();
913 OString aPrefix = "/SdDrawDocument/SdrModel/SdPage/SdrObjList/SdrTableObj/SdrTableObjImpl/TableLayouter/columns/";
914 sal_Int32 nExpectedColumn1 = getXPath(pXmlDoc, aPrefix + "TableLayouter_Layout[1]", "size").toInt32();
915 sal_Int32 nExpectedColumn2 = getXPath(pXmlDoc, aPrefix + "TableLayouter_Layout[2]", "size").toInt32();
916 xmlFreeDoc(pXmlDoc);
917 pXmlDoc = nullptr;
919 // Resize the left column, decrease its width by 1 cm.
920 Point aInnerRowEdge = pObject->GetSnapRect().Center();
921 pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_START, convertMm100ToTwip(aInnerRowEdge.getX()), convertMm100ToTwip(aInnerRowEdge.getY()));
922 pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_END, convertMm100ToTwip(aInnerRowEdge.getX() - 1000), convertMm100ToTwip(aInnerRowEdge.getY()));
924 // Remember the resized column widths.
925 pXmlDoc = parseXmlDump();
926 sal_Int32 nResizedColumn1 = getXPath(pXmlDoc, aPrefix + "TableLayouter_Layout[1]", "size").toInt32();
927 CPPUNIT_ASSERT(nResizedColumn1 < nExpectedColumn1);
928 sal_Int32 nResizedColumn2 = getXPath(pXmlDoc, aPrefix + "TableLayouter_Layout[2]", "size").toInt32();
929 CPPUNIT_ASSERT(nResizedColumn2 > nExpectedColumn2);
930 xmlFreeDoc(pXmlDoc);
931 pXmlDoc = nullptr;
933 // Now undo the resize.
934 pXImpressDocument->GetDocShell()->GetUndoManager()->Undo();
936 // Check the undo result.
937 pXmlDoc = parseXmlDump();
938 sal_Int32 nActualColumn1 = getXPath(pXmlDoc, aPrefix + "TableLayouter_Layout[1]", "size").toInt32();
939 // Expected was 7049, actual was 6048, i.e. the first column width after undo was 1cm smaller than expected.
940 CPPUNIT_ASSERT_EQUAL(nExpectedColumn1, nActualColumn1);
941 sal_Int32 nActualColumn2 = getXPath(pXmlDoc, aPrefix + "TableLayouter_Layout[2]", "size").toInt32();
942 CPPUNIT_ASSERT_EQUAL(nExpectedColumn2, nActualColumn2);
943 xmlFreeDoc(pXmlDoc);
944 pXmlDoc = nullptr;
947 /// A view callback tracks callbacks invoked on one specific view.
948 class ViewCallback
950 SfxViewShell* mpViewShell;
951 int mnView;
952 public:
953 bool m_bGraphicSelectionInvalidated;
954 bool m_bGraphicViewSelectionInvalidated;
955 /// Our current part, to be able to decide if a view cursor/selection is relevant for us.
956 int m_nPart;
957 bool m_bCursorVisibleChanged;
958 bool m_bViewLock;
959 bool m_bTilesInvalidated;
960 std::vector<tools::Rectangle> m_aInvalidations;
961 std::map<int, bool> m_aViewCursorInvalidations;
962 std::map<int, bool> m_aViewCursorVisibilities;
963 bool m_bViewSelectionSet;
964 boost::property_tree::ptree m_aCommentCallbackResult;
966 ViewCallback()
967 : m_bGraphicSelectionInvalidated(false),
968 m_bGraphicViewSelectionInvalidated(false),
969 m_nPart(0),
970 m_bCursorVisibleChanged(false),
971 m_bViewLock(false),
972 m_bTilesInvalidated(false),
973 m_bViewSelectionSet(false)
975 mpViewShell = SfxViewShell::Current();
976 mpViewShell->registerLibreOfficeKitViewCallback(&ViewCallback::callback, this);
977 mnView = SfxLokHelper::getView();
980 ~ViewCallback()
982 SfxLokHelper::setView(mnView);
983 mpViewShell->registerLibreOfficeKitViewCallback(nullptr, nullptr);
986 static void callback(int nType, const char* pPayload, void* pData)
988 static_cast<ViewCallback*>(pData)->callbackImpl(nType, pPayload);
991 void callbackImpl(int nType, const char* pPayload)
993 switch (nType)
995 case LOK_CALLBACK_INVALIDATE_TILES:
997 m_bTilesInvalidated = true;
998 OString text(pPayload);
999 if (!text.startsWith("EMPTY"))
1001 uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated(OUString::createFromAscii(pPayload));
1002 CPPUNIT_ASSERT(aSeq.getLength() == 4 || aSeq.getLength() == 5);
1003 tools::Rectangle aInvalidationRect;
1004 aInvalidationRect.setX(aSeq[0].toInt32());
1005 aInvalidationRect.setY(aSeq[1].toInt32());
1006 aInvalidationRect.setWidth(aSeq[2].toInt32());
1007 aInvalidationRect.setHeight(aSeq[3].toInt32());
1008 m_aInvalidations.push_back(aInvalidationRect);
1011 break;
1012 case LOK_CALLBACK_GRAPHIC_SELECTION:
1014 m_bGraphicSelectionInvalidated = true;
1016 break;
1017 case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
1019 std::stringstream aStream(pPayload);
1020 boost::property_tree::ptree aTree;
1021 boost::property_tree::read_json(aStream, aTree);
1022 if (aTree.get_child("part").get_value<int>() == m_nPart)
1023 // Ignore callbacks which are for a different part.
1024 m_bGraphicViewSelectionInvalidated = true;
1026 break;
1027 case LOK_CALLBACK_CURSOR_VISIBLE:
1029 m_bCursorVisibleChanged = true;
1031 break;
1032 case LOK_CALLBACK_VIEW_LOCK:
1034 std::stringstream aStream(pPayload);
1035 boost::property_tree::ptree aTree;
1036 boost::property_tree::read_json(aStream, aTree);
1037 m_bViewLock = aTree.get_child("rectangle").get_value<std::string>() != "EMPTY";
1039 break;
1040 case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR:
1042 std::stringstream aStream(pPayload);
1043 boost::property_tree::ptree aTree;
1044 boost::property_tree::read_json(aStream, aTree);
1045 int nViewId = aTree.get_child("viewId").get_value<int>();
1046 m_aViewCursorInvalidations[nViewId] = true;
1048 break;
1049 case LOK_CALLBACK_VIEW_CURSOR_VISIBLE:
1051 std::stringstream aStream(pPayload);
1052 boost::property_tree::ptree aTree;
1053 boost::property_tree::read_json(aStream, aTree);
1054 int nViewId = aTree.get_child("viewId").get_value<int>();
1055 m_aViewCursorVisibilities[nViewId] = OString("true") == pPayload;
1057 break;
1058 case LOK_CALLBACK_TEXT_VIEW_SELECTION:
1060 m_bViewSelectionSet = true;
1062 break;
1063 case LOK_CALLBACK_COMMENT:
1065 m_aCommentCallbackResult.clear();
1066 std::stringstream aStream(pPayload);
1067 boost::property_tree::read_json(aStream, m_aCommentCallbackResult);
1068 m_aCommentCallbackResult = m_aCommentCallbackResult.get_child("comment");
1070 break;
1075 void SdTiledRenderingTest::testViewCursors()
1077 // Create two views.
1078 SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
1079 ViewCallback aView1;
1080 SfxLokHelper::createView();
1081 ViewCallback aView2;
1083 // Select the shape in the second view.
1084 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
1085 SdPage* pActualPage = pViewShell->GetActualPage();
1086 SdrObject* pObject = pActualPage->GetObj(0);
1087 SdrView* pView = pViewShell->GetView();
1088 pView->MarkObj(pObject, pView->GetSdrPageView());
1089 Scheduler::ProcessEventsToIdle();
1091 // First view notices that there was a selection change in the other view.
1092 CPPUNIT_ASSERT(aView1.m_bGraphicViewSelectionInvalidated);
1093 // Second view notices that there was a selection change in its own view.
1094 CPPUNIT_ASSERT(aView2.m_bGraphicSelectionInvalidated);
1097 void SdTiledRenderingTest::testViewCursorParts()
1099 // Create two views.
1100 SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
1101 ViewCallback aView1;
1102 SfxLokHelper::createView();
1103 pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
1104 ViewCallback aView2;
1106 // Select the shape in the second view.
1107 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
1108 SdPage* pActualPage = pViewShell->GetActualPage();
1109 SdrObject* pObject = pActualPage->GetObj(0);
1110 SdrView* pView = pViewShell->GetView();
1111 pView->MarkObj(pObject, pView->GetSdrPageView());
1112 Scheduler::ProcessEventsToIdle();
1113 // First view notices that there was a selection change in the other view.
1114 CPPUNIT_ASSERT(aView1.m_bGraphicViewSelectionInvalidated);
1115 pView->UnmarkAllObj(pView->GetSdrPageView());
1117 // Now switch to the second part in the second view.
1118 pXImpressDocument->setPart(1);
1119 aView2.m_nPart = 1;
1120 aView1.m_bGraphicViewSelectionInvalidated = false;
1121 pActualPage = pViewShell->GetActualPage();
1122 pObject = pActualPage->GetObj(0);
1123 pView->MarkObj(pObject, pView->GetSdrPageView());
1124 Scheduler::ProcessEventsToIdle();
1125 // First view ignores view selection, as it would be for part 1, and it's in part 0.
1126 // This failed when the "part" was always 0 in the callback.
1127 CPPUNIT_ASSERT(!aView1.m_bGraphicViewSelectionInvalidated);
1130 void SdTiledRenderingTest::testCursorViews()
1132 // Create the first view.
1133 SdXImpressDocument* pXImpressDocument = createDoc("title-shape.odp");
1134 int nView1 = SfxLokHelper::getView();
1135 ViewCallback aView1;
1137 // Begin text edit on the only object on the slide.
1138 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
1139 SdrView* pView = pViewShell->GetView();
1140 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
1141 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
1142 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
1143 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
1144 Scheduler::ProcessEventsToIdle();
1145 CPPUNIT_ASSERT(pView->IsTextEdit());
1147 // Make sure that cursor state is not changed just because we create a second view.
1148 aView1.m_bCursorVisibleChanged = false;
1149 SfxLokHelper::createView();
1150 pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
1151 Scheduler::ProcessEventsToIdle();
1152 CPPUNIT_ASSERT(!aView1.m_bCursorVisibleChanged);
1154 // Make sure that typing in the first view causes an invalidation in the
1155 // second view as well, even if the second view was created after begin
1156 // text edit in the first view.
1157 ViewCallback aView2;
1158 // This failed: the second view didn't get a lock notification, even if the
1159 // first view already started text edit.
1160 CPPUNIT_ASSERT(aView2.m_bViewLock);
1161 SfxLokHelper::setView(nView1);
1162 aView2.m_bTilesInvalidated = false;
1163 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
1164 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
1165 Scheduler::ProcessEventsToIdle();
1166 // This failed: the second view was not invalidated when pressing a key in
1167 // the first view.
1168 CPPUNIT_ASSERT(aView2.m_bTilesInvalidated);
1171 void SdTiledRenderingTest::testViewLock()
1173 // Load a document that has a shape and create two views.
1174 SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
1175 ViewCallback aView1;
1176 SfxLokHelper::createView();
1177 pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
1179 // Begin text edit in the second view and assert that the first gets a lock
1180 // notification.
1181 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
1182 SdPage* pActualPage = pViewShell->GetActualPage();
1183 SdrObject* pObject = pActualPage->GetObj(0);
1184 SdrView* pView = pViewShell->GetView();
1185 aView1.m_bViewLock = false;
1186 pView->SdrBeginTextEdit(pObject);
1187 CPPUNIT_ASSERT(aView1.m_bViewLock);
1189 // End text edit in the second view, and assert that the lock is removed in
1190 // the first view.
1191 pView->SdrEndTextEdit();
1192 CPPUNIT_ASSERT(!aView1.m_bViewLock);
1195 void SdTiledRenderingTest::testUndoLimiting()
1197 // Create the first view.
1198 SdXImpressDocument* pXImpressDocument = createDoc("title-shape.odp");
1199 sd::ViewShell* pViewShell1 = pXImpressDocument->GetDocShell()->GetViewShell();
1200 int nView1 = SfxLokHelper::getView();
1201 SfxLokHelper::createView();
1202 sd::ViewShell* pViewShell2 = pXImpressDocument->GetDocShell()->GetViewShell();
1203 CPPUNIT_ASSERT(pViewShell1 != pViewShell2);
1205 // Begin text edit on the only object on the slide.
1206 SfxLokHelper::setView(nView1);
1207 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
1208 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
1209 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
1210 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
1211 Scheduler::ProcessEventsToIdle();
1212 CPPUNIT_ASSERT(pViewShell1->GetView()->IsTextEdit());
1214 // Now check view2 cannot undo actions.
1216 SfxRequest aReq2(SID_UNDO, SfxCallMode::SLOT, pXImpressDocument->GetDocShell()->GetDoc()->GetPool());
1217 aReq2.AppendItem(SfxUInt16Item(SID_UNDO, 1));
1218 pViewShell2->ExecuteSlot(aReq2);
1219 const SfxUInt32Item* pUInt32Item = dynamic_cast<const SfxUInt32Item*>(aReq2.GetReturnValue());
1220 CPPUNIT_ASSERT(pUInt32Item);
1221 CPPUNIT_ASSERT_EQUAL(static_cast< sal_uInt32 >(SID_REPAIRPACKAGE), pUInt32Item->GetValue());
1224 // Now check view1 can undo action
1226 SfxRequest aReq1(SID_UNDO, SfxCallMode::SLOT, pXImpressDocument->GetDocShell()->GetDoc()->GetPool());
1227 aReq1.AppendItem(SfxUInt16Item(SID_UNDO, 1));
1228 pViewShell1->ExecuteSlot(aReq1);
1229 CPPUNIT_ASSERT(aReq1.IsDone());
1232 mxComponent->dispose();
1233 mxComponent.clear();
1236 void SdTiledRenderingTest::testCreateViewGraphicSelection()
1238 // Load a document and register a callback.
1239 SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
1240 ViewCallback aView1;
1242 // Select the only shape in the document and assert that the graphic selection is changed.
1243 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
1244 SdPage* pActualPage = pViewShell->GetActualPage();
1245 SdrObject* pObject = pActualPage->GetObj(0);
1246 SdrView* pView = pViewShell->GetView();
1247 aView1.m_bGraphicSelectionInvalidated = false;
1248 pView->MarkObj(pObject, pView->GetSdrPageView());
1249 CPPUNIT_ASSERT(aView1.m_bGraphicSelectionInvalidated);
1251 // Now create a new view.
1252 aView1.m_bGraphicSelectionInvalidated = false;
1253 SfxLokHelper::createView();
1254 pXImpressDocument->initializeForTiledRendering({});
1255 // This failed, creating a new view affected the graphic selection of an
1256 // existing view.
1257 CPPUNIT_ASSERT(!aView1.m_bGraphicSelectionInvalidated);
1259 // Check that when the first view has a shape selected and we register a
1260 // callback on the second view, then it gets a "graphic view selection".
1261 ViewCallback aView2;
1262 // This failed, the created new view had no "view selection" of the first
1263 // view's selected shape.
1264 CPPUNIT_ASSERT(aView2.m_bGraphicViewSelectionInvalidated);
1267 void SdTiledRenderingTest::testCreateViewTextCursor()
1269 // Load a document and register a callback.
1270 SdXImpressDocument* pXImpressDocument = createDoc("title-shape.odp");
1271 ViewCallback aView1;
1273 // Begin text edit.
1274 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
1275 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
1276 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
1277 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
1278 Scheduler::ProcessEventsToIdle();
1279 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
1280 SdrView* pSdrView = pViewShell->GetView();
1281 CPPUNIT_ASSERT(pSdrView->IsTextEdit());
1283 // Create an editeng text selection.
1284 EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView();
1285 // 0th para, 0th char -> 0th para, 1st char.
1286 ESelection aWordSelection(0, 0, 0, 1);
1287 rEditView.SetSelection(aWordSelection);
1289 // Make sure that creating a new view either doesn't affect the previous
1290 // one, or at least the effect is not visible at the end.
1291 aView1.m_aViewCursorInvalidations.clear();
1292 aView1.m_aViewCursorVisibilities.clear();
1293 SfxLokHelper::createView();
1294 pXImpressDocument->initializeForTiledRendering({});
1295 ViewCallback aView2;
1296 bool bFoundCursor = false;
1297 for (const auto& rInvalidation : aView1.m_aViewCursorInvalidations)
1299 auto itVisibility = aView1.m_aViewCursorVisibilities.find(rInvalidation.first);
1300 // For each cursor invalidation: if there is no visibility or the visibility is true, that's a problem.
1301 if (itVisibility == aView1.m_aViewCursorVisibilities.end() || itVisibility->second)
1303 bFoundCursor = true;
1304 break;
1307 // This failed: the second view created an unexpected view cursor in the
1308 // first view.
1309 CPPUNIT_ASSERT(!bFoundCursor);
1310 // This failed: the text view selection of the first view wasn't seen by
1311 // the second view.
1312 CPPUNIT_ASSERT(aView2.m_bViewSelectionSet);
1315 void SdTiledRenderingTest::testTdf102223()
1317 // Load the document.
1318 SdXImpressDocument* pXImpressDocument = createDoc("tdf102223.odp");
1319 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
1320 SdPage* pActualPage = pViewShell->GetActualPage();
1321 auto pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pActualPage->GetObj(2));
1322 CPPUNIT_ASSERT(pTableObject);
1323 SdrView* pView = pViewShell->GetView();
1325 // select contents of cell
1326 ::tools::Rectangle aRect = pTableObject->GetCurrentBoundRect();
1327 pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
1328 convertMm100ToTwip(aRect.getX() + 2), convertMm100ToTwip(aRect.getY() + 2),
1329 1, MOUSE_LEFT, 0);
1330 pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
1331 convertMm100ToTwip(aRect.getX() + 2), convertMm100ToTwip(aRect.getY() + 2),
1332 1, MOUSE_LEFT, 0);
1333 Scheduler::ProcessEventsToIdle();
1334 pView->SdrBeginTextEdit(pTableObject);
1335 CPPUNIT_ASSERT(pView->GetTextEditObject());
1336 EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
1337 rEditView.SetSelection(ESelection(0, 0, 0, 3)); // start para, start char, end para, end char.
1338 CPPUNIT_ASSERT_EQUAL(OUString("Red"), rEditView.GetSelected());
1339 const SvxFontHeightItem& rItem = rEditView.GetAttribs().Get(EE_CHAR_FONTHEIGHT);
1340 CPPUNIT_ASSERT_EQUAL(int(1411), static_cast<int>(rItem.GetHeight()));
1342 // cut contents of cell
1343 uno::Sequence<beans::PropertyValue> aArgs;
1344 comphelper::dispatchCommand(".uno:Cut", aArgs);
1346 pView->SdrEndTextEdit(false);
1347 pView->SdrBeginTextEdit(pTableObject);
1348 CPPUNIT_ASSERT(pView->GetTextEditObject());
1349 EditView& rEditView2 = pView->GetTextEditOutlinerView()->GetEditView();
1350 rEditView2.SetSelection(ESelection(0, 0, 0, 1)); // start para, start char, end para, end char.
1351 const SvxFontHeightItem& rItem2 = rEditView2.GetAttribs().Get(EE_CHAR_FONTHEIGHT);
1352 CPPUNIT_ASSERT_EQUAL(int(1411), static_cast<int>(rItem2.GetHeight()));
1355 void SdTiledRenderingTest::testPostKeyEventInvalidation()
1357 // Load a document and begin text edit on the first slide.
1358 SdXImpressDocument* pXImpressDocument = createDoc("2slides.odp");
1359 CPPUNIT_ASSERT_EQUAL(0, pXImpressDocument->getPart());
1360 ViewCallback aView1;
1361 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
1362 SdrView* pView = pViewShell->GetView();
1363 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
1364 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
1365 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_F2);
1366 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_F2);
1367 Scheduler::ProcessEventsToIdle();
1368 CPPUNIT_ASSERT(pView->GetTextEditObject());
1370 // Create a second view and begin text edit there as well, in parallel.
1371 SfxLokHelper::createView();
1372 pXImpressDocument->initializeForTiledRendering({});
1373 ViewCallback aView2;
1374 pXImpressDocument->setPart(1);
1375 sd::ViewShell* pViewShell2 = pXImpressDocument->GetDocShell()->GetViewShell();
1376 SdrView* pView2 = pViewShell2->GetView();
1377 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
1378 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
1379 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_F2);
1380 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_F2);
1381 Scheduler::ProcessEventsToIdle();
1382 CPPUNIT_ASSERT(pView2->GetTextEditObject());
1384 // Now go left with the cursor in the second view and watch for
1385 // invalidations.
1386 aView2.m_bTilesInvalidated = false;
1387 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT);
1388 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT);
1389 Scheduler::ProcessEventsToIdle();
1390 // This failed: moving the cursor caused unexpected invalidation.
1391 CPPUNIT_ASSERT(!aView2.m_bTilesInvalidated);
1395 * tests a cut/paste bug around bullet items in a list
1397 void SdTiledRenderingTest::testTdf103083()
1399 // Load the document.
1400 SdXImpressDocument* pXImpressDocument = createDoc("tdf103083.fodp");
1401 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
1402 SdPage* pActualPage = pViewShell->GetActualPage();
1404 SdrObject* pObject1 = pActualPage->GetObj(1);
1405 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(OBJ_OUTLINETEXT), pObject1->GetObjIdentifier());
1406 SdrTextObj* pTextObject = static_cast<SdrTextObj*>(pObject1);
1408 SdrView* pView = pViewShell->GetView();
1410 // select contents of bullet item
1411 ::tools::Rectangle aRect = pTextObject->GetCurrentBoundRect();
1412 pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
1413 convertMm100ToTwip(aRect.getX() + 2), convertMm100ToTwip(aRect.getY() + 2),
1414 1, MOUSE_LEFT, 0);
1415 pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
1416 convertMm100ToTwip(aRect.getX() + 2), convertMm100ToTwip(aRect.getY() + 2),
1417 1, MOUSE_LEFT, 0);
1418 Scheduler::ProcessEventsToIdle();
1419 pView->SdrBeginTextEdit(pTextObject);
1420 CPPUNIT_ASSERT(pView->GetTextEditObject());
1421 EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
1422 rEditView.SetSelection(ESelection(2, 0, 2, 33)); // start para, start char, end para, end char.
1423 CPPUNIT_ASSERT_EQUAL(OUString("They have all the same formatting"), rEditView.GetSelected());
1424 SdrOutliner* pOutliner = pView->GetTextEditOutliner();
1425 CPPUNIT_ASSERT_EQUAL(OUString("No-Logo Content~LT~Gliederung 2"),
1426 pOutliner->GetStyleSheet(2)->GetName());
1427 const SfxItemSet& rParagraphItemSet1 = pTextObject->GetOutlinerParaObject()->GetTextObject().GetParaAttribs(2);
1428 CPPUNIT_ASSERT_EQUAL(sal_uInt16(3), rParagraphItemSet1.Count());
1430 // cut contents of bullet item
1431 comphelper::dispatchCommand(".uno:Cut", uno::Sequence<beans::PropertyValue>());
1433 CPPUNIT_ASSERT(pView->GetTextEditObject());
1434 EditView& rEditView2 = pView->GetTextEditOutlinerView()->GetEditView();
1435 rEditView2.SetSelection(ESelection(2, 0, 2, 10)); // start para, start char, end para, end char.
1436 CPPUNIT_ASSERT_EQUAL(OUString(), rEditView2.GetSelected());
1438 // paste contents of bullet item
1439 comphelper::dispatchCommand(".uno:Paste", uno::Sequence<beans::PropertyValue>());
1441 // send an ESC key to trigger the commit of the edit to the main model
1442 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE);
1443 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
1444 Scheduler::ProcessEventsToIdle();
1446 pView->SdrBeginTextEdit(pTextObject);
1447 CPPUNIT_ASSERT(pView->GetTextEditObject());
1448 pOutliner = pView->GetTextEditOutliner();
1449 EditView& rEditView3 = pView->GetTextEditOutlinerView()->GetEditView();
1450 rEditView3.SetSelection(ESelection(2, 0, 2, 33)); // start para, start char, end para, end char.
1451 CPPUNIT_ASSERT_EQUAL(OUString("They have all the same formatting"), rEditView3.GetSelected());
1452 CPPUNIT_ASSERT_EQUAL(OUString("No-Logo Content~LT~Gliederung 2"),
1453 pOutliner->GetStyleSheet(2)->GetName());
1455 const SfxItemSet& rParagraphItemSet2 = pTextObject->GetOutlinerParaObject()->GetTextObject().GetParaAttribs(2);
1456 CPPUNIT_ASSERT_EQUAL(sal_uInt16(3), rParagraphItemSet2.Count());
1460 * tests a clone-formatting bug around table cell attributes
1462 void SdTiledRenderingTest::testTdf104405()
1464 // Load the document.
1465 SdXImpressDocument* pXImpressDocument = createDoc("tdf104405.fodp");
1466 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
1467 SdPage* pActualPage = pViewShell->GetActualPage();
1468 SdrObject* pObject = pActualPage->GetObj(2);
1469 auto pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pObject);
1470 CPPUNIT_ASSERT(pTableObject);
1472 // select the middle cell
1473 SdrView* pView = pViewShell->GetView();
1474 pView->MarkObj(pTableObject, pView->GetSdrPageView());
1475 pTableObject->setActiveCell(sdr::table::CellPos(2,1));
1476 pView->SdrBeginTextEdit(pTableObject);
1477 EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
1478 rEditView.SetSelection(ESelection(0, 0, 0, 3)); // start para, start char, end para, end char.
1480 // trigger the clone-formatting/paintbrush command to copy formatting contents of cell
1481 uno::Sequence< beans::PropertyValue > aArgs(1);
1482 aArgs[0].Name = "PersistentCopy";
1483 aArgs[0].Value <<= true;
1484 comphelper::dispatchCommand(".uno:FormatPaintbrush", aArgs);
1486 Scheduler::ProcessEventsToIdle();
1488 // now click on the table
1489 pView->MarkObj(pTableObject, pView->GetSdrPageView());
1490 pTableObject->setActiveCell(sdr::table::CellPos(0,0));
1491 pView->SdrEndTextEdit(false);
1492 pView->SdrBeginTextEdit(pTableObject);
1493 EditView& rEditView2 = pView->GetTextEditOutlinerView()->GetEditView();
1494 rEditView2.SetSelection(ESelection(0, 0, 0, 3)); // start para, start char, end para, end char.
1495 ::tools::Rectangle aRect = pTableObject->GetCurrentBoundRect();
1496 pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
1497 convertMm100ToTwip(aRect.getX()), convertMm100ToTwip(aRect.getY()),
1498 1, MOUSE_LEFT, 0);
1499 pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
1500 convertMm100ToTwip(aRect.getX()), convertMm100ToTwip(aRect.getY()),
1501 1, MOUSE_LEFT, 0);
1503 Scheduler::ProcessEventsToIdle();
1505 // check that the first cell has acquired the resulting vertical style
1506 xmlDocPtr pXmlDoc = parseXmlDump();
1507 OString aPrefix = "/SdDrawDocument/SdrModel/SdPage/SdrObjList/SdrTableObj/SdrTableObjImpl"
1508 "/TableModel/Cell[1]/DefaultProperties/SfxItemSet/SdrTextVertAdjustItem";
1509 // the following name has a compiler-dependent part
1510 CPPUNIT_ASSERT_EQUAL(OUString("2"), getXPath(pXmlDoc, aPrefix, "value"));
1511 xmlFreeDoc(pXmlDoc);
1514 void SdTiledRenderingTest::testTdf81754()
1516 SdXImpressDocument* pXImpressDocument = createDoc("tdf81754.pptx");
1517 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
1518 SdPage* pActualPage = pViewShell->GetActualPage();
1519 SdrObject* pObject = pActualPage->GetObj(1);
1521 SdrTextObj* pTextObj = static_cast<SdrTextObj*>(pObject);
1522 SdrView* pView = pViewShell->GetView();
1523 pView->MarkObj(pTextObj, pView->GetSdrPageView());
1524 SfxStringItem aInputString(SID_ATTR_CHAR, "x");
1525 pViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR,
1526 SfxCallMode::SYNCHRON, { &aInputString });
1528 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
1529 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
1530 Scheduler::ProcessEventsToIdle();
1532 // now save, reload, and assert that we did not lose the edit
1533 ::sd::DrawDocShellRef xDocShRef = saveAndReload(pXImpressDocument->GetDocShell(), PPTX);
1535 const SdrPage* pPage = GetPage(1, xDocShRef);
1536 SdrTextObj* pTextObject = dynamic_cast<SdrTextObj*>(pPage->GetObj(1));
1537 CPPUNIT_ASSERT(pTextObject);
1539 OutlinerParaObject* pOutlinerParagraphObject = pTextObject->GetOutlinerParaObject();
1540 const EditTextObject& aEdit = pOutlinerParagraphObject->GetTextObject();
1542 CPPUNIT_ASSERT_EQUAL(OUString("Somethingxx"), aEdit.GetText(0));
1544 xDocShRef->DoClose();
1547 void SdTiledRenderingTest::testTdf105502()
1549 // Load the document.
1550 SdXImpressDocument* pXImpressDocument = createDoc("tdf105502.odp");
1551 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
1552 sd::Window* pWindow = pViewShell->GetActiveWindow();
1553 CPPUNIT_ASSERT(pWindow);
1554 SdPage* pActualPage = pViewShell->GetActualPage();
1555 SdrObject* pObject = pActualPage->GetObj(0);
1556 auto pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pObject);
1557 CPPUNIT_ASSERT(pTableObject);
1559 // Select the first row.
1560 sd::View* pView = pViewShell->GetView();
1561 pView->MarkObj(pObject, pView->GetSdrPageView());
1562 pView->SdrBeginTextEdit(pObject);
1563 rtl::Reference<sdr::SelectionController> xSelectionController(pView->getSelectionController());
1564 CPPUNIT_ASSERT(xSelectionController.is());
1565 SfxRequest aRequest(pViewShell->GetViewFrame(), SID_TABLE_SELECT_ROW);
1566 xSelectionController->Execute(aRequest);
1568 // Assert that the A1:B1 selection succeeded.
1569 CPPUNIT_ASSERT(xSelectionController->hasSelectedCells());
1570 sdr::table::CellPos aFirstCell;
1571 sdr::table::CellPos aLastCell;
1572 xSelectionController->getSelectedCells(aFirstCell, aLastCell);
1573 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aFirstCell.mnCol);
1574 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aFirstCell.mnRow);
1575 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aLastCell.mnCol);
1576 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aLastCell.mnRow);
1578 // Grow font size for the selection.
1579 comphelper::dispatchCommand(".uno:Grow", {});
1580 Scheduler::ProcessEventsToIdle();
1582 // Assert that the selected A1 has now a larger font than the unselected
1583 // A2.
1584 xmlDocPtr pXmlDoc = parseXmlDump();
1585 sal_Int32 nA1Height = getXPath(pXmlDoc, "//Cell[1]/SdrText/OutlinerParaObject/EditTextObject/ContentInfo/SfxItemSet/SvxFontHeightItem[1]", "height").toInt32();
1586 sal_Int32 nA2Height = getXPath(pXmlDoc, "//Cell[3]/SdrText/OutlinerParaObject/EditTextObject/ContentInfo/attribs[1]/SvxFontHeightItem", "height").toInt32();
1587 // This failed when FuText::ChangeFontSize() never did "continue" in the
1588 // text loop, instead of doing so depending on what IsInSelection() returns.
1589 CPPUNIT_ASSERT(nA1Height > nA2Height);
1591 // Check that selection remains the same
1592 CPPUNIT_ASSERT(xSelectionController->hasSelectedCells());
1593 xSelectionController->getSelectedCells(aFirstCell, aLastCell);
1594 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aFirstCell.mnCol);
1595 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aFirstCell.mnRow);
1596 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aLastCell.mnCol);
1597 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aLastCell.mnRow);
1599 xmlFreeDoc(pXmlDoc);
1602 void SdTiledRenderingTest::testCommentCallbacks()
1604 // Load the document.
1605 // Set the tiled annotations off
1606 comphelper::LibreOfficeKit::setTiledAnnotations(false);
1608 SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp", comphelper::InitPropertySequence(
1610 {".uno:Author", uno::makeAny(OUString("LOK User1"))},
1611 }));
1612 ViewCallback aView1;
1613 int nView1 = SfxLokHelper::getView();
1615 SfxLokHelper::createView();
1616 uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
1618 {".uno:Author", uno::makeAny(OUString("LOK User2"))},
1619 }));
1620 pXImpressDocument->initializeForTiledRendering(aArgs);
1621 ViewCallback aView2;
1622 int nView2 = SfxLokHelper::getView();
1624 SfxLokHelper::setView(nView1);
1626 // Add a new comment
1627 aArgs = comphelper::InitPropertySequence(
1629 {"Text", uno::makeAny(OUString("Comment"))},
1631 comphelper::dispatchCommand(".uno:InsertAnnotation", aArgs);
1632 Scheduler::ProcessEventsToIdle();
1634 // We received a LOK_CALLBACK_COMMENT callback with comment 'Add' action
1635 CPPUNIT_ASSERT_EQUAL(std::string("Add"), aView1.m_aCommentCallbackResult.get<std::string>("action"));
1636 CPPUNIT_ASSERT_EQUAL(std::string("Add"), aView2.m_aCommentCallbackResult.get<std::string>("action"));
1637 int nComment1 = aView1.m_aCommentCallbackResult.get<int>("id");
1638 CPPUNIT_ASSERT_EQUAL(nComment1, aView2.m_aCommentCallbackResult.get<int>("id"));
1639 css::util::DateTime aDateTime;
1640 OUString aDateTimeString = OUString::createFromAscii(aView1.m_aCommentCallbackResult.get<std::string>("dateTime").c_str());
1641 CPPUNIT_ASSERT(utl::ISO8601parseDateTime(aDateTimeString, aDateTime));
1642 CPPUNIT_ASSERT_EQUAL(std::string("LOK User1"), aView1.m_aCommentCallbackResult.get<std::string>("author"));
1643 CPPUNIT_ASSERT_EQUAL(std::string("LOK User1"), aView2.m_aCommentCallbackResult.get<std::string>("author"));
1644 CPPUNIT_ASSERT_EQUAL(std::string("Comment"), aView1.m_aCommentCallbackResult.get<std::string>("text"));
1645 CPPUNIT_ASSERT_EQUAL(std::string("Comment"), aView2.m_aCommentCallbackResult.get<std::string>("text"));
1646 CPPUNIT_ASSERT(!aView1.m_aCommentCallbackResult.get<std::string>("parthash").empty());
1647 CPPUNIT_ASSERT(!aView2.m_aCommentCallbackResult.get<std::string>("parthash").empty());
1649 // Reply to a just added comment
1650 SfxLokHelper::setView(nView2);
1651 aArgs = comphelper::InitPropertySequence(
1653 {"Id", uno::makeAny(OUString::number(nComment1))},
1654 {"Text", uno::makeAny(OUString("Reply to comment"))},
1656 comphelper::dispatchCommand(".uno:ReplyToAnnotation", aArgs);
1657 Scheduler::ProcessEventsToIdle();
1659 // We received a LOK_CALLBACK_COMMENT callback with comment 'Modify' action
1660 CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView1.m_aCommentCallbackResult.get<std::string>("action"));
1661 CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView2.m_aCommentCallbackResult.get<std::string>("action"));
1662 CPPUNIT_ASSERT_EQUAL(nComment1, aView1.m_aCommentCallbackResult.get<int>("id"));
1663 CPPUNIT_ASSERT_EQUAL(nComment1, aView2.m_aCommentCallbackResult.get<int>("id"));
1664 CPPUNIT_ASSERT_EQUAL(std::string("LOK User2"), aView1.m_aCommentCallbackResult.get<std::string>("author"));
1665 CPPUNIT_ASSERT_EQUAL(std::string("LOK User2"), aView2.m_aCommentCallbackResult.get<std::string>("author"));
1666 OUString aReplyTextView1 = OUString::createFromAscii(aView1.m_aCommentCallbackResult.get<std::string>("text").c_str());
1667 OUString aReplyTextView2 = OUString::createFromAscii(aView2.m_aCommentCallbackResult.get<std::string>("text").c_str());
1668 CPPUNIT_ASSERT(aReplyTextView1.startsWith("Reply to LOK User1"));
1669 CPPUNIT_ASSERT(aReplyTextView1.endsWith("Reply to comment"));
1670 CPPUNIT_ASSERT(aReplyTextView2.startsWith("Reply to LOK User1"));
1671 CPPUNIT_ASSERT(aReplyTextView2.endsWith("Reply to comment"));
1672 CPPUNIT_ASSERT(!aView1.m_aCommentCallbackResult.get<std::string>("parthash").empty());
1673 CPPUNIT_ASSERT(!aView2.m_aCommentCallbackResult.get<std::string>("parthash").empty());
1675 // Edit this annotation now
1676 aArgs = comphelper::InitPropertySequence(
1678 {"Id", uno::makeAny(OUString::number(nComment1))},
1679 {"Text", uno::makeAny(OUString("Edited comment"))},
1681 comphelper::dispatchCommand(".uno:EditAnnotation", aArgs);
1682 Scheduler::ProcessEventsToIdle();
1684 // We received a LOK_CALLBACK_COMMENT callback with comment 'Modify' action
1685 CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView1.m_aCommentCallbackResult.get<std::string>("action"));
1686 CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView2.m_aCommentCallbackResult.get<std::string>("action"));
1687 CPPUNIT_ASSERT_EQUAL(nComment1, aView1.m_aCommentCallbackResult.get<int>("id"));
1688 CPPUNIT_ASSERT_EQUAL(nComment1, aView2.m_aCommentCallbackResult.get<int>("id"));
1689 CPPUNIT_ASSERT(!aView1.m_aCommentCallbackResult.get<std::string>("parthash").empty());
1690 CPPUNIT_ASSERT(!aView2.m_aCommentCallbackResult.get<std::string>("parthash").empty());
1691 CPPUNIT_ASSERT_EQUAL(std::string("Edited comment"), aView1.m_aCommentCallbackResult.get<std::string>("text"));
1692 CPPUNIT_ASSERT_EQUAL(std::string("Edited comment"), aView2.m_aCommentCallbackResult.get<std::string>("text"));
1694 // Delete the comment
1695 aArgs = comphelper::InitPropertySequence(
1697 {"Id", uno::makeAny(OUString::number(nComment1))},
1699 comphelper::dispatchCommand(".uno:DeleteAnnotation", aArgs);
1700 Scheduler::ProcessEventsToIdle();
1702 // We received a LOK_CALLBACK_COMMENT callback with comment 'Remove' action
1703 CPPUNIT_ASSERT_EQUAL(std::string("Remove"), aView1.m_aCommentCallbackResult.get<std::string>("action"));
1704 CPPUNIT_ASSERT_EQUAL(std::string("Remove"), aView2.m_aCommentCallbackResult.get<std::string>("action"));
1705 CPPUNIT_ASSERT_EQUAL(nComment1, aView1.m_aCommentCallbackResult.get<int>("id"));
1706 CPPUNIT_ASSERT_EQUAL(nComment1, aView2.m_aCommentCallbackResult.get<int>("id"));
1708 comphelper::LibreOfficeKit::setTiledAnnotations(true);
1711 void SdTiledRenderingTest::testMultiViewInsertDeletePage()
1713 // Load the document.
1714 SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
1715 ViewCallback aView1;
1716 int nView1 = SfxLokHelper::getView();
1717 uno::Sequence<beans::PropertyValue> aArgs;
1718 SdDrawDocument* pDoc = pXImpressDocument->GetDocShell()->GetDoc();
1720 // Create second view
1721 SfxLokHelper::createView();
1722 pXImpressDocument->initializeForTiledRendering(aArgs);
1723 ViewCallback aView2;
1724 int nView2 = SfxLokHelper::getView();
1726 // the document has 8 slides
1727 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(8), pDoc->GetSdPageCount(PageKind::Standard));
1729 // Switch to 5th page in 2nd view
1730 pXImpressDocument->setPart(4);
1732 // Insert slide in 1st view
1733 SfxLokHelper::setView(nView1);
1734 comphelper::dispatchCommand(".uno:InsertPage", aArgs);
1735 Scheduler::ProcessEventsToIdle();
1737 // See if the current slide number changed in 2nd view too
1738 SfxLokHelper::setView(nView2);
1739 CPPUNIT_ASSERT_EQUAL(5, pXImpressDocument->getPart());
1741 // Delete the page in 1st view now
1742 SfxLokHelper::setView(nView1);
1743 comphelper::dispatchCommand(".uno:DeletePage", aArgs);
1744 Scheduler::ProcessEventsToIdle();
1746 // See if current slide number changed in 2nd view too
1747 SfxLokHelper::setView(nView2);
1748 CPPUNIT_ASSERT_EQUAL(4, pXImpressDocument->getPart());
1751 void SdTiledRenderingTest::testDisableUndoRepair()
1753 // Load the document.
1754 SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
1755 SfxViewShell* pView1 = SfxViewShell::Current();
1756 int nView1 = SfxLokHelper::getView();
1757 SfxLokHelper::createView();
1758 SfxViewShell* pView2 = SfxViewShell::Current();
1759 int nView2 = SfxLokHelper::getView();
1761 std::unique_ptr<SfxPoolItem> pItem1;
1762 std::unique_ptr<SfxPoolItem> pItem2;
1763 CPPUNIT_ASSERT_EQUAL(SfxItemState::DISABLED, pView1->GetViewFrame()->GetBindings().QueryState(SID_UNDO, pItem1));
1764 CPPUNIT_ASSERT_EQUAL(SfxItemState::DISABLED, pView2->GetViewFrame()->GetBindings().QueryState(SID_UNDO, pItem2));
1767 // Insert a character in the first view.
1768 SfxLokHelper::setView(nView1);
1769 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
1770 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
1771 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'h', 0);
1772 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'h', 0);
1773 Scheduler::ProcessEventsToIdle();
1775 std::unique_ptr<SfxPoolItem> xItem1;
1776 std::unique_ptr<SfxPoolItem> xItem2;
1777 pView1->GetViewFrame()->GetBindings().QueryState(SID_UNDO, xItem1);
1778 pView2->GetViewFrame()->GetBindings().QueryState(SID_UNDO, xItem2);
1779 CPPUNIT_ASSERT(!dynamic_cast< const SfxUInt32Item* >(xItem1.get()));
1780 const SfxUInt32Item* pUInt32Item = dynamic_cast<const SfxUInt32Item*>(xItem2.get());
1781 CPPUNIT_ASSERT(pUInt32Item);
1782 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(SID_REPAIRPACKAGE), pUInt32Item->GetValue());
1785 // Insert a character in the second view.
1786 SfxLokHelper::setView(nView2);
1787 pXImpressDocument->setPart(1);
1788 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
1789 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
1790 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'c', 0);
1791 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'c', 0);
1792 Scheduler::ProcessEventsToIdle();
1794 std::unique_ptr<SfxPoolItem> xItem1;
1795 std::unique_ptr<SfxPoolItem> xItem2;
1796 pView1->GetViewFrame()->GetBindings().QueryState(SID_UNDO, xItem1);
1797 pView2->GetViewFrame()->GetBindings().QueryState(SID_UNDO, xItem2);
1798 CPPUNIT_ASSERT(!dynamic_cast< const SfxUInt32Item* >(xItem2.get()));
1799 const SfxUInt32Item* pUInt32Item = dynamic_cast<const SfxUInt32Item*>(xItem1.get());
1800 CPPUNIT_ASSERT(pUInt32Item);
1801 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(SID_REPAIRPACKAGE), pUInt32Item->GetValue());
1805 void SdTiledRenderingTest::testDocumentRepair()
1807 // Create two views.
1808 SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
1809 CPPUNIT_ASSERT(pXImpressDocument);
1811 // view #1
1812 SfxViewShell* pView1 = SfxViewShell::Current();
1814 // view #2
1815 SfxLokHelper::createView();
1816 SfxViewShell* pView2 = SfxViewShell::Current();
1817 int nView2 = SfxLokHelper::getView();
1818 CPPUNIT_ASSERT(pView1 != pView2);
1820 std::unique_ptr<SfxPoolItem> xItem1;
1821 std::unique_ptr<SfxPoolItem> xItem2;
1822 pView1->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, xItem1);
1823 pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, xItem2);
1824 const SfxBoolItem* pItem1 = dynamic_cast<const SfxBoolItem*>(xItem1.get());
1825 const SfxBoolItem* pItem2 = dynamic_cast<const SfxBoolItem*>(xItem2.get());
1826 CPPUNIT_ASSERT(pItem1);
1827 CPPUNIT_ASSERT(pItem2);
1828 CPPUNIT_ASSERT_EQUAL(false, pItem1->GetValue());
1829 CPPUNIT_ASSERT_EQUAL(false, pItem2->GetValue());
1832 // Insert a character in the second view.
1833 SfxLokHelper::setView(nView2);
1834 pXImpressDocument->setPart(1);
1835 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
1836 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
1837 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'c', 0);
1838 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'c', 0);
1839 Scheduler::ProcessEventsToIdle();
1841 std::unique_ptr<SfxPoolItem> xItem1;
1842 std::unique_ptr<SfxPoolItem> xItem2;
1843 pView1->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, xItem1);
1844 pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, xItem2);
1845 const SfxBoolItem* pItem1 = dynamic_cast<const SfxBoolItem*>(xItem1.get());
1846 const SfxBoolItem* pItem2 = dynamic_cast<const SfxBoolItem*>(xItem2.get());
1847 CPPUNIT_ASSERT(pItem1);
1848 CPPUNIT_ASSERT(pItem2);
1849 CPPUNIT_ASSERT_EQUAL(true, pItem1->GetValue());
1850 CPPUNIT_ASSERT_EQUAL(true, pItem2->GetValue());
1854 void SdTiledRenderingTest::testLanguageStatus()
1856 // Load the document.
1857 createDoc("dummy.odp");
1858 SfxViewShell* pView1 = SfxViewShell::Current();
1859 SfxLokHelper::createView();
1860 SfxViewShell* pView2 = SfxViewShell::Current();
1862 std::unique_ptr<SfxPoolItem> xItem1;
1863 std::unique_ptr<SfxPoolItem> xItem2;
1864 pView1->GetViewFrame()->GetBindings().QueryState(SID_LANGUAGE_STATUS, xItem1);
1865 pView2->GetViewFrame()->GetBindings().QueryState(SID_LANGUAGE_STATUS, xItem2);
1866 auto pStringItem = dynamic_cast<const SfxStringItem*>(xItem1.get());
1867 CPPUNIT_ASSERT(pStringItem);
1869 CPPUNIT_ASSERT_EQUAL(OUString("English (USA);en-US"), pStringItem->GetValue());
1871 CPPUNIT_ASSERT(dynamic_cast< const SfxStringItem* >(xItem2.get()));
1875 void SdTiledRenderingTest::testLanguageAllText()
1877 // Load the document, which has a single shape, with Hungarian text.
1878 createDoc("language-all-text.odp");
1880 // Set the language to English for all text.
1881 uno::Sequence<beans::PropertyValue> aArgs = comphelper::InitPropertySequence({
1882 { "Language", uno::makeAny(OUString("Default_English (USA)")) },
1884 comphelper::dispatchCommand(".uno:LanguageStatus", aArgs);
1885 Scheduler::ProcessEventsToIdle();
1887 // Assert that the shape text language was changed.
1888 uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, uno::UNO_QUERY);
1889 uno::Reference<drawing::XDrawPage> xPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0),
1890 uno::UNO_QUERY);
1891 uno::Reference<beans::XPropertySet> xShape(xPage->getByIndex(0), uno::UNO_QUERY);
1892 uno::Reference<beans::XPropertySet> xRun(
1893 getRunFromParagraph(0, getParagraphFromShape(0, xShape)), uno::UNO_QUERY);
1894 lang::Locale aLocale;
1895 xRun->getPropertyValue("CharLocale") >>= aLocale;
1896 // Without the accompanying fix in place, this test would have failed with 'Expected: en;
1897 // Actual: hu', as the shape text language was not set.
1898 CPPUNIT_ASSERT_EQUAL(OUString("en"), aLocale.Language);
1901 void SdTiledRenderingTest::testDefaultView()
1903 // Load the document with notes view.
1904 SdXImpressDocument* pXImpressDocument = createDoc("notes-view.odp");
1905 sd::ViewShell* pView = pXImpressDocument->GetDocShell()->GetViewShell();
1907 std::unique_ptr<SfxPoolItem> xItem1;
1908 std::unique_ptr<SfxPoolItem> xItem2;
1909 pView->GetViewFrame()->GetBindings().QueryState(SID_NORMAL_MULTI_PANE_GUI, xItem1);
1910 pView->GetViewFrame()->GetBindings().QueryState(SID_NOTES_MODE, xItem2);
1911 const SfxBoolItem* pImpressView = dynamic_cast< const SfxBoolItem* >(xItem1.get());
1912 const SfxBoolItem* pNotesView = dynamic_cast< const SfxBoolItem* >(xItem2.get());
1913 CPPUNIT_ASSERT(pImpressView);
1914 CPPUNIT_ASSERT(pNotesView);
1915 CPPUNIT_ASSERT_EQUAL(true, pImpressView->GetValue());
1916 CPPUNIT_ASSERT_EQUAL(false, pNotesView->GetValue());
1920 void SdTiledRenderingTest::testIMESupport()
1922 // Load the document with notes view.
1923 SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
1924 VclPtr<vcl::Window> pDocWindow = pXImpressDocument->getDocWindow();
1925 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
1926 SdrObject* pObject = pViewShell->GetActualPage()->GetObj(0);
1927 SdrTextObj* pTextObj = static_cast<SdrTextObj*>(pObject);
1928 SdrView* pView = pViewShell->GetView();
1929 pView->MarkObj(pTextObj, pView->GetSdrPageView());
1930 SfxStringItem aInputString(SID_ATTR_CHAR, "x");
1931 pViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR,
1932 SfxCallMode::SYNCHRON, { &aInputString });
1934 // sequence of chinese IME compositions when 'nihao' is typed in an IME
1935 const std::vector<OString> aUtf8Inputs{ "年", "你", "你好", "你哈", "你好", "你好" };
1936 std::vector<OUString> aInputs;
1937 std::transform(aUtf8Inputs.begin(), aUtf8Inputs.end(),
1938 std::back_inserter(aInputs), [](OString aInput) {
1939 return OUString::fromUtf8(aInput);
1941 for (const auto& aInput: aInputs)
1943 pDocWindow->PostExtTextInputEvent(VclEventId::ExtTextInput, aInput);
1945 pDocWindow->PostExtTextInputEvent(VclEventId::EndExtTextInput, "");
1947 // the cursor should be at position 3rd
1948 EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
1949 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), rEditView.GetSelection().nStartPos);
1951 ESelection aWordSelection(0, 0, 0, 3); // start para, start char, end para, end char.
1952 rEditView.SetSelection(aWordSelection);
1953 // content contains only the last IME composition, not all
1954 CPPUNIT_ASSERT_EQUAL(OUString("x").concat(aInputs[aInputs.size() - 1]), rEditView.GetSelected());
1957 void SdTiledRenderingTest::testTdf115783()
1959 // Load the document.
1960 SdXImpressDocument* pXImpressDocument = createDoc("tdf115783.fodp");
1961 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
1962 SdPage* pActualPage = pViewShell->GetActualPage();
1963 SdrObject* pObject = pActualPage->GetObj(0);
1964 auto pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pObject);
1965 CPPUNIT_ASSERT(pTableObject);
1966 SdrView* pView = pViewShell->GetView();
1967 pView->MarkObj(pTableObject, pView->GetSdrPageView());
1969 // Create a cell selection and set font height.
1970 // Go to the end of the B1 cell.
1971 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT);
1972 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT);
1973 // Create a B1->C1 cell selection.
1974 const int nShiftRight = KEY_SHIFT + KEY_RIGHT;
1975 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, nShiftRight);
1976 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, nShiftRight);
1977 uno::Sequence<beans::PropertyValue> aArgs = comphelper::InitPropertySequence({
1978 { "FontHeight.Height", uno::makeAny(static_cast<float>(12)) },
1980 comphelper::dispatchCommand(".uno:FontHeight", aArgs);
1981 Scheduler::ProcessEventsToIdle();
1983 // Create a text selection on the B1 cell.
1984 pTableObject->setActiveCell(sdr::table::CellPos(1, 0));
1985 pView->SdrBeginTextEdit(pTableObject);
1986 EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
1987 // Start para, start char, end para, end char.
1988 rEditView.SetSelection(ESelection(0, 0, 0, 5));
1989 CPPUNIT_ASSERT_EQUAL(OUString("hello"), rEditView.GetSelected());
1991 // Copy selection, paste at the start of the cell.
1992 aArgs = {};
1993 comphelper::dispatchCommand(".uno:Copy", aArgs);
1994 Scheduler::ProcessEventsToIdle();
1995 rEditView.SetSelection(ESelection(0, 0, 0, 0));
1996 aArgs = {};
1997 comphelper::dispatchCommand(".uno:Paste", aArgs);
1998 Scheduler::ProcessEventsToIdle();
1999 pView->SdrEndTextEdit();
2001 // And now verify that the cell has the correct font size.
2002 uno::Reference<table::XCellRange> xTable = pTableObject->getTable();
2003 CPPUNIT_ASSERT(xTable.is());
2004 uno::Reference<text::XTextRange> xCell(xTable->getCellByPosition(1, 0), uno::UNO_QUERY);
2005 CPPUNIT_ASSERT(xCell.is());
2006 uno::Reference<container::XEnumerationAccess> xText(xCell->getText(), uno::UNO_QUERY);
2007 CPPUNIT_ASSERT(xText.is());
2008 uno::Reference<container::XEnumerationAccess> xParagraph(
2009 xText->createEnumeration()->nextElement(), uno::UNO_QUERY);
2010 CPPUNIT_ASSERT(xParagraph.is());
2011 uno::Reference<text::XTextRange> xPortion(xParagraph->createEnumeration()->nextElement(),
2012 uno::UNO_QUERY);
2013 CPPUNIT_ASSERT(xPortion.is());
2014 // This failed, it was only "hello" as the paragraph had 2 portions: a
2015 // "hello" with 12pt size and a "hello" with 18pt.
2016 CPPUNIT_ASSERT_EQUAL(OUString("hellohello"), xPortion->getString());
2017 uno::Reference<beans::XPropertySet> xPropertySet(xPortion, uno::UNO_QUERY);
2018 int nHeight = xPropertySet->getPropertyValue("CharHeight").get<float>();
2019 // Make sure that the single font size for the cell is the expected one.
2020 CPPUNIT_ASSERT_EQUAL(12, nHeight);
2023 void SdTiledRenderingTest::testPasteTextOnSlide()
2025 // Load the document.
2026 SdXImpressDocument* pXImpressDocument = createDoc("paste_text_onslide.odp");
2027 CPPUNIT_ASSERT(pXImpressDocument);
2029 // select second text object
2030 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
2031 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
2032 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
2033 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
2034 Scheduler::ProcessEventsToIdle();
2036 // step into text editing
2037 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, '1', 0);
2038 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, '1', 0);
2039 Scheduler::ProcessEventsToIdle();
2041 // select full text
2042 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT | KEY_SHIFT);
2043 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT | KEY_SHIFT);
2044 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT | KEY_SHIFT);
2045 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT | KEY_SHIFT);
2046 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT | KEY_SHIFT);
2047 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT | KEY_SHIFT);
2048 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT | KEY_SHIFT);
2049 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT | KEY_SHIFT);
2050 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT | KEY_SHIFT);
2051 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT | KEY_SHIFT);
2052 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT | KEY_SHIFT);
2053 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT | KEY_SHIFT);
2054 Scheduler::ProcessEventsToIdle();
2056 // Copy some text
2057 comphelper::dispatchCommand(".uno:Copy", uno::Sequence<beans::PropertyValue>());
2058 Scheduler::ProcessEventsToIdle();
2060 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE);
2061 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
2062 Scheduler::ProcessEventsToIdle();
2064 // Paste onto the slide
2065 comphelper::dispatchCommand(".uno:Paste", uno::Sequence<beans::PropertyValue>());
2066 Scheduler::ProcessEventsToIdle();
2068 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE);
2069 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
2070 Scheduler::ProcessEventsToIdle();
2072 // Check the position of the newly added text shape, created for pasted text
2073 SdPage* pActualPage = pXImpressDocument->GetDocShell()->GetViewShell()->GetActualPage();
2074 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pActualPage->GetObjCount());
2075 SdrObject* pObject = pActualPage->GetObj(2);
2076 CPPUNIT_ASSERT(pObject);
2077 SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>(pObject);
2078 CPPUNIT_ASSERT(pTextObj);
2079 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(OBJ_TEXT), pTextObj->GetObjIdentifier());
2080 // This test is unreliable: it gives alternating results for the following coordinates.
2081 // As a compromise, instead of disabling it altogether, we allow for both sets of values.
2082 const Point aPos = pTextObj->GetLastBoundRect().TopLeft();
2083 if (aPos.getX() < 10000)
2085 // We get this with 'make CppunitTest_sd_tiledrendering'
2086 CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<long>(6739), aPos.getX(), 100);
2087 CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<long>(6822), aPos.getY(), 100);
2089 else
2091 // We get this with 'make check'
2092 CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<long>(12990), aPos.getX(), 100);
2093 CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<long>(7393), aPos.getY(), 100);
2097 void SdTiledRenderingTest::testTdf115873()
2099 // Initialize the navigator.
2100 SdXImpressDocument* pXImpressDocument = createDoc("tdf115873.fodp");
2101 SfxViewShell* pViewShell = SfxViewShell::Current();
2102 CPPUNIT_ASSERT(pViewShell);
2103 SfxBindings& rBindings = pViewShell->GetViewFrame()->GetBindings();
2104 ScopedVclPtrInstance<SdNavigatorWin> pNavigator(nullptr, &rBindings);
2105 pNavigator->InitTreeLB(pXImpressDocument->GetDoc());
2106 pNavigator->Show();
2107 VclPtr<SdPageObjsTLB> pObjects = pNavigator->GetObjects();
2108 pObjects->Select(pObjects->GetEntry(0));
2109 sd::ViewShell* pSdViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
2110 SdrView* pSdrView = pSdViewShell->GetView();
2111 pSdrView->UnmarkAllObj(pSdrView->GetSdrPageView());
2113 // Make sure that no shapes are selected.
2114 const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
2115 Scheduler::ProcessEventsToIdle();
2116 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), rMarkList.GetMarkCount());
2118 // Single-click with the mouse.
2119 short nHeight = pObjects->GetEntryHeight();
2120 // Position of the center of the 2nd entry (first is the slide, second is
2121 // the shape).
2122 Point aPoint(pObjects->GetOutputWidthPixel() / 2, nHeight * 1.5);
2123 MouseEvent aMouseEvent(aPoint, /*nClicks=*/1, MouseEventModifiers::NONE, MOUSE_LEFT);
2124 pObjects->MouseButtonDown(aMouseEvent);
2125 pObjects->MouseButtonUp(aMouseEvent);
2126 Scheduler::ProcessEventsToIdle();
2127 // This failed, single-click did not result in a shape selection (only
2128 // double-click did).
2129 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rMarkList.GetMarkCount());
2132 void SdTiledRenderingTest::testTdf115873Group()
2134 // Initialize the navigator.
2135 SdXImpressDocument* pXImpressDocument = createDoc("tdf115873-group.fodp");
2136 SfxViewShell* pViewShell = SfxViewShell::Current();
2137 CPPUNIT_ASSERT(pViewShell);
2138 SfxBindings& rBindings = pViewShell->GetViewFrame()->GetBindings();
2139 ScopedVclPtrInstance<SdNavigatorWin> pNavigator(nullptr, &rBindings);
2140 pNavigator->InitTreeLB(pXImpressDocument->GetDoc());
2141 VclPtr<SdPageObjsTLB> pObjects = pNavigator->GetObjects();
2142 // This failed, Fill() and IsEqualToDoc() were out of sync for group
2143 // shapes.
2144 CPPUNIT_ASSERT(pObjects->IsEqualToDoc(pXImpressDocument->GetDoc()));
2147 void SdTiledRenderingTest::testCutSelectionChange()
2149 // Load the document.
2150 SdXImpressDocument* pXImpressDocument = createDoc("cut_selection_change.odp");
2151 CPPUNIT_ASSERT(pXImpressDocument);
2153 sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
2154 pViewShell->GetViewShellBase().registerLibreOfficeKitViewCallback(&SdTiledRenderingTest::callback, this);
2155 Scheduler::ProcessEventsToIdle();
2157 // Select first text object
2158 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
2159 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
2160 Scheduler::ProcessEventsToIdle();
2162 // step into text editing
2163 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, '1', 0);
2164 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, '1', 0);
2165 Scheduler::ProcessEventsToIdle();
2167 // select some text
2168 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT | KEY_SHIFT);
2169 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT | KEY_SHIFT);
2170 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT | KEY_SHIFT);
2171 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT | KEY_SHIFT);
2172 Scheduler::ProcessEventsToIdle();
2174 // Check that we have a selection before cutting
2175 CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), m_aSelection.size());
2177 // Cut the selected text
2178 comphelper::dispatchCommand(".uno:Cut", uno::Sequence<beans::PropertyValue>());
2179 Scheduler::ProcessEventsToIdle();
2181 // Selection is removed
2182 CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(0), m_aSelection.size());
2185 void SdTiledRenderingTest::testRegenerateDiagram()
2187 // Load the document.
2188 SdXImpressDocument* pXImpressDocument = createDoc("regenerate-diagram.pptx");
2189 CPPUNIT_ASSERT(pXImpressDocument);
2191 SdPage* pActualPage = pXImpressDocument->GetDocShell()->GetViewShell()->GetActualPage();
2192 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), pActualPage->GetObj(0)->GetSubList()->GetObjCount());
2194 // select diagram
2195 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
2196 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
2197 Scheduler::ProcessEventsToIdle();
2199 // enter group
2200 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::F3);
2201 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::F3);
2202 Scheduler::ProcessEventsToIdle();
2204 // select shape and delete
2205 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
2206 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
2207 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
2208 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
2209 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::DELETE);
2210 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::DELETE);
2211 Scheduler::ProcessEventsToIdle();
2213 // exit group
2214 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
2215 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
2216 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_MOD1 | awt::Key::F3);
2217 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_MOD1 | awt::Key::F3);
2218 Scheduler::ProcessEventsToIdle();
2220 // select diagram
2221 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
2222 pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
2223 Scheduler::ProcessEventsToIdle();
2225 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pActualPage->GetObj(0)->GetSubList()->GetObjCount());
2227 // regenerate diagram
2228 comphelper::dispatchCommand(".uno:RegenerateDiagram", uno::Sequence<beans::PropertyValue>());
2229 Scheduler::ProcessEventsToIdle();
2231 // diagram content (child shape count) should be the same as in the beginning
2232 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), pActualPage->GetObj(0)->GetSubList()->GetObjCount());
2235 void SdTiledRenderingTest::testInsertDeletePageInvalidation()
2237 // Load the document.
2238 SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
2239 ViewCallback aView1;
2240 CPPUNIT_ASSERT_EQUAL(8, pXImpressDocument->getParts());
2242 // Insert slide
2243 aView1.m_bTilesInvalidated = false;
2244 aView1.m_aInvalidations.clear();
2245 comphelper::dispatchCommand(".uno:InsertPage", uno::Sequence<beans::PropertyValue>());
2246 Scheduler::ProcessEventsToIdle();
2247 CPPUNIT_ASSERT(aView1.m_bTilesInvalidated);
2248 CPPUNIT_ASSERT_EQUAL(9, pXImpressDocument->getParts());
2249 CPPUNIT_ASSERT_EQUAL(size_t(9), aView1.m_aInvalidations.size());
2251 // Delete slide
2252 aView1.m_bTilesInvalidated = false;
2253 aView1.m_aInvalidations.clear();
2254 comphelper::dispatchCommand(".uno:DeletePage", uno::Sequence<beans::PropertyValue>());
2255 Scheduler::ProcessEventsToIdle();
2256 CPPUNIT_ASSERT(aView1.m_bTilesInvalidated);
2257 CPPUNIT_ASSERT_EQUAL(8, pXImpressDocument->getParts());
2258 CPPUNIT_ASSERT_EQUAL(size_t(8), aView1.m_aInvalidations.size());
2261 CPPUNIT_TEST_SUITE_REGISTRATION(SdTiledRenderingTest);
2263 CPPUNIT_PLUGIN_IMPLEMENT();
2265 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */