summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2021-10-07 16:48:46 +0200
committerTomaž Vajngerl <quikee@gmail.com>2021-11-12 14:08:08 +0100
commit723db12abd7c238e11dab0271516b6f4415e52eb (patch)
treeb61726c403a558caf81691db11f5bd3a33227ba4
parent567f8d111701c288671440b6f75d67a57be43ff5 (diff)
svx: Don't end text edit mode for all views
This allows multiple views to not disturb each other editing inside a impress document. With the ending of text edit for all views still enabled, one view can cancel other views text editing just by moving or resizing a unrelated shape in the document. To make this possible we also need a view-local undo manager for the text edit mode, which is independent of the document undo manager. When the text edit mode ends, all the changes will be added as one change to the document undo stack. This prevents any conflicts in the undo stack that could be made when 2 views are editing the same document at the same time. This also adds the test for the new use case and changes the existing tests to reflect the change. Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123220 Tested-by: Tomaž Vajngerl <quikee@gmail.com> Reviewed-by: Tomaž Vajngerl <quikee@gmail.com> (cherry picked from commit c175c1dc19d0edc8ca66e39f0b4b8af04e3d6c87) Change-Id: I04edb4f91d7e111a490c946f7121cbca75f818d7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125070 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r--include/svx/svdedtv.hxx1
-rw-r--r--include/svx/svdedxv.hxx13
-rw-r--r--sc/source/ui/inc/drawview.hxx4
-rw-r--r--sc/source/ui/view/drawview.cxx9
-rw-r--r--sd/qa/unit/misc-tests.cxx34
-rw-r--r--sd/qa/unit/tiledrendering/data/TextBoxAndRect.odgbin0 -> 10474 bytes
-rw-r--r--sd/qa/unit/tiledrendering/tiledrendering.cxx339
-rw-r--r--sd/source/ui/inc/View.hxx3
-rw-r--r--sd/source/ui/view/drviews1.cxx4
-rw-r--r--sd/source/ui/view/sdview.cxx10
-rw-r--r--svx/source/svdraw/svddrgmt.cxx2
-rw-r--r--svx/source/svdraw/svdedtv.cxx10
-rw-r--r--svx/source/svdraw/svdedtv1.cxx24
-rw-r--r--svx/source/svdraw/svdedxv.cxx17
-rw-r--r--sw/qa/extras/tiledrendering/data/shape.fodt20
-rw-r--r--sw/qa/extras/tiledrendering/tiledrendering.cxx16
-rw-r--r--sw/source/core/draw/dview.cxx10
-rw-r--r--sw/source/core/inc/dview.hxx4
18 files changed, 456 insertions, 64 deletions
diff --git a/include/svx/svdedtv.hxx b/include/svx/svdedtv.hxx
index 51da6124ed88..71e014970888 100644
--- a/include/svx/svdedtv.hxx
+++ b/include/svx/svdedtv.hxx
@@ -195,6 +195,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( SdrObject& rO );
void AddUndoActions( std::vector< std::unique_ptr<SdrUndoAction> > );
diff --git a/include/svx/svdedxv.hxx b/include/svx/svdedxv.hxx
index 1f9fcf0b898d..737da8ca4896 100644
--- a/include/svx/svdedxv.hxx
+++ b/include/svx/svdedxv.hxx
@@ -104,20 +104,17 @@ protected:
private:
SfxUndoManager* mpOldTextEditUndoManager;
+ std::unique_ptr<SdrUndoManager> mpLocalTextEditUndoManager;
SVX_DLLPRIVATE void ImpClearVars();
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);
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.
@@ -177,6 +174,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/source/ui/inc/drawview.hxx b/sc/source/ui/inc/drawview.hxx
index 46f5598705f2..aa5e1bbb8533 100644
--- a/sc/source/ui/inc/drawview.hxx
+++ b/sc/source/ui/inc/drawview.hxx
@@ -52,8 +52,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 c7d12df62209..6959726b4efe 100644
--- a/sc/source/ui/view/drawview.cxx
+++ b/sc/source/ui/view/drawview.cxx
@@ -1103,10 +1103,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 pDoc ? dynamic_cast< SdrUndoManager* >(pDoc->GetUndoManager()) : nullptr;
+ 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/unit/misc-tests.cxx b/sd/qa/unit/misc-tests.cxx
index 5797bdda4348..4e9dfe4c8b59 100644
--- a/sd/qa/unit/misc-tests.cxx
+++ b/sd/qa/unit/misc-tests.cxx
@@ -64,7 +64,7 @@ public:
void testTdf96206();
void testTdf96708();
void testTdf99396();
- void testTdf99396TextEdit();
+ void testTableObjectUndoTest();
void testFillGradient();
void testTdf44774();
void testTdf38225();
@@ -81,7 +81,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);
@@ -252,8 +252,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("/sd/qa/unit/data/tdf99396.odp"), ODP);
sd::ViewShell* pViewShell = xDocSh->GetViewShell();
@@ -279,14 +281,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();
@@ -304,6 +318,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();
@@ -319,6 +337,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
@@ -329,8 +350,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
new file mode 100644
index 000000000000..aa1a37b83147
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/TextBoxAndRect.odg
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx b/sd/qa/unit/tiledrendering/tiledrendering.cxx
index 99c30b852a40..fae683532057 100644
--- a/sd/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx
@@ -132,6 +132,7 @@ public:
void testSlideDuplicateUndo();
void testMoveShapeHandle();
void testDeleteTable();
+ void testShapeEditInMultipleViews();
CPPUNIT_TEST_SUITE(SdTiledRenderingTest);
CPPUNIT_TEST(testCreateDestroy);
@@ -189,7 +190,7 @@ public:
CPPUNIT_TEST(testSlideDuplicateUndo);
CPPUNIT_TEST(testMoveShapeHandle);
CPPUNIT_TEST(testDeleteTable);
-
+ CPPUNIT_TEST(testShapeEditInMultipleViews);
CPPUNIT_TEST_SUITE_END();
private:
@@ -1316,6 +1317,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());
@@ -2073,11 +2106,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;
@@ -2092,15 +2133,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.
@@ -2111,15 +2161,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()));
}
}
@@ -2136,17 +2194,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());
}
@@ -2158,16 +2219,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());
}
}
@@ -2689,7 +2757,244 @@ void SdTiledRenderingTest::testMoveShapeHandle()
CPPUNIT_ASSERT_EQUAL(x-1, oldX);
CPPUNIT_ASSERT_EQUAL(y-1, oldY);
}
+}
+
+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);
diff --git a/sd/source/ui/inc/View.hxx b/sd/source/ui/inc/View.hxx
index 4693ce3e9596..152ed5d33c91 100644
--- a/sd/source/ui/inc/View.hxx
+++ b/sd/source/ui/inc/View.hxx
@@ -139,6 +139,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 bdbf06b72361..468a2cba3078 100644
--- a/sd/source/ui/view/drviews1.cxx
+++ b/sd/source/ui/view/drviews1.cxx
@@ -343,7 +343,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 0abaff31fc9f..f6bf3381231b 100644
--- a/sd/source/ui/view/sdview.cxx
+++ b/sd/source/ui/view/sdview.cxx
@@ -79,6 +79,8 @@
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <DrawController.hxx>
+#include <undo/undomanager.hxx>
+
#include <memory>
#include <numeric>
@@ -618,6 +620,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 80c421e40149..bbb640e6c6c7 100644
--- a/svx/source/svdraw/svddrgmt.cxx
+++ b/svx/source/svdraw/svddrgmt.cxx
@@ -1360,7 +1360,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 b48174ad8b57..44d9684e2ef9 100644
--- a/svx/source/svdraw/svdedtv.cxx
+++ b/svx/source/svdraw/svdedtv.cxx
@@ -1059,4 +1059,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 830ef238c590..21a0830bbd1a 100644
--- a/svx/source/svdraw/svdedtv1.cxx
+++ b/svx/source/svdraw/svdedtv1.cxx
@@ -99,7 +99,7 @@ void SdrEditView::SetMarkedObjRect(const tools::Rectangle& rRect)
const bool bUndo = IsUndoEnabled();
if( bUndo )
{
- EndTextEditAllViews();
+ EndTextEditCurrentView();
BegUndo(ImpGetDescriptionString(STR_EditPosSize));
}
@@ -190,7 +190,7 @@ void SdrEditView::MoveMarkedObj(const Size& rSiz, bool bCopy)
if( bUndo )
{
- EndTextEditAllViews();
+ EndTextEditCurrentView();
OUString aStr(SvxResId(STR_EditMove));
if (bCopy)
aStr += SvxResId(STR_EditWithCopy);
@@ -223,7 +223,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);
@@ -258,7 +258,7 @@ void SdrEditView::ResizeMultMarkedObj(const Point& rRef,
const bool bUndo = IsUndoEnabled();
if( bUndo )
{
- EndTextEditAllViews();
+ EndTextEditCurrentView();
BegUndo(ImpGetDescriptionString(STR_EditResize));
}
@@ -319,7 +319,7 @@ void SdrEditView::RotateMarkedObj(const Point& rRef, long nAngle, bool bCopy)
const bool bUndo = IsUndoEnabled();
if( bUndo )
{
- EndTextEditAllViews();
+ EndTextEditCurrentView();
OUString aStr {ImpGetDescriptionString(STR_EditRotate)};
if (bCopy) aStr+=SvxResId(STR_EditWithCopy);
BegUndo(aStr);
@@ -376,7 +376,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)
@@ -476,7 +476,7 @@ void SdrEditView::ShearMarkedObj(const Point& rRef, long nAngle, bool bVShear, b
if( bUndo )
{
- EndTextEditAllViews();
+ EndTextEditCurrentView();
OUString aStr {ImpGetDescriptionString(STR_EditShear)};
if (bCopy)
aStr+=SvxResId(STR_EditWithCopy);
@@ -592,7 +592,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);
@@ -666,7 +666,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);
@@ -1111,7 +1111,7 @@ void SdrEditView::SetAttrToMarked(const SfxItemSet& rAttr, bool bReplaceAll)
const bool bUndo = IsUndoEnabled();
if( bUndo )
{
- EndTextEditAllViews();
+ EndTextEditCurrentView();
BegUndo(ImpGetDescriptionString(STR_EditSetAttributes));
}
@@ -1291,7 +1291,7 @@ void SdrEditView::SetStyleSheetToMarked(SfxStyleSheet* pStyleSheet, bool bDontRe
if( bUndo )
{
- EndTextEditAllViews();
+ EndTextEditCurrentView();
OUString aStr;
if (pStyleSheet!=nullptr)
aStr = ImpGetDescriptionString(STR_EditSetStylesheet);
@@ -1859,7 +1859,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 32d8ad82360b..32057e0b5163 100644
--- a/svx/source/svdraw/svdedxv.cxx
+++ b/svx/source/svdraw/svdedxv.cxx
@@ -1066,10 +1066,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,
@@ -1370,7 +1371,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)
{
@@ -1444,7 +1449,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)
{
@@ -1476,6 +1481,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 4994797328b8..9f7eca8b1241 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -1300,6 +1300,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();
@@ -1310,7 +1311,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);
@@ -1418,11 +1418,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());
}
@@ -1450,7 +1453,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 f9ef11b99897..ab69b7af2d68 100644
--- a/sw/source/core/draw/dview.cxx
+++ b/sw/source/core/draw/dview.cxx
@@ -984,12 +984,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 ? dynamic_cast< SdrUndoManager* >(&(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 2251efa48a76..4cd23aee519c 100644
--- a/sw/source/core/inc/dview.hxx
+++ b/sw/source/core/inc/dview.hxx
@@ -76,8 +76,8 @@ protected:
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(