cui/source/dialogs/DiagramDialog.cxx           |   90 ++++++++++++++++++++++---
 cui/source/factory/dlgfact.cxx                 |    6 +
 cui/source/factory/dlgfact.hxx                 |    2 
 cui/source/inc/DiagramDialog.hxx               |    9 +-
 include/svx/diagram/datamodel.hxx              |   20 +++++
 include/svx/strings.hrc                        |    1 
 include/svx/svdogrp.hxx                        |   13 +++
 include/svx/svdundo.hxx                        |   25 ++++++
 include/vcl/abstdlg.hxx                        |    4 -
 oox/source/drawingml/diagram/diagramhelper.cxx |   20 +++++
 oox/source/drawingml/diagram/diagramhelper.hxx |    8 ++
 sc/source/ui/drawfunc/drawsh5.cxx              |    2 
 sd/source/ui/view/drviews3.cxx                 |    2 
 svx/source/diagram/datamodel.cxx               |   27 +++++++
 svx/source/svdraw/svdundo.cxx                  |   53 ++++++++++++++
 sw/source/uibase/shells/drwbassh.cxx           |    2 
 16 files changed, 265 insertions(+), 19 deletions(-)

New commits:
commit 1e016920769ae524575e40b1ec317c700ba0daa3
Author:     Armin Le Grand (Allotropia) <[email protected]>
AuthorDate: Tue May 10 15:59:29 2022 +0200
Commit:     Armin Le Grand <[email protected]>
CommitDate: Wed May 11 14:17:34 2022 +0200

    Advanced Diagram support: UNDO/REDO support for Diagram DataModel
    
    Added support for UNDO/REDO for changes in Diagram ModelData.
    This is currenly applied/used in the DiagramDialog for it's
    Add/Remove actions (also supports Cancel of that dialog 1st
    time ever). But it is defined more general to add/support
    manipulating actions like clone/change_text etc. Also the
    UI/dialog at he end will not be/stay modal, so this is a
    test implemenation how to use it.
    
    It uses an extract/apply mechanism to get/set the Diagram
    ModelData at/for the UNDO action. That may be expanded as
    needed for additional data in he future. It may also be
    considered to modify the Connection/Point ModelData to
    shared_ptr internally completely to avoid copying these
    at all. OTOH it is not that much data to handle at all.
    
    Change-Id: I4702ed908b79a476177fe66c0e3284898c6adda5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134118
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <[email protected]>

diff --git a/cui/source/dialogs/DiagramDialog.cxx 
b/cui/source/dialogs/DiagramDialog.cxx
index 9c5816cf4b2b..ea592767461d 100644
--- a/cui/source/dialogs/DiagramDialog.cxx
+++ b/cui/source/dialogs/DiagramDialog.cxx
@@ -11,12 +11,15 @@
 
 #include <comphelper/dispatchcommand.hxx>
 #include <svx/svdogrp.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdundo.hxx>
 #include <com/sun/star/beans/PropertyValue.hpp>
+#include <svx/diagram/datamodel.hxx>
 
-DiagramDialog::DiagramDialog(weld::Window* pWindow,
-                             const std::shared_ptr<IDiagramHelper>& 
pDiagramHelper)
+DiagramDialog::DiagramDialog(weld::Window* pWindow, SdrObjGroup& rDiagram)
     : GenericDialogController(pWindow, "cui/ui/diagramdialog.ui", 
"DiagramDialog")
-    , mpDiagramHelper(pDiagramHelper)
+    , m_rDiagram(rDiagram)
+    , m_nUndos(0)
     , mpBtnOk(m_xBuilder->weld_button("btnOk"))
     , mpBtnCancel(m_xBuilder->weld_button("btnCancel"))
     , mpBtnAdd(m_xBuilder->weld_button("btnAdd"))
@@ -24,6 +27,7 @@ DiagramDialog::DiagramDialog(weld::Window* pWindow,
     , mpTreeDiagram(m_xBuilder->weld_tree_view("treeDiagram"))
     , mpTextAdd(m_xBuilder->weld_text_view("textAdd"))
 {
+    mpBtnCancel->connect_clicked(LINK(this, DiagramDialog, OnAddCancel));
     mpBtnAdd->connect_clicked(LINK(this, DiagramDialog, OnAddClick));
     mpBtnRemove->connect_clicked(LINK(this, DiagramDialog, OnRemoveClick));
 
@@ -37,13 +41,51 @@ DiagramDialog::DiagramDialog(weld::Window* pWindow,
     });
 }
 
