1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <test/bootstrapfixture.hxx>
11 #include <test/helper/transferable.hxx>
12 #include <unotest/macros_test.hxx>
13 #include <test/xmltesttools.hxx>
14 #include <boost/property_tree/json_parser.hpp>
16 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
17 #include <com/sun/star/frame/Desktop.hpp>
18 #include <com/sun/star/frame/DispatchHelper.hpp>
19 #include <com/sun/star/datatransfer/clipboard/SystemClipboard.hpp>
20 #include <com/sun/star/datatransfer/UnsupportedFlavorException.hpp>
21 #include <comphelper/dispatchcommand.hxx>
22 #include <comphelper/processfactory.hxx>
23 #include <comphelper/propertysequence.hxx>
24 #include <osl/conditn.hxx>
25 #include <sfx2/dispatch.hxx>
26 #include <sfx2/viewfrm.hxx>
27 #include <svl/stritem.hxx>
29 #include <comphelper/lok.hxx>
30 #include <comphelper/propertyvalue.hxx>
31 #include <sfx2/childwin.hxx>
32 #include <sfx2/lokhelper.hxx>
33 #include <svx/svdpage.hxx>
34 #include <vcl/svapp.hxx>
35 #include <vcl/scheduler.hxx>
36 #include <vcl/vclevent.hxx>
37 #include <vcl/virdev.hxx>
38 #include <vcl/unohelp2.hxx>
40 #include <comphelper/string.hxx>
41 #include <tools/json_writer.hxx>
42 #include <docoptio.hxx>
47 #include <tabvwsh.hxx>
49 #include <document.hxx>
51 #include <drwlayer.hxx>
55 static std::ostream
& operator<<(std::ostream
& os
, ViewShellId
const & id
)
57 os
<< static_cast<sal_Int32
>(id
); return os
;
63 char const DATA_DIRECTORY
[] = "/sc/qa/unit/tiledrendering/data/";
65 class ScTiledRenderingTest
: public test::BootstrapFixture
, public unotest::MacrosTest
, public XmlTestTools
68 ScTiledRenderingTest();
69 virtual void setUp() override
;
70 virtual void tearDown() override
;
72 void testRowColumnHeaders();
73 void testRowColumnSelections();
74 void testSortAscendingDescending();
76 void testDocumentSize();
77 void testEmptyColumnSelection();
78 void testViewCursors();
79 void testTextViewSelection();
80 void testDocumentSizeChanged();
82 void testColRowResize();
83 void testUndoShells();
84 void testCreateViewGraphicSelection();
85 void testTextEditViews();
86 void testTextEditViewInvalidations();
87 void testGraphicInvalidate();
89 void testHideColRow();
90 void testInvalidateOnCopyPasteCells();
91 void testInvalidateOnInserRowCol();
92 void testCommentCallback();
93 void testUndoLimiting();
94 void testUndoRepairDispatch();
95 void testInsertGraphicInvalidations();
96 void testDocumentSizeWithTwoViews();
97 void testDisableUndoRepair();
98 void testDocumentRepair();
99 void testLanguageStatus();
100 void testMultiViewCopyPaste();
101 void testIMESupport();
102 void testFilterDlg();
103 void testVbaRangeCopyPaste();
104 void testInvalidationLoop();
105 void testPageDownInvalidation();
106 void testSheetChangeInvalidation();
107 void testInsertDeletePageInvalidation();
108 void testGetRowColumnHeadersInvalidation();
109 void testJumpHorizontallyInvalidation();
110 void testJumpToLastRowInvalidation();
111 void testSheetGeometryDataInvariance();
112 void testSheetGeometryDataCorrectness();
113 void testDeleteCellMultilineContent();
114 void testSpellOnlineParameter();
116 CPPUNIT_TEST_SUITE(ScTiledRenderingTest
);
117 CPPUNIT_TEST(testRowColumnHeaders
);
118 CPPUNIT_TEST(testRowColumnSelections
);
119 CPPUNIT_TEST(testSortAscendingDescending
);
120 CPPUNIT_TEST(testPartHash
);
121 CPPUNIT_TEST(testDocumentSize
);
122 CPPUNIT_TEST(testEmptyColumnSelection
);
123 CPPUNIT_TEST(testViewCursors
);
124 CPPUNIT_TEST(testTextViewSelection
);
125 CPPUNIT_TEST(testDocumentSizeChanged
);
126 CPPUNIT_TEST(testViewLock
);
127 CPPUNIT_TEST(testColRowResize
);
128 CPPUNIT_TEST(testUndoShells
);
129 CPPUNIT_TEST(testCreateViewGraphicSelection
);
130 CPPUNIT_TEST(testTextEditViews
);
131 CPPUNIT_TEST(testTextEditViewInvalidations
);
132 CPPUNIT_TEST(testGraphicInvalidate
);
133 CPPUNIT_TEST(testAutoSum
);
134 CPPUNIT_TEST(testHideColRow
);
135 CPPUNIT_TEST(testInvalidateOnCopyPasteCells
);
136 CPPUNIT_TEST(testInvalidateOnInserRowCol
);
137 CPPUNIT_TEST(testCommentCallback
);
138 CPPUNIT_TEST(testUndoLimiting
);
139 CPPUNIT_TEST(testUndoRepairDispatch
);
140 CPPUNIT_TEST(testInsertGraphicInvalidations
);
141 CPPUNIT_TEST(testDocumentSizeWithTwoViews
);
142 CPPUNIT_TEST(testDisableUndoRepair
);
143 CPPUNIT_TEST(testDocumentRepair
);
144 CPPUNIT_TEST(testLanguageStatus
);
145 CPPUNIT_TEST(testMultiViewCopyPaste
);
146 CPPUNIT_TEST(testIMESupport
);
147 CPPUNIT_TEST(testFilterDlg
);
148 CPPUNIT_TEST(testVbaRangeCopyPaste
);
149 CPPUNIT_TEST(testInvalidationLoop
);
150 CPPUNIT_TEST(testPageDownInvalidation
);
151 CPPUNIT_TEST(testSheetChangeInvalidation
);
152 CPPUNIT_TEST(testInsertDeletePageInvalidation
);
153 CPPUNIT_TEST(testGetRowColumnHeadersInvalidation
);
154 CPPUNIT_TEST(testJumpHorizontallyInvalidation
);
155 CPPUNIT_TEST(testJumpToLastRowInvalidation
);
156 CPPUNIT_TEST(testSheetGeometryDataInvariance
);
157 CPPUNIT_TEST(testSheetGeometryDataCorrectness
);
158 CPPUNIT_TEST(testDeleteCellMultilineContent
);
159 CPPUNIT_TEST(testSpellOnlineParameter
);
160 CPPUNIT_TEST_SUITE_END();
163 ScModelObj
* createDoc(const char* pName
);
164 static void callback(int nType
, const char* pPayload
, void* pData
);
165 void callbackImpl(int nType
, const char* pPayload
);
167 /// document size changed callback.
168 osl::Condition m_aDocSizeCondition
;
169 Size m_aDocumentSize
;
171 uno::Reference
<lang::XComponent
> mxComponent
;
174 ScTiledRenderingTest::ScTiledRenderingTest()
178 void ScTiledRenderingTest::setUp()
180 test::BootstrapFixture::setUp();
182 mxDesktop
.set(css::frame::Desktop::create(comphelper::getComponentContext(getMultiServiceFactory())));
185 void ScTiledRenderingTest::tearDown()
187 if (mxComponent
.is())
189 ScModelObj
* pModelObj
= static_cast<ScModelObj
*>(mxComponent
.get());
190 ScDocShell
* pDocSh
= dynamic_cast< ScDocShell
* >( pModelObj
->GetEmbeddedObject() );
193 ScTabViewShell
* pViewShell
= pDocSh
->GetBestViewShell(false);
196 // The current view is unregistered here, multiple views have to be unregistered
197 // in the test function itself.
198 pViewShell
->registerLibreOfficeKitViewCallback(nullptr, nullptr);
201 mxComponent
->dispose();
203 comphelper::LibreOfficeKit::setActive(false);
205 test::BootstrapFixture::tearDown();
208 ScModelObj
* ScTiledRenderingTest::createDoc(const char* pName
)
210 if (mxComponent
.is())
211 mxComponent
->dispose();
212 mxComponent
= loadFromDesktop(m_directories
.getURLFromSrc(DATA_DIRECTORY
) + OUString::createFromAscii(pName
), "com.sun.star.sheet.SpreadsheetDocument");
213 ScModelObj
* pModelObj
= dynamic_cast<ScModelObj
*>(mxComponent
.get());
214 CPPUNIT_ASSERT(pModelObj
);
215 pModelObj
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
219 void ScTiledRenderingTest::callback(int nType
, const char* pPayload
, void* pData
)
221 static_cast<ScTiledRenderingTest
*>(pData
)->callbackImpl(nType
, pPayload
);
224 /* TODO when needed...
225 static std::vector<OUString> lcl_convertSeparated(const OUString& rString, sal_Unicode nSeparator)
227 std::vector<OUString> aRet;
229 sal_Int32 nIndex = 0;
232 OUString aToken = rString.getToken(0, nSeparator, nIndex);
233 aToken = aToken.trim();
234 if (!aToken.isEmpty())
235 aRet.push_back(aToken);
242 static void lcl_convertRectangle(const OUString& rString, Rectangle& rRectangle)
244 uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated(rString);
245 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4), aSeq.getLength());
246 rRectangle.setX(aSeq[0].toInt32());
247 rRectangle.setY(aSeq[1].toInt32());
248 rRectangle.setWidth(aSeq[2].toInt32());
249 rRectangle.setHeight(aSeq[3].toInt32());
253 void ScTiledRenderingTest::callbackImpl(int nType
, const char* pPayload
)
257 case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED
:
259 OString
aPayload(pPayload
);
260 sal_Int32 nIndex
= 0;
261 OString aToken
= aPayload
.getToken(0, ',', nIndex
);
262 m_aDocumentSize
.setWidth(aToken
.toInt32());
263 aToken
= aPayload
.getToken(0, ',', nIndex
);
264 m_aDocumentSize
.setHeight(aToken
.toInt32());
265 m_aDocSizeCondition
.set();
271 void ScTiledRenderingTest::testRowColumnSelections()
273 comphelper::LibreOfficeKit::setActive();
274 ScModelObj
* pModelObj
= createDoc("select-row-cols.ods");
276 // Select the 5th row with no modifier
277 uno::Sequence
<beans::PropertyValue
> aArgs( comphelper::InitPropertySequence({
278 { "Row", uno::Any(sal_Int32(5 - 1)) },
279 { "Modifier", uno::Any(sal_uInt16(0)) }
281 comphelper::dispatchCommand(".uno:SelectRow", aArgs
);
283 // Check if it is selected
284 OString aResult
= apitest::helper::transferable::getTextSelection(pModelObj
->getSelection(), "text/plain;charset=utf-8");
285 OString
aExpected("1\t2\t3\t4\t5\t6\t7\t8\t9\t10\t11\t12\t13\t14\t15\t16\t17\t18\t19\t20\t21\n");
286 CPPUNIT_ASSERT_EQUAL(aExpected
, aResult
);
288 // Select the 10th row with shift modifier
289 aArgs
[0].Name
= "Row";
290 aArgs
[0].Value
<<= static_cast<sal_Int32
>(10 - 1);
291 aArgs
[1].Name
= "Modifier";
292 aArgs
[1].Value
<<= KEY_SHIFT
;
293 comphelper::dispatchCommand(".uno:SelectRow", aArgs
);
295 // Check if all the rows from 5th to 10th get selected
296 aResult
= apitest::helper::transferable::getTextSelection(pModelObj
->getSelection(), "text/plain;charset=utf-8");
297 aExpected
= "1\t2\t3\t4\t5\t6\t7\t8\t9\t10\t11\t12\t13\t14\t15\t16\t17\t18\t19\t20\t21\n2\t3\t4\t5\t6\t7\t8\t9\t10\t11\t12\t13\t14\t15\t16\t17\t18\t19\t20\t21\t22\n3\t4\t5\t6\t7\t8\t9\t10\t11\t12\t13\t14\t15\t16\t17\t18\t19\t20\t21\t22\t23\n4\t5\t6\t7\t8\t9\t10\t11\t12\t13\t14\t15\t16\t17\t18\t19\t20\t21\t22\t23\t24\n5\t6\t7\t8\t9\t10\t11\t12\t13\t14\t15\t16\t17\t18\t19\t20\t21\t22\t23\t24\t25\n6\t7\t8\t9\t10\t11\t12\t13\t14\t15\t16\t17\t18\t19\t20\t21\t22\t23\t24\t25\t26\n";
298 CPPUNIT_ASSERT_EQUAL(aExpected
, aResult
);
300 // Select the 10th row with ctrl modifier
301 aArgs
[0].Name
= "Row";
302 aArgs
[0].Value
<<= static_cast<sal_Int32
>(13 - 1);
303 aArgs
[1].Name
= "Modifier";
304 aArgs
[1].Value
<<= KEY_MOD1
;
305 comphelper::dispatchCommand(".uno:SelectRow", aArgs
);
307 // When we copy this, we don't get anything useful, but we must not crash
309 aResult
= apitest::helper::transferable::getTextSelection(pModelObj
->getSelection(), "text/plain;charset=utf-8");
310 CPPUNIT_ASSERT_EQUAL(OString(), aResult
);
312 // TODO check that we really selected what we wanted here
314 // Select Column 5 with ctrl modifier
315 aArgs
[0].Name
= "Col";
316 aArgs
[0].Value
<<= static_cast<sal_Int32
>(5 - 1);
317 aArgs
[1].Name
= "Modifier";
318 aArgs
[1].Value
<<= KEY_MOD1
;
319 comphelper::dispatchCommand(".uno:SelectColumn", aArgs
);
321 // When we copy this, we don't get anything useful, but we must not crash
323 aResult
= apitest::helper::transferable::getTextSelection(pModelObj
->getSelection(), "text/plain;charset=utf-8");
324 CPPUNIT_ASSERT_EQUAL(OString(), aResult
);
326 // TODO check that we really selected what we wanted here
328 // Test for deselection of already selected rows
329 // First Deselect Row 13 because copy doesn't work for multiple selections
330 aArgs
[0].Name
= "Row";
331 aArgs
[0].Value
<<= static_cast<sal_Int32
>(13 - 1);
332 aArgs
[1].Name
= "Modifier";
333 aArgs
[1].Value
<<= KEY_MOD1
;
334 comphelper::dispatchCommand(".uno:SelectRow", aArgs
);
337 aArgs
[0].Name
= "Row";
338 aArgs
[0].Value
<<= static_cast<sal_Int32
>(10 - 1);
339 aArgs
[1].Name
= "Modifier";
340 aArgs
[1].Value
<<= KEY_MOD1
;
341 comphelper::dispatchCommand(".uno:SelectRow", aArgs
);
343 // Click at row 6 holding shift
344 aArgs
[0].Name
= "Row";
345 aArgs
[0].Value
<<= static_cast<sal_Int32
>(6 - 1);
346 aArgs
[1].Name
= "Modifier";
347 aArgs
[1].Value
<<= KEY_SHIFT
;
348 comphelper::dispatchCommand(".uno:SelectRow", aArgs
);
350 // only row 5 should remain selected
351 aResult
= apitest::helper::transferable::getTextSelection(pModelObj
->getSelection(), "text/plain;charset=utf-8");
352 aExpected
= "1\t2\t3\t4\t5\t6\t7\t8\t9\t10\t11\t12\t13\t14\t15\t16\t17\t18\t19\t20\t21\n";
353 CPPUNIT_ASSERT_EQUAL(aExpected
, aResult
);
356 void ScTiledRenderingTest::testSortAscendingDescending()
358 comphelper::LibreOfficeKit::setActive();
359 ScModelObj
* pModelObj
= createDoc("sort-range.ods");
360 ScDocument
* pDoc
= pModelObj
->GetDocument();
362 // select the values in the first column
363 pModelObj
->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN
, 551, 129, 1, MOUSE_LEFT
, 0);
364 pModelObj
->postMouseEvent(LOK_MOUSEEVENT_MOUSEMOVE
, 820, 1336, 1, MOUSE_LEFT
, 0);
365 pModelObj
->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP
, 820, 1359, 1, MOUSE_LEFT
, 0);
366 Scheduler::ProcessEventsToIdle();
369 uno::Sequence
<beans::PropertyValue
> aArgs
;
370 comphelper::dispatchCommand(".uno:SortAscending", aArgs
);
373 for (SCROW r
= 0; r
< 6; ++r
)
375 CPPUNIT_ASSERT_EQUAL(double(r
+ 1), pDoc
->GetValue(ScAddress(0, r
, 0)));
379 comphelper::dispatchCommand(".uno:SortDescending", aArgs
);
382 for (SCROW r
= 0; r
< 6; ++r
)
384 CPPUNIT_ASSERT_EQUAL(double(6 - r
), pDoc
->GetValue(ScAddress(0, r
, 0)));
387 // nothing else was sorted
388 CPPUNIT_ASSERT_EQUAL(double(1), pDoc
->GetValue(ScAddress(1, 0, 0)));
389 CPPUNIT_ASSERT_EQUAL(double(3), pDoc
->GetValue(ScAddress(1, 1, 0)));
390 CPPUNIT_ASSERT_EQUAL(double(2), pDoc
->GetValue(ScAddress(1, 2, 0)));
393 void ScTiledRenderingTest::testPartHash()
395 comphelper::LibreOfficeKit::setActive();
396 ScModelObj
* pModelObj
= createDoc("sort-range.ods");
398 int nParts
= pModelObj
->getParts();
399 for (int it
= 0; it
< nParts
; it
++)
401 CPPUNIT_ASSERT(!pModelObj
->getPartHash(it
).isEmpty());
404 // check part that it does not exists
405 CPPUNIT_ASSERT(pModelObj
->getPartHash(100).isEmpty());
408 void ScTiledRenderingTest::testDocumentSize()
410 comphelper::LibreOfficeKit::setActive();
411 ScModelObj
* pModelObj
= createDoc("sort-range.ods");
412 ScDocShell
* pDocSh
= dynamic_cast< ScDocShell
* >( pModelObj
->GetEmbeddedObject() );
413 CPPUNIT_ASSERT(pDocSh
);
415 ScTabViewShell
* pViewShell
= pDocSh
->GetBestViewShell(false);
416 CPPUNIT_ASSERT(pViewShell
);
418 pViewShell
->registerLibreOfficeKitViewCallback(&ScTiledRenderingTest::callback
, this);
420 // check initial document size
421 Size aDocSize
= pModelObj
->getDocumentSize();
422 CPPUNIT_ASSERT(aDocSize
.Width() > 0);
423 CPPUNIT_ASSERT(aDocSize
.Height() > 0);
426 pViewShell
->SetCursor(100, 0);
428 osl::Condition::Result aResult
= m_aDocSizeCondition
.wait(std::chrono::seconds(2));
429 CPPUNIT_ASSERT_EQUAL(osl::Condition::result_ok
, aResult
);
432 pViewShell
->SetCursor(0, 100);
434 aResult
= m_aDocSizeCondition
.wait(std::chrono::seconds(2));
435 CPPUNIT_ASSERT_EQUAL(osl::Condition::result_ok
, aResult
);
438 void ScTiledRenderingTest::testEmptyColumnSelection()
440 comphelper::LibreOfficeKit::setActive();
441 ScModelObj
* pModelObj
= createDoc("select-row-cols.ods");
443 // Select empty column, 1000
444 uno::Sequence
<beans::PropertyValue
> aArgs( comphelper::InitPropertySequence({
445 { "Col", uno::Any(sal_Int32(1000 - 1)) },
446 { "Modifier", uno::Any(sal_uInt16(0)) }
448 comphelper::dispatchCommand(".uno:SelectColumn", aArgs
);
450 // should be an empty string
451 CPPUNIT_ASSERT_EQUAL(OString(), apitest::helper::transferable::getTextSelection(pModelObj
->getSelection(), "text/plain;charset=utf-8"));
454 /// A view callback tracks callbacks invoked on one specific view.
455 class ViewCallback final
457 SfxViewShell
* mpViewShell
;
460 bool m_bOwnCursorInvalidated
;
461 bool m_bViewCursorInvalidated
;
462 bool m_bTextViewSelectionInvalidated
;
463 bool m_bGraphicSelection
;
464 bool m_bGraphicViewSelection
;
465 bool m_bFullInvalidateTiles
;
466 bool m_bInvalidateTiles
;
467 std::vector
<tools::Rectangle
> m_aInvalidations
;
468 std::vector
<int> m_aInvalidationsParts
;
470 OString m_sCellFormula
;
471 boost::property_tree::ptree m_aCommentCallbackResult
;
472 OString m_sInvalidateHeader
;
474 ViewCallback(bool bDeleteListenerOnDestruct
=true)
475 : m_bOwnCursorInvalidated(false),
476 m_bViewCursorInvalidated(false),
477 m_bTextViewSelectionInvalidated(false),
478 m_bGraphicSelection(false),
479 m_bGraphicViewSelection(false),
480 m_bFullInvalidateTiles(false),
481 m_bInvalidateTiles(false),
484 mpViewShell
= SfxViewShell::Current();
485 mpViewShell
->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, this);
486 mnView
= SfxLokHelper::getView();
487 if (!bDeleteListenerOnDestruct
)
488 mpViewShell
= nullptr;
495 SfxLokHelper::setView(mnView
);
496 mpViewShell
->registerLibreOfficeKitViewCallback(nullptr, nullptr);
500 static void callback(int nType
, const char* pPayload
, void* pData
)
502 static_cast<ViewCallback
*>(pData
)->callbackImpl(nType
, pPayload
);
505 void callbackImpl(int nType
, const char* pPayload
)
509 case LOK_CALLBACK_CELL_CURSOR
:
511 m_bOwnCursorInvalidated
= true;
514 case LOK_CALLBACK_CELL_VIEW_CURSOR
:
516 m_bViewCursorInvalidated
= true;
519 case LOK_CALLBACK_TEXT_VIEW_SELECTION
:
521 m_bTextViewSelectionInvalidated
= true;
524 case LOK_CALLBACK_VIEW_LOCK
:
526 std::stringstream
aStream(pPayload
);
527 boost::property_tree::ptree aTree
;
528 boost::property_tree::read_json(aStream
, aTree
);
529 m_bViewLock
= aTree
.get_child("rectangle").get_value
<std::string
>() != "EMPTY";
532 case LOK_CALLBACK_GRAPHIC_SELECTION
:
534 m_bGraphicSelection
= true;
537 case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION
:
539 m_bGraphicViewSelection
= true;
542 case LOK_CALLBACK_INVALIDATE_TILES
:
544 OString
text(pPayload
);
545 if (text
.startsWith("EMPTY"))
547 m_bFullInvalidateTiles
= true;
551 uno::Sequence
<OUString
> aSeq
= comphelper::string::convertCommaSeparated(OUString::createFromAscii(pPayload
));
552 CPPUNIT_ASSERT(aSeq
.getLength() == 4 || aSeq
.getLength() == 5);
553 tools::Rectangle aInvalidationRect
;
554 aInvalidationRect
.setX(aSeq
[0].toInt32());
555 aInvalidationRect
.setY(aSeq
[1].toInt32());
556 aInvalidationRect
.setWidth(aSeq
[2].toInt32());
557 aInvalidationRect
.setHeight(aSeq
[3].toInt32());
558 m_aInvalidations
.push_back(aInvalidationRect
);
559 if (aSeq
.getLength() == 5)
560 m_aInvalidationsParts
.push_back(aSeq
[4].toInt32());
561 m_bInvalidateTiles
= true;
565 case LOK_CALLBACK_CELL_FORMULA
:
567 m_sCellFormula
= pPayload
;
570 case LOK_CALLBACK_COMMENT
:
572 m_aCommentCallbackResult
.clear();
573 std::stringstream
aStream(pPayload
);
574 boost::property_tree::read_json(aStream
, m_aCommentCallbackResult
);
575 m_aCommentCallbackResult
= m_aCommentCallbackResult
.get_child("comment");
578 case LOK_CALLBACK_INVALIDATE_HEADER
:
580 m_sInvalidateHeader
= pPayload
;
587 void ScTiledRenderingTest::testViewCursors()
589 comphelper::LibreOfficeKit::setActive();
591 ScModelObj
* pModelObj
= createDoc("select-row-cols.ods");
593 SfxLokHelper::createView();
594 pModelObj
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
595 ViewCallback
aView2(/*bDeleteListenerOnDestruct*/false);
596 // This was false, the new view did not get the view (cell) cursor of the old view.
597 CPPUNIT_ASSERT(aView2
.m_bViewCursorInvalidated
);
598 CPPUNIT_ASSERT(aView2
.m_bOwnCursorInvalidated
);
599 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::DOWN
);
600 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::DOWN
);
601 Scheduler::ProcessEventsToIdle();
602 SfxLokHelper::destroyView(SfxLokHelper::getView());
603 CPPUNIT_ASSERT(aView1
.m_bViewCursorInvalidated
);
606 void ScTiledRenderingTest::testTextViewSelection()
608 comphelper::LibreOfficeKit::setActive();
610 // Create two views, and leave the second one current.
611 ScModelObj
* pModelObj
= createDoc("select-row-cols.ods");
613 SfxLokHelper::createView();
614 pModelObj
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
617 // Create a selection on two cells in the second view, that's a text selection in LOK terms.
618 aView1
.m_bTextViewSelectionInvalidated
= false;
619 dispatchCommand(mxComponent
, ".uno:GoRightSel", {});
620 Scheduler::ProcessEventsToIdle();
621 // Make sure the first view got its notification.
622 CPPUNIT_ASSERT(aView1
.m_bTextViewSelectionInvalidated
);
625 void ScTiledRenderingTest::testDocumentSizeChanged()
627 comphelper::LibreOfficeKit::setActive();
629 // Load a document that doesn't have much content.
630 createDoc("small.ods");
631 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ScTiledRenderingTest::callback
, this);
633 // Go to the A30 cell -- that will extend the document size.
634 uno::Sequence
<beans::PropertyValue
> aPropertyValues
=
636 comphelper::makePropertyValue("ToPoint", OUString("$A$30")),
638 dispatchCommand(mxComponent
, ".uno:GoToCell", aPropertyValues
);
639 Scheduler::ProcessEventsToIdle();
640 // Assert that the size in the payload is not 0.
641 CPPUNIT_ASSERT(m_aDocumentSize
.getWidth() > 0);
642 CPPUNIT_ASSERT(m_aDocumentSize
.getHeight() > 0);
645 void ScTiledRenderingTest::testViewLock()
647 comphelper::LibreOfficeKit::setActive();
649 // Load a document that has a shape and create two views.
650 ScModelObj
* pModelObj
= createDoc("shape.ods");
652 SfxLokHelper::createView();
653 pModelObj
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
656 // Begin text edit in the second view and assert that the first gets a lock
658 const ScViewData
* pViewData
= ScDocShell::GetViewData();
659 ScTabViewShell
* pViewShell
= pViewData
->GetViewShell();
660 CPPUNIT_ASSERT(pViewShell
);
661 SdrModel
* pDrawModel
= pViewData
->GetDocument().GetDrawLayer();
662 SdrPage
* pDrawPage
= pDrawModel
->GetPage(0);
663 SdrObject
* pObject
= pDrawPage
->GetObj(0);
664 SdrView
* pView
= pViewShell
->GetScDrawView();
665 aView1
.m_bViewLock
= false;
666 pView
->SdrBeginTextEdit(pObject
);
667 CPPUNIT_ASSERT(aView1
.m_bViewLock
);
669 // End text edit in the second view, and assert that the lock is removed in
671 pView
->SdrEndTextEdit();
672 CPPUNIT_ASSERT(!aView1
.m_bViewLock
);
675 void ScTiledRenderingTest::testColRowResize()
677 comphelper::LibreOfficeKit::setActive();
678 ScModelObj
* pModelObj
= createDoc("sort-range.ods");
679 ScDocShell
* pDocSh
= dynamic_cast< ScDocShell
* >( pModelObj
->GetEmbeddedObject() );
680 CPPUNIT_ASSERT(pDocSh
);
682 ScTabViewShell
* pViewShell
= pDocSh
->GetBestViewShell(false);
683 CPPUNIT_ASSERT(pViewShell
);
685 pViewShell
->registerLibreOfficeKitViewCallback(&ScTiledRenderingTest::callback
, this);
687 ScDocument
& rDoc
= pDocSh
->GetDocument();
690 uno::Sequence
<beans::PropertyValue
> aArgs( comphelper::InitPropertySequence({
691 { "ColumnWidth", uno::Any(sal_uInt16(4000)) }, // 4cm
692 { "Column", uno::Any(sal_Int16(3)) }
694 comphelper::dispatchCommand(".uno:ColumnWidth", aArgs
);
696 sal_uInt16 nWidth
= rDoc
.GetColWidth(static_cast<SCCOL
>(2), static_cast<SCTAB
>(0), false) * HMM_PER_TWIPS
;
697 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(4000), nWidth
);
700 uno::Sequence
<beans::PropertyValue
> aArgs2( comphelper::InitPropertySequence({
701 { "RowHeight", uno::Any(sal_uInt16(2000)) },
702 { "Row", uno::Any(sal_Int16(5)) },
704 comphelper::dispatchCommand(".uno:RowHeight", aArgs2
);
706 sal_uInt16 nHeight
= rDoc
.GetRowHeight(static_cast<SCROW
>(4), static_cast<SCTAB
>(0), false) * HMM_PER_TWIPS
;
707 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(2000), nHeight
);
710 void ScTiledRenderingTest::testUndoShells()
712 comphelper::LibreOfficeKit::setActive();
713 ScModelObj
* pModelObj
= createDoc("small.ods");
714 // Clear the currently selected cell.
715 comphelper::dispatchCommand(".uno:ClearContents", {});
717 auto pDocShell
= dynamic_cast<ScDocShell
*>(pModelObj
->GetEmbeddedObject());
718 CPPUNIT_ASSERT(pDocShell
);
719 ScDocument
& rDoc
= pDocShell
->GetDocument();
720 SfxUndoManager
* pUndoManager
= rDoc
.GetUndoManager();
721 CPPUNIT_ASSERT(pUndoManager
);
722 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pUndoManager
->GetUndoActionCount());
723 sal_Int32 nView1
= SfxLokHelper::getView();
724 // This was -1: ScSimpleUndo did not remember what view shell created it.
725 CPPUNIT_ASSERT_EQUAL(ViewShellId(nView1
), pUndoManager
->GetUndoAction()->GetViewShellId());
728 bool lcl_hasEditView(const ScViewData
& rViewData
)
730 bool bResult
= false;
731 for (unsigned int i
=0; i
<4; i
++)
733 bResult
= rViewData
.HasEditView( static_cast<ScSplitPos
>(i
) );
739 void ScTiledRenderingTest::testTextEditViews()
741 comphelper::LibreOfficeKit::setActive();
743 ScModelObj
* pModelObj
= createDoc("small.ods");
744 CPPUNIT_ASSERT(pModelObj
);
745 ScViewData
* pViewData
= ScDocShell::GetViewData();
746 CPPUNIT_ASSERT(pViewData
);
750 CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData
));
752 // text edit a cell in view #1
753 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'x', 0);
754 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'x', 0);
755 Scheduler::ProcessEventsToIdle();
756 CPPUNIT_ASSERT(lcl_hasEditView(*pViewData
));
759 SfxLokHelper::createView();
760 pModelObj
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
763 // move cell cursor i view #2
764 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::DOWN
);
765 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::DOWN
);
766 Scheduler::ProcessEventsToIdle();
768 // check that text edit view in view #1 has not be killed
769 CPPUNIT_ASSERT(lcl_hasEditView(*pViewData
));
772 void ScTiledRenderingTest::testTextEditViewInvalidations()
774 comphelper::LibreOfficeKit::setActive();
776 ScModelObj
* pModelObj
= createDoc("small.ods");
777 CPPUNIT_ASSERT(pModelObj
);
778 ScViewData
* pViewData
= ScDocShell::GetViewData();
779 CPPUNIT_ASSERT(pViewData
);
782 int nView1
= SfxLokHelper::getView();
784 CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData
));
787 SfxLokHelper::createView();
788 pModelObj
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
791 // text edit a cell in view #1
792 SfxLokHelper::setView(nView1
);
793 aView2
.m_bInvalidateTiles
= false;
794 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'x', 0);
795 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'x', 0);
796 Scheduler::ProcessEventsToIdle();
797 CPPUNIT_ASSERT(lcl_hasEditView(*pViewData
));
798 CPPUNIT_ASSERT(aView2
.m_bInvalidateTiles
);
800 // text edit a cell in view #1 until
801 // we can be sure we are out of the initial tile
802 for (int i
= 0; i
< 40; ++i
)
804 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'x', 0);
805 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'x', 0);
807 Scheduler::ProcessEventsToIdle();
809 // text edit a cell in view #1 inside the new tile and
810 // check that view #2 receive a tile invalidate message
811 aView2
.m_bInvalidateTiles
= false;
812 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'x', 0);
813 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'x', 0);
814 Scheduler::ProcessEventsToIdle();
815 CPPUNIT_ASSERT(aView2
.m_bInvalidateTiles
);
818 SfxLokHelper::createView();
819 pModelObj
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
822 // text edit a cell in view #1
823 SfxLokHelper::setView(nView1
);
824 aView3
.m_bInvalidateTiles
= false;
825 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'y', 0);
826 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'y', 0);
827 Scheduler::ProcessEventsToIdle();
828 CPPUNIT_ASSERT(aView3
.m_bInvalidateTiles
);
831 void ScTiledRenderingTest::testCreateViewGraphicSelection()
834 comphelper::LibreOfficeKit::setActive();
836 // Load a document that has a shape and create two views.
837 ScModelObj
* pModelObj
= createDoc("shape.ods");
840 // Mark the graphic in the first view.
841 const ScViewData
* pViewData
= ScDocShell::GetViewData();
842 ScTabViewShell
* pViewShell
= pViewData
->GetViewShell();
843 CPPUNIT_ASSERT(pViewShell
);
844 SdrModel
* pDrawModel
= pViewData
->GetDocument().GetDrawLayer();
845 SdrPage
* pDrawPage
= pDrawModel
->GetPage(0);
846 SdrObject
* pObject
= pDrawPage
->GetObj(0);
847 SdrView
* pView
= pViewShell
->GetScDrawView();
848 aView1
.m_bGraphicSelection
= false;
849 aView1
.m_bGraphicViewSelection
= false;
850 pView
->MarkObj(pObject
, pView
->GetSdrPageView());
851 CPPUNIT_ASSERT(aView1
.m_bGraphicSelection
);
853 // Create a second view.
854 int nView1
= SfxLokHelper::getView();
855 SfxLokHelper::createView();
856 pModelObj
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
858 CPPUNIT_ASSERT(aView2
.m_bGraphicViewSelection
);
859 CPPUNIT_ASSERT(aView1
.m_bGraphicViewSelection
);
861 SfxLokHelper::setView(nView1
);
862 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
865 void ScTiledRenderingTest::testGraphicInvalidate()
868 comphelper::LibreOfficeKit::setActive();
870 // Load a document that has a shape and create two views.
871 ScModelObj
* pModelObj
= createDoc("shape.ods");
874 // Click to select graphic
875 aView
.m_bGraphicSelection
= false;
876 pModelObj
->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN
, /*x=*/ 1,/*y=*/ 1,/*count=*/ 1, /*buttons=*/ 1, /*modifier=*/0);
877 pModelObj
->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP
, /*x=*/ 1, /*y=*/ 1, /*count=*/ 1, /*buttons=*/ 1, /*modifier=*/0);
878 Scheduler::ProcessEventsToIdle();
879 CPPUNIT_ASSERT(aView
.m_bGraphicSelection
);
882 aView
.m_bGraphicSelection
= false;
883 pModelObj
->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN
, /*x=*/ 1,/*y=*/ 1,/*count=*/ 1, /*buttons=*/ 1, /*modifier=*/0);
884 pModelObj
->postMouseEvent(LOK_MOUSEEVENT_MOUSEMOVE
, /*x=*/ 1,/*y=*/ 10,/*count=*/ 1, /*buttons=*/ 1, /*modifier=*/0);
885 pModelObj
->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP
, /*x=*/ 1, /*y=*/ 10, /*count=*/ 1, /*buttons=*/ 1, /*modifier=*/0);
886 Scheduler::ProcessEventsToIdle();
887 CPPUNIT_ASSERT(!aView
.m_bFullInvalidateTiles
);
890 Scheduler::ProcessEventsToIdle();
891 CPPUNIT_ASSERT(!aView
.m_bFullInvalidateTiles
);
894 void ScTiledRenderingTest::testAutoSum()
897 comphelper::LibreOfficeKit::setActive();
898 createDoc("small.ods");
902 uno::Sequence
<beans::PropertyValue
> aArgs
;
903 comphelper::dispatchCommand(".uno:AutoSum", aArgs
);
904 Scheduler::ProcessEventsToIdle();
905 CPPUNIT_ASSERT(aView
.m_sCellFormula
.startsWith("=SUM("));
908 void ScTiledRenderingTest::testHideColRow()
911 comphelper::LibreOfficeKit::setActive();
912 createDoc("small.ods");
914 uno::Sequence
<beans::PropertyValue
> aArgs( comphelper::InitPropertySequence({
915 { "Col", uno::Any(sal_Int32(2 - 1)) },
916 { "Modifier", uno::Any(KEY_SHIFT
) }
918 comphelper::dispatchCommand(".uno:SelectColumn", aArgs
);
920 uno::Sequence
<beans::PropertyValue
> aArgs2( comphelper::InitPropertySequence({
921 { "Col", uno::Any(sal_Int32(3 - 1)) },
922 { "Modifier", uno::Any(sal_uInt16(0)) }
925 comphelper::dispatchCommand(".uno:SelectColumn", aArgs2
);
926 Scheduler::ProcessEventsToIdle();
929 SCCOL nOldCurX
= ScDocShell::GetViewData()->GetCurX();
930 SCROW nOldCurY
= ScDocShell::GetViewData()->GetCurY();
932 uno::Sequence
<beans::PropertyValue
> aArgs
;
933 comphelper::dispatchCommand(".uno:HideColumn", aArgs
);
934 Scheduler::ProcessEventsToIdle();
937 SCCOL nNewCurX
= ScDocShell::GetViewData()->GetCurX();
938 SCROW nNewCurY
= ScDocShell::GetViewData()->GetCurY();
939 CPPUNIT_ASSERT(nNewCurX
> nOldCurX
);
940 CPPUNIT_ASSERT_EQUAL(nOldCurY
, nNewCurY
);
942 uno::Sequence
<beans::PropertyValue
> aArgs( comphelper::InitPropertySequence({
943 { "Row", uno::Any(sal_Int32(6 - 1)) },
944 { "Modifier", uno::Any(KEY_SHIFT
) }
946 comphelper::dispatchCommand(".uno:SelectRow", aArgs
);
948 uno::Sequence
<beans::PropertyValue
> aArgs2( comphelper::InitPropertySequence({
949 { "Row", uno::Any(sal_Int32(7 - 1)) },
950 { "Modifier", uno::Any(sal_uInt16(0)) }
952 comphelper::dispatchCommand(".uno:SelectRow", aArgs2
);
953 Scheduler::ProcessEventsToIdle();
956 nOldCurX
= ScDocShell::GetViewData()->GetCurX();
957 nOldCurY
= ScDocShell::GetViewData()->GetCurY();
959 uno::Sequence
<beans::PropertyValue
> aArgs
;
960 comphelper::dispatchCommand(".uno:HideRow", aArgs
);
961 Scheduler::ProcessEventsToIdle();
963 nNewCurX
= ScDocShell::GetViewData()->GetCurX();
964 nNewCurY
= ScDocShell::GetViewData()->GetCurY();
965 CPPUNIT_ASSERT(nNewCurY
> nOldCurY
);
966 CPPUNIT_ASSERT_EQUAL(nOldCurX
, nNewCurX
);
969 void ScTiledRenderingTest::testInvalidateOnCopyPasteCells()
972 comphelper::LibreOfficeKit::setActive();
973 ScModelObj
* pModelObj
= createDoc("small.ods");
974 CPPUNIT_ASSERT(pModelObj
);
979 uno::Sequence
<beans::PropertyValue
> aArgs
;
980 // select and copy cells
981 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_HOME
| KEY_MOD1
);
982 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, KEY_HOME
| KEY_MOD1
);
983 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_DOWN
| KEY_SHIFT
);
984 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, KEY_DOWN
| KEY_SHIFT
);
985 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_RIGHT
| KEY_SHIFT
);
986 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, KEY_RIGHT
| KEY_SHIFT
);
987 Scheduler::ProcessEventsToIdle();
988 comphelper::dispatchCommand(".uno:Copy", aArgs
);
990 // move to destination cell
991 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_DOWN
);
992 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, KEY_DOWN
);
993 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_DOWN
| KEY_MOD1
);
994 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, KEY_DOWN
| KEY_MOD1
);
995 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_UP
);
996 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, KEY_UP
);
997 Scheduler::ProcessEventsToIdle();
1000 aView
.m_bInvalidateTiles
= false;
1001 comphelper::dispatchCommand(".uno:Paste", aArgs
);
1002 Scheduler::ProcessEventsToIdle();
1003 CPPUNIT_ASSERT(aView
.m_bInvalidateTiles
);
1006 void ScTiledRenderingTest::testInvalidateOnInserRowCol()
1009 comphelper::LibreOfficeKit::setActive();
1010 ScModelObj
* pModelObj
= createDoc("small.ods");
1011 CPPUNIT_ASSERT(pModelObj
);
1016 uno::Sequence
<beans::PropertyValue
> aArgs
;
1018 for (int i
= 0; i
< 200; ++i
)
1020 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_DOWN
);
1021 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, KEY_DOWN
);
1023 Scheduler::ProcessEventsToIdle();
1026 aView
.m_bInvalidateTiles
= false;
1027 aView
.m_aInvalidations
.clear();
1028 comphelper::dispatchCommand(".uno:InsertRows", aArgs
);
1029 Scheduler::ProcessEventsToIdle();
1030 CPPUNIT_ASSERT(aView
.m_bInvalidateTiles
);
1031 CPPUNIT_ASSERT_EQUAL(size_t(2), aView
.m_aInvalidations
.size());
1032 CPPUNIT_ASSERT_EQUAL(tools::Rectangle(-75, 50985, 32212230, 63990), aView
.m_aInvalidations
[0]);
1034 // move on the right
1035 for (int i
= 0; i
< 200; ++i
)
1037 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_RIGHT
);
1038 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, KEY_RIGHT
);
1040 Scheduler::ProcessEventsToIdle();
1043 aView
.m_bInvalidateTiles
= false;
1044 aView
.m_aInvalidations
.clear();
1045 comphelper::dispatchCommand(".uno:InsertColumns", aArgs
);
1046 Scheduler::ProcessEventsToIdle();
1047 CPPUNIT_ASSERT(aView
.m_bInvalidateTiles
);
1048 CPPUNIT_ASSERT_EQUAL(size_t(2), aView
.m_aInvalidations
.size());
1049 CPPUNIT_ASSERT_EQUAL(tools::Rectangle(253650, -15, 32212230, 63990), aView
.m_aInvalidations
[0]);
1052 void ScTiledRenderingTest::testCommentCallback()
1055 comphelper::LibreOfficeKit::setActive();
1056 // Comments callback are emitted only if tiled annotations are off
1057 comphelper::LibreOfficeKit::setTiledAnnotations(false);
1060 ScModelObj
* pModelObj
= createDoc("small.ods");
1061 ViewCallback aView1
;
1062 int nView1
= SfxLokHelper::getView();
1064 // Create a 2nd view
1065 SfxLokHelper::createView();
1066 pModelObj
->initializeForTiledRendering({});
1067 ViewCallback aView2
;
1069 SfxLokHelper::setView(nView1
);
1071 // Add a new comment
1072 uno::Sequence
<beans::PropertyValue
> aArgs(comphelper::InitPropertySequence(
1074 {"Text", uno::makeAny(OUString("Comment"))},
1075 {"Author", uno::makeAny(OUString("LOK User1"))},
1077 comphelper::dispatchCommand(".uno:InsertAnnotation", aArgs
);
1078 Scheduler::ProcessEventsToIdle();
1080 // We received a LOK_CALLBACK_COMMENT callback with comment 'Add' action
1081 CPPUNIT_ASSERT_EQUAL(std::string("Add"), aView1
.m_aCommentCallbackResult
.get
<std::string
>("action"));
1082 CPPUNIT_ASSERT_EQUAL(std::string("Add"), aView2
.m_aCommentCallbackResult
.get
<std::string
>("action"));
1083 CPPUNIT_ASSERT_EQUAL(std::string("1"), aView1
.m_aCommentCallbackResult
.get
<std::string
>("id"));
1084 CPPUNIT_ASSERT_EQUAL(std::string("1"), aView2
.m_aCommentCallbackResult
.get
<std::string
>("id"));
1085 CPPUNIT_ASSERT_EQUAL(std::string("0"), aView1
.m_aCommentCallbackResult
.get
<std::string
>("tab"));
1086 CPPUNIT_ASSERT_EQUAL(std::string("0"), aView2
.m_aCommentCallbackResult
.get
<std::string
>("tab"));
1087 CPPUNIT_ASSERT_EQUAL(std::string("LOK User1"), aView1
.m_aCommentCallbackResult
.get
<std::string
>("author"));
1088 CPPUNIT_ASSERT_EQUAL(std::string("LOK User1"), aView2
.m_aCommentCallbackResult
.get
<std::string
>("author"));
1089 CPPUNIT_ASSERT_EQUAL(std::string("Comment"), aView1
.m_aCommentCallbackResult
.get
<std::string
>("text"));
1090 CPPUNIT_ASSERT_EQUAL(std::string("Comment"), aView2
.m_aCommentCallbackResult
.get
<std::string
>("text"));
1091 CPPUNIT_ASSERT_EQUAL(std::string("0, 255, 1274, 254"), aView1
.m_aCommentCallbackResult
.get
<std::string
>("cellPos"));
1092 CPPUNIT_ASSERT_EQUAL(std::string("0, 255, 1274, 254"), aView2
.m_aCommentCallbackResult
.get
<std::string
>("cellPos"));
1094 std::string aCommentId
= aView1
.m_aCommentCallbackResult
.get
<std::string
>("id");
1097 // Select some random cell, we should be able to edit the cell note without
1098 // selecting the cell
1099 ScTabViewShell
* pTabViewShell
= dynamic_cast<ScTabViewShell
*>(SfxViewShell::Current());
1101 pTabViewShell
->SetCursor(3, 100);
1102 aArgs
= comphelper::InitPropertySequence(
1104 {"Id", uno::makeAny(OUString::createFromAscii(aCommentId
.c_str()))},
1105 {"Text", uno::makeAny(OUString("Edited comment"))},
1106 {"Author", uno::makeAny(OUString("LOK User2"))},
1108 comphelper::dispatchCommand(".uno:EditAnnotation", aArgs
);
1109 Scheduler::ProcessEventsToIdle();
1111 // We received a LOK_CALLBACK_COMMENT callback with comment 'Modify' action
1112 CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView1
.m_aCommentCallbackResult
.get
<std::string
>("action"));
1113 CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView2
.m_aCommentCallbackResult
.get
<std::string
>("action"));
1114 CPPUNIT_ASSERT_EQUAL(aCommentId
, aView1
.m_aCommentCallbackResult
.get
<std::string
>("id"));
1115 CPPUNIT_ASSERT_EQUAL(aCommentId
, aView2
.m_aCommentCallbackResult
.get
<std::string
>("id"));
1116 CPPUNIT_ASSERT_EQUAL(std::string("LOK User2"), aView1
.m_aCommentCallbackResult
.get
<std::string
>("author"));
1117 CPPUNIT_ASSERT_EQUAL(std::string("LOK User2"), aView2
.m_aCommentCallbackResult
.get
<std::string
>("author"));
1118 CPPUNIT_ASSERT_EQUAL(std::string("Edited comment"), aView1
.m_aCommentCallbackResult
.get
<std::string
>("text"));
1119 CPPUNIT_ASSERT_EQUAL(std::string("Edited comment"), aView2
.m_aCommentCallbackResult
.get
<std::string
>("text"));
1120 CPPUNIT_ASSERT_EQUAL(std::string("0, 255, 1274, 254"), aView1
.m_aCommentCallbackResult
.get
<std::string
>("cellPos"));
1121 CPPUNIT_ASSERT_EQUAL(std::string("0, 255, 1274, 254"), aView2
.m_aCommentCallbackResult
.get
<std::string
>("cellPos"));
1123 // Delete the comment
1125 pTabViewShell
->SetCursor(4, 43);
1126 aArgs
= comphelper::InitPropertySequence(
1128 {"Id", uno::makeAny(OUString::createFromAscii(aCommentId
.c_str()))}
1130 comphelper::dispatchCommand(".uno:DeleteNote", aArgs
);
1131 Scheduler::ProcessEventsToIdle();
1133 // We received a LOK_CALLBACK_COMMENT callback with comment 'Remove' action
1134 CPPUNIT_ASSERT_EQUAL(std::string("Remove"), aView1
.m_aCommentCallbackResult
.get
<std::string
>("action"));
1135 CPPUNIT_ASSERT_EQUAL(std::string("Remove"), aView2
.m_aCommentCallbackResult
.get
<std::string
>("action"));
1136 CPPUNIT_ASSERT_EQUAL(aCommentId
, aView1
.m_aCommentCallbackResult
.get
<std::string
>("id"));
1137 CPPUNIT_ASSERT_EQUAL(aCommentId
, aView2
.m_aCommentCallbackResult
.get
<std::string
>("id"));
1139 comphelper::LibreOfficeKit::setTiledAnnotations(true);
1142 void ScTiledRenderingTest::testUndoLimiting()
1144 comphelper::LibreOfficeKit::setActive();
1146 ScModelObj
* pModelObj
= createDoc("small.ods");
1147 CPPUNIT_ASSERT(pModelObj
);
1148 ScDocument
* pDoc
= pModelObj
->GetDocument();
1149 CPPUNIT_ASSERT(pDoc
);
1150 SfxUndoManager
* pUndoManager
= pDoc
->GetUndoManager();
1151 CPPUNIT_ASSERT(pUndoManager
);
1154 int nView1
= SfxLokHelper::getView();
1155 ViewCallback aView1
;
1158 SfxLokHelper::createView();
1159 int nView2
= SfxLokHelper::getView();
1160 pModelObj
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
1161 ViewCallback aView2
;
1163 // text edit a cell in view #1
1164 SfxLokHelper::setView(nView1
);
1165 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'x', 0);
1166 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'x', 0);
1167 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::RETURN
);
1168 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::RETURN
);
1169 Scheduler::ProcessEventsToIdle();
1171 // check that undo action count in not 0
1172 CPPUNIT_ASSERT_EQUAL(std::size_t(1), pUndoManager
->GetUndoActionCount());
1174 // try to execute undo in view #2
1175 SfxLokHelper::setView(nView2
);
1176 comphelper::dispatchCommand(".uno:Undo", {});
1177 Scheduler::ProcessEventsToIdle();
1178 // check that undo has not been executed on view #2
1179 CPPUNIT_ASSERT_EQUAL(std::size_t(1), pUndoManager
->GetUndoActionCount());
1181 // try to execute undo in view #1
1182 SfxLokHelper::setView(nView1
);
1183 comphelper::dispatchCommand(".uno:Undo", {});
1184 Scheduler::ProcessEventsToIdle();
1185 // check that undo has been executed on view #1
1186 CPPUNIT_ASSERT_EQUAL(std::size_t(0), pUndoManager
->GetUndoActionCount());
1188 // check that redo action count in not 0
1189 CPPUNIT_ASSERT_EQUAL(std::size_t(1), pUndoManager
->GetRedoActionCount());
1191 // try to execute redo in view #2
1192 SfxLokHelper::setView(nView2
);
1193 comphelper::dispatchCommand(".uno:Redo", {});
1194 Scheduler::ProcessEventsToIdle();
1195 // check that redo has not been executed on view #2
1196 CPPUNIT_ASSERT_EQUAL(std::size_t(1), pUndoManager
->GetRedoActionCount());
1198 // try to execute redo in view #1
1199 SfxLokHelper::setView(nView1
);
1200 comphelper::dispatchCommand(".uno:Redo", {});
1201 Scheduler::ProcessEventsToIdle();
1202 // check that redo has been executed on view #1
1203 CPPUNIT_ASSERT_EQUAL(std::size_t(0), pUndoManager
->GetRedoActionCount());
1206 void ScTiledRenderingTest::testUndoRepairDispatch()
1208 comphelper::LibreOfficeKit::setActive();
1210 ScModelObj
* pModelObj
= createDoc("small.ods");
1211 CPPUNIT_ASSERT(pModelObj
);
1212 ScDocument
* pDoc
= pModelObj
->GetDocument();
1213 CPPUNIT_ASSERT(pDoc
);
1214 SfxUndoManager
* pUndoManager
= pDoc
->GetUndoManager();
1215 CPPUNIT_ASSERT(pUndoManager
);
1218 int nView1
= SfxLokHelper::getView();
1219 ViewCallback aView1
;
1222 SfxLokHelper::createView();
1223 int nView2
= SfxLokHelper::getView();
1224 pModelObj
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
1225 ViewCallback aView2
;
1227 // text edit a cell in view #1
1228 SfxLokHelper::setView(nView1
);
1229 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'x', 0);
1230 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'x', 0);
1231 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::RETURN
);
1232 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::RETURN
);
1233 Scheduler::ProcessEventsToIdle();
1235 // check that undo action count in not 0
1236 CPPUNIT_ASSERT_EQUAL(std::size_t(1), pUndoManager
->GetUndoActionCount());
1238 // try to execute undo in view #2
1239 SfxLokHelper::setView(nView2
);
1240 comphelper::dispatchCommand(".uno:Undo", {});
1241 Scheduler::ProcessEventsToIdle();
1242 // check that undo has not been executed on view #2
1243 CPPUNIT_ASSERT_EQUAL(std::size_t(1), pUndoManager
->GetUndoActionCount());
1245 // try to execute undo in view #2 in repair mode
1246 SfxLokHelper::setView(nView2
);
1247 uno::Sequence
<beans::PropertyValue
> aPropertyValues(comphelper::InitPropertySequence(
1249 {"Repair", uno::makeAny(true)}
1251 comphelper::dispatchCommand(".uno:Undo", aPropertyValues
);
1252 Scheduler::ProcessEventsToIdle();
1253 // check that undo has been executed on view #2 in repair mode
1254 CPPUNIT_ASSERT_EQUAL(std::size_t(0), pUndoManager
->GetUndoActionCount());
1257 void ScTiledRenderingTest::testInsertGraphicInvalidations()
1259 comphelper::LibreOfficeKit::setActive();
1261 ScModelObj
* pModelObj
= createDoc("small.ods");
1262 CPPUNIT_ASSERT(pModelObj
);
1263 ScViewData
* pViewData
= ScDocShell::GetViewData();
1264 CPPUNIT_ASSERT(pViewData
);
1269 // we need to paint a tile in the view for triggering the tile invalidation solution
1270 int nCanvasWidth
= 256;
1271 int nCanvasHeight
= 256;
1272 std::vector
<unsigned char> aBuffer(nCanvasWidth
* nCanvasHeight
* 4);
1273 ScopedVclPtrInstance
<VirtualDevice
> pDevice(DeviceFormat::DEFAULT
);
1274 pDevice
->SetOutputSizePixelScaleOffsetAndBuffer(Size(nCanvasWidth
, nCanvasHeight
), Fraction(1.0), Point(), aBuffer
.data());
1275 pModelObj
->paintTile(*pDevice
, nCanvasWidth
, nCanvasHeight
, /*nTilePosX=*/0, /*nTilePosY=*/0, /*nTileWidth=*/3840, /*nTileHeight=*/3840);
1276 Scheduler::ProcessEventsToIdle();
1278 // insert an image in view and see if both views are invalidated
1279 aView
.m_bInvalidateTiles
= false;
1280 uno::Sequence
<beans::PropertyValue
> aArgs( comphelper::InitPropertySequence({
1281 { "FileName", uno::Any(m_directories
.getURLFromSrc(DATA_DIRECTORY
) + "smile.png") }
1283 comphelper::dispatchCommand(".uno:InsertGraphic", aArgs
);
1284 Scheduler::ProcessEventsToIdle();
1285 CPPUNIT_ASSERT(aView
.m_bInvalidateTiles
);
1287 // undo image insertion in view and see if both views are invalidated
1288 aView
.m_bInvalidateTiles
= false;
1289 uno::Sequence
<beans::PropertyValue
> aArgs2
;
1290 comphelper::dispatchCommand(".uno:Undo", aArgs2
);
1291 Scheduler::ProcessEventsToIdle();
1292 CPPUNIT_ASSERT(aView
.m_bInvalidateTiles
);
1295 void ScTiledRenderingTest::testDocumentSizeWithTwoViews()
1297 comphelper::LibreOfficeKit::setActive();
1299 // Open a document that has the cursor far away & paint a tile
1300 ScModelObj
* pModelObj
= createDoc("cursor-away.ods");
1302 // Set the visible area, and press page down
1303 pModelObj
->setClientVisibleArea(tools::Rectangle(750, 1861, 20583, 6997));
1304 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::PAGEDOWN
);
1305 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::PAGEDOWN
);
1306 Scheduler::ProcessEventsToIdle();
1308 int nCanvasWidth
= 256;
1309 int nCanvasHeight
= 256;
1310 std::vector
<unsigned char> aBuffer1(nCanvasWidth
* nCanvasHeight
* 4);
1311 ScopedVclPtrInstance
<VirtualDevice
> pDevice1(DeviceFormat::DEFAULT
);
1312 pDevice1
->SetOutputSizePixelScaleOffsetAndBuffer(Size(nCanvasWidth
, nCanvasHeight
), Fraction(1.0), Point(), aBuffer1
.data());
1313 pModelObj
->paintTile(*pDevice1
, nCanvasWidth
, nCanvasHeight
, /*nTilePosX=*/0, /*nTilePosY=*/291840, /*nTileWidth=*/3840, /*nTileHeight=*/3840);
1314 Scheduler::ProcessEventsToIdle();
1316 // Create a new view
1317 int nView1
= SfxLokHelper::getView();
1318 SfxLokHelper::createView();
1320 std::vector
<unsigned char> aBuffer2(nCanvasWidth
* nCanvasHeight
* 4);
1321 ScopedVclPtrInstance
<VirtualDevice
> pDevice2(DeviceFormat::DEFAULT
);
1322 pDevice2
->SetOutputSizePixelScaleOffsetAndBuffer(Size(nCanvasWidth
, nCanvasHeight
), Fraction(1.0), Point(), aBuffer2
.data());
1323 pModelObj
->paintTile(*pDevice2
, nCanvasWidth
, nCanvasHeight
, /*nTilePosX=*/0, /*nTilePosY=*/291840, /*nTileWidth=*/3840, /*nTileHeight=*/3840);
1324 Scheduler::ProcessEventsToIdle();
1326 // Check that the tiles actually have the same content
1327 for (size_t i
= 0; i
< aBuffer1
.size(); ++i
)
1328 CPPUNIT_ASSERT_EQUAL(aBuffer1
[i
], aBuffer2
[i
]);
1330 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
1331 SfxLokHelper::setView(nView1
);
1332 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
1335 void ScTiledRenderingTest::testDisableUndoRepair()
1337 comphelper::LibreOfficeKit::setActive();
1338 ScModelObj
* pModelObj
= createDoc("cursor-away.ods");
1339 CPPUNIT_ASSERT(pModelObj
);
1342 int nView1
= SfxLokHelper::getView();
1343 SfxViewShell
* pView1
= SfxViewShell::Current();
1346 SfxLokHelper::createView();
1347 int nView2
= SfxLokHelper::getView();
1348 SfxViewShell
* pView2
= SfxViewShell::Current();
1349 CPPUNIT_ASSERT(pView1
!= pView2
);
1351 SfxItemSet
aSet1(pView1
->GetPool(), svl::Items
<SID_UNDO
, SID_UNDO
>{});
1352 SfxItemSet
aSet2(pView2
->GetPool(), svl::Items
<SID_UNDO
, SID_UNDO
>{});
1353 pView1
->GetSlotState(SID_UNDO
, nullptr, &aSet1
);
1354 pView2
->GetSlotState(SID_UNDO
, nullptr, &aSet2
);
1355 CPPUNIT_ASSERT_EQUAL(SfxItemState::DISABLED
, aSet1
.GetItemState(SID_UNDO
));
1356 CPPUNIT_ASSERT_EQUAL(SfxItemState::DISABLED
, aSet2
.GetItemState(SID_UNDO
));
1359 // text edit a cell in view #1
1360 SfxLokHelper::setView(nView1
);
1361 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'h', 0);
1362 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'h', 0);
1363 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::RETURN
);
1364 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::RETURN
);
1365 Scheduler::ProcessEventsToIdle();
1367 SfxItemSet
aSet1(pView1
->GetPool(), svl::Items
<SID_UNDO
, SID_UNDO
>{});
1368 SfxItemSet
aSet2(pView2
->GetPool(), svl::Items
<SID_UNDO
, SID_UNDO
>{});
1369 pView1
->GetSlotState(SID_UNDO
, nullptr, &aSet1
);
1370 pView2
->GetSlotState(SID_UNDO
, nullptr, &aSet2
);
1371 CPPUNIT_ASSERT_EQUAL(SfxItemState::SET
, aSet1
.GetItemState(SID_UNDO
));
1372 CPPUNIT_ASSERT(dynamic_cast< const SfxStringItem
* >(aSet1
.GetItem(SID_UNDO
)));
1373 CPPUNIT_ASSERT_EQUAL(SfxItemState::SET
, aSet2
.GetItemState(SID_UNDO
));
1374 CPPUNIT_ASSERT(dynamic_cast< const SfxUInt32Item
* >(aSet2
.GetItem(SID_UNDO
)));
1375 const SfxUInt32Item
* pUInt32Item
= dynamic_cast<const SfxUInt32Item
*>(aSet2
.GetItem(SID_UNDO
));
1376 CPPUNIT_ASSERT(pUInt32Item
);
1377 CPPUNIT_ASSERT_EQUAL(static_cast< sal_uInt32
>(SID_REPAIRPACKAGE
), pUInt32Item
->GetValue());
1380 // text edit a cell in view #2
1381 SfxLokHelper::setView(nView2
);
1382 pModelObj
->setPart(1);
1383 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'c', 0);
1384 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'c', 0);
1385 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::RETURN
);
1386 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::RETURN
);
1387 Scheduler::ProcessEventsToIdle();
1389 SfxItemSet
aSet1(pView1
->GetPool(), svl::Items
<SID_UNDO
, SID_UNDO
>{});
1390 SfxItemSet
aSet2(pView2
->GetPool(), svl::Items
<SID_UNDO
, SID_UNDO
>{});
1391 pView1
->GetSlotState(SID_UNDO
, nullptr, &aSet1
);
1392 pView2
->GetSlotState(SID_UNDO
, nullptr, &aSet2
);
1393 CPPUNIT_ASSERT_EQUAL(SfxItemState::SET
, aSet1
.GetItemState(SID_UNDO
));
1394 const SfxUInt32Item
* pUInt32Item
= dynamic_cast<const SfxUInt32Item
*>(aSet1
.GetItem(SID_UNDO
));
1395 CPPUNIT_ASSERT(pUInt32Item
);
1396 CPPUNIT_ASSERT_EQUAL(static_cast< sal_uInt32
>(SID_REPAIRPACKAGE
), pUInt32Item
->GetValue());
1397 CPPUNIT_ASSERT_EQUAL(SfxItemState::SET
, aSet2
.GetItemState(SID_UNDO
));
1398 CPPUNIT_ASSERT(dynamic_cast< const SfxStringItem
* >(aSet2
.GetItem(SID_UNDO
)));
1401 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
1402 SfxLokHelper::setView(nView1
);
1403 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
1406 void ScTiledRenderingTest::testDocumentRepair()
1408 comphelper::LibreOfficeKit::setActive();
1410 // Create two views.
1411 ScModelObj
* pModelObj
= createDoc("cursor-away.ods");
1412 CPPUNIT_ASSERT(pModelObj
);
1415 SfxViewShell
* pView1
= SfxViewShell::Current();
1418 int nView1
= SfxLokHelper::getView();
1419 SfxLokHelper::createView();
1420 SfxViewShell
* pView2
= SfxViewShell::Current();
1421 int nView2
= SfxLokHelper::getView();
1422 CPPUNIT_ASSERT(pView1
!= pView2
);
1424 std::unique_ptr
<SfxPoolItem
> xItem1
;
1425 std::unique_ptr
<SfxPoolItem
> xItem2
;
1426 pView1
->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR
, xItem1
);
1427 pView2
->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR
, xItem2
);
1428 const SfxBoolItem
* pItem1
= dynamic_cast< const SfxBoolItem
* >(xItem1
.get());
1429 const SfxBoolItem
* pItem2
= dynamic_cast< const SfxBoolItem
* >(xItem2
.get());
1430 CPPUNIT_ASSERT(pItem1
);
1431 CPPUNIT_ASSERT(pItem2
);
1432 CPPUNIT_ASSERT_EQUAL(false, pItem1
->GetValue());
1433 CPPUNIT_ASSERT_EQUAL(false, pItem2
->GetValue());
1436 // Insert a character in the second view.
1437 SfxLokHelper::setView(nView2
);
1438 pModelObj
->setPart(1);
1439 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'c', 0);
1440 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'c', 0);
1441 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::RETURN
);
1442 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::RETURN
);
1443 Scheduler::ProcessEventsToIdle();
1445 std::unique_ptr
<SfxPoolItem
> xItem1
;
1446 std::unique_ptr
<SfxPoolItem
> xItem2
;
1447 pView1
->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR
, xItem1
);
1448 pView2
->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR
, xItem2
);
1449 const SfxBoolItem
* pItem1
= dynamic_cast< const SfxBoolItem
* >(xItem1
.get());
1450 const SfxBoolItem
* pItem2
= dynamic_cast< const SfxBoolItem
* >(xItem2
.get());
1451 CPPUNIT_ASSERT(pItem1
);
1452 CPPUNIT_ASSERT(pItem2
);
1453 CPPUNIT_ASSERT_EQUAL(true, pItem1
->GetValue());
1454 CPPUNIT_ASSERT_EQUAL(true, pItem2
->GetValue());
1457 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
1458 SfxLokHelper::setView(nView1
);
1459 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
1462 void ScTiledRenderingTest::testLanguageStatus()
1464 comphelper::LibreOfficeKit::setActive();
1465 ScModelObj
* pModelObj
= createDoc("small.ods");
1466 CPPUNIT_ASSERT(pModelObj
);
1467 ScDocShell
* pDocSh
= dynamic_cast< ScDocShell
* >( pModelObj
->GetEmbeddedObject() );
1468 CPPUNIT_ASSERT(pDocSh
);
1471 SfxViewShell
* pView1
= SfxViewShell::Current();
1474 int nView1
= SfxLokHelper::getView();
1475 SfxLokHelper::createView();
1476 SfxViewShell
* pView2
= SfxViewShell::Current();
1477 CPPUNIT_ASSERT(pView1
!= pView2
);
1479 std::unique_ptr
<SfxPoolItem
> xItem1
;
1480 std::unique_ptr
<SfxPoolItem
> xItem2
;
1481 pView1
->GetViewFrame()->GetBindings().QueryState(SID_LANGUAGE_STATUS
, xItem1
);
1482 pView2
->GetViewFrame()->GetBindings().QueryState(SID_LANGUAGE_STATUS
, xItem2
);
1483 const SfxStringItem
* pItem1
= dynamic_cast<const SfxStringItem
*>(xItem1
.get());
1484 const SfxStringItem
* pItem2
= dynamic_cast<const SfxStringItem
*>(xItem2
.get());
1485 CPPUNIT_ASSERT(pItem1
);
1486 CPPUNIT_ASSERT(pItem2
);
1487 CPPUNIT_ASSERT(!pItem1
->GetValue().isEmpty());
1488 CPPUNIT_ASSERT(!pItem2
->GetValue().isEmpty());
1492 SfxStringItem
aLangString(SID_LANGUAGE_STATUS
, "Default_Spanish (Bolivia)");
1493 pView1
->GetViewFrame()->GetDispatcher()->ExecuteList(SID_LANGUAGE_STATUS
,
1494 SfxCallMode::SYNCHRON
, { &aLangString
});
1498 std::unique_ptr
<SfxPoolItem
> xItem1
;
1499 std::unique_ptr
<SfxPoolItem
> xItem2
;
1500 pView1
->GetViewFrame()->GetBindings().QueryState(SID_LANGUAGE_STATUS
, xItem1
);
1501 pView2
->GetViewFrame()->GetBindings().QueryState(SID_LANGUAGE_STATUS
, xItem2
);
1502 const SfxStringItem
* pItem1
= dynamic_cast<const SfxStringItem
*>(xItem1
.get());
1503 const SfxStringItem
* pItem2
= dynamic_cast<const SfxStringItem
*>(xItem2
.get());
1504 CPPUNIT_ASSERT(pItem1
);
1505 CPPUNIT_ASSERT(pItem2
);
1506 const OUString
aLangBolivia("Spanish (Bolivia);es-BO");
1507 CPPUNIT_ASSERT_EQUAL(aLangBolivia
, pItem1
->GetValue());
1508 CPPUNIT_ASSERT_EQUAL(aLangBolivia
, pItem2
->GetValue());
1511 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
1512 SfxLokHelper::setView(nView1
);
1513 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
1516 void ScTiledRenderingTest::testMultiViewCopyPaste()
1518 comphelper::LibreOfficeKit::setActive();
1520 ScModelObj
* pModelObj
= createDoc("empty.ods");
1521 ScDocument
* pDoc
= pModelObj
->GetDocument();
1522 CPPUNIT_ASSERT(pDoc
);
1524 pDoc
->SetString(ScAddress(0, 0, 0), "TestCopy1");
1525 pDoc
->SetString(ScAddress(1, 0, 0), "TestCopy2");
1528 ScTabViewShell
* pView1
= dynamic_cast<ScTabViewShell
*>(SfxViewShell::Current());
1529 CPPUNIT_ASSERT(pView1
);
1530 // emulate clipboard
1531 pView1
->GetViewData().GetActiveWin()->SetClipboard(css::datatransfer::clipboard::SystemClipboard::create(comphelper::getProcessComponentContext()));
1534 int nView1
= SfxLokHelper::getView();
1535 SfxLokHelper::createView();
1536 ScTabViewShell
* pView2
= dynamic_cast<ScTabViewShell
*>(SfxViewShell::Current());
1537 // emulate clipboard
1538 pView2
->GetViewData().GetActiveWin()->SetClipboard(css::datatransfer::clipboard::SystemClipboard::create(comphelper::getProcessComponentContext()));
1539 CPPUNIT_ASSERT(pView2
);
1540 CPPUNIT_ASSERT(pView1
!= pView2
);
1541 CPPUNIT_ASSERT(pView1
->GetViewData().GetActiveWin()->GetClipboard() != pView2
->GetViewData().GetActiveWin()->GetClipboard());
1544 pView1
->SetCursor(0, 0);
1545 pView1
->GetViewFrame()->GetBindings().Execute(SID_COPY
);
1548 pView2
->SetCursor(1, 0);
1549 pView2
->GetViewFrame()->GetBindings().Execute(SID_COPY
);
1551 // paste text view 1
1552 pView1
->SetCursor(0, 1);
1553 pView1
->GetViewFrame()->GetBindings().Execute(SID_PASTE
);
1555 // paste text view 2
1556 pView2
->SetCursor(1, 1);
1557 pView2
->GetViewFrame()->GetBindings().Execute(SID_PASTE
);
1559 CPPUNIT_ASSERT_EQUAL(OUString("TestCopy1"), pDoc
->GetString(ScAddress(0, 1, 0)));
1560 CPPUNIT_ASSERT_EQUAL(OUString("TestCopy2"), pDoc
->GetString(ScAddress(1, 1, 0)));
1562 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
1563 SfxLokHelper::setView(nView1
);
1564 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
1567 void ScTiledRenderingTest::testIMESupport()
1569 comphelper::LibreOfficeKit::setActive();
1571 ScModelObj
* pModelObj
= createDoc("empty.ods");
1572 VclPtr
<vcl::Window
> pDocWindow
= pModelObj
->getDocWindow();
1573 ScDocument
* pDoc
= pModelObj
->GetDocument();
1575 ScTabViewShell
* pView
= dynamic_cast<ScTabViewShell
*>(SfxViewShell::Current());
1576 CPPUNIT_ASSERT(pView
);
1578 pView
->SetCursor(0, 0);
1579 // sequence of chinese IME compositions when 'nihao' is typed in an IME
1580 const std::vector
<OString
> aUtf8Inputs
{ "å¹´", "ä½ ", "ä½ å¥½", "ä½ å“ˆ", "ä½ å¥½", "ä½ å¥½" };
1581 std::vector
<OUString
> aInputs
;
1582 std::transform(aUtf8Inputs
.begin(), aUtf8Inputs
.end(),
1583 std::back_inserter(aInputs
), [](OString aInput
) {
1584 return OUString::fromUtf8(aInput
);
1586 for (const auto& aInput
: aInputs
)
1588 pDocWindow
->PostExtTextInputEvent(VclEventId::ExtTextInput
, aInput
);
1590 pDocWindow
->PostExtTextInputEvent(VclEventId::EndExtTextInput
, "");
1592 // commit the string to the cell
1593 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::RETURN
);
1594 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::RETURN
);
1595 Scheduler::ProcessEventsToIdle();
1597 CPPUNIT_ASSERT_EQUAL(aInputs
[aInputs
.size() - 1], pDoc
->GetString(ScAddress(0, 0, 0)));
1600 void ScTiledRenderingTest::testFilterDlg()
1602 comphelper::LibreOfficeKit::setActive();
1604 createDoc("empty.ods");
1607 SfxViewShell
* pView1
= SfxViewShell::Current();
1608 int nView1
= SfxLokHelper::getView();
1611 SfxLokHelper::createView();
1612 SfxViewShell
* pView2
= SfxViewShell::Current();
1613 CPPUNIT_ASSERT(pView1
!= pView2
);
1615 pView2
->GetViewFrame()->GetDispatcher()->Execute(SID_FILTER
,
1616 SfxCallMode::SLOT
|SfxCallMode::RECORD
);
1619 Scheduler::ProcessEventsToIdle();
1620 SfxChildWindow
* pRefWindow
= pView2
->GetViewFrame()->GetChildWindow(SID_FILTER
);
1621 CPPUNIT_ASSERT(pRefWindow
);
1624 SfxLokHelper::setView(nView1
);
1625 CPPUNIT_ASSERT_EQUAL(true, pView2
->GetViewFrame()->GetDispatcher()->IsLocked());
1626 CPPUNIT_ASSERT_EQUAL(false, pView1
->GetViewFrame()->GetDispatcher()->IsLocked());
1628 pRefWindow
->GetController()->response(RET_CANCEL
);
1630 CPPUNIT_ASSERT_EQUAL(false, pView2
->GetViewFrame()->GetDispatcher()->IsLocked());
1631 CPPUNIT_ASSERT_EQUAL(false, pView1
->GetViewFrame()->GetDispatcher()->IsLocked());
1633 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
1634 SfxLokHelper::setView(nView1
);
1635 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
1638 void ScTiledRenderingTest::testSpellOnlineParameter()
1640 ScModelObj
* pModelObj
= createDoc("empty.ods");
1641 ScDocument
* pDoc
= pModelObj
->GetDocument();
1642 bool bSet
= pDoc
->GetDocOptions().IsAutoSpell();
1644 uno::Sequence
<beans::PropertyValue
> params
=
1646 comphelper::makePropertyValue("Enable", uno::makeAny(!bSet
)),
1648 dispatchCommand(mxComponent
, ".uno:SpellOnline", params
);
1649 CPPUNIT_ASSERT_EQUAL(!bSet
, pDoc
->GetDocOptions().IsAutoSpell());
1651 // set the same state as now and we don't expect any change (no-toggle)
1654 comphelper::makePropertyValue("Enable", uno::makeAny(!bSet
)),
1656 dispatchCommand(mxComponent
, ".uno:SpellOnline", params
);
1657 CPPUNIT_ASSERT_EQUAL(!bSet
, pDoc
->GetDocOptions().IsAutoSpell());
1660 void ScTiledRenderingTest::testVbaRangeCopyPaste()
1662 comphelper::LibreOfficeKit::setActive();
1663 ScModelObj
* pModelObj
= createDoc("RangeCopyPaste.ods");
1664 ScDocShell
* pDocShell
= dynamic_cast< ScDocShell
* >( pModelObj
->GetEmbeddedObject() );
1665 CPPUNIT_ASSERT(pDocShell
);
1668 uno::Sequence
< uno::Any
> aOutParam
;
1669 uno::Sequence
< uno::Any
> aParams
;
1670 uno::Sequence
< sal_Int16
> aOutParamIndex
;
1672 SfxObjectShell::CallXScript(
1674 "vnd.sun.Star.script:Standard.Module1.Test_RangeCopyPaste?language=Basic&location=document",
1675 aParams
, aRet
, aOutParamIndex
, aOutParam
);
1677 CPPUNIT_ASSERT(!pDocShell
->GetClipData().is());
1680 void ScTiledRenderingTest::testInvalidationLoop()
1682 // Load the document with a form control.
1683 createDoc("invalidation-loop.fods");
1684 // Without the accompanying fix in place, this test would have never returned due to an infinite
1685 // invalidation loop between ScGridWindow::Paint() and vcl::Window::ImplPosSizeWindow().
1686 Scheduler::ProcessEventsToIdle();
1689 void ScTiledRenderingTest::testPageDownInvalidation()
1691 comphelper::LibreOfficeKit::setActive();
1693 ScModelObj
* pModelObj
= createDoc("empty.ods");
1694 ScViewData
* pViewData
= ScDocShell::GetViewData();
1695 CPPUNIT_ASSERT(pViewData
);
1697 int nView1
= SfxLokHelper::getView();
1698 ViewCallback aView1
;
1699 CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData
));
1701 SfxLokHelper::setView(nView1
);
1702 aView1
.m_bInvalidateTiles
= false;
1703 aView1
.m_aInvalidations
.clear();
1704 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, awt::Key::PAGEDOWN
, 0);
1705 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, awt::Key::PAGEDOWN
, 0);
1706 Scheduler::ProcessEventsToIdle();
1707 CPPUNIT_ASSERT(aView1
.m_bInvalidateTiles
);
1708 CPPUNIT_ASSERT_EQUAL(size_t(3), aView1
.m_aInvalidations
.size());
1709 CPPUNIT_ASSERT_EQUAL(tools::Rectangle(15, 15, 1230, 225), aView1
.m_aInvalidations
[0]);
1712 void ScTiledRenderingTest::testSheetChangeInvalidation()
1714 comphelper::LibreOfficeKit::setActive();
1716 ScModelObj
* pModelObj
= createDoc("two_sheets.ods");
1717 ScViewData
* pViewData
= ScDocShell::GetViewData();
1718 CPPUNIT_ASSERT(pViewData
);
1720 int nView1
= SfxLokHelper::getView();
1721 ViewCallback aView1
;
1722 CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData
));
1724 SfxLokHelper::setView(nView1
);
1725 aView1
.m_bInvalidateTiles
= false;
1726 aView1
.m_aInvalidations
.clear();
1727 aView1
.m_aInvalidationsParts
.clear();
1728 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::PAGEDOWN
| KEY_MOD1
);
1729 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::PAGEDOWN
| KEY_MOD1
);
1730 Scheduler::ProcessEventsToIdle();
1731 CPPUNIT_ASSERT(aView1
.m_bInvalidateTiles
);
1732 CPPUNIT_ASSERT_EQUAL(size_t(2), aView1
.m_aInvalidations
.size());
1733 CPPUNIT_ASSERT_EQUAL(tools::Rectangle(0, 0, 1310720, 268435456), aView1
.m_aInvalidations
[0]);
1734 CPPUNIT_ASSERT_EQUAL(tools::Rectangle(0, 0, 1000000000, 1000000000), aView1
.m_aInvalidations
[1]);
1735 CPPUNIT_ASSERT_EQUAL(size_t(1), aView1
.m_aInvalidationsParts
.size());
1736 CPPUNIT_ASSERT_EQUAL(pModelObj
->getPart(), aView1
.m_aInvalidationsParts
[0]);
1739 void ScTiledRenderingTest::testInsertDeletePageInvalidation()
1741 comphelper::LibreOfficeKit::setActive();
1743 ScModelObj
* pModelObj
= createDoc("insert_delete_sheet.ods");
1744 // the document has 1 sheet
1745 CPPUNIT_ASSERT_EQUAL(1, pModelObj
->getParts());
1746 ScViewData
* pViewData
= ScDocShell::GetViewData();
1747 CPPUNIT_ASSERT(pViewData
);
1749 int nView1
= SfxLokHelper::getView();
1750 ViewCallback aView1
;
1751 CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData
));
1753 SfxLokHelper::setView(nView1
);
1754 aView1
.m_bInvalidateTiles
= false;
1755 aView1
.m_aInvalidations
.clear();
1757 uno::Sequence
<beans::PropertyValue
> aArgs( comphelper::InitPropertySequence({
1758 { "Name", uno::Any(OUString("")) },
1759 { "Index", uno::Any(sal_Int32(1)) }
1761 comphelper::dispatchCommand(".uno:Insert", aArgs
);
1762 Scheduler::ProcessEventsToIdle();
1763 CPPUNIT_ASSERT(aView1
.m_bInvalidateTiles
);
1764 CPPUNIT_ASSERT_EQUAL(size_t(6), aView1
.m_aInvalidations
.size());
1765 CPPUNIT_ASSERT_EQUAL(tools::Rectangle(0, 0, 1000000000, 1000000000), aView1
.m_aInvalidations
[0]);
1766 CPPUNIT_ASSERT_EQUAL(2, pModelObj
->getParts());
1769 aView1
.m_bInvalidateTiles
= false;
1770 aView1
.m_aInvalidations
.clear();
1771 uno::Sequence
<beans::PropertyValue
> aArgs2( comphelper::InitPropertySequence({
1772 { "Index", uno::Any(sal_Int32(1)) }
1774 comphelper::dispatchCommand(".uno:Remove", aArgs2
);
1775 Scheduler::ProcessEventsToIdle();
1776 CPPUNIT_ASSERT(aView1
.m_bInvalidateTiles
);
1777 CPPUNIT_ASSERT_EQUAL(size_t(5), aView1
.m_aInvalidations
.size());
1778 CPPUNIT_ASSERT_EQUAL(tools::Rectangle(0, 0, 1000000000, 1000000000), aView1
.m_aInvalidations
[0]);
1779 CPPUNIT_ASSERT_EQUAL(1, pModelObj
->getParts());
1782 void ScTiledRenderingTest::testGetRowColumnHeadersInvalidation()
1784 comphelper::LibreOfficeKit::setActive();
1786 ScModelObj
* pModelObj
= createDoc("empty.ods");
1787 ScViewData
* pViewData
= ScDocShell::GetViewData();
1788 CPPUNIT_ASSERT(pViewData
);
1790 int nView1
= SfxLokHelper::getView();
1791 ViewCallback aView1
;
1792 CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData
));
1794 SfxLokHelper::setView(nView1
);
1795 aView1
.m_bInvalidateTiles
= false;
1796 aView1
.m_aInvalidations
.clear();
1797 tools::JsonWriter aJsonWriter1
;
1798 pModelObj
->getRowColumnHeaders(tools::Rectangle(0, 15, 19650, 5400), aJsonWriter1
);
1799 free(aJsonWriter1
.extractData());
1800 Scheduler::ProcessEventsToIdle();
1801 CPPUNIT_ASSERT(aView1
.m_bInvalidateTiles
);
1802 CPPUNIT_ASSERT_EQUAL(size_t(1), aView1
.m_aInvalidations
.size());
1803 CPPUNIT_ASSERT_EQUAL(tools::Rectangle(26775, 0, 49725, 13005), aView1
.m_aInvalidations
[0]);
1805 // Extend area top-to-bottom
1806 aView1
.m_bInvalidateTiles
= false;
1807 aView1
.m_aInvalidations
.clear();
1808 tools::JsonWriter aJsonWriter2
;
1809 pModelObj
->getRowColumnHeaders(tools::Rectangle(0, 5400, 19650, 9800), aJsonWriter2
);
1810 free(aJsonWriter2
.extractData());
1811 Scheduler::ProcessEventsToIdle();
1812 CPPUNIT_ASSERT(aView1
.m_bInvalidateTiles
);
1813 CPPUNIT_ASSERT_EQUAL(size_t(1), aView1
.m_aInvalidations
.size());
1814 CPPUNIT_ASSERT_EQUAL(tools::Rectangle(0, 13005, 49725, 19380), aView1
.m_aInvalidations
[0]);
1816 // Extend area left-to-right
1817 aView1
.m_bInvalidateTiles
= false;
1818 aView1
.m_aInvalidations
.clear();
1819 tools::JsonWriter aJsonWriter3
;
1820 pModelObj
->getRowColumnHeaders(tools::Rectangle(5400, 5400, 25050, 9800), aJsonWriter3
);
1821 free(aJsonWriter3
.extractData());
1822 Scheduler::ProcessEventsToIdle();
1823 CPPUNIT_ASSERT(aView1
.m_bInvalidateTiles
);
1824 CPPUNIT_ASSERT_EQUAL(size_t(1), aView1
.m_aInvalidations
.size());
1825 CPPUNIT_ASSERT_EQUAL(tools::Rectangle(49725, 0, 75225, 19380), aView1
.m_aInvalidations
[0]);
1828 void ScTiledRenderingTest::testJumpHorizontallyInvalidation()
1830 comphelper::LibreOfficeKit::setActive();
1832 ScModelObj
* pModelObj
= createDoc("empty.ods");
1833 ScViewData
* pViewData
= ScDocShell::GetViewData();
1834 CPPUNIT_ASSERT(pViewData
);
1836 int nView1
= SfxLokHelper::getView();
1837 ViewCallback aView1
;
1838 CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData
));
1840 SfxLokHelper::setView(nView1
);
1841 aView1
.m_bInvalidateTiles
= false;
1842 aView1
.m_aInvalidations
.clear();
1843 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::PAGEDOWN
| KEY_MOD2
);
1844 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::PAGEDOWN
| KEY_MOD2
);
1845 Scheduler::ProcessEventsToIdle();
1846 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::PAGEDOWN
| KEY_MOD2
);
1847 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::PAGEDOWN
| KEY_MOD2
);
1848 Scheduler::ProcessEventsToIdle();
1849 CPPUNIT_ASSERT(aView1
.m_bInvalidateTiles
);
1850 CPPUNIT_ASSERT_EQUAL(size_t(1), aView1
.m_aInvalidations
.size());
1851 CPPUNIT_ASSERT_EQUAL(tools::Rectangle(26775, 0, 39525, 13005), aView1
.m_aInvalidations
[0]);
1854 void ScTiledRenderingTest::testJumpToLastRowInvalidation()
1856 comphelper::LibreOfficeKit::setActive();
1858 ScModelObj
* pModelObj
= createDoc("empty.ods");
1859 ScViewData
* pViewData
= ScDocShell::GetViewData();
1860 CPPUNIT_ASSERT(pViewData
);
1862 int nView1
= SfxLokHelper::getView();
1863 ViewCallback aView1
;
1864 CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData
));
1866 SfxLokHelper::setView(nView1
);
1867 aView1
.m_bInvalidateTiles
= false;
1868 aView1
.m_aInvalidations
.clear();
1869 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::DOWN
| KEY_MOD1
);
1870 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::DOWN
| KEY_MOD1
);
1871 Scheduler::ProcessEventsToIdle();
1872 CPPUNIT_ASSERT(aView1
.m_bInvalidateTiles
);
1873 CPPUNIT_ASSERT_EQUAL(size_t(1), aView1
.m_aInvalidations
.size());
1874 CPPUNIT_ASSERT_EQUAL(tools::Rectangle(0, 13005, 26775, 127500255), aView1
.m_aInvalidations
[0]);
1877 // We need to ensure that views are not perterbed by rendering (!?) hmm ...
1878 void ScTiledRenderingTest::testRowColumnHeaders()
1880 comphelper::LibreOfficeKit::setActive();
1882 ScModelObj
* pModelObj
= createDoc("empty.ods");
1883 ScViewData
* pViewData
= ScDocShell::GetViewData();
1884 CPPUNIT_ASSERT(pViewData
);
1887 ViewCallback aView1
;
1888 int nView1
= SfxLokHelper::getView();
1889 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
1890 CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData
));
1893 SfxLokHelper::createView();
1894 int nView2
= SfxLokHelper::getView();
1895 ViewCallback aView2
;
1896 pModelObj
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
1897 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView2
);
1899 // ViewRowColumnHeaders test
1900 SfxLokHelper::setView(nView1
);
1901 tools::JsonWriter aJsonWriter1
;
1902 pModelObj
->getRowColumnHeaders(tools::Rectangle(65,723,10410,4695), aJsonWriter1
);
1903 OString aHeaders1
= aJsonWriter1
.extractAsOString();
1905 SfxLokHelper::setView(nView2
);
1907 pModelObj
->setClientVisibleArea(tools::Rectangle(0, 0, 22474, 47333));
1908 pModelObj
->setClientZoom(256, 256, 6636, 6636);
1909 tools::JsonWriter aJsonWriter2
;
1910 pModelObj
->getRowColumnHeaders(tools::Rectangle(65,723,10410,4695), aJsonWriter2
);
1911 OString aHeaders2
= aJsonWriter2
.extractAsOString();
1913 // Check vs. view #1
1914 SfxLokHelper::setView(nView1
);
1915 tools::JsonWriter aJsonWriter3
;
1916 pModelObj
->getRowColumnHeaders(tools::Rectangle(65,723,10410,4695), aJsonWriter3
);
1917 OString aHeaders1_2
= aJsonWriter3
.extractAsOString();
1918 CPPUNIT_ASSERT_EQUAL(aHeaders1
, aHeaders1_2
);
1920 // Check vs. view #2
1921 SfxLokHelper::setView(nView2
);
1922 tools::JsonWriter aJsonWriter4
;
1923 pModelObj
->getRowColumnHeaders(tools::Rectangle(65,723,10410,4695), aJsonWriter4
);
1924 OString aHeaders2_2
= aJsonWriter4
.extractAsOString();
1925 CPPUNIT_ASSERT_EQUAL(aHeaders2
, aHeaders2_2
);
1927 SfxLokHelper::setView(nView1
);
1928 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
1929 SfxLokHelper::setView(nView2
);
1930 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
1933 // Helper structs for setup and testing of ScModelObj::getSheetGeometryData()
1942 typedef std::vector
<SpanEntry
> SpanList
;
1946 // TODO: Add group info too to test.
1948 void setDataToDoc(ScDocument
* pDoc
, bool bCol
) const
1950 SCCOLROW nStart
= 0;
1952 for (const auto& rSpan
: aSizes
)
1956 for (SCCOLROW nIdx
= nStart
; nIdx
<= rSpan
.nEnd
; ++nIdx
)
1957 pDoc
->SetColWidthOnly(nIdx
, 0, rSpan
.nVal
);
1960 pDoc
->SetRowHeightOnly(nStart
, rSpan
.nEnd
, 0, rSpan
.nVal
);
1962 nStart
= rSpan
.nEnd
+ 1;
1967 for (const auto& rSpan
: aHidden
)
1970 pDoc
->SetColHidden(nStart
, rSpan
.nEnd
, 0, !!rSpan
.nVal
);
1972 pDoc
->SetRowHidden(nStart
, rSpan
.nEnd
, 0, !!rSpan
.nVal
);
1974 nStart
= rSpan
.nEnd
+ 1;
1977 // There is no ScDocument interface to set ScTable::mpFilteredCols
1978 // It seems ScTable::mpFilteredCols is not really used !?
1984 for (const auto& rSpan
: aFiltered
)
1986 pDoc
->SetRowFiltered(nStart
, rSpan
.nEnd
, 0, !!rSpan
.nVal
);
1987 nStart
= rSpan
.nEnd
+ 1;
1991 void testPropertyTree(const boost::property_tree::ptree
& rTree
, bool bCol
) const
1993 struct SpanListWithKey
1996 const SpanList
& rSpanList
;
1999 const SpanListWithKey aPairList
[] = {
2000 { "sizes", aSizes
},
2001 { "hidden", aHidden
},
2002 { "filtered", aFiltered
}
2005 for (const auto& rEntry
: aPairList
)
2007 // There is no ScDocument interface to set ScTable::mpFilteredCols
2008 // It seems ScTable::mpFilteredCols is not really used !?
2009 if (bCol
&& rEntry
.aKey
== "filtered")
2012 bool bBooleanValue
= rEntry
.aKey
!= "sizes";
2013 OString aExpectedEncoding
;
2015 for (const auto& rSpan
: rEntry
.rSpanList
)
2017 size_t nVal
= rSpan
.nVal
;
2018 if (bBooleanValue
&& bFirst
)
2019 nVal
= static_cast<size_t>(!!nVal
);
2020 if (!bBooleanValue
|| bFirst
)
2021 aExpectedEncoding
+= OString::number(nVal
) + ":";
2022 aExpectedEncoding
+= OString::number(rSpan
.nEnd
) + " ";
2026 // Get the tree's value for the property key ("sizes"/"hidden"/"filtered").
2027 OString aTreeValue
= rTree
.get
<std::string
>(rEntry
.aKey
.getStr()).c_str();
2029 CPPUNIT_ASSERT_EQUAL(aExpectedEncoding
, aTreeValue
);
2034 class SheetGeometryData
2045 { { STD_COL_WIDTH
, MAXCOL
} },
2054 { { ScGlobal::nStdRowHeight
, MAXROW
} },
2062 SheetGeometryData(const SheetDimData
& rCols
, const SheetDimData
& rRows
) :
2063 aCols(rCols
), aRows(rRows
)
2066 void setDataToDoc(ScDocument
* pDoc
) const
2068 aCols
.setDataToDoc(pDoc
, true);
2069 aRows
.setDataToDoc(pDoc
, false);
2072 void parseTest(const OString
& rJSON
) const
2074 // Assumes all flags passed to getSheetGeometryData() are true.
2075 boost::property_tree::ptree aTree
;
2076 std::stringstream
aStream(rJSON
.getStr());
2077 boost::property_tree::read_json(aStream
, aTree
);
2079 CPPUNIT_ASSERT_EQUAL(OString(".uno:SheetGeometryData"), OString(aTree
.get
<std::string
>("commandName").c_str()));
2081 aCols
.testPropertyTree(aTree
.get_child("columns"), true);
2082 aRows
.testPropertyTree(aTree
.get_child("rows"), false);
2086 // getSheetGeometryData() should return the exact same message
2087 // irrespective of client zoom and view-area. Switching views
2088 // should also not alter it.
2089 void ScTiledRenderingTest::testSheetGeometryDataInvariance()
2091 comphelper::LibreOfficeKit::setActive();
2093 ScModelObj
* pModelObj
= createDoc("empty.ods");
2094 const SheetGeometryData
aSGData(
2099 { STD_COL_WIDTH
, 20 },
2100 { 2*STD_COL_WIDTH
, 26 },
2101 { STD_COL_WIDTH
, MAXCOL
}
2145 ScDocument
* pDoc
= pModelObj
->GetDocument();
2147 ScViewData
* pViewData
= ScDocShell::GetViewData();
2148 CPPUNIT_ASSERT(pViewData
);
2151 ViewCallback aView1
;
2152 int nView1
= SfxLokHelper::getView();
2153 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
2156 SfxLokHelper::createView();
2157 int nView2
= SfxLokHelper::getView();
2158 ViewCallback aView2
;
2159 pModelObj
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
2160 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView2
);
2162 // Try with the default empty document once (nIdx = 0) and then with sheet geometry settings (nIdx = 1)
2163 for (size_t nIdx
= 0; nIdx
< 2; ++nIdx
)
2166 aSGData
.setDataToDoc(pDoc
);
2168 SfxLokHelper::setView(nView1
);
2169 OString aGeomStr1
= pModelObj
->getSheetGeometryData(/*bColumns*/ true, /*bRows*/ true, /*bSizes*/ true,
2170 /*bHidden*/ true, /*bFiltered*/ true, /*bGroups*/ true);
2172 SfxLokHelper::setView(nView2
);
2173 pModelObj
->setClientVisibleArea(tools::Rectangle(0, 0, 22474, 47333));
2174 pModelObj
->setClientZoom(256, 256, 6636, 6636);
2175 OString aGeomStr2
= pModelObj
->getSheetGeometryData(/*bColumns*/ true, /*bRows*/ true, /*bSizes*/ true,
2176 /*bHidden*/ true, /*bFiltered*/ true, /*bGroups*/ true);
2178 // Check vs. view #1
2179 SfxLokHelper::setView(nView1
);
2180 OString aGeomStr1_2
= pModelObj
->getSheetGeometryData(/*bColumns*/ true, /*bRows*/ true, /*bSizes*/ true,
2181 /*bHidden*/ true, /*bFiltered*/ true, /*bGroups*/ true);
2182 CPPUNIT_ASSERT_EQUAL(aGeomStr1
, aGeomStr1_2
);
2184 // Check vs. view #2
2185 SfxLokHelper::setView(nView2
);
2186 OString aGeomStr2_2
= pModelObj
->getSheetGeometryData(/*bColumns*/ true, /*bRows*/ true, /*bSizes*/ true,
2187 /*bHidden*/ true, /*bFiltered*/ true, /*bGroups*/ true);
2188 CPPUNIT_ASSERT_EQUAL(aGeomStr2
, aGeomStr2_2
);
2191 SfxLokHelper::setView(nView1
);
2192 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
2193 SfxLokHelper::setView(nView2
);
2194 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
2197 void ScTiledRenderingTest::testSheetGeometryDataCorrectness()
2199 comphelper::LibreOfficeKit::setActive();
2201 ScModelObj
* pModelObj
= createDoc("empty.ods");
2202 const SheetGeometryData
aSGData(
2207 { STD_COL_WIDTH
, 20 },
2208 { 2*STD_COL_WIDTH
, 26 },
2209 { STD_COL_WIDTH
, MAXCOL
}
2253 ScDocument
* pDoc
= pModelObj
->GetDocument();
2255 ScViewData
* pViewData
= ScDocShell::GetViewData();
2256 CPPUNIT_ASSERT(pViewData
);
2259 ViewCallback aView1
;
2260 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
2262 // with the default empty sheet and test the JSON encoding.
2263 OString aGeomDefaultStr
= pModelObj
->getSheetGeometryData(/*bColumns*/ true, /*bRows*/ true, /*bSizes*/ true,
2264 /*bHidden*/ true, /*bFiltered*/ true, /*bGroups*/ true);
2265 SheetGeometryData().parseTest(aGeomDefaultStr
);
2267 // Apply geometry settings to the sheet and then test the resulting JSON encoding.
2268 aSGData
.setDataToDoc(pDoc
);
2269 OString aGeomStr
= pModelObj
->getSheetGeometryData(/*bColumns*/ true, /*bRows*/ true, /*bSizes*/ true,
2270 /*bHidden*/ true, /*bFiltered*/ true, /*bGroups*/ true);
2271 aSGData
.parseTest(aGeomStr
);
2273 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
2276 void ScTiledRenderingTest::testDeleteCellMultilineContent()
2278 comphelper::LibreOfficeKit::setActive();
2280 ScModelObj
* pModelObj
= createDoc("multiline.ods");
2281 CPPUNIT_ASSERT(pModelObj
);
2282 ScViewData
* pViewData
= ScDocShell::GetViewData();
2283 CPPUNIT_ASSERT(pViewData
);
2284 ScDocShell
* pDocSh
= dynamic_cast< ScDocShell
* >( pModelObj
->GetEmbeddedObject() );
2285 CPPUNIT_ASSERT(pDocSh
);
2288 ViewCallback aView1
;
2289 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
2290 CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData
));
2292 aView1
.m_sInvalidateHeader
= "";
2293 ScDocument
& rDoc
= pDocSh
->GetDocument();
2294 sal_uInt16 nRow1Height
= rDoc
.GetRowHeight(static_cast<SCROW
>(0), static_cast<SCTAB
>(0), false);
2296 // delete multiline cell content in view #1
2297 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::DOWN
);
2298 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::DOWN
);
2299 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::DELETE
);
2300 pModelObj
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::DELETE
);
2301 Scheduler::ProcessEventsToIdle();
2303 // check if the row header has been invalidated and if the involved row is of the expected height
2304 CPPUNIT_ASSERT_EQUAL(OString("row"), aView1
.m_sInvalidateHeader
);
2305 sal_uInt16 nRow2Height
= rDoc
.GetRowHeight(static_cast<SCROW
>(0), static_cast<SCTAB
>(0), false);
2306 CPPUNIT_ASSERT_EQUAL(nRow1Height
, nRow2Height
);
2307 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
2312 CPPUNIT_TEST_SUITE_REGISTRATION(ScTiledRenderingTest
);
2314 CPPUNIT_PLUGIN_IMPLEMENT();
2316 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */