include/svx/diagram/datamodel.hxx              |   18 ++
 oox/source/drawingml/diagram/datamodel.cxx     |   13 +
 oox/source/drawingml/diagram/diagram.cxx       |   39 ++++-
 oox/source/drawingml/diagram/diagram.hxx       |    4 
 oox/source/drawingml/diagram/diagramhelper.cxx |   49 +++++--
 svx/source/diagram/datamodel.cxx               |  171 ++++++++++++++++++++++++-
 6 files changed, 270 insertions(+), 24 deletions(-)

New commits:
commit edadfb564f1334887df473f9bc05dab6b1e7ef9d
Author:     Armin Le Grand (Allotropia) <armin.le.gr...@me.com>
AuthorDate: Wed Apr 13 17:17:35 2022 +0200
Commit:     Armin Le Grand <armin.le.gr...@me.com>
CommitDate: Thu Apr 14 11:02:19 2022 +0200

    Advanced Diagram support: Secure properties at Diagram ModelData
    
    Additionally to the Text/Attributes already saved/secured after
    Diagram import, secure more data that is part of the Diagram
    ModelData. This is about attributes (e.g. FillStyle/LineStyle,
    TextAttributes, ...) in UNO API formt that will be secured/
    attached to the Diagram ModelData in it's
    svx::diagram::Point structure.
    This is done for all those entries for which a XShape will/
    would be incarnated, thus associated to entries that will
    get a visualization, including the BackgroundObject.
    From that data, at re-creation time, the attributes can be
    re-applied to the re-created XShape(s), also after changes
    to the Diagram Model Data (e.g. Add/Remove).
    This is - besides the already added securing of the Style/
    Theme - a 2nd method for lossless re-creation. For the
    BackgroundObject - if it has FillStyles - it is even the
    only method to secure that data and thus necessary for that
    case. The selection of atributes that gets secured is minimal
    for now and may/need to be extended for existing cases
    accordingly.
    
    Change-Id: Ie9b72b9b9135113cf858d57fe6cd8622d736c4a4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132976
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <armin.le.gr...@me.com>

diff --git a/include/svx/diagram/datamodel.hxx 
b/include/svx/diagram/datamodel.hxx
index c42a3d26a115..686835ee378f 100644
--- a/include/svx/diagram/datamodel.hxx
+++ b/include/svx/diagram/datamodel.hxx
@@ -29,8 +29,8 @@
 #include <rtl/ustrbuf.hxx>
 
 #include <com/sun/star/uno/Sequence.hxx>
-#include <com/sun/star/beans/PropertyValue.hpp>
 #include <com/sun/star/xml/dom/XDocument.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
 
 namespace svx::diagram {
 
@@ -83,11 +83,21 @@ struct SVXCORE_DLLPUBLIC TextBody
     OUString msText;
 
     // attributes from TextBody::getTextProperties()
-    css::uno::Sequence< css::beans::PropertyValue > maTextProps;
+    std::vector< std::pair< OUString, css::uno::Any >> maTextProps;
 };
 
 typedef std::shared_ptr< TextBody > TextBodyPtr;
 
+/** Styles for a Point (FillStyle/LineStyle/...)
+ */
+struct SVXCORE_DLLPUBLIC PointStyle
+{
+    // attributes (LineStyle/FillStyle/...)
+    std::vector< std::pair< OUString, css::uno::Any >> maProperties;
+};
+
+typedef std::shared_ptr< PointStyle > PointStylePtr;
+
 /** A point
  */
 struct SVXCORE_DLLPUBLIC Point
@@ -95,6 +105,7 @@ struct SVXCORE_DLLPUBLIC Point
     Point();
 
     TextBodyPtr msTextBody;
+    PointStylePtr msPointStylePtr;
 
     OUString msCnxId;
     OUString msModelId;
@@ -136,6 +147,9 @@ struct SVXCORE_DLLPUBLIC Point
     bool          mbCustomVerticalFlip;
     bool          mbCustomText;
     bool          mbIsPlaceholder;
+
+    void securePropertiesFromXShape(const css::uno::Reference< 
css::drawing::XShape >& rXShape);
+    void restorePropertiesToXShape(const css::uno::Reference< 
css::drawing::XShape >& rXShape) const;
 };
 
 typedef std::vector< Point >        Points;
