oox/source/drawingml/diagram/datamodel.cxx |   59 +++++++++++++++++++++++++++--
 oox/source/drawingml/diagram/datamodel.hxx |   11 ++++-
 oox/source/drawingml/diagram/diagram.cxx   |    8 +++
 3 files changed, 71 insertions(+), 7 deletions(-)

New commits:
commit 2b56631f9406b29eebcfcbe8dec5348590b4b817
Author:     Armin Le Grand (Allotropia) <armin.le.gr...@me.com>
AuthorDate: Fri Mar 25 16:34:30 2022 +0100
Commit:     Armin Le Grand <armin.le.gr...@me.com>
CommitDate: Sat Mar 26 15:36:01 2022 +0100

    Advanced Diagram support: Preparations to make oox-Shape temporary
    
    When we come from the LO-side of things and need to (re)create the
    Diagram, no oox-Shapes can exist by definition. That forces to see
    oox-Shapes as temporary helper objects.
    Since some ModelData is at the oox-Shape after importing a Diagram
    that data needs to be identified and added to the Diagram
    ModelData.
    On the other path, when (re)creating a Diagram from the ModelData,
    oox-Shapes are needed to use the currently existing mechanism
    in the import-Filter to create XShapes froom the oox-Shapes. In
    that path, the Diagram ModelData needs to be applied to the
    newly created oox-Shape.
    For now I have identified e.g. the Text as such data value. In
    the future there may be more ModelData of that type identified
    and may need to be added. To support that, I have added methods
    to do that.
    It may even be feasible in debug builds to add code to compare
    the imported oox-Shape with a temporarily (re)created one to
    allow easier identification of yet missing secured/copied
    ModelData.
    To make that mechanism obligatory I have added code in
    DiagramData::build() that deletes all oox-Shapes which were
    created at Diagam import. This is necessary. That way, the
    (re)creation is used for Diagram re-creation and can be already
    used and tested.
    
    Deleting all oox-Shapes in build() immediately triggered an
    error in a UnitTest: testPictureStrip. This shows that here
    some ModelData in form of BitmapData is not secured - proof
    of concept and what I described above.
    To get forward, I adapted to not delete oox-Shapes when
    Diagram import is executed. Thus, the UnitTests work, and
    the ReCreate can be used to trigger that behaviour. As
    an end result this has to be re-activated. It allows now
    to search and add the missing model data from the test file
    used in that UnitTest.
    
    Change-Id: I6bc39a0898c7be1b4c656875f6d7508c36c9bea8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132127
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <armin.le.gr...@me.com>

diff --git a/oox/source/drawingml/diagram/datamodel.cxx 
b/oox/source/drawingml/diagram/datamodel.cxx
index c68ee40cd71c..325259295fef 100644
--- a/oox/source/drawingml/diagram/datamodel.cxx
+++ b/oox/source/drawingml/diagram/datamodel.cxx
@@ -68,11 +68,53 @@ Shape* DiagramData::getOrCreateAssociatedShape(const 
dgm::Point& rPoint, bool bC
     if(!rShapePtr && bCreateOnDemand)
     {
         const_cast<ShapePtr&>(rShapePtr) = std::make_shared<Shape>();
+
+        // If we did create a new oox::drawingml::Shape, directly apply
+        // available data from the Diagram ModelData to it as preparation
+        restoreDataFromModelToShapeAfterReCreation(rPoint, *rShapePtr);
     }
 
     return rShapePtr.get();
 }
 
+void DiagramData::restoreDataFromModelToShapeAfterReCreation(const dgm::Point& 
rPoint, Shape& rNewShape) const
+{
+    // If we did create a new oox::drawingml::Shape, directly apply
+    // available data from the Diagram ModelData to it as preparation
+
+    // This is e.g. the Text, but may get more (styles?)
+    const auto pTextForShape = maPointTextMap.find(rPoint.msModelId);
+    if (pTextForShape != maPointTextMap.end())
+    {
+        rNewShape.setTextBody(pTextForShape->second);
+    }
+}
+
+void DiagramData::secureDataFromShapeToModelAfterDiagramImport()
+{
+    // After Diagram import, parts of the Diagram ModelData is at the
+    // oox::drawingml::Shape. Since these objects are temporary helpers,
+    // secure that data at the Diagram ModelData by copying.
+
+    // This is currently mainly the Text, but may get more (styles?)
+    for (auto & point : maPoints)
+    {
+        Shape* pShapeCandidate(getOrCreateAssociatedShape(point));
+
+        if(nullptr != pShapeCandidate
+            && pShapeCandidate->getTextBody()
+            && !pShapeCandidate->getTextBody()->isEmpty())
+        {
+            maPointTextMap[point.msModelId] = pShapeCandidate->getTextBody();
+        }
+    }
+
+    // At this place a mechanism to find missing data should be added:
+    // Create a Shape from so-far secured data & compare it with the
+    // imported one. Report differences to allow extending the mechanism
+    // more easily.
+}
+
 DiagramData::DiagramData() :
     mpFillProperties( std::make_shared<FillProperties>() )
 {
@@ -242,7 +284,7 @@ OUString DiagramData::addNode(const OUString& rText)
     maPoints.push_back(aDataPoint);
     maPoints.push_back(aPresPoint);
 
-    build();
+    build(true);
     return sNewNodeId;
 }
 