+IMPL_LINK_NOARG(DiagramDialog, OnAddCancel, weld::Button&, void)
+{
+    // If the user cancels the dialog, undo all changes done so far. It may
+    // even be feasible to then delete the redo-stack, since it stays
+    // available (?) - but it does no harm either...
+    while (0 != m_nUndos)
+    {
+        comphelper::dispatchCommand(".uno:Undo", {});
+        m_nUndos--;
+    }
+
+    m_xDialog->response(RET_CANCEL);
+}
+
 IMPL_LINK_NOARG(DiagramDialog, OnAddClick, weld::Button&, void)
 {
+    if (!m_rDiagram.isDiagram())
+        return;
+
     OUString sText = mpTextAdd->get_text();
+    const std::shared_ptr<IDiagramHelper>& 
pDiagramHelper(m_rDiagram.getDiagramHelper());
 
-    if (!sText.isEmpty())
+    if (pDiagramHelper && !sText.isEmpty())
     {
-        OUString sNodeId = mpDiagramHelper->addNode(sText);
+        SdrModel& rDrawModel(m_rDiagram.getSdrModelFromSdrObject());
+        const bool bUndo(rDrawModel.IsUndoEnabled());
+        svx::diagram::DiagramDataStatePtr aStartState;
+
+        if (bUndo)
+        {
+            // rescue all start state Diagram-defining data
+            aStartState = pDiagramHelper->extractDiagramDataState();
+        }
+
+        OUString sNodeId = pDiagramHelper->addNode(sText);
+
+        if (bUndo)
+        {
+            // create undo action. That will internally secure the
+            // current Diagram-defining data as end state
+            rDrawModel.AddUndo(
+                
rDrawModel.GetSdrUndoFactory().CreateUndoDiagramModelData(m_rDiagram, 
aStartState));
+            m_nUndos++;
+        }
+
         std::unique_ptr<weld::TreeIter> pEntry(mpTreeDiagram->make_iterator());
         mpTreeDiagram->insert(nullptr, -1, &sText, &sNodeId, nullptr, nullptr, 
false, pEntry.get());
         mpTreeDiagram->select(*pEntry);
@@ -53,11 +95,35 @@ IMPL_LINK_NOARG(DiagramDialog, OnAddClick, weld::Button&, 
void)
 
 IMPL_LINK_NOARG(DiagramDialog, OnRemoveClick, weld::Button&, void)
 {
+    if (!m_rDiagram.isDiagram())
+        return;
+
     std::unique_ptr<weld::TreeIter> pEntry(mpTreeDiagram->make_iterator());
-    if (mpTreeDiagram->get_selected(pEntry.get()))
+    const std::shared_ptr<IDiagramHelper>& 
pDiagramHelper(m_rDiagram.getDiagramHelper());
+
+    if (pDiagramHelper && mpTreeDiagram->get_selected(pEntry.get()))
     {
-        if (mpDiagramHelper->removeNode(mpTreeDiagram->get_id(*pEntry)))
+        SdrModel& rDrawModel(m_rDiagram.getSdrModelFromSdrObject());
+        const bool bUndo(rDrawModel.IsUndoEnabled());
+        svx::diagram::DiagramDataStatePtr aStartState;
+
+        if (bUndo)
+        {
+            // rescue all start state Diagram-defining data
+            aStartState = pDiagramHelper->extractDiagramDataState();
+        }
+
+        if (pDiagramHelper->removeNode(mpTreeDiagram->get_id(*pEntry)))
         {
+            if (bUndo)
+            {
+                // create undo action. That will internally secure the
+                // current Diagram-defining data as end state
+                
rDrawModel.AddUndo(rDrawModel.GetSdrUndoFactory().CreateUndoDiagramModelData(
+                    m_rDiagram, aStartState));
+                m_nUndos++;
+            }
+
             mpTreeDiagram->remove(*pEntry);
             comphelper::dispatchCommand(".uno:RegenerateDiagram", {});
         }
@@ -66,7 +132,15 @@ IMPL_LINK_NOARG(DiagramDialog, OnRemoveClick, 
weld::Button&, void)
 
 void DiagramDialog::populateTree(const weld::TreeIter* pParent, const 
OUString& rParentId)
 {
-    auto aItems = mpDiagramHelper->getChildren(rParentId);
+    if (!m_rDiagram.isDiagram())
+        return;
+
+    const std::shared_ptr<IDiagramHelper>& 
pDiagramHelper(m_rDiagram.getDiagramHelper());
+
+    if (!pDiagramHelper)
+        return;
+
+    auto aItems = pDiagramHelper->getChildren(rParentId);
     for (auto& aItem : aItems)
     {
         std::unique_ptr<weld::TreeIter> pEntry(mpTreeDiagram->make_iterator());
diff --git a/cui/source/factory/dlgfact.cxx b/cui/source/factory/dlgfact.cxx
index c7a8a204e075..28d473479ac7 100644
--- a/cui/source/factory/dlgfact.cxx
+++ b/cui/source/factory/dlgfact.cxx
@@ -1524,10 +1524,12 @@ 
AbstractDialogFactory_Impl::CreateToolbarmodeDialog(weld::Window* pParent)
 }
 
 VclPtr<AbstractDiagramDialog>
-AbstractDialogFactory_Impl::CreateDiagramDialog(weld::Window* pParent, const 
std::shared_ptr<IDiagramHelper>& pDiagramHelper)
+AbstractDialogFactory_Impl::CreateDiagramDialog(
+    weld::Window* pParent,
+    SdrObjGroup& rDiagram)
 {
     return VclPtr<AbstractDiagramDialog_Impl>::Create(
-        std::make_unique<DiagramDialog>(pParent, pDiagramHelper));
+        std::make_unique<DiagramDialog>(pParent, rDiagram));
 }
 
 #ifdef _WIN32
diff --git a/cui/source/factory/dlgfact.hxx b/cui/source/factory/dlgfact.hxx
index 3ce135927f14..1b9c85f66841 100644
--- a/cui/source/factory/dlgfact.hxx
+++ b/cui/source/factory/dlgfact.hxx
@@ -608,7 +608,7 @@ public:
 
     virtual VclPtr<AbstractDiagramDialog> CreateDiagramDialog(
         weld::Window* pParent,
-        const std::shared_ptr<IDiagramHelper>& pDiagramHelper) override;
+        SdrObjGroup& rDiagram) override;
 
 #ifdef _WIN32
     virtual VclPtr<VclAbstractDialog> CreateFileExtCheckDialog(weld::Window* 
pParent,
diff --git a/cui/source/inc/DiagramDialog.hxx b/cui/source/inc/DiagramDialog.hxx
index 397aab44f50f..71a5bd9b79c4 100644
--- a/cui/source/inc/DiagramDialog.hxx
+++ b/cui/source/inc/DiagramDialog.hxx
@@ -12,17 +12,19 @@
 #include <tools/link.hxx>
 #include <vcl/weld.hxx>
 
-class IDiagramHelper;
+class SdrObjGroup;
 
 /** Edit Diagram dialog */
 class DiagramDialog : public weld::GenericDialogController
 {
 public:
-    DiagramDialog(weld::Window* pWindow, const 
std::shared_ptr<IDiagramHelper>& pDiagramHelper);
+    DiagramDialog(weld::Window* pWindow, SdrObjGroup& rDiagram);
     virtual ~DiagramDialog() override;
 
 private:
-    const std::shared_ptr<IDiagramHelper> mpDiagramHelper;
+    SdrObjGroup& m_rDiagram;
+    sal_uInt32 m_nUndos;
+
     std::unique_ptr<weld::Button> mpBtnOk;
     std::unique_ptr<weld::Button> mpBtnCancel;
     std::unique_ptr<weld::Button> mpBtnAdd;
@@ -30,6 +32,7 @@ private:
     std::unique_ptr<weld::TreeView> mpTreeDiagram;
     std::unique_ptr<weld::TextView> mpTextAdd;
 
+    DECL_LINK(OnAddCancel, weld::Button&, void);
     DECL_LINK(OnAddClick, weld::Button&, void);
     DECL_LINK(OnRemoveClick, weld::Button&, void);
 
diff --git a/include/svx/diagram/datamodel.hxx 
b/include/svx/diagram/datamodel.hxx
index 7a080f8703ee..850cd8f78271 100644
--- a/include/svx/diagram/datamodel.hxx
+++ b/include/svx/diagram/datamodel.hxx
@@ -154,6 +154,22 @@ struct SVXCORE_DLLPUBLIC Point
 
 typedef std::vector< Point >        Points;
 
+/** Snippet of Diagram ModelData for Diagram-defining data undo/redo
+ */
+class SVXCORE_DLLPUBLIC DiagramDataState
+{
+    Connections maConnections;
+    Points maPoints;
+
+public:
+    DiagramDataState(const Connections& rConnections, const Points& rPoints);
+
+    Connections& getConnections() { return maConnections; }
+    Points& getPoints() { return maPoints; }
+};
+
+typedef std::shared_ptr< DiagramDataState > DiagramDataStatePtr;
+
 /** The collected Diagram ModelData
  */
 class SVXCORE_DLLPUBLIC DiagramData
@@ -207,6 +223,10 @@ public:
     OUString addNode(const OUString& rText);
     bool removeNode(const OUString& rNodeId);
 
+    // Undo/Redo helpers to extract/restore Diagram-defining data
+    DiagramDataStatePtr extractDiagramDataState() const;
+    void applyDiagramDataState(const DiagramDataStatePtr& rState);
+
 protected:
     // helpers
     void getChildrenString(OUStringBuffer& rBuf, const Point* pPoint, 
sal_Int32 nLevel) const;
diff --git a/include/svx/strings.hrc b/include/svx/strings.hrc
index e9b354f6f151..17f2b17d6081 100644
--- a/include/svx/strings.hrc
+++ b/include/svx/strings.hrc
@@ -210,6 +210,7 @@
 #define STR_DragInsertGluePoint                             
NC_("STR_DragInsertGluePoint", "Insert gluepoint to %1")
 #define STR_DragMethMovHdl                                  
NC_("STR_DragMethMovHdl", "Move reference-point")
 #define STR_DragMethObjOwn                                  
NC_("STR_DragMethObjOwn", "Geometrically change %1")
+#define STR_DiagramModelDataChange                          
NC_("STR_DiagramModelDataChange", "Diagram change %1")
 #define STR_DragMethMove                                    
NC_("STR_DragMethMove", "Move %1")
 #define STR_DragMethResize                                  
NC_("STR_DragMethResize", "Resize %1")
 #define STR_DragMethRotate                                  
NC_("STR_DragMethRotate", "Rotate %1")
diff --git a/include/svx/svdogrp.hxx b/include/svx/svdogrp.hxx
index 5aab501ec9e4..c411a049c959 100644
--- a/include/svx/svdogrp.hxx
+++ b/include/svx/svdogrp.hxx
@@ -27,6 +27,13 @@
 // Forward declarations
 class SfxItemSet;
 class SdrObjGroup;
+namespace svx
+{
+namespace diagram
+{
+class DiagramDataState;
+}
+}
 
 // Helper class to allow administer advanced Diagram related
 // data and functionality
@@ -81,6 +88,12 @@ public:
     virtual OUString addNode(const OUString& rText) = 0;
     virtual bool removeNode(const OUString& rNodeId) = 0;
 
+    // Undo/Redo helpers for extracting/restoring Diagram-defining data
+    virtual std::shared_ptr<svx::diagram::DiagramDataState> 
extractDiagramDataState() const = 0;
+    virtual void
+    applyDiagramDataState(const 
std::shared_ptr<svx::diagram::DiagramDataState>& rState)
+        = 0;
+
     bool UseDiagramThemeData() const { return mbUseDiagramThemeData; }
     bool UseDiagramModelData() const { return mbUseDiagramModelData; }
     bool ForceThemePtrRecreation() const { return mbForceThemePtrRecreation; };
diff --git a/include/svx/svdundo.hxx b/include/svx/svdundo.hxx
index c4116616e43a..01b4f6749770 100644
--- a/include/svx/svdundo.hxx
+++ b/include/svx/svdundo.hxx
@@ -49,6 +49,10 @@ class SdrLayerAdmin;
 class SdrObjGeoData;
 class OutlinerParaObject;
 
+namespace svx { namespace diagram {
+    class DiagramDataState;
+}}
+
 /**
  * Abstract base class (ABC) for all UndoActions of DrawingEngine
  */
@@ -224,6 +228,24 @@ public:
     void SetSkipChangeLayout(bool bOn) { mbSkipChangeLayout=bOn; }
 };
 
+// Diagram ModelData changes
+class SVXCORE_DLLPUBLIC SdrUndoDiagramModelData : public SdrUndoObj
+{
+    std::shared_ptr< svx::diagram::DiagramDataState > m_aStartState;
+    std::shared_ptr< svx::diagram::DiagramDataState > m_aEndState;
+
+    void implUndoRedo(bool bUndo);
+
+public:
+    SdrUndoDiagramModelData(SdrObject& rNewObj, std::shared_ptr< 
svx::diagram::DiagramDataState >& rStartState);
+    virtual ~SdrUndoDiagramModelData() override;
+
+    virtual void Undo() override;
+    virtual void Redo() override;
+
+    virtual OUString GetComment() const override;
+};
+
 /**
  * Manipulation of an ObjList: New Object, DeleteObj, SetObjZLevel, Grouping, 
...
  * Abstract base class.
@@ -741,6 +763,9 @@ public:
                                                     const OUString& sOldStr,
                                                     const OUString& sNewStr );
 
+    // Diagram ModelData changes
+    virtual std::unique_ptr<SdrUndoAction> CreateUndoDiagramModelData( 
SdrObject& rObject, std::shared_ptr< svx::diagram::DiagramDataState >& 
rStartState );
+
     // Layer
     virtual std::unique_ptr<SdrUndoAction> CreateUndoNewLayer(sal_uInt16 
nLayerNum, SdrLayerAdmin& rNewLayerAdmin, SdrModel& rNewModel);
     virtual std::unique_ptr<SdrUndoAction> CreateUndoDeleteLayer(sal_uInt16 
nLayerNum, SdrLayerAdmin& rNewLayerAdmin, SdrModel& rNewModel);
diff --git a/include/vcl/abstdlg.hxx b/include/vcl/abstdlg.hxx
index f6097f940655..79b2b32a9836 100644
--- a/include/vcl/abstdlg.hxx
+++ b/include/vcl/abstdlg.hxx
@@ -34,7 +34,7 @@ namespace com::sun::star::frame { class XModel; }
 
 class Dialog;
 class BitmapEx;
-class IDiagramHelper;
+class SdrObjGroup;
 namespace weld
 {
     class Dialog;
@@ -179,7 +179,7 @@ public:
 
     virtual VclPtr<AbstractDiagramDialog> CreateDiagramDialog(
         weld::Window* pParent,
-        const std::shared_ptr<IDiagramHelper>& pDiagramHelper) = 0;
+        SdrObjGroup& rDiagram) = 0;
 
 #ifdef _WIN32
     virtual VclPtr<VclAbstractDialog>
diff --git a/oox/source/drawingml/diagram/diagramhelper.cxx 
b/oox/source/drawingml/diagram/diagramhelper.cxx
index 0164ce0845d3..7859a9667e7b 100644
--- a/oox/source/drawingml/diagram/diagramhelper.cxx
+++ b/oox/source/drawingml/diagram/diagramhelper.cxx
@@ -198,6 +198,26 @@ bool AdvancedDiagramHelper::removeNode(const OUString& 
rNodeId)
     return bRetval;
 }
 
+svx::diagram::DiagramDataStatePtr 
AdvancedDiagramHelper::extractDiagramDataState() const
+{
+    if(!mpDiagramPtr)
+    {
+        return svx::diagram::DiagramDataStatePtr();
+    }
+
+    return mpDiagramPtr->getData()->extractDiagramDataState();
+}
+
+void AdvancedDiagramHelper::applyDiagramDataState(const 
svx::diagram::DiagramDataStatePtr& rState)
+{
+    if(!mpDiagramPtr)
+    {
+        return;
+    }
+
+    mpDiagramPtr->getData()->applyDiagramDataState(rState);
+}
+
 void AdvancedDiagramHelper::doAnchor(SdrObjGroup& rTarget, 
::oox::drawingml::Shape& rRootShape)
 {
     if(!mpDiagramPtr)
diff --git a/oox/source/drawingml/diagram/diagramhelper.hxx 
b/oox/source/drawingml/diagram/diagramhelper.hxx
index cede1aeeccf9..e47047746776 100644
--- a/oox/source/drawingml/diagram/diagramhelper.hxx
+++ b/oox/source/drawingml/diagram/diagramhelper.hxx
@@ -25,6 +25,10 @@
 #include <oox/shape/ShapeFilterBase.hxx>
 #include <svx/svdogrp.hxx>
 
+namespace svx { namespace diagram {
+    class DiagramDataState;
+}}
+
 namespace oox::drawingml {
 
 class Diagram;
@@ -73,6 +77,10 @@ public:
     virtual OUString addNode(const OUString& rText) override;
     virtual bool removeNode(const OUString& rNodeId) override;
 
+    // Undo/Redo helpers to extract/restore Diagram-defining data
+    virtual std::shared_ptr< svx::diagram::DiagramDataState > 
extractDiagramDataState() const override;
+    virtual void applyDiagramDataState(const std::shared_ptr< 
svx::diagram::DiagramDataState >& rState) override;
+
     void doAnchor(SdrObjGroup& rTarget, ::oox::drawingml::Shape& rRootShape);
     std::shared_ptr< ::oox::drawingml::Theme > getOrCreateThemePtr(
         rtl::Reference< oox::shape::ShapeFilterBase>& rxFilter ) const;
diff --git a/sc/source/ui/drawfunc/drawsh5.cxx 
b/sc/source/ui/drawfunc/drawsh5.cxx
index a3c37eed1e15..c06b1b646760 100644
--- a/sc/source/ui/drawfunc/drawsh5.cxx
+++ b/sc/source/ui/drawfunc/drawsh5.cxx
@@ -298,7 +298,7 @@ void ScDrawShell::ExecDrawFunc( SfxRequest& rReq )
                             vcl::Window* pWin = rViewData.GetActiveWin();
                             ScopedVclPtr<VclAbstractDialog> pDlg = 
pFact->CreateDiagramDialog(
                                 pWin ? pWin->GetFrameWeld() : nullptr,
-                                pAnchorObj->getDiagramHelper());
+                                *pAnchorObj);
                             pDlg->Execute();
                         }
                     }
diff --git a/sd/source/ui/view/drviews3.cxx b/sd/source/ui/view/drviews3.cxx
index c80c6b3bbd5b..6a7c778d8a6f 100644
--- a/sd/source/ui/view/drviews3.cxx
+++ b/sd/source/ui/view/drviews3.cxx
@@ -506,7 +506,7 @@ void  DrawViewShell::ExecCtrl(SfxRequest& rReq)
                         VclAbstractDialogFactory* pFact = 
VclAbstractDialogFactory::Create();
                         ScopedVclPtr<VclAbstractDialog> pDlg = 
pFact->CreateDiagramDialog(
                             GetFrameWeld(),
-                            pAnchorObj->getDiagramHelper());
+                            *pAnchorObj);
                         pDlg->Execute();
                     }
                 }
diff --git a/svx/source/diagram/datamodel.cxx b/svx/source/diagram/datamodel.cxx
index fd562645eaa0..e45fe7fb4c3a 100644
--- a/svx/source/diagram/datamodel.cxx
+++ b/svx/source/diagram/datamodel.cxx
@@ -141,6 +141,33 @@ bool DiagramData::removeNode(const OUString& rNodeId)
     return true;
 }
 
+DiagramDataState::DiagramDataState(const Connections& rConnections, const 
Points& rPoints)
+: maConnections(rConnections)
+, maPoints(rPoints)
+{
+}
+
+DiagramDataStatePtr DiagramData::extractDiagramDataState() const
+{
+    // Just copy all Connections && Points. The shared_ptr data in
+    // Point-entries is no problem, it just continues exiting shared
+    return std::make_shared< DiagramDataState >(maConnections, maPoints);
+}
+
+void DiagramData::applyDiagramDataState(const DiagramDataStatePtr& rState)
+{
+    if(rState)
+    {
+        maConnections = rState->getConnections();
+        maPoints = rState->getPoints();
+
+        // Reset temporary buffered ModelData association lists & rebuild them
+        // and the Diagram DataModel. Do that here *immediately* to prevent
+        // re-usage of potentially invalid Connection/Point objects
+        buildDiagramDataModel(true);
+    }
+}
+
 void DiagramData::getChildrenString(
     OUStringBuffer& rBuf,
     const svx::diagram::Point* pPoint,
diff --git a/svx/source/svdraw/svdundo.cxx b/svx/source/svdraw/svdundo.cxx
index f1c97c4c16a8..b61ad93fde90 100644
--- a/svx/source/svdraw/svdundo.cxx
+++ b/svx/source/svdraw/svdundo.cxx
@@ -45,6 +45,7 @@
 #include <svx/svdoashp.hxx>
 #include <sal/log.hxx>
 #include <osl/diagnose.h>
+#include <svx/diagram/datamodel.hxx>
 
 
 // iterates over all views and unmarks this SdrObject if it is marked
@@ -628,6 +629,52 @@ OUString SdrUndoGeoObj::GetComment() const
     return ImpGetDescriptionStr(STR_DragMethObjOwn);
 }
 
+SdrUndoDiagramModelData::SdrUndoDiagramModelData(SdrObject& rNewObj, 
svx::diagram::DiagramDataStatePtr& rStartState)
+: SdrUndoObj(rNewObj)
+, m_aStartState(rStartState)
+, m_aEndState()
+{
+    SdrObjGroup* pDiagram(dynamic_cast<SdrObjGroup*>(&rNewObj));
+
+    if(pDiagram && pDiagram->isDiagram())
+    {
+        m_aEndState = pDiagram->getDiagramHelper()->extractDiagramDataState();
+    }
+}
+
+SdrUndoDiagramModelData::~SdrUndoDiagramModelData()
+{
+}
+
+void SdrUndoDiagramModelData::implUndoRedo(bool bUndo)
+{
+    if(nullptr == pObj)
+        return;
+
+    SdrObjGroup* pDiagram(dynamic_cast<SdrObjGroup*>(pObj));
+
+    if(nullptr == pDiagram || !pDiagram->isDiagram())
+        return;
+
+    pDiagram->getDiagramHelper()->applyDiagramDataState(
+        bUndo ? m_aStartState : m_aEndState);
+    pDiagram->getDiagramHelper()->reLayout(*pDiagram);
+}
+
+void SdrUndoDiagramModelData::Undo()
+{
+    implUndoRedo(true);
+}
+
+void SdrUndoDiagramModelData::Redo()
+{
+    implUndoRedo(false);
+}
+
+OUString SdrUndoDiagramModelData::GetComment() const
+{
+    return ImpGetDescriptionStr(STR_DiagramModelDataChange);
+}
 
 SdrUndoObjList::SdrUndoObjList(SdrObject& rNewObj, bool bOrdNumDirect)
     : SdrUndoObj(rNewObj)
@@ -1676,6 +1723,12 @@ std::unique_ptr<SdrUndoAction> 
SdrUndoFactory::CreateUndoGeoObject( SdrObject& r
     return std::make_unique<SdrUndoGeoObj>( rObject );
 }
 
+// Diagram ModelData changes
+std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoDiagramModelData( 
SdrObject& rObject, std::shared_ptr< svx::diagram::DiagramDataState >& 
rStartState )
+{
+    return std::make_unique<SdrUndoDiagramModelData>( rObject, rStartState );
+}
+
 std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoAttrObject( 
SdrObject& rObject, bool bStyleSheet1, bool bSaveText )
 {
     return std::make_unique<SdrUndoAttrObj>( rObject, bStyleSheet1, bSaveText 
);
diff --git a/sw/source/uibase/shells/drwbassh.cxx 
b/sw/source/uibase/shells/drwbassh.cxx
index 8679a3fc4d47..77325a28eddb 100644
--- a/sw/source/uibase/shells/drwbassh.cxx
+++ b/sw/source/uibase/shells/drwbassh.cxx
@@ -461,7 +461,7 @@ void SwDrawBaseShell::Execute(SfxRequest const &rReq)
                             VclAbstractDialogFactory* pFact = 
VclAbstractDialogFactory::Create();
                             ScopedVclPtr<VclAbstractDialog> pDlg = 
pFact->CreateDiagramDialog(
                                 GetView().GetFrameWeld(),
-                                pAnchorObj->getDiagramHelper());
+                                *pAnchorObj);
                             pDlg->Execute();
                         }
                     }

Reply via email to