diff --git a/oox/source/drawingml/diagram/datamodel.cxx 
b/oox/source/drawingml/diagram/datamodel.cxx
index cc8924228e23..f0a3cef66903 100644
--- a/oox/source/drawingml/diagram/datamodel.cxx
+++ b/oox/source/drawingml/diagram/datamodel.cxx
@@ -68,15 +68,15 @@ void 
DiagramData::restoreDataFromModelToShapeAfterReCreation(const svx::diagram:
         pTextRun->getText() = rPoint.msTextBody->msText;
         aNewTextBody->addParagraph().addRun(pTextRun);
 
-        if(rPoint.msTextBody->maTextProps.hasElements())
+        if(!rPoint.msTextBody->maTextProps.empty())
         {
             oox::PropertyMap& 
rTargetMap(aNewTextBody->getTextProperties().maPropertyMap);
 
             for (auto const& prop : rPoint.msTextBody->maTextProps)
             {
-                sal_Int32 nPropId(oox::PropertyMap::getPropertyId(prop.Name));
+                const sal_Int32 
nPropId(oox::PropertyMap::getPropertyId(prop.first));
                 if(nPropId > 0)
-                    rTargetMap.setAnyProperty(nPropId, prop.Value);
+                    rTargetMap.setAnyProperty(nPropId, prop.second);
             }
         }
     }
@@ -99,7 +99,12 @@ void 
DiagramData::secureDataFromShapeToModelAfterDiagramImport()
             {
                 point.msTextBody = std::make_shared<svx::diagram::TextBody>();
                 point.msTextBody->msText = 
pShapeCandidate->getTextBody()->toString();
-                point.msTextBody->maTextProps = 
pShapeCandidate->getTextBody()->getTextProperties().maPropertyMap.makePropertyValueSequence();
+
+                const uno::Sequence< beans::PropertyValue > aTextProps(
+                    
pShapeCandidate->getTextBody()->getTextProperties().maPropertyMap.makePropertyValueSequence());
+
+                for (auto const& prop : aTextProps)
+                    
point.msTextBody->maTextProps.push_back(std::pair(prop.Name, prop.Value));
             }
 
             // At this place a mechanism to find missing data should be added:
diff --git a/oox/source/drawingml/diagram/diagram.cxx 
b/oox/source/drawingml/diagram/diagram.cxx
index 484e7af9fd13..56b9b791e022 100644
--- a/oox/source/drawingml/diagram/diagram.cxx
+++ b/oox/source/drawingml/diagram/diagram.cxx
@@ -103,6 +103,40 @@ static void removeUnneededGroupShapes(const ShapePtr& 
pShape)
     }
 }
 