@@ -294,7 +336,7 @@ bool DiagramData::removeNode(const OUString& rNodeId)
 
     // TODO: fix source/dest order
 
-    build();
+    build(true);
     return true;
 }
 
@@ -338,8 +380,14 @@ static sal_Int32 calcDepth( std::u16string_view rNodeName,
     return 0;
 }
 
-void DiagramData::build()
+void DiagramData::build(bool bClearOoxShapes)
 {
+    // Delete/remove all existing oox::drawingml::Shape
+    if(bClearOoxShapes)
+    {
+        maPointShapeMap.clear();
+    }
+
     // build name-object maps
     maPointNameMap.clear();
     maPointsPresNameMap.clear();
@@ -384,8 +432,11 @@ void DiagramData::build()
         output << "];" << std::endl;
 #endif
 
+        // Create/get shape. Re-create here, that may also set needed
+        // and available data from the Diagram ModelData at the Shape
+        Shape* pShape(getOrCreateAssociatedShape(point, true));
+
         // does currpoint have any text set?
-        Shape* pShape(getOrCreateAssociatedShape(point));
         if( nullptr != pShape && pShape->getTextBody() && 
!pShape->getTextBody()->isEmpty() )
         {
 #ifdef DEBUG_OOX_DIAGRAM
diff --git a/oox/source/drawingml/diagram/datamodel.hxx 
b/oox/source/drawingml/diagram/datamodel.hxx
index 8e4417652a57..292b31c6dabd 100644
--- a/oox/source/drawingml/diagram/datamodel.hxx
+++ b/oox/source/drawingml/diagram/datamodel.hxx
@@ -146,6 +146,7 @@ class DiagramData
 {
 public:
     typedef std::map< OUString, ShapePtr > PointShapeMap;
+    typedef std::map< OUString, TextBodyPtr > PointTextMap;
     typedef std::map< OUString, dgm::Point* > PointNameMap;
     typedef std::map< OUString, std::vector<dgm::Point*> > PointsNameMap;
     typedef std::map< OUString, const dgm::Connection* > ConnectionNameMap;
@@ -163,7 +164,7 @@ public:
     virtual ~DiagramData() {}
 
     // creates temporary processing data from model data
-    void build();
+    void build(bool bClearOoxShapes);
 
     FillPropertiesPtr & getFillProperties()
         { return mpFillProperties; }
@@ -189,6 +190,10 @@ public:
 
     Shape* getOrCreateAssociatedShape(const dgm::Point& rPoint, bool 
bCreateOnDemand = false) const;
 
+    // get/set data between Diagram DataModel and oox::drawingml::Shape
+    void secureDataFromShapeToModelAfterDiagramImport();
+    void restoreDataFromModelToShapeAfterReCreation(const dgm::Point& rPoint, 
Shape& rNewShape) const;
+
 private:
     void getChildrenString(OUStringBuffer& rBuf, const dgm::Point* pPoint, 
sal_Int32 nLevel) const;
     void addConnection(sal_Int32 nType, const OUString& sSourceId, const 
OUString& sDestId);
@@ -198,9 +203,11 @@ private:
 
     // the model definition,
     // - FillStyle
-    // - logic connections/associations
+    // - Texts for oox::drawingml::Points/dgm::Points, associated by ModelId
+    // - logic connections/assoziations
     // - data point entries
     FillPropertiesPtr mpFillProperties;
+    PointTextMap      maPointTextMap;
     dgm::Connections  maConnections;
     dgm::Points       maPoints;
 
diff --git a/oox/source/drawingml/diagram/diagram.cxx 
b/oox/source/drawingml/diagram/diagram.cxx
index c27c60b529ec..a1300ee908c8 100644
--- a/oox/source/drawingml/diagram/diagram.cxx
+++ b/oox/source/drawingml/diagram/diagram.cxx
@@ -403,8 +403,14 @@ void loadDiagram( ShapePtr const & pShape,
         }
     }
 
+    // After Diagram import, parts of the Diagram ModelData is at the
+    // oox::drawingml::Shape. Since these objects are temporary helpers,
+    // secure that data at the Diagram ModelData by copying.
+    pData->secureDataFromShapeToModelAfterDiagramImport();
+
     // collect data, init maps
-    pData->build();
+    // for Diagram import, do - for now - NOT clear all oox::drawingml::Shape
+    pData->build(false);
 
     // diagram loaded. now lump together & attach to shape
     pDiagram->addTo(pShape);

Reply via email to