diff options
-rw-r--r-- | include/svx/svdedtv.hxx | 1 | ||||
-rw-r--r-- | include/svx/svdedxv.hxx | 13 | ||||
-rw-r--r-- | sc/qa/unit/uicalc/uicalc.cxx | 3 | ||||
-rw-r--r-- | sc/source/ui/inc/drawview.hxx | 4 | ||||
-rw-r--r-- | sc/source/ui/view/drawview.cxx | 9 | ||||
-rw-r--r-- | sd/qa/uitest/impress_tests/tdf130440.py | 13 | ||||
-rw-r--r-- | sd/qa/unit/misc-tests.cxx | 34 | ||||
-rw-r--r-- | sd/qa/unit/tiledrendering/data/TextBoxAndRect.odg | bin | 0 -> 10474 bytes | |||
-rw-r--r-- | sd/qa/unit/tiledrendering/tiledrendering.cxx | 341 | ||||
-rw-r--r-- | sd/source/ui/inc/View.hxx | 3 | ||||
-rw-r--r-- | sd/source/ui/view/drviews1.cxx | 4 | ||||
-rw-r--r-- | sd/source/ui/view/sdview.cxx | 10 | ||||
-rw-r--r-- | svx/source/svdraw/svddrgmt.cxx | 2 | ||||
-rw-r--r-- | svx/source/svdraw/svdedtv.cxx | 12 | ||||
-rw-r--r-- | svx/source/svdraw/svdedtv1.cxx | 24 | ||||
-rw-r--r-- | svx/source/svdraw/svdedxv.cxx | 17 | ||||
-rw-r--r-- | sw/qa/extras/tiledrendering/data/shape.fodt | 20 | ||||
-rw-r--r-- | sw/qa/extras/tiledrendering/tiledrendering.cxx | 16 | ||||
-rw-r--r-- | sw/source/core/draw/dview.cxx | 10 | ||||
-rw-r--r-- | sw/source/core/inc/dview.hxx | 4 |
20 files changed, 471 insertions, 69 deletions
diff --git a/include/svx/svdedtv.hxx b/include/svx/svdedtv.hxx index a21eeb3e0a43..6f80c3aca0fa 100644 --- a/include/svx/svdedtv.hxx +++ b/include/svx/svdedtv.hxx @@ -188,6 +188,7 @@ public: * Checks if this or other views have an active text edit, if true, end them. */ void EndTextEditAllViews() const; + void EndTextEditCurrentView(); std::vector< std::unique_ptr<SdrUndoAction> > CreateConnectorUndo( const SdrObject& rO ); void AddUndoActions( std::vector< std::unique_ptr<SdrUndoAction> > ); diff --git a/include/svx/svdedxv.hxx b/include/svx/svdedxv.hxx index a4f457c9aeba..a05a61c36c8d 100644 --- a/include/svx/svdedxv.hxx +++ b/include/svx/svdedxv.hxx @@ -109,18 +109,15 @@ protected: private: SfxUndoManager* mpOldTextEditUndoManager; + std::unique_ptr<SdrUndoManager> mpLocalTextEditUndoManager; protected: - // central method to get an SdrUndoManager for enhanced TextEdit. Default will - // try to return a dynamic_casted GetModel()->GetSdrUndoManager(). Applications - // which want to use this feature will need to override this virtual method, - // provide their document UndoManager and derive it from SdrUndoManager. - virtual SdrUndoManager* getSdrUndoManagerForEnhancedTextEdit() const; + // Create a local UndoManager that is used for text editing. + virtual std::unique_ptr<SdrUndoManager> createLocalTextUndoManager(); void ImpMoveCursorAfterChainingEvent(TextChainCursorManager *pCursorManager); std::unique_ptr<TextChainCursorManager> ImpHandleMotionThroughBoxesKeyInput(const KeyEvent& rKEvt, bool *bOutHandled); - OutlinerView* ImpFindOutlinerView(vcl::Window const * pWin) const; // Create a new OutlinerView at the heap and initialize all required parameters. @@ -180,6 +177,10 @@ public: virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override; virtual void ModelHasChanged() override; + const std::unique_ptr<SdrUndoManager>& getViewLocalUndoManager() const + { + return mpLocalTextEditUndoManager; + } // TextEdit over an outliner diff --git a/sc/qa/unit/uicalc/uicalc.cxx b/sc/qa/unit/uicalc/uicalc.cxx index 3c3d15f1d399..46c430c7e087 100644 --- a/sc/qa/unit/uicalc/uicalc.cxx +++ b/sc/qa/unit/uicalc/uicalc.cxx @@ -951,6 +951,9 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf119793) pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); Scheduler::ProcessEventsToIdle(); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_ESCAPE); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_ESCAPE); + Scheduler::ProcessEventsToIdle(); dispatchCommand(mxComponent, ".uno:Undo", {}); Scheduler::ProcessEventsToIdle(); diff --git a/sc/source/ui/inc/drawview.hxx b/sc/source/ui/inc/drawview.hxx index 7e0db5eb0a0d..816a3428aacf 100644 --- a/sc/source/ui/inc/drawview.hxx +++ b/sc/source/ui/inc/drawview.hxx @@ -51,8 +51,8 @@ class ScDrawView final : public FmFormView void ImplClearCalcDropMarker(); - // support enhanced text edit for draw objects - virtual SdrUndoManager* getSdrUndoManagerForEnhancedTextEdit() const override; + // Create a local UndoManager + std::unique_ptr<SdrUndoManager> createLocalTextUndoManager() override; public: ScDrawView( diff --git a/sc/source/ui/view/drawview.cxx b/sc/source/ui/view/drawview.cxx index ed0cf254ba10..0254e62fb2be 100644 --- a/sc/source/ui/view/drawview.cxx +++ b/sc/source/ui/view/drawview.cxx @@ -1107,10 +1107,13 @@ bool ScDrawView::calculateGridOffsetForB2DRange( return true; } -// support enhanced text edit for draw objects -SdrUndoManager* ScDrawView::getSdrUndoManagerForEnhancedTextEdit() const +// Create a new view-local UndoManager manager for Calc +std::unique_ptr<SdrUndoManager> ScDrawView::createLocalTextUndoManager() { - return dynamic_cast<SdrUndoManager*>(rDoc.GetUndoManager()); + std::unique_ptr<SdrUndoManager> pUndoManager(new SdrUndoManager); + ScDocShell* pDocShell = pViewData ? pViewData->GetDocShell() : nullptr; + pUndoManager->SetDocShell(pDocShell); + return pUndoManager; } // #i123922# helper to apply a Graphic to an existing SdrObject diff --git a/sd/qa/uitest/impress_tests/tdf130440.py b/sd/qa/uitest/impress_tests/tdf130440.py index ea6b398a2841..0672e14f2f59 100644 --- a/sd/qa/uitest/impress_tests/tdf130440.py +++ b/sd/qa/uitest/impress_tests/tdf130440.py @@ -24,24 +24,31 @@ class tdf129346(UITestCase): xDoc = self.xUITest.getTopFocusWindow() xEdit = xDoc.getChild("impress_win") + # Type "test" into the text box xEdit.executeAction("TYPE", mkPropertyValues({"TEXT":"test"})) - - self.xUITest.executeCommand(".uno:Undo") + # Go to Page 1, which also forces to end edit box + xEdit.executeAction("GOTO", mkPropertyValues({"PAGE": "1"})) xToolkit.processEventsToIdle() - self.assertEqual(document.CurrentController.getCurrentPage().Number, 2) + # We should be at Page 1 + self.assertEqual(document.CurrentController.getCurrentPage().Number, 1) + + # Undo sends us to Page 2 and undo-es the text edit self.xUITest.executeCommand(".uno:Undo") xToolkit.processEventsToIdle() self.assertEqual(document.CurrentController.getCurrentPage().Number, 2) + # Undo sends us to page 1 and undo-es command ".uno:DuplicatePage" self.xUITest.executeCommand(".uno:Undo") xToolkit.processEventsToIdle() self.assertEqual(document.CurrentController.getCurrentPage().Number, 1) + # Redo ".uno:DuplicatePage" - we go to Page 2 self.xUITest.executeCommand(".uno:Redo") xToolkit.processEventsToIdle() self.assertEqual(document.CurrentController.getCurrentPage().Number, 2) + # Redo text edit self.xUITest.executeCommand(".uno:Redo") xDoc = self.xUITest.getTopFocusWindow() diff --git a/sd/qa/unit/misc-tests.cxx b/sd/qa/unit/misc-tests.cxx index ba888c280601..dc2f4324c240 100644 --- a/sd/qa/unit/misc-tests.cxx +++ b/sd/qa/unit/misc-tests.cxx @@ -70,7 +70,7 @@ public: void testTdf96206(); void testTdf96708(); void testTdf99396(); - void testTdf99396TextEdit(); + void testTableObjectUndoTest(); void testFillGradient(); void testTdf44774(); void testTdf38225(); @@ -93,7 +93,7 @@ public: CPPUNIT_TEST(testTdf96206); CPPUNIT_TEST(testTdf96708); CPPUNIT_TEST(testTdf99396); - CPPUNIT_TEST(testTdf99396TextEdit); + CPPUNIT_TEST(testTableObjectUndoTest); CPPUNIT_TEST(testFillGradient); CPPUNIT_TEST(testTdf44774); CPPUNIT_TEST(testTdf38225); @@ -251,8 +251,10 @@ void SdMiscTest::testTdf99396() xDocSh->DoClose(); } -void SdMiscTest::testTdf99396TextEdit() +void SdMiscTest::testTableObjectUndoTest() { + // See tdf#99396 for the issue + // Load the document and select the table. sd::DrawDocShellRef xDocSh = Load(m_directories.getURLFromSrc(u"/sd/qa/unit/data/tdf99396.odp"), ODP); sd::ViewShell* pViewShell = xDocSh->GetViewShell(); @@ -278,14 +280,26 @@ void SdMiscTest::testTdf99396TextEdit() const SfxItemSet* pArgs = aRequest.GetArgs(); pView->SetAttributes(*pArgs); } + const auto& pLocalUndoManager = pView->getViewLocalUndoManager(); + CPPUNIT_ASSERT_EQUAL(size_t(1), pLocalUndoManager->GetUndoActionCount()); + CPPUNIT_ASSERT_EQUAL(OUString("Apply attributes"), pLocalUndoManager->GetUndoActionComment()); { auto pTableController = dynamic_cast<sdr::table::SvxTableController*>(pView->getSelectionController().get()); CPPUNIT_ASSERT(pTableController); SfxRequest aRequest(pViewShell->GetViewFrame(), SID_TABLE_VERT_BOTTOM); pTableController->Execute(aRequest); } + // Global change "Format cell" is applied only - Change the vertical alignment to "Bottom" + CPPUNIT_ASSERT_EQUAL(size_t(1), xDocSh->GetDoc()->GetUndoManager()->GetUndoActionCount()); + CPPUNIT_ASSERT_EQUAL(OUString("Format cell"), xDocSh->GetDoc()->GetUndoManager()->GetUndoActionComment()); + pView->SdrEndTextEdit(); + // End of text edit, so the text edit action is added to the undo stack + CPPUNIT_ASSERT_EQUAL(size_t(2), xDocSh->GetDoc()->GetUndoManager()->GetUndoActionCount()); + CPPUNIT_ASSERT_EQUAL(OUString("Edit text of Table"), xDocSh->GetDoc()->GetUndoManager()->GetUndoActionComment(0)); + CPPUNIT_ASSERT_EQUAL(OUString("Format cell"), xDocSh->GetDoc()->GetUndoManager()->GetUndoActionComment(1)); + // Check that the result is what we expect. { uno::Reference<table::XTable> xTable = pTableObject->getTable(); @@ -303,6 +317,10 @@ void SdMiscTest::testTdf99396TextEdit() // Now undo. xDocSh->GetUndoManager()->Undo(); + // Undoing the last action - one left + CPPUNIT_ASSERT_EQUAL(size_t(1), xDocSh->GetDoc()->GetUndoManager()->GetUndoActionCount()); + CPPUNIT_ASSERT_EQUAL(OUString("Format cell"), xDocSh->GetDoc()->GetUndoManager()->GetUndoActionComment(0)); + // Check again that the result is what we expect. { uno::Reference<table::XTable> xTable = pTableObject->getTable(); @@ -318,6 +336,9 @@ void SdMiscTest::testTdf99396TextEdit() CPPUNIT_ASSERT_EQUAL(SvxAdjust::Center, pAdjust->GetAdjust()); } + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(size_t(1), xDocSh->GetDoc()->GetUndoManager()->GetUndoActionCount()); + CPPUNIT_ASSERT_EQUAL(OUString("Format cell"), xDocSh->GetDoc()->GetUndoManager()->GetUndoActionComment(0)); /* * now test tdf#103950 - Undo does not revert bundled font size changes for table cells @@ -328,8 +349,11 @@ void SdMiscTest::testTdf99396TextEdit() SfxRequest aRequest(pViewShell->GetViewFrame(), SID_GROW_FONT_SIZE); static_cast<sd::DrawViewShell*>(pViewShell)->ExecChar(aRequest); } - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), xDocSh->GetDoc()->GetUndoManager()->GetUndoActionCount()); - + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), xDocSh->GetDoc()->GetUndoManager()->GetUndoActionCount()); + CPPUNIT_ASSERT_EQUAL(OUString("Apply attributes to Table"), xDocSh->GetDoc()->GetUndoManager()->GetUndoActionComment(0)); + CPPUNIT_ASSERT_EQUAL(OUString("Grow font size"), xDocSh->GetDoc()->GetUndoManager()->GetUndoActionComment(1)); + CPPUNIT_ASSERT_EQUAL(OUString("Format cell"), xDocSh->GetDoc()->GetUndoManager()->GetUndoActionComment(2)); xDocSh->DoClose(); } diff --git a/sd/qa/unit/tiledrendering/data/TextBoxAndRect.odg b/sd/qa/unit/tiledrendering/data/TextBoxAndRect.odg Binary files differnew file mode 100644 index 000000000000..aa1a37b83147 --- /dev/null +++ b/sd/qa/unit/tiledrendering/data/TextBoxAndRect.odg diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx b/sd/qa/unit/tiledrendering/tiledrendering.cxx index 89ab2d62b815..a41e050bac06 100644 --- a/sd/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx @@ -139,6 +139,7 @@ public: void testMoveShapeHandle(); void testDeleteTable(); void testPasteUndo(); + void testShapeEditInMultipleViews(); CPPUNIT_TEST_SUITE(SdTiledRenderingTest); CPPUNIT_TEST(testCreateDestroy); @@ -197,7 +198,7 @@ public: CPPUNIT_TEST(testMoveShapeHandle); CPPUNIT_TEST(testDeleteTable); CPPUNIT_TEST(testPasteUndo); - + CPPUNIT_TEST(testShapeEditInMultipleViews); CPPUNIT_TEST_SUITE_END(); virtual void libreOfficeKitViewCallback(int nType, const char* pPayload) override; @@ -1325,6 +1326,38 @@ void SdTiledRenderingTest::testUndoLimiting() Scheduler::ProcessEventsToIdle(); CPPUNIT_ASSERT(pViewShell1->GetView()->IsTextEdit()); + // View2 UNDO stack should be empty + { + SfxRequest aReq2(SID_UNDO, SfxCallMode::SLOT, pXImpressDocument->GetDocShell()->GetDoc()->GetPool()); + aReq2.AppendItem(SfxUInt16Item(SID_UNDO, 1)); + pViewShell2->ExecuteSlot(aReq2); + const auto* pReturnValue = aReq2.GetReturnValue(); + CPPUNIT_ASSERT(!pReturnValue); + } + + // View1 can UNDO + { + SfxRequest aReq1(SID_UNDO, SfxCallMode::SLOT, pXImpressDocument->GetDocShell()->GetDoc()->GetPool()); + aReq1.AppendItem(SfxUInt16Item(SID_UNDO, 1)); + pViewShell1->ExecuteSlot(aReq1); + CPPUNIT_ASSERT(aReq1.IsDone()); + } + + // View1 can REDO + { + SfxRequest aReq1(SID_REDO, SfxCallMode::SLOT, pXImpressDocument->GetDocShell()->GetDoc()->GetPool()); + aReq1.AppendItem(SfxUInt16Item(SID_REDO, 1)); + pViewShell1->ExecuteSlot(aReq1); + CPPUNIT_ASSERT(aReq1.IsDone()); + } + + // Exit text edit mode + pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE); + pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE); + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT(!pViewShell1->GetView()->IsTextEdit()); + // Now check view2 cannot undo actions. { SfxRequest aReq2(SID_UNDO, SfxCallMode::SLOT, pXImpressDocument->GetDocShell()->GetDoc()->GetPool()); @@ -2062,11 +2095,19 @@ void SdTiledRenderingTest::testDisableUndoRepair() { // Load the document. SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp"); + + // Create View 1 SfxViewShell* pView1 = SfxViewShell::Current(); + sd::ViewShell* pViewShell1 = pXImpressDocument->GetDocShell()->GetViewShell(); int nView1 = SfxLokHelper::getView(); + + // Create View 2 SfxLokHelper::createView(); SfxViewShell* pView2 = SfxViewShell::Current(); + sd::ViewShell* pViewShell2 = pXImpressDocument->GetDocShell()->GetViewShell(); int nView2 = SfxLokHelper::getView(); + + // Check UNDO is disabled { std::unique_ptr<SfxPoolItem> pItem1; std::unique_ptr<SfxPoolItem> pItem2; @@ -2081,15 +2122,24 @@ void SdTiledRenderingTest::testDisableUndoRepair() pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'h', 0); pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'h', 0); Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT(pViewShell1->GetView()->IsTextEdit()); + pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE); + pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT(!pViewShell1->GetView()->IsTextEdit()); + + // Check { std::unique_ptr<SfxPoolItem> xItem1; - std::unique_ptr<SfxPoolItem> xItem2; pView1->GetViewFrame()->GetBindings().QueryState(SID_UNDO, xItem1); + const auto* pUInt32Item1 = dynamic_cast<const SfxUInt32Item*>(xItem1.get()); + CPPUNIT_ASSERT(!pUInt32Item1); + + std::unique_ptr<SfxPoolItem> xItem2; pView2->GetViewFrame()->GetBindings().QueryState(SID_UNDO, xItem2); - CPPUNIT_ASSERT(!dynamic_cast< const SfxUInt32Item* >(xItem1.get())); - const SfxUInt32Item* pUInt32Item = dynamic_cast<const SfxUInt32Item*>(xItem2.get()); - CPPUNIT_ASSERT(pUInt32Item); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(SID_REPAIRPACKAGE), pUInt32Item->GetValue()); + const auto* pUInt32Item2 = dynamic_cast<const SfxUInt32Item*>(xItem2.get()); + CPPUNIT_ASSERT(pUInt32Item2); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(SID_REPAIRPACKAGE), pUInt32Item2->GetValue()); } // Insert a character in the second view. @@ -2100,15 +2150,23 @@ void SdTiledRenderingTest::testDisableUndoRepair() pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'c', 0); pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'c', 0); Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT(pViewShell2->GetView()->IsTextEdit()); + pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE); + pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT(!pViewShell2->GetView()->IsTextEdit()); + + // Check { std::unique_ptr<SfxPoolItem> xItem1; - std::unique_ptr<SfxPoolItem> xItem2; pView1->GetViewFrame()->GetBindings().QueryState(SID_UNDO, xItem1); - pView2->GetViewFrame()->GetBindings().QueryState(SID_UNDO, xItem2); - CPPUNIT_ASSERT(!dynamic_cast< const SfxUInt32Item* >(xItem2.get())); const SfxUInt32Item* pUInt32Item = dynamic_cast<const SfxUInt32Item*>(xItem1.get()); CPPUNIT_ASSERT(pUInt32Item); CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(SID_REPAIRPACKAGE), pUInt32Item->GetValue()); + + std::unique_ptr<SfxPoolItem> xItem2; + pView2->GetViewFrame()->GetBindings().QueryState(SID_UNDO, xItem2); + CPPUNIT_ASSERT(!dynamic_cast< const SfxUInt32Item* >(xItem2.get())); } } @@ -2125,17 +2183,20 @@ void SdTiledRenderingTest::testDocumentRepair() SfxLokHelper::createView(); SfxViewShell* pView2 = SfxViewShell::Current(); int nView2 = SfxLokHelper::getView(); + sd::ViewShell* pViewShell2 = pXImpressDocument->GetDocShell()->GetViewShell(); + CPPUNIT_ASSERT(pView1 != pView2); { std::unique_ptr<SfxPoolItem> xItem1; - std::unique_ptr<SfxPoolItem> xItem2; pView1->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, xItem1); - pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, xItem2); const SfxBoolItem* pItem1 = dynamic_cast<const SfxBoolItem*>(xItem1.get()); - const SfxBoolItem* pItem2 = dynamic_cast<const SfxBoolItem*>(xItem2.get()); CPPUNIT_ASSERT(pItem1); - CPPUNIT_ASSERT(pItem2); CPPUNIT_ASSERT_EQUAL(false, pItem1->GetValue()); + + std::unique_ptr<SfxPoolItem> xItem2; + pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, xItem2); + const SfxBoolItem* pItem2 = dynamic_cast<const SfxBoolItem*>(xItem2.get()); + CPPUNIT_ASSERT(pItem2); CPPUNIT_ASSERT_EQUAL(false, pItem2->GetValue()); } @@ -2147,16 +2208,23 @@ void SdTiledRenderingTest::testDocumentRepair() pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'c', 0); pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'c', 0); Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT(pViewShell2->GetView()->IsTextEdit()); + pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE); + pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT(!pViewShell2->GetView()->IsTextEdit()); + { std::unique_ptr<SfxPoolItem> xItem1; - std::unique_ptr<SfxPoolItem> xItem2; pView1->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, xItem1); - pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, xItem2); const SfxBoolItem* pItem1 = dynamic_cast<const SfxBoolItem*>(xItem1.get()); - const SfxBoolItem* pItem2 = dynamic_cast<const SfxBoolItem*>(xItem2.get()); CPPUNIT_ASSERT(pItem1); - CPPUNIT_ASSERT(pItem2); CPPUNIT_ASSERT_EQUAL(true, pItem1->GetValue()); + + std::unique_ptr<SfxPoolItem> xItem2; + pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, xItem2); + const SfxBoolItem* pItem2 = dynamic_cast<const SfxBoolItem*>(xItem2.get()); + CPPUNIT_ASSERT(pItem2); CPPUNIT_ASSERT_EQUAL(true, pItem2->GetValue()); } } @@ -2681,7 +2749,6 @@ void SdTiledRenderingTest::testMoveShapeHandle() CPPUNIT_ASSERT_EQUAL(x-1, oldX); CPPUNIT_ASSERT_EQUAL(y-1, oldY); } - } void SdTiledRenderingTest::testPasteUndo() @@ -2718,6 +2785,244 @@ void SdTiledRenderingTest::testPasteUndo() CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aSelection.nStartPos); } +void SdTiledRenderingTest::testShapeEditInMultipleViews() +{ + SdXImpressDocument* pXImpressDocument = createDoc("TextBoxAndRect.odg"); + pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + SdDrawDocument* pDocument = pXImpressDocument->GetDoc(); + + // Create view 1 + const int nView1 = SfxLokHelper::getView(); + sd::ViewShell* pViewShell1 = pXImpressDocument->GetDocShell()->GetViewShell(); + SdrView* pView1 = pViewShell1->GetView(); + Scheduler::ProcessEventsToIdle(); + + // Create view 2 + SfxLokHelper::createView(); + const int nView2 = SfxLokHelper::getView(); + CPPUNIT_ASSERT(nView1 != nView2); + + sd::ViewShell* pViewShell2 = pXImpressDocument->GetDocShell()->GetViewShell(); + SdrView* pView2 = pViewShell2->GetView(); + Scheduler::ProcessEventsToIdle(); + + // Switch to view 1 + SfxLokHelper::setView(nView1); + + SdPage* pPage1 = pViewShell1->GetActualPage(); + + SdrObject* pTextBoxObject = pPage1->GetObj(0); + CPPUNIT_ASSERT_EQUAL(OUString("Text Box"), pTextBoxObject->GetName()); + + SdrObject* pRectangleObject = pPage1->GetObj(1); + CPPUNIT_ASSERT_EQUAL(OUString("Rect"), pRectangleObject->GetName()); + + SdrObject* pTableObject = pPage1->GetObj(2); + CPPUNIT_ASSERT_EQUAL(OUString("Table1"), pTableObject->GetName()); + + // Scenario 1 + // 2 shapes - "Text Box" and "Rect" + // View1 - "Text Box" enters text edit mode, View 2 - moves the "Rect" around + { + sd::UndoManager* pUndoManager = pDocument->GetUndoManager(); + CPPUNIT_ASSERT_EQUAL(size_t(0), pUndoManager->GetUndoActionCount()); + + pView1->SdrBeginTextEdit(pTextBoxObject); + CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit()); + CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit()); + + // Local undo count for View1 is 0 + CPPUNIT_ASSERT_EQUAL(size_t(0), pView1->getViewLocalUndoManager()->GetUndoActionCount()); + // Write 'test' in View1 + SfxStringItem aInputString(SID_ATTR_CHAR, "test"); + pViewShell1->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR, SfxCallMode::SYNCHRON, { &aInputString }); + // Local undo count for View1 is now 1 + CPPUNIT_ASSERT_EQUAL(size_t(1), pView1->getViewLocalUndoManager()->GetUndoActionCount()); + + // Mark rectangle object + pView2->MarkObj(pRectangleObject, pView2->GetSdrPageView()); + + // Check the initial position of the object + tools::Rectangle aRectangle = pRectangleObject->GetLogicRect(); + CPPUNIT_ASSERT_EQUAL(6250L, aRectangle.TopLeft().X()); + CPPUNIT_ASSERT_EQUAL(7000L, aRectangle.TopLeft().Y()); + CPPUNIT_ASSERT_EQUAL(6501L, aRectangle.GetWidth()); + CPPUNIT_ASSERT_EQUAL(4501L, aRectangle.GetHeight()); + + // On View2 - Move handle 0 on the shape to a new mosition - resize + Point aNewPosition = aRectangle.TopLeft() + Point(-1250, -1000); + pView2->MoveShapeHandle(0, aNewPosition, -1); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(size_t(1), pUndoManager->GetUndoActionCount()); + + // Check the object has a new size + aRectangle = pRectangleObject->GetLogicRect(); + CPPUNIT_ASSERT_EQUAL(5000L, aRectangle.TopLeft().X()); + CPPUNIT_ASSERT_EQUAL(6000L, aRectangle.TopLeft().Y()); + CPPUNIT_ASSERT_EQUAL(7751L, aRectangle.GetWidth()); + CPPUNIT_ASSERT_EQUAL(5501L, aRectangle.GetHeight()); + + // View1 is still in text edit mode... + CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit()); + CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit()); + + // On View2 - relative move the shape to a different position + pView2->MoveMarkedObj(Size(1000, 2000), /*bCopy=*/false); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(size_t(2), pUndoManager->GetUndoActionCount()); + + // Check the object is at a different position + aRectangle = pRectangleObject->GetLogicRect(); + CPPUNIT_ASSERT_EQUAL(6000L, aRectangle.TopLeft().X()); + CPPUNIT_ASSERT_EQUAL(8000L, aRectangle.TopLeft().Y()); + CPPUNIT_ASSERT_EQUAL(7751L, aRectangle.GetWidth()); + CPPUNIT_ASSERT_EQUAL(5501L, aRectangle.GetHeight()); + + // View1 is still in text edit mode... + CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit()); + CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit()); + + // End Text edit - check undo count increase from 2 -> 3 + CPPUNIT_ASSERT_EQUAL(size_t(2), pUndoManager->GetUndoActionCount()); + pView1->SdrEndTextEdit(); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(size_t(3), pUndoManager->GetUndoActionCount()); + + // Check that both views exited the text edit mode + CPPUNIT_ASSERT_EQUAL(false, pView1->IsTextEdit()); + CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit()); + } + + // Scenario 2 + // 1 shapes - "Text Box" + // View1 - "Text Box" enters text edit mode, View 2 - moves the "Text Box" around + { + sd::UndoManager* pUndoManager = pDocument->GetUndoManager(); + CPPUNIT_ASSERT_EQUAL(size_t(3), pUndoManager->GetUndoActionCount()); + + pView1->SdrBeginTextEdit(pTextBoxObject); + CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit()); + CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit()); + + // Local undo count for View1 is 0 + CPPUNIT_ASSERT_EQUAL(size_t(0), pView1->getViewLocalUndoManager()->GetUndoActionCount()); + // Write 'test' in View1 + SfxStringItem aInputString(SID_ATTR_CHAR, "test"); + pViewShell1->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR, SfxCallMode::SYNCHRON, { &aInputString }); + // Local undo count for View1 is now 1 + CPPUNIT_ASSERT_EQUAL(size_t(1), pView1->getViewLocalUndoManager()->GetUndoActionCount()); + + // Mark rectangle object + pView2->MarkObj(pTextBoxObject, pView2->GetSdrPageView()); + + // Check the initial position of the object + tools::Rectangle aRectangle = pTextBoxObject->GetLogicRect(); + CPPUNIT_ASSERT_EQUAL(2250L, aRectangle.TopLeft().X()); + CPPUNIT_ASSERT_EQUAL(2000L, aRectangle.TopLeft().Y()); + CPPUNIT_ASSERT_EQUAL(4501L, aRectangle.GetWidth()); + CPPUNIT_ASSERT_EQUAL(2001L, aRectangle.GetHeight()); + + // On View2 - Move handle 0 on the shape to a new mosition - resize + Point aNewPosition = aRectangle.TopLeft() + Point(-1250, -1000); + pView2->MoveShapeHandle(0, aNewPosition, -1); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(size_t(4), pUndoManager->GetUndoActionCount()); + + // Check the object has a new size + aRectangle = pTextBoxObject->GetLogicRect(); + CPPUNIT_ASSERT_EQUAL(1000L, aRectangle.TopLeft().X()); + CPPUNIT_ASSERT_EQUAL(1000L, aRectangle.TopLeft().Y()); + CPPUNIT_ASSERT_EQUAL(4990L, aRectangle.GetWidth()); + CPPUNIT_ASSERT_EQUAL(2175L, aRectangle.GetHeight()); + + // View1 is still in text edit mode... + CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit()); + CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit()); + + // On View2 - relative move the shape to a different position + pView2->MoveMarkedObj(Size(1000, 2000), /*bCopy=*/false); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(size_t(5), pUndoManager->GetUndoActionCount()); + + // Check the object is at a different position + aRectangle = pTextBoxObject->GetLogicRect(); + CPPUNIT_ASSERT_EQUAL(2000L, aRectangle.TopLeft().X()); + CPPUNIT_ASSERT_EQUAL(3000L, aRectangle.TopLeft().Y()); + CPPUNIT_ASSERT_EQUAL(4990L, aRectangle.GetWidth()); + CPPUNIT_ASSERT_EQUAL(2175L, aRectangle.GetHeight()); + + // View1 is still in text edit mode... + CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit()); + CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit()); + + // End Text edit - check undo count increase from 5 -> 6 + CPPUNIT_ASSERT_EQUAL(size_t(5), pUndoManager->GetUndoActionCount()); + pView1->SdrEndTextEdit(); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(size_t(6), pUndoManager->GetUndoActionCount()); + + // Check that both views exited the text edit mode + CPPUNIT_ASSERT_EQUAL(false, pView1->IsTextEdit()); + CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit()); + } + + // Scenario 3 + // 1 shapes - "Table1" + // View1 - "Table1" enters text edit mode, View 2 - moves the "Table1" around + { + sd::UndoManager* pUndoManager = pDocument->GetUndoManager(); + CPPUNIT_ASSERT_EQUAL(size_t(6), pUndoManager->GetUndoActionCount()); + + pView1->SdrBeginTextEdit(pTableObject); + CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit()); + CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit()); + + // Local undo count for View1 is 0 + CPPUNIT_ASSERT_EQUAL(size_t(0), pView1->getViewLocalUndoManager()->GetUndoActionCount()); + // Write 'test' in View1 + SfxStringItem aInputString(SID_ATTR_CHAR, "test"); + pViewShell1->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR, SfxCallMode::SYNCHRON, { &aInputString }); + // Local undo count for View1 is now 1 + CPPUNIT_ASSERT_EQUAL(size_t(1), pView1->getViewLocalUndoManager()->GetUndoActionCount()); + + // Mark rectangle object + pView2->MarkObj(pTableObject, pView2->GetSdrPageView()); + + // Check the initial position of the table + tools::Rectangle aRectangle = pTableObject->GetLogicRect(); + CPPUNIT_ASSERT_EQUAL(2919L, aRectangle.TopLeft().X()); + CPPUNIT_ASSERT_EQUAL(18063L, aRectangle.TopLeft().Y()); + CPPUNIT_ASSERT_EQUAL(14099L, aRectangle.GetWidth()); + CPPUNIT_ASSERT_EQUAL(5999L, aRectangle.GetHeight()); + + // On View2 - relative move the shape to a different position + pView2->MoveMarkedObj(Size(1000, 2000), /*bCopy=*/false); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(size_t(7), pUndoManager->GetUndoActionCount()); + + // Check the object is at a different position + aRectangle = pTableObject->GetLogicRect(); + CPPUNIT_ASSERT_EQUAL(3919L, aRectangle.TopLeft().X()); + CPPUNIT_ASSERT_EQUAL(20063L, aRectangle.TopLeft().Y()); + CPPUNIT_ASSERT_EQUAL(14099L, aRectangle.GetWidth()); + CPPUNIT_ASSERT_EQUAL(5999L, aRectangle.GetHeight()); + + // View1 is still in text edit mode... + CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit()); + CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit()); + + // End Text edit - check undo count increase from 7 -> 8 + CPPUNIT_ASSERT_EQUAL(size_t(7), pUndoManager->GetUndoActionCount()); + pView1->SdrEndTextEdit(); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(size_t(8), pUndoManager->GetUndoActionCount()); + + // Check that both views exited the text edit mode + CPPUNIT_ASSERT_EQUAL(false, pView1->IsTextEdit()); + CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit()); + } +} + CPPUNIT_TEST_SUITE_REGISTRATION(SdTiledRenderingTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sd/source/ui/inc/View.hxx b/sd/source/ui/inc/View.hxx index 744023acb573..b0ad4ca2ff87 100644 --- a/sd/source/ui/inc/View.hxx +++ b/sd/source/ui/inc/View.hxx @@ -142,6 +142,9 @@ public: ViewShell* GetViewShell() const { return mpViewSh; } SfxViewShell* GetSfxViewShell() const override; + // Create a local UndoManager + std::unique_ptr<SdrUndoManager> createLocalTextUndoManager() override; + virtual bool SdrBeginTextEdit(SdrObject* pObj, SdrPageView* pPV = nullptr, vcl::Window* pWin = nullptr, bool bIsNewObj = false, SdrOutliner* pGivenOutliner = nullptr, OutlinerView* pGivenOutlinerView = nullptr, bool bDontDeleteOutliner = false, bool bOnlyOneView = false, bool bGrabFocus = true) override; diff --git a/sd/source/ui/view/drviews1.cxx b/sd/source/ui/view/drviews1.cxx index 6c1df14a3961..4c3e446963a5 100644 --- a/sd/source/ui/view/drviews1.cxx +++ b/sd/source/ui/view/drviews1.cxx @@ -344,7 +344,9 @@ void DrawViewShell::ChangeEditMode(EditMode eEMode, bool bIsLayerModeActive) if ( mpDrawView->IsTextEdit() ) { - mpDrawView->SdrEndTextEdit(); + // This exits the text edit mode when going in and out of window focus, which is not needed + // Let's keep this call as comment for now as it probably just needs a better conditional. + // mpDrawView->SdrEndTextEdit(); } LayerTabBar* pLayerBar = GetLayerTabControl(); diff --git a/sd/source/ui/view/sdview.cxx b/sd/source/ui/view/sdview.cxx index d977334013f1..fadd89b99033 100644 --- a/sd/source/ui/view/sdview.cxx +++ b/sd/source/ui/view/sdview.cxx @@ -82,6 +82,8 @@ #include <DrawController.hxx> #include <svtools/optionsdrawinglayer.hxx> +#include <undo/undomanager.hxx> + #include <memory> #include <numeric> @@ -624,6 +626,14 @@ SfxViewShell* View::GetSfxViewShell() const return pRet; } +// Create a new view-local UndoManager manager for Impress/Draw +std::unique_ptr<SdrUndoManager> View::createLocalTextUndoManager() +{ + std::unique_ptr<SdrUndoManager> pUndoManager(new sd::UndoManager); + pUndoManager->SetDocShell(mpDocSh); + return pUndoManager; +} + bool View::SdrBeginTextEdit( SdrObject* pObj, SdrPageView* pPV, vcl::Window* pWin, bool bIsNewObj, diff --git a/svx/source/svdraw/svddrgmt.cxx b/svx/source/svdraw/svddrgmt.cxx index 7d5fb61569b7..bdba8aa0d7f4 100644 --- a/svx/source/svdraw/svddrgmt.cxx +++ b/svx/source/svdraw/svddrgmt.cxx @@ -1345,7 +1345,7 @@ bool SdrDragObjOwn::EndSdrDrag(bool /*bCopy*/) if( bUndo ) { - getSdrDragView().EndTextEditAllViews(); + getSdrDragView().EndTextEditCurrentView(); if(!getSdrDragView().IsInsObjPoint() && pObj->IsInserted() ) { if (DragStat().IsEndDragChangesAttributes()) diff --git a/svx/source/svdraw/svdedtv.cxx b/svx/source/svdraw/svdedtv.cxx index 0d4bb55d09f5..47f5c971e543 100644 --- a/svx/source/svdraw/svdedtv.cxx +++ b/svx/source/svdraw/svdedtv.cxx @@ -1000,7 +1000,7 @@ bool SdrEditView::InsertObjectAtView(SdrObject* pObj, SdrPageView& rPV, SdrInser } if( IsUndoEnabled()) { - EndTextEditAllViews(); + EndTextEditCurrentView(); AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pObj)); } @@ -1080,4 +1080,14 @@ void SdrEditView::EndTextEditAllViews() const } } +void SdrEditView::EndTextEditCurrentView() +{ + if (IsTextEdit()) + { + SdrView* pSdrView = dynamic_cast<SdrView*>(this); + if (pSdrView) + pSdrView->SdrEndTextEdit(); + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/svdraw/svdedtv1.cxx b/svx/source/svdraw/svdedtv1.cxx index 81cf6e6f0b0b..852d160ccd98 100644 --- a/svx/source/svdraw/svdedtv1.cxx +++ b/svx/source/svdraw/svdedtv1.cxx @@ -95,7 +95,7 @@ void SdrEditView::SetMarkedObjRect(const tools::Rectangle& rRect) const bool bUndo = IsUndoEnabled(); if( bUndo ) { - EndTextEditAllViews(); + EndTextEditCurrentView(); BegUndo(ImpGetDescriptionString(STR_EditPosSize)); } @@ -186,7 +186,7 @@ void SdrEditView::MoveMarkedObj(const Size& rSiz, bool bCopy) if( bUndo ) { - EndTextEditAllViews(); + EndTextEditCurrentView(); OUString aStr(SvxResId(STR_EditMove)); if (bCopy) aStr += SvxResId(STR_EditWithCopy); @@ -219,7 +219,7 @@ void SdrEditView::ResizeMarkedObj(const Point& rRef, const Fraction& xFact, cons const bool bUndo = IsUndoEnabled(); if( bUndo ) { - EndTextEditAllViews(); + EndTextEditCurrentView(); OUString aStr {ImpGetDescriptionString(STR_EditResize)}; if (bCopy) aStr+=SvxResId(STR_EditWithCopy); @@ -254,7 +254,7 @@ void SdrEditView::ResizeMultMarkedObj(const Point& rRef, const bool bUndo = IsUndoEnabled(); if( bUndo ) { - EndTextEditAllViews(); + EndTextEditCurrentView(); BegUndo(ImpGetDescriptionString(STR_EditResize)); } @@ -301,7 +301,7 @@ void SdrEditView::RotateMarkedObj(const Point& rRef, Degree100 nAngle, bool bCop const bool bUndo = IsUndoEnabled(); if( bUndo ) { - EndTextEditAllViews(); + EndTextEditCurrentView(); OUString aStr {ImpGetDescriptionString(STR_EditRotate)}; if (bCopy) aStr+=SvxResId(STR_EditWithCopy); BegUndo(aStr); @@ -358,7 +358,7 @@ void SdrEditView::MirrorMarkedObj(const Point& rRef1, const Point& rRef2, bool b if( bUndo ) { - EndTextEditAllViews(); + EndTextEditCurrentView(); OUString aStr; Point aDif(rRef2-rRef1); if (aDif.X()==0) @@ -458,7 +458,7 @@ void SdrEditView::ShearMarkedObj(const Point& rRef, Degree100 nAngle, bool bVShe if( bUndo ) { - EndTextEditAllViews(); + EndTextEditCurrentView(); OUString aStr {ImpGetDescriptionString(STR_EditShear)}; if (bCopy) aStr+=SvxResId(STR_EditWithCopy); @@ -574,7 +574,7 @@ void SdrEditView::CrookMarkedObj(const Point& rRef, const Point& rRad, SdrCrookM if( bUndo ) { - EndTextEditAllViews(); + EndTextEditCurrentView(); OUString aStr {ImpGetDescriptionString(bNoContortion ? STR_EditCrook : STR_EditCrookContortion)}; if (bCopy) aStr+=SvxResId(STR_EditWithCopy); @@ -648,7 +648,7 @@ void SdrEditView::DistortMarkedObj(const tools::Rectangle& rRef, const XPolygon& if( bUndo ) { - EndTextEditAllViews(); + EndTextEditCurrentView(); OUString aStr {ImpGetDescriptionString(STR_EditDistort)}; if (bCopy) aStr+=SvxResId(STR_EditWithCopy); @@ -1098,7 +1098,7 @@ void SdrEditView::SetAttrToMarked(const SfxItemSet& rAttr, bool bReplaceAll) const bool bUndo = IsUndoEnabled(); if( bUndo ) { - EndTextEditAllViews(); + EndTextEditCurrentView(); BegUndo(ImpGetDescriptionString(STR_EditSetAttributes)); } @@ -1277,7 +1277,7 @@ void SdrEditView::SetStyleSheetToMarked(SfxStyleSheet* pStyleSheet, bool bDontRe if( bUndo ) { - EndTextEditAllViews(); + EndTextEditCurrentView(); OUString aStr; if (pStyleSheet!=nullptr) aStr = ImpGetDescriptionString(STR_EditSetStylesheet); @@ -1844,7 +1844,7 @@ void SdrEditView::AlignMarkedObjects(SdrHorAlign eHor, SdrVertAlign eVert) const bool bUndo = IsUndoEnabled(); if( bUndo ) { - EndTextEditAllViews(); + EndTextEditCurrentView(); OUString aStr(GetDescriptionOfMarkedObjects()); if (eHor==SdrHorAlign::NONE) { diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx index db0ccf6ea486..3717fdce2c08 100644 --- a/svx/source/svdraw/svdedxv.cxx +++ b/svx/source/svdraw/svdedxv.cxx @@ -1060,10 +1060,11 @@ IMPL_LINK(SdrObjEditView, ImpOutlinerCalcFieldValueHdl, EditFieldInfo*, pFI, voi IMPL_LINK_NOARG(SdrObjEditView, EndTextEditHdl, SdrUndoManager*, void) { SdrEndTextEdit(); } -SdrUndoManager* SdrObjEditView::getSdrUndoManagerForEnhancedTextEdit() const +// Default implementation - null UndoManager +std::unique_ptr<SdrUndoManager> SdrObjEditView::createLocalTextUndoManager() { - // default returns registered UndoManager - return GetModel() ? dynamic_cast<SdrUndoManager*>(GetModel()->GetSdrUndoManager()) : nullptr; + SAL_WARN("svx", "SdrObjEditView::createLocalTextUndoManager needs to be overridden"); + return std::unique_ptr<SdrUndoManager>(); } bool SdrObjEditView::SdrBeginTextEdit(SdrObject* pObj_, SdrPageView* pPV, vcl::Window* pWin, @@ -1360,7 +1361,11 @@ bool SdrObjEditView::SdrBeginTextEdit(SdrObject* pObj_, SdrPageView* pPV, vcl::W if (GetModel() && IsUndoEnabled() && !GetModel()->GetDisableTextEditUsesCommonUndoManager()) { - SdrUndoManager* pSdrUndoManager = getSdrUndoManagerForEnhancedTextEdit(); + SdrUndoManager* pSdrUndoManager = nullptr; + mpLocalTextEditUndoManager = createLocalTextUndoManager(); + + if (mpLocalTextEditUndoManager) + pSdrUndoManager = mpLocalTextEditUndoManager.get(); if (pSdrUndoManager) { @@ -1434,7 +1439,7 @@ SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(bool bDontDeleteReally) if (pOriginal) { // check if we got back our document undo manager - SdrUndoManager* pSdrUndoManager = getSdrUndoManagerForEnhancedTextEdit(); + SdrUndoManager* pSdrUndoManager = mpLocalTextEditUndoManager.get(); if (pSdrUndoManager && dynamic_cast<SdrUndoManager*>(pOriginal) == pSdrUndoManager) { @@ -1467,6 +1472,8 @@ SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(bool bDontDeleteReally) "expected document UndoManager (!)"); delete pOriginal; } + + mpLocalTextEditUndoManager.reset(); } } else diff --git a/sw/qa/extras/tiledrendering/data/shape.fodt b/sw/qa/extras/tiledrendering/data/shape.fodt index feefe48bcde3..4e9a7f629ba4 100644 --- a/sw/qa/extras/tiledrendering/data/shape.fodt +++ b/sw/qa/extras/tiledrendering/data/shape.fodt @@ -1,5 +1,20 @@ <?xml version="1.0" encoding="UTF-8"?> -<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text"> + +<office:document xmlns:officeooo="http://openoffice.org/2009/office" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rpt="http://openoffice.org/2005/report" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="GB" style:letter-kerning="true" style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Droid Sans Devanagari1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/> + </style:default-style> + </office:styles> + <office:automatic-styles> + <style:style style:name="gr1" style:family="graphic"> + <style:graphic-properties draw:textarea-horizontal-align="justify" draw:textarea-vertical-align="middle" draw:auto-grow-height="false" fo:min-height="1.9cm" fo:min-width="3.471cm" style:run-through="foreground" style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="from-left" style:horizontal-rel="paragraph"/> + </style:style> + </office:automatic-styles> <office:body> <office:text> <text:sequence-decls> @@ -7,8 +22,9 @@ <text:sequence-decl text:display-outline-level="0" text:name="Table"/> <text:sequence-decl text:display-outline-level="0" text:name="Text"/> <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> + <text:sequence-decl text:display-outline-level="0" text:name="Figure"/> </text:sequence-decls> - <text:p><draw:custom-shape text:anchor-type="paragraph" draw:z-index="0" svg:width="4.883cm" svg:height="3.225cm" svg:x="2.602cm" svg:y="1.178cm"> + <text:p text:style-name="Standard"><draw:custom-shape text:anchor-type="paragraph" draw:z-index="0" draw:name="Shape1" draw:style-name="gr1" svg:width="4.908cm" svg:height="2.687cm" svg:x="1.575cm" svg:y="-0.132cm"> <text:p/> <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:glue-points="10800 0 3163 3163 0 10800 3163 18437 10800 21600 18437 18437 21600 10800 18437 3163" draw:text-areas="3163 3163 18437 18437" draw:type="ellipse" draw:enhanced-path="U 10800 10800 10800 10800 0 360 Z N"/> </draw:custom-shape>Hello.</text:p> diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx index 8f637753d1d4..9eaca7d123a7 100644 --- a/sw/qa/extras/tiledrendering/tiledrendering.cxx +++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx @@ -1311,6 +1311,7 @@ void SwTiledRenderingTest::testUndoShapeLimiting() pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); Scheduler::ProcessEventsToIdle(); + pWrtShell2->EndTextEdit(); // Assert that the first view can't and the second view can undo the insertion. SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc(); @@ -1321,7 +1322,6 @@ void SwTiledRenderingTest::testUndoShapeLimiting() rUndoManager.SetView(&pWrtShell2->GetView()); CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rUndoManager.GetUndoActionCount()); - pWrtShell2->EndTextEdit(); rUndoManager.SetView(nullptr); SfxLokHelper::setView(nView1); @@ -1426,11 +1426,14 @@ void SwTiledRenderingTest::testShapeTextUndoShells() pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); Scheduler::ProcessEventsToIdle(); + pWrtShell->EndTextEdit(); // Make sure that the undo item remembers who created it. SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc(); sw::UndoManager& rUndoManager = pDoc->GetUndoManager(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rUndoManager.GetUndoActionCount()); + CPPUNIT_ASSERT_EQUAL(size_t(1), rUndoManager.GetUndoActionCount()); + CPPUNIT_ASSERT_EQUAL(OUString("Edit text of Shape 'Shape1'"), rUndoManager.GetUndoActionComment(0)); + // This was -1: the view shell id for the undo action wasn't known. CPPUNIT_ASSERT_EQUAL(ViewShellId(nView1), rUndoManager.GetUndoAction()->GetViewShellId()); } @@ -1457,7 +1460,14 @@ void SwTiledRenderingTest::testShapeTextUndoGroupShells() // Make sure that the undo item remembers who created it. SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc(); sw::UndoManager& rUndoManager = pDoc->GetUndoManager(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rUndoManager.GetUndoActionCount()); + CPPUNIT_ASSERT_EQUAL(size_t(0), rUndoManager.GetUndoActionCount()); + + pWrtShell->EndTextEdit(); + pWrtShell->GetView().BeginTextEdit(pObject, pView->GetSdrPageView(), pWrtShell->GetWin()); + + CPPUNIT_ASSERT_EQUAL(size_t(1), rUndoManager.GetUndoActionCount()); + CPPUNIT_ASSERT_EQUAL(OUString("Edit text of Shape 'Shape1'"), rUndoManager.GetUndoActionComment(0)); + // This was -1: the view shell id for the (top) undo list action wasn't known. CPPUNIT_ASSERT_EQUAL(ViewShellId(nView1), rUndoManager.GetUndoAction()->GetViewShellId()); diff --git a/sw/source/core/draw/dview.cxx b/sw/source/core/draw/dview.cxx index 33d6a83fb1f8..510addf10a9c 100644 --- a/sw/source/core/draw/dview.cxx +++ b/sw/source/core/draw/dview.cxx @@ -998,12 +998,12 @@ void SwDrawView::DeleteMarked() pTmpRoot->EndAllAction(); } -// support enhanced text edit for draw objects -SdrUndoManager* SwDrawView::getSdrUndoManagerForEnhancedTextEdit() const +// Create a new view-local UndoManager manager for Writer +std::unique_ptr<SdrUndoManager> SwDrawView::createLocalTextUndoManager() { - SwDoc* pDoc = Imp().GetShell()->GetDoc(); - - return pDoc ? &(pDoc->GetUndoManager()) : nullptr; + std::unique_ptr<SdrUndoManager> pUndoManager(new SdrUndoManager); + pUndoManager->SetDocShell(SfxObjectShell::Current()); + return pUndoManager; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/inc/dview.hxx b/sw/source/core/inc/dview.hxx index 3e9f4e6c9864..cdcf3f265985 100644 --- a/sw/source/core/inc/dview.hxx +++ b/sw/source/core/inc/dview.hxx @@ -75,8 +75,8 @@ class SwDrawView final : public FmFormView using FmFormView::CheckSingleSdrObjectHit; virtual SdrObject* CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObject* pObj, SdrPageView* pPV, SdrSearchOptions nOptions, const SdrLayerIDSet* pMVisLay) const override; - // support enhanced text edit for draw objects - virtual SdrUndoManager* getSdrUndoManagerForEnhancedTextEdit() const override; + // Create a local UndoManager + std::unique_ptr<SdrUndoManager> createLocalTextUndoManager() override; public: SwDrawView( |