+void DiagramLayout::secureDataFromXShapeToModelAfterDiagramImport()
+{
+    // maPresPointShapeMap types: < const svx::diagram::Point*, ShapePtr >
+    for (const auto& pEntry : maPresPointShapeMap)
+    {
+        if(nullptr != pEntry.first && pEntry.second)
+        {
+            const css::uno::Reference< css::drawing::XShape >& 
rXShape(pEntry.second->getXShape());
+
+            if(rXShape)
+            {
+                
const_cast<svx::diagram::Point*>(pEntry.first)->securePropertiesFromXShape(rXShape);
+            }
+        }
+    }
+}
+
+void DiagramLayout::restoreDataFromModelToXShapeAfterDiagramReCreate()
+{
+    // maPresPointShapeMap types: < const svx::diagram::Point*, ShapePtr >
+    for (const auto& pEntry : maPresPointShapeMap)
+    {
+        if(nullptr != pEntry.first && pEntry.second)
+        {
+            const css::uno::Reference< css::drawing::XShape >& 
rXShape(pEntry.second->getXShape());
+
+            if(rXShape)
+            {
+                pEntry.first->restorePropertiesToXShape(rXShape);
+            }
+        }
+    }
+}
+
 void Diagram::addTo( const ShapePtr & pParentShape )
 {
     if (pParentShape->getSize().Width == 0 || pParentShape->getSize().Height 
== 0)
@@ -403,11 +437,6 @@ 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
     // for Diagram import, do - for now - NOT clear all oox::drawingml::Shape
     pData->buildDiagramDataModel(false);
diff --git a/oox/source/drawingml/diagram/diagram.hxx 
b/oox/source/drawingml/diagram/diagram.hxx
index f58c762f6a1a..43516d4a270d 100644
--- a/oox/source/drawingml/diagram/diagram.hxx
+++ b/oox/source/drawingml/diagram/diagram.hxx
@@ -79,6 +79,10 @@ public:
     PresPointShapeMap & getPresPointShapeMap()
         { return maPresPointShapeMap; }
 
+    // get/set data between Diagram DataModel and oox::drawingml::Shape
+    void secureDataFromXShapeToModelAfterDiagramImport();
+    void restoreDataFromModelToXShapeAfterDiagramReCreate();
+
 private:
     Diagram& mrDgm;
     OUString msDefStyle;
diff --git a/oox/source/drawingml/diagram/diagramhelper.cxx 
b/oox/source/drawingml/diagram/diagramhelper.cxx
index cc6efd9ba50e..6dc991149b01 100644
--- a/oox/source/drawingml/diagram/diagramhelper.cxx
+++ b/oox/source/drawingml/diagram/diagramhelper.cxx
@@ -103,7 +103,9 @@ void AdvancedDiagramHelper::reLayout(SdrObjGroup& rTarget)
 
     // set oox::Theme at Filter. All LineStyle/FillStyle/Colors/Attributes
     // will be taken from there
-    xFilter->setCurrentTheme(getOrCreateThemePtr(xFilter));
+    static bool bUseDiagramThemeData(false);
+    if(bUseDiagramThemeData)
+        xFilter->setCurrentTheme(getOrCreateThemePtr(xFilter));
 
     css::uno::Reference< css::lang::XComponent > aComponentModel( rUnoModel, 
uno::UNO_QUERY );
     xFilter->setTargetDocument(aComponentModel);
@@ -126,11 +128,16 @@ void AdvancedDiagramHelper::reLayout(SdrObjGroup& rTarget)
             pShapePtr->getFillProperties());
     }
 
-    // Re-apply remembered geometry
-    rTarget.TRSetBaseGeometry(aTransformation, aPolyPolygon);
-
     // sync FontHeights
     mpDiagramPtr->syncDiagramFontHeights();
+
+    // re-apply secured data from ModelData
+    static bool bUseDiagramModelData(true);
+    if(bUseDiagramModelData)
+        
mpDiagramPtr->getLayout()->restoreDataFromModelToXShapeAfterDiagramReCreate();
+
+    // Re-apply remembered geometry
+    rTarget.TRSetBaseGeometry(aTransformation, aPolyPolygon);
 }
 
 OUString AdvancedDiagramHelper::getString() const
@@ -155,22 +162,42 @@ std::vector<std::pair<OUString, OUString>> 
AdvancedDiagramHelper::getChildren(co
 
 OUString AdvancedDiagramHelper::addNode(const OUString& rText)
 {
+    OUString aRetval;
+
     if(hasDiagramData())
     {
-        return mpDiagramPtr->getData()->addNode(rText);
+        aRetval = mpDiagramPtr->getData()->addNode(rText);
+
+        // reset temporary buffered ModelData association lists & rebuild them
+        // and the Diagram DataModel
+        mpDiagramPtr->getData()->buildDiagramDataModel(true);
+
+        // also reset temporary buffered layout data - that might
+        // still refer to changed oox::Shape data
+        mpDiagramPtr->getLayout()->getPresPointShapeMap().clear();
     }
 
-    return OUString();
+    return aRetval;
 }
 
 bool AdvancedDiagramHelper::removeNode(const OUString& rNodeId)
 {
+    bool bRetval(false);
+
     if(hasDiagramData())
     {
-        return mpDiagramPtr->getData()->removeNode(rNodeId);
+        bRetval = mpDiagramPtr->getData()->removeNode(rNodeId);
+
+        // reset temporary buffered ModelData association lists & rebuild them
+        // and the Diagram DataModel
+        mpDiagramPtr->getData()->buildDiagramDataModel(true);
+
+        // also reset temporary buffered layout data - that might
+        // still refer to changed oox::Shape data
+        mpDiagramPtr->getLayout()->getPresPointShapeMap().clear();
     }
 
-    return false;
+    return bRetval;
 }
 
 void AdvancedDiagramHelper::doAnchor(SdrObjGroup& rTarget)
@@ -182,6 +209,12 @@ void AdvancedDiagramHelper::doAnchor(SdrObjGroup& rTarget)
 
     mpDiagramPtr->syncDiagramFontHeights();
 
+    // 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.
+    mpDiagramPtr->getData()->secureDataFromShapeToModelAfterDiagramImport();
+    mpDiagramPtr->getLayout()->secureDataFromXShapeToModelAfterDiagramImport();
+
     anchorToSdrObjGroup(rTarget);
 }
 
