/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// Start text edit of the empty title shape.
SdPage* pActualPage = pViewShell->GetActualPage();
SdrObject* pObject = pActualPage->GetObj(0);
SdrView* pView = pViewShell->GetView();
pView->SdrBeginTextEdit(pObject);
CPPUNIT_ASSERT(pView->GetTextEditObject());
// Check that the top left 256x256px tile would be invalidated.
CPPUNIT_ASSERT(!m_aInvalidation.IsEmpty());
::tools::Rectangle aTopLeft(0, 0, 256*15, 256*15); // 1 px = 15 twips, assuming 96 DPI.
CPPUNIT_ASSERT(m_aInvalidation.Overlaps(aTopLeft));
}
CPPUNIT_ASSERT(pView->GetTextEditObject());
EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView(); // Did we manage to enter a second character?
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), rEditView.GetSelection().start.nIndex);
ESelection aWordSelection(0, 0, 0, 2); // start para, start char, end para, end char.
rEditView.SetSelection(aWordSelection); // Did we enter the expected character?
CPPUNIT_ASSERT_EQUAL(u"xx"_ustr, rEditView.GetSelected());
}
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testPostMouseEvent)
{
SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pActualPage = pViewShell->GetActualPage();
SdrObject* pObject = pActualPage->GetObj(0);
CPPUNIT_ASSERT_EQUAL(SdrObjKind::TitleText, pObject->GetObjIdentifier());
SdrTextObj* pTextObj = static_cast<SdrTextObj*>(pObject);
SdrView* pView = pViewShell->GetView();
pView->MarkObj(pTextObj, pView->GetSdrPageView());
SfxStringItem aInputString(SID_ATTR_CHAR, u"x"_ustr);
pViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR,
SfxCallMode::SYNCHRON, { &aInputString });
CPPUNIT_ASSERT(pView->GetTextEditObject());
EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView(); // Did we manage to go after the first character?
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), rEditView.GetSelection().start.nIndex);
vcl::Cursor* pCursor = rEditView.GetCursor();
Point aPosition(pCursor->GetPos().getX(), pCursor->GetPos().getY() + pCursor->GetSize().Height() / 2);
aPosition.setX(aPosition.getX() - 1000);
pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
o3tl::toTwips(aPosition.getX(), o3tl::Length::mm100), o3tl::toTwips(aPosition.getY(), o3tl::Length::mm100),
1, MOUSE_LEFT, 0);
pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
o3tl::toTwips(aPosition.getX(), o3tl::Length::mm100), o3tl::toTwips(aPosition.getY(), o3tl::Length::mm100),
1, MOUSE_LEFT, 0);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT(pView->GetTextEditObject()); // The new cursor position must be before the first word.
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), rEditView.GetSelection().start.nIndex);
}
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSetTextSelection)
{
SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
uno::Reference<container::XIndexAccess> xDrawPage(pXImpressDocument->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
xShape->setString(u"Aaa bbb."_ustr); // Create a selection on the second word.
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pActualPage = pViewShell->GetActualPage();
SdrObject* pObject = pActualPage->GetObj(0);
SdrView* pView = pViewShell->GetView();
pView->SdrBeginTextEdit(pObject);
CPPUNIT_ASSERT(pView->GetTextEditObject());
EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
ESelection aWordSelection(0, 4, 0, 7);
rEditView.SetSelection(aWordSelection); // Did we indeed manage to select the second word?
CPPUNIT_ASSERT_EQUAL(u"bbb"_ustr, rEditView.GetSelected());
// Now use setTextSelection() to move the end of the selection 1000 twips right.
vcl::Cursor* pCursor = rEditView.GetCursor();
Point aEnd = pCursor->GetPos();
aEnd.setX(aEnd.getX() + 1000);
pXImpressDocument->setTextSelection(LOK_SETTEXTSELECTION_END, aEnd.getX(), aEnd.getY()); // The new selection must include the ending dot, too -- but not the first word.
CPPUNIT_ASSERT_EQUAL(u"bbb."_ustr, rEditView.GetSelected());
}
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testGetTextSelection)
{
SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
uno::Reference<container::XIndexAccess> xDrawPage(pXImpressDocument->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
xShape->setString(u"Shape"_ustr); // Create a selection on the shape text.
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pActualPage = pViewShell->GetActualPage();
SdrObject* pObject = pActualPage->GetObj(0);
SdrView* pView = pViewShell->GetView();
pView->SdrBeginTextEdit(pObject);
CPPUNIT_ASSERT(pView->GetTextEditObject());
EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
ESelection aWordSelection(0, 0, 0, 5);
rEditView.SetSelection(aWordSelection); // Did we indeed manage to copy the selected text?
CPPUNIT_ASSERT_EQUAL("Shape"_ostr, apitest::helper::transferable::getTextSelection(pXImpressDocument->getSelection(), "text/plain;charset=utf-8"_ostr));
// Make sure returned RTF is not empty.
CPPUNIT_ASSERT(!apitest::helper::transferable::getTextSelection(pXImpressDocument->getSelection(), "text/rtf"_ostr).isEmpty());
}
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSetGraphicSelection)
{
SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pPage = pViewShell->GetActualPage();
SdrObject* pObject = pPage->GetObj(0);
SdrHdlList handleList(nullptr);
pObject->AddToHdlList(handleList); // Make sure the rectangle has 8 handles: at each corner and at the center of each edge.
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(8), handleList.GetHdlCount()); // Take the bottom center one.
SdrHdl* pHdl = handleList.GetHdl(6);
CPPUNIT_ASSERT_EQUAL(int(SdrHdlKind::Lower), static_cast<int>(pHdl->GetKind()));
::tools::Rectangle aShapeBefore = pObject->GetSnapRect(); // Resize.
pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_START, o3tl::toTwips(pHdl->GetPos().getX(), o3tl::Length::mm100), o3tl::toTwips(pHdl->GetPos().getY(), o3tl::Length::mm100));
pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_END, o3tl::toTwips(pHdl->GetPos().getX(), o3tl::Length::mm100), o3tl::toTwips(pHdl->GetPos().getY() + 1000, o3tl::Length::mm100));
// Assert that view shell ID tracking works.
sal_Int32 nView1 = SfxLokHelper::getView();
SdDrawDocument* pDocument = pXImpressDocument->GetDoc();
sd::UndoManager* pUndoManager = pDocument->GetUndoManager();
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pUndoManager->GetUndoActionCount()); auto pListAction = dynamic_cast<SfxListUndoAction*>(pUndoManager->GetUndoAction());
CPPUNIT_ASSERT(pListAction); for (size_t i = 0; i < pListAction->maUndoActions.size(); ++i) // The second item was -1 here, view shell ID wasn't known.
CPPUNIT_ASSERT_EQUAL(ViewShellId(nView1), pListAction->GetUndoAction(i)->GetViewShellId());
::tools::Rectangle aShapeAfter = pObject->GetSnapRect(); // Check that a resize happened, but aspect ratio is not kept.
CPPUNIT_ASSERT_EQUAL(aShapeBefore.getOpenWidth(), aShapeAfter.getOpenWidth());
CPPUNIT_ASSERT(aShapeBefore.getOpenHeight() < aShapeAfter.getOpenHeight());
}
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testUndoShells)
{ // Load a document and set the page size.
SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
{
{"AttributePageSize.Width", uno::Any(static_cast<sal_Int32>(10000))},
{"AttributePageSize.Height", uno::Any(static_cast<sal_Int32>(10000))},
}));
dispatchCommand(mxComponent, u".uno:AttributePageSize"_ustr, aPropertyValues);
// Assert that view shell ID tracking works for SdUndoAction subclasses.
SdDrawDocument* pDocument = pXImpressDocument->GetDoc();
sd::UndoManager* pUndoManager = pDocument->GetUndoManager();
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pUndoManager->GetUndoActionCount());
sal_Int32 nView1 = SfxLokHelper::getView(); // This was -1, SdUndoGroup did not track what view shell created it.
CPPUNIT_ASSERT_EQUAL(ViewShellId(nView1), pUndoManager->GetUndoAction()->GetViewShellId());
}
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testResetSelection)
{
SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
uno::Reference<container::XIndexAccess> xDrawPage(pXImpressDocument->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
xShape->setString(u"Aaa bbb."_ustr); // Create a selection on the second word.
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pActualPage = pViewShell->GetActualPage();
SdrObject* pObject = pActualPage->GetObj(0);
SdrView* pView = pViewShell->GetView();
pView->SdrBeginTextEdit(pObject);
CPPUNIT_ASSERT(pView->GetTextEditObject());
EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
ESelection aWordSelection(0, 4, 0, 7);
rEditView.SetSelection(aWordSelection); // Did we indeed manage to select the second word?
CPPUNIT_ASSERT_EQUAL(u"bbb"_ustr, rEditView.GetSelected());
// Now use resetSelection() to reset the selection.
pXImpressDocument->resetSelection();
CPPUNIT_ASSERT(!pView->GetTextEditObject());
}
namespace
{
std::vector<OUString> getCurrentParts(SdXImpressDocument* pDocument)
{ int parts = pDocument->getParts();
std::vector<OUString> result;
result.reserve(parts); for (int i = 0; i < parts; i++)
{
result.push_back(pDocument->getPartName(i));
}
// Select the table by marking it + starting and ending text edit.
SdrView* pView = pViewShell->GetView();
pView->MarkObj(pObject, pView->GetSdrPageView());
pView->SdrBeginTextEdit(pObject);
pView->SdrEndTextEdit();
// Now undo the resize.
pXImpressDocument->GetDocShell()->GetUndoManager()->Undo();
// Check the undo result.
sal_Int32 nActualRow1 = xRow1->getPropertyValue(u"Size"_ustr).get<sal_Int32>();
CPPUNIT_ASSERT_EQUAL(nExpectedRow1, nActualRow1);
sal_Int32 nActualRow2 = xRow2->getPropertyValue(u"Size"_ustr).get<sal_Int32>(); // Expected was 4000, actual was 4572, i.e. the second row after undo was larger than expected.
CPPUNIT_ASSERT_EQUAL(nExpectedRow2, nActualRow2);
}
// Select the table by marking it + starting and ending text edit.
SdrView* pView = pViewShell->GetView();
pView->MarkObj(pObject, pView->GetSdrPageView());
pView->SdrBeginTextEdit(pObject);
pView->SdrEndTextEdit();
// Resize the left column, decrease its width by 1 cm.
Point aInnerRowEdge = pObject->GetSnapRect().Center();
pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_START, o3tl::toTwips(aInnerRowEdge.getX(), o3tl::Length::mm100), o3tl::toTwips(aInnerRowEdge.getY(), o3tl::Length::mm100));
pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_END, o3tl::toTwips(aInnerRowEdge.getX() - 1000, o3tl::Length::mm100), o3tl::toTwips(aInnerRowEdge.getY(), o3tl::Length::mm100));
// Select the shape in the second view.
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pActualPage = pViewShell->GetActualPage();
SdrObject* pObject = pActualPage->GetObj(0);
SdrView* pView = pViewShell->GetView();
pView->MarkObj(pObject, pView->GetSdrPageView());
Scheduler::ProcessEventsToIdle();
// First view notices that there was a selection change in the other view.
CPPUNIT_ASSERT(aView1.m_bGraphicViewSelectionInvalidated); // Second view notices that there was a selection change in its own view.
CPPUNIT_ASSERT(aView2.m_bGraphicSelectionInvalidated);
}
// Select the shape in the second view.
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pActualPage = pViewShell->GetActualPage();
SdrObject* pObject = pActualPage->GetObj(0);
SdrView* pView = pViewShell->GetView();
pView->MarkObj(pObject, pView->GetSdrPageView());
Scheduler::ProcessEventsToIdle(); // First view notices that there was a selection change in the other view.
CPPUNIT_ASSERT(aView1.m_bGraphicViewSelectionInvalidated);
pView->UnmarkAllObj(pView->GetSdrPageView());
// Now switch to the second part in the second view.
pXImpressDocument->setPart(1);
aView2.m_nPart = 1;
aView1.m_bGraphicViewSelectionInvalidated = false;
pActualPage = pViewShell->GetActualPage();
pObject = pActualPage->GetObj(0);
pView->MarkObj(pObject, pView->GetSdrPageView());
Scheduler::ProcessEventsToIdle(); // First view ignores view selection, as it would be for part 1, and it's in part 0. // This failed when the "part" was always 0 in the callback.
CPPUNIT_ASSERT(!aView1.m_bGraphicViewSelectionInvalidated);
}
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCursorViews)
{ // Create the first view.
SdXImpressDocument* pXImpressDocument = createDoc("title-shape.odp"); int nView1 = SfxLokHelper::getView();
SdTestViewCallback aView1;
// Begin text edit on the only object on the slide.
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdrView* pView = pViewShell->GetView();
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT(pView->IsTextEdit());
// Make sure that cursor state is not changed just because we create a second view.
aView1.m_bCursorVisibleChanged = false;
SfxLokHelper::createView();
pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT(!aView1.m_bCursorVisibleChanged);
// Make sure that typing in the first view causes an invalidation in the // second view as well, even if the second view was created after begin // text edit in the first view.
SdTestViewCallback aView2; // This failed: the second view didn't get a lock notification, even if the // first view already started text edit.
CPPUNIT_ASSERT(aView2.m_bViewLock);
SfxLokHelper::setView(nView1);
aView2.m_bTilesInvalidated = false;
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
Scheduler::ProcessEventsToIdle(); // This failed: the second view was not invalidated when pressing a key in // the first view.
CPPUNIT_ASSERT(aView2.m_bTilesInvalidated);
}
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCursorVisibility_SingleClick)
{ // Single-clicking in a text box enters editing only // when it's on the text, even if it's the default text.
// Begin text edit on the only object on the slide.
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pActualPage = pViewShell->GetActualPage();
SdrObject* pObject1 = pActualPage->GetObj(0);
CPPUNIT_ASSERT(pObject1 != nullptr);
CPPUNIT_ASSERT_EQUAL(SdrObjKind::TitleText, pObject1->GetObjIdentifier());
SdrTextObj* pTextObject = static_cast<SdrTextObj*>(pObject1);
// Click once outside of the text (in the first quartile) => no editing. const ::tools::Rectangle aRect = pTextObject->GetCurrentBoundRect(); constauto cornerX = o3tl::toTwips(aRect.Left() + (aRect.getOpenWidth() / 4), o3tl::Length::mm100); constauto cornerY = o3tl::toTwips(aRect.Top() + (aRect.getOpenHeight() / 4), o3tl::Length::mm100);
pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
cornerX, cornerY,
1, MOUSE_LEFT, 0);
pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
cornerX, cornerY,
1, MOUSE_LEFT, 0);
Scheduler::ProcessEventsToIdle();
// No editing.
CPPUNIT_ASSERT(!pViewShell->GetView()->IsTextEdit());
CPPUNIT_ASSERT(!aView1.m_bCursorVisible);
// Click again, now on the text, in the center, to start editing. constauto centerX = o3tl::toTwips(aRect.Left() + (aRect.getOpenWidth() / 2), o3tl::Length::mm100); constauto centerY = o3tl::toTwips(aRect.Top() + (aRect.getOpenHeight() / 2), o3tl::Length::mm100);
pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
centerX, centerY,
1, MOUSE_LEFT, 0);
pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
centerX, centerY,
1, MOUSE_LEFT, 0);
Scheduler::ProcessEventsToIdle();
// We must be in text editing mode and have cursor visible.
CPPUNIT_ASSERT(pViewShell->GetView()->IsTextEdit());
CPPUNIT_ASSERT(aView1.m_bCursorVisible);
}
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCursorVisibility_DoubleClick)
{ // Double-clicking anywhere in the TextBox should start editing.
// Create the first view.
SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
SdTestViewCallback aView1;
// Begin text edit on the only object on the slide.
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pActualPage = pViewShell->GetActualPage();
SdrObject* pObject1 = pActualPage->GetObj(0);
CPPUNIT_ASSERT(pObject1 != nullptr);
CPPUNIT_ASSERT_EQUAL(SdrObjKind::TitleText, pObject1->GetObjIdentifier());
SdrTextObj* pTextObject = static_cast<SdrTextObj*>(pObject1);
// We must be in text editing mode and have cursor visible.
CPPUNIT_ASSERT(pViewShell->GetView()->IsTextEdit());
CPPUNIT_ASSERT(aView1.m_bCursorVisible);
}
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCursorVisibility_MultiView)
{ // Create the first view.
SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp"); constint nView1 = SfxLokHelper::getView();
SdTestViewCallback aView1;
// Begin text edit on the only object on the slide.
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pActualPage = pViewShell->GetActualPage();
SdrObject* pObject1 = pActualPage->GetObj(0);
CPPUNIT_ASSERT(pObject1);
CPPUNIT_ASSERT_EQUAL(SdrObjKind::TitleText, pObject1->GetObjIdentifier());
SdrTextObj* pTextObject = static_cast<SdrTextObj*>(pObject1);
// Make sure that cursor state is not changed just because we create a second view.
SfxLokHelper::createView();
pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); constint nView2 = SfxLokHelper::getView();
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(false, aView1.m_bCursorVisibleChanged);
CPPUNIT_ASSERT_EQUAL(false, aView1.m_aViewCursorVisibilities[nView2]);
// Also check that the second view gets the notifications.
SdTestViewCallback aView2;
// We must be in text editing mode and have cursor visible.
CPPUNIT_ASSERT(pViewShell->GetView()->IsTextEdit());
CPPUNIT_ASSERT(aView1.m_bCursorVisible);
CPPUNIT_ASSERT_EQUAL(false, aView1.m_aViewCursorVisibilities[nView2]);
// Begin text edit on the only object on the slide.
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pActualPage = pViewShell->GetActualPage();
SdrObject* pObject1 = pActualPage->GetObj(0);
CPPUNIT_ASSERT(pObject1 != nullptr);
CPPUNIT_ASSERT_EQUAL(SdrObjKind::TitleText, pObject1->GetObjIdentifier());
SdrTextObj* pTextObject = static_cast<SdrTextObj*>(pObject1);
// Click once on the text to start editing. const ::tools::Rectangle aRect = pTextObject->GetCurrentBoundRect(); constauto centerX = o3tl::toTwips(aRect.Left() + (aRect.getOpenWidth() / 2), o3tl::Length::mm100); constauto centerY = o3tl::toTwips(aRect.Top() + (aRect.getOpenHeight() / 2), o3tl::Length::mm100);
pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
centerX, centerY,
1, MOUSE_LEFT, 0);
pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
centerX, centerY,
1, MOUSE_LEFT, 0);
Scheduler::ProcessEventsToIdle();
// We must be in text editing mode and have cursor visible.
CPPUNIT_ASSERT(pViewShell->GetView()->IsTextEdit());
CPPUNIT_ASSERT(aView1.m_bCursorVisible);
// End editing by pressing the escape key.
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
Scheduler::ProcessEventsToIdle();
// We must be in text editing mode and have cursor visible.
CPPUNIT_ASSERT(!pViewShell->GetView()->IsTextEdit());
CPPUNIT_ASSERT_EQUAL(false, aView1.m_bCursorVisible);
}
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testViewLock)
{ // Load a document that has a shape and create two views.
SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
SdTestViewCallback aView1;
SfxLokHelper::createView();
pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
// Begin text edit in the second view and assert that the first gets a lock // notification.
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pActualPage = pViewShell->GetActualPage();
SdrObject* pObject = pActualPage->GetObj(0);
SdrView* pView = pViewShell->GetView();
aView1.m_bViewLock = false;
pView->SdrBeginTextEdit(pObject);
CPPUNIT_ASSERT(aView1.m_bViewLock);
// End text edit in the second view, and assert that the lock is removed in // the first view.
pView->SdrEndTextEdit();
CPPUNIT_ASSERT(!aView1.m_bViewLock);
}
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testUndoLimiting)
{ // Create the first view.
SdXImpressDocument* pXImpressDocument = createDoc("title-shape.odp");
sd::ViewShell* pViewShell1 = pXImpressDocument->GetDocShell()->GetViewShell(); int nView1 = SfxLokHelper::getView();
SfxLokHelper::createView();
sd::ViewShell* pViewShell2 = pXImpressDocument->GetDocShell()->GetViewShell();
CPPUNIT_ASSERT(pViewShell1 != pViewShell2);
// Begin text edit on the only object on the slide.
SfxLokHelper::setView(nView1);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT(pViewShell1->GetView()->IsTextEdit());
// Now check view1 can undo action
{
SfxRequest aReq1(SID_UNDO, SfxCallMode::SLOT, pXImpressDocument->GetDocShell()->GetDoc()->GetPool());
aReq1.AppendItem(SfxUInt16Item(SID_UNDO, 1));
pViewShell1->ExecuteSlot(aReq1);
CPPUNIT_ASSERT(aReq1.IsDone());
}
}
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCreateViewGraphicSelection)
{ // Load a document and register a callback.
SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
SdTestViewCallback aView1;
// Select the only shape in the document and assert that the graphic selection is changed.
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pActualPage = pViewShell->GetActualPage();
SdrObject* pObject = pActualPage->GetObj(0);
SdrView* pView = pViewShell->GetView();
aView1.m_bGraphicSelectionInvalidated = false;
pView->MarkObj(pObject, pView->GetSdrPageView());
CPPUNIT_ASSERT(aView1.m_bGraphicSelectionInvalidated);
// Now create a new view.
aView1.m_bGraphicSelectionInvalidated = false;
SfxLokHelper::createView();
pXImpressDocument->initializeForTiledRendering({}); // This failed, creating a new view affected the graphic selection of an // existing view.
CPPUNIT_ASSERT(!aView1.m_bGraphicSelectionInvalidated);
// Check that when the first view has a shape selected and we register a // callback on the second view, then it gets a "graphic view selection".
SdTestViewCallback aView2; // This failed, the created new view had no "view selection" of the first // view's selected shape.
CPPUNIT_ASSERT(aView2.m_bGraphicViewSelectionInvalidated);
}
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCreateViewTextCursor)
{ // Load a document and register a callback.
SdXImpressDocument* pXImpressDocument = createDoc("title-shape.odp");
SdTestViewCallback aView1;
// Make sure that creating a new view either doesn't affect the previous // one, or at least the effect is not visible at the end.
aView1.m_aViewCursorInvalidations.clear();
aView1.m_aViewCursorVisibilities.clear();
SfxLokHelper::createView();
pXImpressDocument->initializeForTiledRendering({});
SdTestViewCallback aView2; bool bFoundCursor = false; for (constauto& rInvalidation : aView1.m_aViewCursorInvalidations)
{ auto itVisibility = aView1.m_aViewCursorVisibilities.find(rInvalidation.first); // For each cursor invalidation: if there is no visibility or the visibility is true, that's a problem. if (itVisibility == aView1.m_aViewCursorVisibilities.end() || itVisibility->second)
{
bFoundCursor = true; break;
}
} // This failed: the second view created an unexpected view cursor in the // first view.
CPPUNIT_ASSERT(!bFoundCursor); // This failed: the text view selection of the first view wasn't seen by // the second view.
CPPUNIT_ASSERT(aView2.m_bViewSelectionSet);
}
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testPostKeyEventInvalidation)
{ // Load a document and begin text edit on the first slide.
SdXImpressDocument* pXImpressDocument = createDoc("2slides.odp");
CPPUNIT_ASSERT_EQUAL(0, pXImpressDocument->getPart());
SdTestViewCallback aView1;
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdrView* pView = pViewShell->GetView();
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_F2);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_F2);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT(pView->GetTextEditObject());
// Create a second view and begin text edit there as well, in parallel.
SfxLokHelper::createView();
pXImpressDocument->initializeForTiledRendering({});
SdTestViewCallback aView2;
pXImpressDocument->setPart(1);
sd::ViewShell* pViewShell2 = pXImpressDocument->GetDocShell()->GetViewShell();
SdrView* pView2 = pViewShell2->GetView();
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_F2);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_F2);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT(pView2->GetTextEditObject());
// Now go left with the cursor in the second view and watch for // invalidations.
aView2.m_bTilesInvalidated = false;
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT);
Scheduler::ProcessEventsToIdle(); // This failed: moving the cursor caused unexpected invalidation.
CPPUNIT_ASSERT(!aView2.m_bTilesInvalidated);
}
/** * tests a cut/paste bug around bullet items in a list and * graphic (bitmap) bullet items in a list (Tdf103083, Tdf166882)
*/
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testClipNumRules)
{
std::vector<constchar*> aFileNames = { "tdf103083.fodp", "tdf166882.odp" }; for (constchar* pFileName : aFileNames)
{ // Load the document.
SdXImpressDocument* pXImpressDocument = createDoc(pFileName);
CPPUNIT_ASSERT(pXImpressDocument);
// cut contents of bullet item
dispatchCommand(mxComponent, u".uno:Cut"_ustr, uno::Sequence<beans::PropertyValue>());
CPPUNIT_ASSERT(pView->GetTextEditObject());
EditView& rEditView2 = pView->GetTextEditOutlinerView()->GetEditView();
rEditView2.SetSelection(ESelection(2, 0, 2, 10)); // start para, start char, end para, end char.
CPPUNIT_ASSERT_EQUAL(OUString(), rEditView2.GetSelected());
// paste contents of bullet item
dispatchCommand(mxComponent, u".uno:Paste"_ustr, uno::Sequence<beans::PropertyValue>());
// send an ESC key to trigger the commit of the edit to the main model
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE);
pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
Scheduler::ProcessEventsToIdle();
pView->SdrBeginTextEdit(pTextObject);
CPPUNIT_ASSERT(pView->GetTextEditObject());
pOutliner = pView->GetTextEditOutliner();
EditView& rEditView3 = pView->GetTextEditOutlinerView()->GetEditView();
rEditView3.SetSelection(ESelection(2, 0, 2, 33)); // start para, start char, end para, end char.
CPPUNIT_ASSERT_EQUAL(u"They have all the same formatting"_ustr, rEditView3.GetSelected());
CPPUNIT_ASSERT_EQUAL(u"No-Logo Content~LT~Gliederung 2"_ustr,
pOutliner->GetStyleSheet(2)->GetName());
/** * tests a clone-formatting bug around table cell attributes
*/
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testTdf104405)
{ // Load the document.
SdXImpressDocument* pXImpressDocument = createDoc("tdf104405.fodp");
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pActualPage = pViewShell->GetActualPage();
SdrObject* pObject = pActualPage->GetObj(2); auto pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pObject);
CPPUNIT_ASSERT(pTableObject);
// select the middle cell
SdrView* pView = pViewShell->GetView();
pView->MarkObj(pTableObject, pView->GetSdrPageView());
pTableObject->setActiveCell(sdr::table::CellPos(2,1));
pView->SdrBeginTextEdit(pTableObject);
EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
rEditView.SetSelection(ESelection(0, 0, 0, 3)); // start para, start char, end para, end char.
// trigger the clone-formatting/paintbrush command to copy formatting contents of cell
uno::Sequence aArgs{ comphelper::makePropertyValue(u"PersistentCopy"_ustr, true) };
dispatchCommand(mxComponent, u".uno:FormatPaintbrush"_ustr, aArgs);
// now click on the table
pView->MarkObj(pTableObject, pView->GetSdrPageView());
pTableObject->setActiveCell(sdr::table::CellPos(0,0));
pView->SdrEndTextEdit(false);
pView->SdrBeginTextEdit(pTableObject);
EditView& rEditView2 = pView->GetTextEditOutlinerView()->GetEditView();
rEditView2.SetSelection(ESelection(0, 0, 0, 3)); // start para, start char, end para, end char.
::tools::Rectangle aRect = pTableObject->GetCurrentBoundRect();
pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
o3tl::toTwips(aRect.Left(), o3tl::Length::mm100), o3tl::toTwips(aRect.Top(), o3tl::Length::mm100),
1, MOUSE_LEFT, 0);
pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
o3tl::toTwips(aRect.Left(), o3tl::Length::mm100), o3tl::toTwips(aRect.Top(), o3tl::Length::mm100),
1, MOUSE_LEFT, 0);
Scheduler::ProcessEventsToIdle();
// check that the first cell has acquired the resulting vertical style
xmlDocUniquePtr pXmlDoc = parseXmlDump(); // the following name has a compiler-dependent part
CPPUNIT_ASSERT_EQUAL(
u"2"_ustr,
getXPath(
pXmlDoc, "/SdDrawDocument/SdrModel/maPages/SdPage/SdrPage/SdrObjList/SdrTableObj/SdrTableObjImpl" "/TableModel/Cell[1]/DefaultProperties/SfxItemSet/SdrTextVertAdjustItem", "value"));
}
// Grow font size for the selection.
dispatchCommand(mxComponent, u".uno:Grow"_ustr, {});
// Assert that the selected A1 has now a larger font than the unselected // A2.
xmlDocUniquePtr pXmlDoc = parseXmlDump();
sal_Int32 nA1Height = getXPath(pXmlDoc, "//Cell[1]/SdrText/OutlinerParaObject/EditTextObject/ContentInfo/SfxItemSet/SvxFontHeightItem[1]", "height").toInt32();
sal_Int32 nA2Height = getXPath(pXmlDoc, "//Cell[3]/SdrText/OutlinerParaObject/EditTextObject/ContentInfo/attribs[1]/SvxFontHeightItem", "height").toInt32(); // This failed when FuText::ChangeFontSize() never did "continue" in the // text loop, instead of doing so depending on what IsInSelection() returns.
CPPUNIT_ASSERT(nA1Height > nA2Height);
// Check that selection remains the same
CPPUNIT_ASSERT(xSelectionController->hasSelectedCells());
xSelectionController->getSelectedCells(aFirstCell, aLastCell);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aFirstCell.mnCol);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aFirstCell.mnRow);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aLastCell.mnCol);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aLastCell.mnRow);
}
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testShowAndUseGridCallbacks)
{ /* Showing and hiding grid is done via one command. Command toggles the grid state. Also "snapping the objects to grid" feature is toggled via one command. Here we switch on and off these 2 features and check the callbacks.
*/
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCommentCallbacks)
{ // Load the document. // Set the tiled annotations off
comphelper::LibreOfficeKit::setTiledAnnotations(false);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.