diff --git a/svx/source/diagram/datamodel.cxx b/svx/source/diagram/datamodel.cxx
index a586f0556d31..44e9977326a0 100644
--- a/svx/source/diagram/datamodel.cxx
+++ b/svx/source/diagram/datamodel.cxx
@@ -23,6 +23,15 @@
 
 #include <svx/diagram/datamodel.hxx>
 #include <comphelper/xmltools.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/text/XText.hpp>
+
+#include <editeng/unoprnms.hxx>
 #include <sal/log.hxx>
 
 namespace svx::diagram {
@@ -63,6 +72,163 @@ Point::Point()
 {
 }
 
+static void addProperty(const OUString& rName,
+    const css::uno::Reference< css::beans::XPropertySetInfo >& xInfo,
+    std::vector< std::pair< OUString, css::uno::Any >>& rTarget,
+    const css::uno::Reference< css::beans::XPropertySet >& xPropSet )
+{
+    if(xInfo->hasPropertyByName(rName))
+            rTarget.push_back(std::pair(OUString(rName), 
xPropSet->getPropertyValue(rName)));
+}
+
+void Point::securePropertiesFromXShape(const css::uno::Reference< 
css::drawing::XShape >& rXShape)
+{
+    if(!rXShape)
+        return;
+
+#ifdef DBG_UTIL
+    // to easier decide which additional properties may/should be preserved,
+    // create a full list of set properties to browse/decide (in debugger)
+    const css::uno::Reference< css::beans::XPropertyState > 
xAllPropStates(rXShape, css::uno::UNO_QUERY);
+    const css::uno::Reference< css::beans::XPropertySet > xAllPropSet( 
rXShape, css::uno::UNO_QUERY );
+    const css::uno::Sequence< css::beans::Property > 
allSequence(xAllPropSet->getPropertySetInfo()->getProperties());
+    std::vector< std::pair< OUString, css::uno::Any >> allSetProps;
+    for (auto& rProp : allSequence)
+    {
+        try
+        {
+            if (xAllPropStates->getPropertyState(rProp.Name) == 
css::beans::PropertyState::PropertyState_DIRECT_VALUE)
+            {
+                css::uno::Any 
aValue(xAllPropSet->getPropertyValue(rProp.Name));
+                if(aValue.hasValue())
+                    allSetProps.push_back(std::pair(rProp.Name, aValue));
+            }
+        }
+        catch (...)
+        {
+        }
+    }
+#endif
+
+    const css::uno::Reference< css::beans::XPropertySet > xPropSet( rXShape, 
css::uno::UNO_QUERY );
+    if(!xPropSet)
+        return;
+
+    const css::uno::Reference< css::lang::XServiceInfo > xServiceInfo( 
rXShape, css::uno::UNO_QUERY );
+    if(!xServiceInfo)
+        return;
+
+    const css::uno::Reference< css::beans::XPropertySetInfo > 
xInfo(xPropSet->getPropertySetInfo());
+    if (!xInfo.is())
+        return;
+
+    if(!msPointStylePtr)
+        msPointStylePtr = std::make_shared< svx::diagram::PointStyle >();
+
+    // shortcut to target
+    std::vector< std::pair< OUString, css::uno::Any >>& 
rTarget(msPointStylePtr->maProperties);
+
+    // Note: The Text may also be secured here, so it may also be possible to
+    // secure/store it at PointStyle instead of at TextBody, same maybe 
evaluated
+    // for the text attributes - where when securing here the attributes would 
be
+    // in our UNO API format already.
+    // if(xServiceInfo->supportsService("com.sun.star.drawing.Text"))
+    // {
+    //     css::uno::Reference< css::text::XText > xText(rXShape, 
css::uno::UNO_QUERY);
+    //     const OUString aText(xText->getString());
+    //
+    //     if(!aText.isEmpty())
+    //     {
+    //     }
+    // }
+
+    // Add all kinds of properties that are needed to re-create the XShape.
+    // For now this is a minimal example-selection, it will need to be extended
+    // over time for all kind of cases/properties
+
+    // text properties
+    if(xServiceInfo->supportsService("com.sun.star.drawing.TextProperties"))
+    {
+        addProperty(UNO_NAME_CHAR_COLOR, xInfo, rTarget, xPropSet);
+        addProperty(UNO_NAME_CHAR_HEIGHT, xInfo, rTarget, xPropSet);
+        addProperty(UNO_NAME_CHAR_SHADOWED, xInfo, rTarget, xPropSet);
+        addProperty(UNO_NAME_CHAR_WEIGHT, xInfo, rTarget, xPropSet);
+    }
+
+    // fill properties
+    if(xServiceInfo->supportsService("com.sun.star.drawing.FillProperties"))
+    {
+        css::drawing::FillStyle eFillStyle(css::drawing::FillStyle_NONE);
+        if (xInfo->hasPropertyByName(UNO_NAME_FILLSTYLE))
+            xPropSet->getPropertyValue(UNO_NAME_FILLSTYLE) >>= eFillStyle;
+
+        if(css::drawing::FillStyle_NONE != eFillStyle)
+        {
+            addProperty(UNO_NAME_FILLSTYLE, xInfo, rTarget, xPropSet);
+
+            switch(eFillStyle)
+            {
+                case css::drawing::FillStyle_SOLID:
+                {
+                    addProperty(UNO_NAME_FILLCOLOR, xInfo, rTarget, xPropSet);
+                    break;
+                }
+                default:
+                case css::drawing::FillStyle_NONE:
+                case css::drawing::FillStyle_GRADIENT:
+                case css::drawing::FillStyle_HATCH:
+                case css::drawing::FillStyle_BITMAP:
+                    break;
+            }
+        }
+    }
+
+    // line properties
+    if(xServiceInfo->supportsService("com.sun.star.drawing.LineProperties"))
+    {
+        css::drawing::LineStyle eLineStyle(css::drawing::LineStyle_NONE);
+        if (xInfo->hasPropertyByName(UNO_NAME_LINESTYLE))
+            xPropSet->getPropertyValue(UNO_NAME_LINESTYLE) >>= eLineStyle;
+
+        if(css::drawing::LineStyle_NONE != eLineStyle)
+        {
+            addProperty(UNO_NAME_LINESTYLE, xInfo, rTarget, xPropSet);
+            addProperty(UNO_NAME_LINECOLOR, xInfo, rTarget, xPropSet);
+            addProperty(UNO_NAME_LINEWIDTH, xInfo, rTarget, xPropSet);
+
+            switch(eLineStyle)
+            {
+                case css::drawing::LineStyle_SOLID:
+                    break;
+                default:
+                case css::drawing::LineStyle_NONE:
+                case css::drawing::LineStyle_DASH:
+                    break;
+            }
+        }
+    }
+}
+
+void Point::restorePropertiesToXShape(const css::uno::Reference< 
css::drawing::XShape >& rXShape) const
+{
+    if(!msPointStylePtr)
+        return;
+
+    if(!rXShape)
+        return;
+
+    css::uno::Reference<css::beans::XPropertySet> xPropSet(rXShape, 
css::uno::UNO_QUERY);
+    if(!xPropSet)
+        return;
+
+    std::vector< std::pair< OUString, css::uno::Any >>& 
rSource(msPointStylePtr->maProperties);
+
+    for (auto const& prop : rSource)
+    {
+        xPropSet->setPropertyValue(prop.first, prop.second);
+    }
+}
+
 DiagramData::DiagramData()
 {
 }
@@ -136,9 +302,6 @@ bool DiagramData::removeNode(const OUString& rNodeId)
                    maPoints.end());
 
     // TODO: fix source/dest order
-
-    buildDiagramDataModel(true);
-
     return true;
 }
 
@@ -254,8 +417,6 @@ OUString DiagramData::addNode(const OUString& rText)
     maPoints.push_back(aDataPoint);
     maPoints.push_back(aPresPoint);
 
-    buildDiagramDataModel(true);
-
     return sNewNodeId;
 }
 

Reply via email to