diff options
author | Armin Le Grand (Allotropia) <Armin.Le.Grand@me.com> | 2022-04-19 11:37:57 +0200 |
---|---|---|
committer | Armin Le Grand <Armin.Le.Grand@me.com> | 2022-04-20 09:32:52 +0200 |
commit | d9b3374b13108cf6b847f6eb92fb666194a68770 (patch) | |
tree | eba87516cdef9e68a15ef85fa834b1e89eec54ca | |
parent | f22f83fbac3a0a419c2e95d7b725525fd02649e6 (diff) |
Advanced Diagram support: Use better association Model<->XShape
To have a more direct and more reliable association between the
XShape/oox::Shape and the model data svx::diagram::Point I added
optional usage of the Model-UUID for that at the oox::Shape.
Also added a 'fake' UUID to work with the BackgroundShape's
attributes. Changed all preserve/rescue code to work based on that.
Also cleanups/comments and preparations of some flags in the
Diagram ModelData to steer behaviour on re-ceration.
Change-Id: Ie30effdff34dcdbbc79a766de09157b2a3bd97d3
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133168
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
-rw-r--r-- | include/oox/drawingml/shape.hxx | 6 | ||||
-rw-r--r-- | include/svx/diagram/datamodel.hxx | 46 | ||||
-rw-r--r-- | include/svx/svdogrp.hxx | 30 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/datamodel.cxx | 278 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/datamodel.hxx | 10 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/datamodelcontext.cxx | 2 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/diagram.cxx | 41 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/diagram.hxx | 4 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/diagramhelper.cxx | 17 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/diagramhelper.hxx | 2 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/layoutatomvisitors.cxx | 4 | ||||
-rw-r--r-- | oox/source/drawingml/shape.cxx | 3 | ||||
-rw-r--r-- | svx/source/diagram/datamodel.cxx | 179 | ||||
-rw-r--r-- | svx/source/svdraw/svdogrp.cxx | 8 |
14 files changed, 383 insertions, 247 deletions
diff --git a/include/oox/drawingml/shape.hxx b/include/oox/drawingml/shape.hxx index a16e65a71ef1..3d0ee6ebaec8 100644 --- a/include/oox/drawingml/shape.hxx +++ b/include/oox/drawingml/shape.hxx @@ -118,6 +118,9 @@ public: OUString& getServiceName(){ return msServiceName; } void setServiceName( const char* pServiceName ); + const OUString& getDiagramDataModelID() const { return msDiagramDataModelID; } + void setDiagramDataModelID( const OUString& rDiagramDataModelID ) { msDiagramDataModelID = rDiagramDataModelID; } + PropertyMap& getShapeProperties(){ return maShapeProperties; } LineProperties& getLineProperties() { return *mpLinePropertiesPtr; } @@ -408,6 +411,9 @@ private: // temporary space for DiagramHelper in preparation for collecting data // Note: I tried to use a unique_ptr here, but existing constructor func does not allow that IDiagramHelper* mpDiagramHelper; + + // association-ID to identify the Diagram ModelData + OUString msDiagramDataModelID; }; } diff --git a/include/svx/diagram/datamodel.hxx b/include/svx/diagram/datamodel.hxx index 686835ee378f..7a080f8703ee 100644 --- a/include/svx/diagram/datamodel.hxx +++ b/include/svx/diagram/datamodel.hxx @@ -28,7 +28,6 @@ #include <rtl/ustring.hxx> #include <rtl/ustrbuf.hxx> -#include <com/sun/star/uno/Sequence.hxx> #include <com/sun/star/xml/dom/XDocument.hpp> #include <com/sun/star/drawing/XShape.hpp> @@ -73,9 +72,7 @@ typedef std::vector< Connection > Connections; /** Text and properties for a point * For proof of concept to make TextData available in svx level this * is in a first run pretty simple, but may need to be extended accordingly - * up to similar data as in oox::drawingml::TextBody. Pls have a look at - * secureDataFromShapeToModelAfterDiagramImport() resp. - * restoreDataFromModelToShapeAfterReCreation() on it's usage/purpose + * up to similar data as in oox::drawingml::TextBody. */ struct SVXCORE_DLLPUBLIC TextBody { @@ -104,7 +101,13 @@ struct SVXCORE_DLLPUBLIC Point { Point(); + // The minimal text data from the imported Diagram + // in source format TextBodyPtr msTextBody; + + // The property sequence of pairs<OUString, css::uno::Any>, + // interpreted & assigned by the ::addShape(s) creators in the + // import filter that created a XShape associated/based on this entry PointStylePtr msPointStylePtr; OUString msCnxId; @@ -147,9 +150,6 @@ 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; @@ -183,6 +183,10 @@ public: // creates temporary processing data from model data virtual void buildDiagramDataModel(bool bClearOoxShapes); + // dump to readable format + virtual void dump() const = 0; + + // read accesses Connections& getConnections() { return maConnections; } Points& getPoints() { return maPoints; } StringMap& getPresOfNameMap() { return maPresOfNameMap; } @@ -190,18 +194,21 @@ public: PointsNameMap& getPointsPresNameMap() { return maPointsPresNameMap; } ::std::vector<OUString>& getExtDrawings() { return maExtDrawings; } const Point* getRootPoint() const; - - virtual void dump() const = 0; - OUString getString() const; std::vector<std::pair<OUString, OUString>> getChildren(const OUString& rParentId) const; - OUString addNode(const OUString& rText); - bool removeNode(const OUString& rNodeId); const css::uno::Reference< css::xml::dom::XDocument >& getThemeDocument() const { return mxThemeDocument; } void setThemeDocument( const css::uno::Reference< css::xml::dom::XDocument >& xRef ) { mxThemeDocument = xRef; } + const OUString& getBackgroundShapeModelID() const { return msBackgroundShapeModelID; } + void setBackgroundShapeModelID( const OUString& rModelID ) { msBackgroundShapeModelID = rModelID; } + + // model modifiers + OUString addNode(const OUString& rText); + bool removeNode(const OUString& rNodeId); + protected: + // helpers void getChildrenString(OUStringBuffer& rBuf, const Point* pPoint, sal_Int32 nLevel) const; void addConnection(TypeConstant nType, const OUString& sSourceId, const OUString& sDestId); @@ -211,22 +218,31 @@ protected: // The model definition, the parts available in svx. // See evtl. parts in oox::drawingml::DiagramData that may need t obe accessed // - logic connections/associations + Connections maConnections; + // - data point entries + Points maPoints; + + // - style for the BackgroundShape (if used) + // this is the property sequence of pairs<OUString, css::uno::Any>, + // as interpreted & assigned by the ::addShape(s) creators in the + // import filter + PointStylePtr maBackgroundShapeStyle; + // - Theme definition as css::xml::dom::XDocument // Note: I decided to use dom::XDocument which is already in use, instead of a // temp file what is also possible (implemented that for POC) but would // need to be created in PresentationFragmentHandler::importSlide. If // this needs to be written to a File, please refer to // fileDocxExport::WriteTheme(), look for "OOXTheme" - Connections maConnections; - Points maPoints; css::uno::Reference< css::xml::dom::XDocument > mxThemeDocument; - // temporary processing data, deleted when using build() + // temporary processing data, partially deleted when using build() PointNameMap maPointNameMap; PointsNameMap maPointsPresNameMap; ConnectionNameMap maConnectionNameMap; StringMap maPresOfNameMap; + OUString msBackgroundShapeModelID; }; typedef std::shared_ptr< DiagramData > DiagramDataPtr; diff --git a/include/svx/svdogrp.hxx b/include/svx/svdogrp.hxx index 176892fdd8ac..b6fb1b74e4c2 100644 --- a/include/svx/svdogrp.hxx +++ b/include/svx/svdogrp.hxx @@ -32,6 +32,32 @@ class SdrObjGroup; // data and functionality class SVXCORE_DLLPUBLIC IDiagramHelper { +private: + // These values define behaviour to where take data from at re-creation time. + // Different definitions will have different consequences for re-creation + // of Diagram visualization (if needed/triggered). + // The style attributes per shape e.g. can be re-stored frm either an + // existing Theme, or the preserved key/value list of properties per XShape. + // With the current default settings the re-ceation uses the preserved + // key/value pairs, but re-creation from Theme may also be desirable. It + // is also good to preserve both data packages at initial import to allow + // alternatively one of these two methods for re-construction + + // If true, the oox::Theme data from ::DiagramData get/set/ThemeDocument() + // aka mxThemeDocument - if it exists - will be used to create the style + // attributes for the to-be-created XShapes (theoretically allows re-creation + // with other Theme) + bool mbUseDiagramThemeData; // false + + // If true, the UNO API form of attributes per Point as Key/value list + // that was secured after initial XShape creation is used to create the + // style attributes for the to-be-created XShapes + bool mbUseDiagramModelData; // true + + // If true and mxThemeDocument exists it will be re-imported to + // a newly created oox::drawingml::Theme object + bool mbForceThemePtrReceation; // false + protected: void anchorToSdrObjGroup(SdrObjGroup& rTarget); @@ -54,6 +80,10 @@ public: // add/remove new top-level node to data model, returns its id virtual OUString addNode(const OUString& rText) = 0; virtual bool removeNode(const OUString& rNodeId) = 0; + + bool UseDiagramThemeData() const { return mbUseDiagramThemeData; } + bool UseDiagramModelData() const { return mbUseDiagramModelData; } + bool ForceThemePtrReceation() const { return mbForceThemePtrReceation; }; }; // SdrObjGroup diff --git a/oox/source/drawingml/diagram/datamodel.cxx b/oox/source/drawingml/diagram/datamodel.cxx index f0a3cef66903..bbe23041cf28 100644 --- a/oox/source/drawingml/diagram/datamodel.cxx +++ b/oox/source/drawingml/diagram/datamodel.cxx @@ -26,6 +26,10 @@ #include <drawingml/textparagraph.hxx> #include <drawingml/textrun.hxx> #include <oox/drawingml/shape.hxx> +#include <com/sun/star/beans/XPropertyState.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <editeng/unoprnms.hxx> #include <unordered_set> @@ -60,7 +64,7 @@ void DiagramData::restoreDataFromModelToShapeAfterReCreation(const svx::diagram: // available data from the Diagram ModelData to it as preparation // This is e.g. the Text, but may get more (styles?) - if(rPoint.msTextBody && !rPoint.msTextBody->msText.isEmpty()) + if(!rPoint.msTextBody->msText.isEmpty()) { TextBodyPtr aNewTextBody(std::make_shared<TextBody>()); rNewShape.setTextBody(aNewTextBody); @@ -82,8 +86,199 @@ void DiagramData::restoreDataFromModelToShapeAfterReCreation(const svx::diagram: } } -void DiagramData::secureDataFromShapeToModelAfterDiagramImport() +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 DiagramData::secureStyleDataFromShapeToModel(::oox::drawingml::Shape& rShape) +{ + const std::vector< ShapePtr >& rChildren(rShape.getChildren()); + + if(!rChildren.empty()) + { + // group shape + for (auto& child : rChildren) + { + secureStyleDataFromShapeToModel(*child); + } + + // if group shape we are done. Do not secure properties for group shapes + return; + } + + // we need a XShape + const css::uno::Reference< css::drawing::XShape > &rXShape(rShape.getXShape()); + if(!rXShape) + return; + + // we need a ModelID for association + if(rShape.getDiagramDataModelID().isEmpty()) + return; + + // define target to save to + svx::diagram::PointStyle* pTarget(nullptr); + const bool bIsBackgroundShape(rShape.getDiagramDataModelID() == msBackgroundShapeModelID); + + if(bIsBackgroundShape) + { + // if BackgroundShape, create properties & set as target + if(!maBackgroundShapeStyle) + maBackgroundShapeStyle = std::make_shared< svx::diagram::PointStyle >(); + pTarget = maBackgroundShapeStyle.get(); + } + else + { + // if Shape, seek association + for (auto & point : maPoints) + { + if(point.msModelId == rShape.getDiagramDataModelID()) + { + // found - create properties & set as target + pTarget = point.msPointStylePtr.get(); + + // we are done, there is no 2nd shape with the same ModelID by definition + break; + } + } + } + + // no target -> nothing to do + if(nullptr == pTarget) + 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; + + // 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(!bIsBackgroundShape + && xServiceInfo->supportsService("com.sun.star.drawing.TextProperties")) + { + addProperty(UNO_NAME_CHAR_COLOR, xInfo, pTarget->maProperties, xPropSet); + addProperty(UNO_NAME_CHAR_HEIGHT, xInfo, pTarget->maProperties, xPropSet); + addProperty(UNO_NAME_CHAR_SHADOWED, xInfo, pTarget->maProperties, xPropSet); + addProperty(UNO_NAME_CHAR_WEIGHT, xInfo, pTarget->maProperties, 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, pTarget->maProperties, xPropSet); + + switch(eFillStyle) + { + case css::drawing::FillStyle_SOLID: + { + addProperty(UNO_NAME_FILLCOLOR, xInfo, pTarget->maProperties, 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(!bIsBackgroundShape + && 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, pTarget->maProperties, xPropSet); + addProperty(UNO_NAME_LINECOLOR, xInfo, pTarget->maProperties, xPropSet); + addProperty(UNO_NAME_LINEWIDTH, xInfo, pTarget->maProperties, xPropSet); + + switch(eLineStyle) + { + case css::drawing::LineStyle_SOLID: + break; + default: + case css::drawing::LineStyle_NONE: + case css::drawing::LineStyle_DASH: + break; + } + } + } +} + +void DiagramData::secureDataFromShapeToModelAfterDiagramImport(::oox::drawingml::Shape& rRootShape) +{ + const std::vector< ShapePtr >& rChildren(rRootShape.getChildren()); + + for (auto& child : rChildren) + { + secureStyleDataFromShapeToModel(*child); + } + // 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. @@ -97,7 +292,6 @@ void DiagramData::secureDataFromShapeToModelAfterDiagramImport() { if(pShapeCandidate->getTextBody() && !pShapeCandidate->getTextBody()->isEmpty()) { - point.msTextBody = std::make_shared<svx::diagram::TextBody>(); point.msTextBody->msText = pShapeCandidate->getTextBody()->toString(); const uno::Sequence< beans::PropertyValue > aTextProps( @@ -129,9 +323,85 @@ void DiagramData::secureDataFromShapeToModelAfterDiagramImport() } } +void DiagramData::restoreStyleDataFromShapeToModel(::oox::drawingml::Shape& rShape) +{ + const std::vector< ShapePtr >& rChildren(rShape.getChildren()); + + if(!rChildren.empty()) + { + // group shape + for (auto& child : rChildren) + { + restoreStyleDataFromShapeToModel(*child); + } + + // if group shape we are done. Do not restore properties for group shapes + return; + } + + // we need a XShape + const css::uno::Reference< css::drawing::XShape > &rXShape(rShape.getXShape()); + if(!rXShape) + return; + + // we need a ModelID for association + if(rShape.getDiagramDataModelID().isEmpty()) + return; + + // define source to save to + svx::diagram::PointStyle* pSource(nullptr); + + if(rShape.getDiagramDataModelID() == msBackgroundShapeModelID) + { + // if BackgroundShape, set BackgroundShapeStyle as source + if(maBackgroundShapeStyle) + pSource = maBackgroundShapeStyle.get(); + } + else + { + // if Shape, seek association + for (auto & point : maPoints) + { + if(point.msModelId == rShape.getDiagramDataModelID()) + { + // found - create properties & set as source + pSource = point.msPointStylePtr.get(); + + // we are done, there is no 2nd shape with the same ModelID by definition + break; + } + } + } + + // no source -> nothing to do + if(nullptr == pSource) + return; + + // get target ProperySet of new XShape + css::uno::Reference<css::beans::XPropertySet> xPropSet(rXShape, css::uno::UNO_QUERY); + if(!xPropSet) + return; + + // apply properties + for (auto const& prop : pSource->maProperties) + { + xPropSet->setPropertyValue(prop.first, prop.second); + } +} + +void DiagramData::restoreDataFromShapeToModelAfterDiagramImport(::oox::drawingml::Shape& rRootShape) +{ + const std::vector< ShapePtr >& rChildren(rRootShape.getChildren()); + + for (auto& child : rChildren) + { + restoreStyleDataFromShapeToModel(*child); + } +} + DiagramData::DiagramData() : svx::diagram::DiagramData() -, mpBackgroundFillProperties( std::make_shared<FillProperties>() ) +, mpBackgroundShapeFillProperties( std::make_shared<FillProperties>() ) { } diff --git a/oox/source/drawingml/diagram/datamodel.hxx b/oox/source/drawingml/diagram/datamodel.hxx index f7402cb0681e..21137f6e05d2 100644 --- a/oox/source/drawingml/diagram/datamodel.hxx +++ b/oox/source/drawingml/diagram/datamodel.hxx @@ -44,21 +44,25 @@ public: // creates temporary processing data from model data virtual void buildDiagramDataModel(bool bClearOoxShapes); - FillPropertiesPtr& getBackgroundFillProperties() { return mpBackgroundFillProperties; } + FillPropertiesPtr& getBackgroundShapeFillProperties() { return mpBackgroundShapeFillProperties; } virtual void dump() const; Shape* getOrCreateAssociatedShape(const svx::diagram::Point& rPoint, bool bCreateOnDemand = false) const; // get/set data between Diagram DataModel and oox::drawingml::Shape - void secureDataFromShapeToModelAfterDiagramImport(); + void secureDataFromShapeToModelAfterDiagramImport(::oox::drawingml::Shape& rRootShape); + void restoreDataFromShapeToModelAfterDiagramImport(::oox::drawingml::Shape& rRootShape); static void restoreDataFromModelToShapeAfterReCreation(const svx::diagram::Point& rPoint, Shape& rNewShape); protected: + void secureStyleDataFromShapeToModel(::oox::drawingml::Shape& rShape); + void restoreStyleDataFromShapeToModel(::oox::drawingml::Shape& rShape); + // The model definition, the parts *only* available in oox. Also look for already // defined ModelData in svx::diagram::DiagramData // - FillStyle for Diagram Background (empty constructed, may stay empty) - FillPropertiesPtr mpBackgroundFillProperties; + FillPropertiesPtr mpBackgroundShapeFillProperties; // temporary processing data, deleted when using build(). Association // map between oox::drawingml::Shape and svx::diagram::Point ModelData diff --git a/oox/source/drawingml/diagram/datamodelcontext.cxx b/oox/source/drawingml/diagram/datamodelcontext.cxx index 97484c992ad3..4f0e3f047233 100644 --- a/oox/source/drawingml/diagram/datamodelcontext.cxx +++ b/oox/source/drawingml/diagram/datamodelcontext.cxx @@ -317,7 +317,7 @@ public: case A_TOKEN( solidFill ): // EG_FillProperties return FillPropertiesContext::createFillContext( - *this, aElementToken, rAttribs, *mpDataModel->getBackgroundFillProperties() ); + *this, aElementToken, rAttribs, *mpDataModel->getBackgroundShapeFillProperties() ); case A_TOKEN( effectDag ): case A_TOKEN( effectLst ): // TODO diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx index 56b9b791e022..2ccc67805945 100644 --- a/oox/source/drawingml/diagram/diagram.cxx +++ b/oox/source/drawingml/diagram/diagram.cxx @@ -35,6 +35,7 @@ #include <basegfx/matrix/b2dhommatrix.hxx> #include <svx/svdpage.hxx> #include <oox/ppt/pptimport.hxx> +#include <comphelper/xmltools.hxx> #include "diagramlayoutatoms.hxx" #include "layoutatomvisitors.hxx" @@ -103,39 +104,6 @@ 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 ) { @@ -165,8 +133,13 @@ void Diagram::addTo( const ShapePtr & pParentShape ) pBackground->setSubType(XML_rect); pBackground->getCustomShapeProperties()->setShapePresetType(XML_rect); pBackground->setSize(pParentShape->getSize()); - pBackground->getFillProperties() = *mpData->getBackgroundFillProperties(); + pBackground->getFillProperties() = *mpData->getBackgroundShapeFillProperties(); pBackground->setLocked(true); + + // create and set ModelID for BackgroundShape to allow later association + getData()->setBackgroundShapeModelID(OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8)); + pBackground->setDiagramDataModelID(getData()->getBackgroundShapeModelID()); + auto& aChildren = pParentShape->getChildren(); aChildren.insert(aChildren.begin(), pBackground); } diff --git a/oox/source/drawingml/diagram/diagram.hxx b/oox/source/drawingml/diagram/diagram.hxx index 43516d4a270d..f58c762f6a1a 100644 --- a/oox/source/drawingml/diagram/diagram.hxx +++ b/oox/source/drawingml/diagram/diagram.hxx @@ -79,10 +79,6 @@ 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 6dc991149b01..2ee9e64f2535 100644 --- a/oox/source/drawingml/diagram/diagramhelper.cxx +++ b/oox/source/drawingml/diagram/diagramhelper.cxx @@ -103,8 +103,7 @@ void AdvancedDiagramHelper::reLayout(SdrObjGroup& rTarget) // set oox::Theme at Filter. All LineStyle/FillStyle/Colors/Attributes // will be taken from there - static bool bUseDiagramThemeData(false); - if(bUseDiagramThemeData) + if(UseDiagramThemeData()) xFilter->setCurrentTheme(getOrCreateThemePtr(xFilter)); css::uno::Reference< css::lang::XComponent > aComponentModel( rUnoModel, uno::UNO_QUERY ); @@ -132,9 +131,8 @@ void AdvancedDiagramHelper::reLayout(SdrObjGroup& rTarget) mpDiagramPtr->syncDiagramFontHeights(); // re-apply secured data from ModelData - static bool bUseDiagramModelData(true); - if(bUseDiagramModelData) - mpDiagramPtr->getLayout()->restoreDataFromModelToXShapeAfterDiagramReCreate(); + if(UseDiagramModelData()) + mpDiagramPtr->getData()->restoreDataFromShapeToModelAfterDiagramImport(*pShapePtr); // Re-apply remembered geometry rTarget.TRSetBaseGeometry(aTransformation, aPolyPolygon); @@ -200,7 +198,7 @@ bool AdvancedDiagramHelper::removeNode(const OUString& rNodeId) return bRetval; } -void AdvancedDiagramHelper::doAnchor(SdrObjGroup& rTarget) +void AdvancedDiagramHelper::doAnchor(SdrObjGroup& rTarget, ::oox::drawingml::Shape& rRootShape) { if(!mpDiagramPtr) { @@ -212,8 +210,7 @@ void AdvancedDiagramHelper::doAnchor(SdrObjGroup& rTarget) // 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(); + mpDiagramPtr->getData()->secureDataFromShapeToModelAfterDiagramImport(rRootShape); anchorToSdrObjGroup(rTarget); } @@ -221,11 +218,9 @@ void AdvancedDiagramHelper::doAnchor(SdrObjGroup& rTarget) std::shared_ptr< ::oox::drawingml::Theme > AdvancedDiagramHelper::getOrCreateThemePtr( rtl::Reference< oox::shape::ShapeFilterBase >& rxFilter) const { - static bool bForceThemePtrReceation(false); - // (Re-)Use already existing Theme if existing/imported if possible. // If not, re-import Theme if data is available and thus possible - if(hasDiagramData() && (bForceThemePtrReceation || !mpThemePtr)) + if(hasDiagramData() && (ForceThemePtrReceation() || !mpThemePtr)) { // get the originally imported dom::XDocument const uno::Reference< css::xml::dom::XDocument >& xThemeDocument(mpDiagramPtr->getData()->getThemeDocument()); diff --git a/oox/source/drawingml/diagram/diagramhelper.hxx b/oox/source/drawingml/diagram/diagramhelper.hxx index d8fd46ce57a1..cede1aeeccf9 100644 --- a/oox/source/drawingml/diagram/diagramhelper.hxx +++ b/oox/source/drawingml/diagram/diagramhelper.hxx @@ -73,7 +73,7 @@ public: virtual OUString addNode(const OUString& rText) override; virtual bool removeNode(const OUString& rNodeId) override; - void doAnchor(SdrObjGroup& rTarget); + 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/oox/source/drawingml/diagram/layoutatomvisitors.cxx b/oox/source/drawingml/diagram/layoutatomvisitors.cxx index 927c869a9c38..45f85f808458 100644 --- a/oox/source/drawingml/diagram/layoutatomvisitors.cxx +++ b/oox/source/drawingml/diagram/layoutatomvisitors.cxx @@ -183,6 +183,10 @@ void ShapeTemplateVisitor::visit(ShapeAtom& rAtom) // Fill properties have to be changed as sometimes only the presentation node contains the blip // fill, unshare those. mpShape->cloneFillProperties(); + + // add/set ModelID from currrent node to allow later association + if (mpCurrentNode) + mpShape->setDiagramDataModelID(mpCurrentNode->msModelId); } void ShapeLayoutingVisitor::visit(ConstraintAtom& rAtom) diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx index 12eb72d40542..64ff93fc9bec 100644 --- a/oox/source/drawingml/shape.cxx +++ b/oox/source/drawingml/shape.cxx @@ -193,6 +193,7 @@ Shape::Shape( const ShapePtr& pSourceShape ) , mfAspectRatio(pSourceShape->mfAspectRatio) , mbUseBgFill(pSourceShape->mbUseBgFill) , mpDiagramHelper( nullptr ) +, msDiagramDataModelID(pSourceShape->msDiagramDataModelID) {} Shape::~Shape() @@ -225,7 +226,7 @@ void Shape::propagateDiagramHelper() if(pAnchorObj) { - static_cast<AdvancedDiagramHelper*>(mpDiagramHelper)->doAnchor(*pAnchorObj); + static_cast<AdvancedDiagramHelper*>(mpDiagramHelper)->doAnchor(*pAnchorObj, *this); mpDiagramHelper = nullptr; } } diff --git a/svx/source/diagram/datamodel.cxx b/svx/source/diagram/datamodel.cxx index 44e9977326a0..fd562645eaa0 100644 --- a/svx/source/diagram/datamodel.cxx +++ b/svx/source/diagram/datamodel.cxx @@ -23,15 +23,6 @@ #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 { @@ -44,7 +35,9 @@ Connection::Connection() } Point::Point() -: mnXMLType(XML_none) +: msTextBody(std::make_shared< TextBody >()) +, msPointStylePtr(std::make_shared< PointStyle >()) +, mnXMLType(XML_none) , mnMaxChildren(-1) , mnPreferredChildren(-1) , mnDirection(XML_norm) @@ -72,163 +65,6 @@ 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() { } @@ -319,8 +155,7 @@ void DiagramData::getChildrenString( rBuf.append('\t'); rBuf.append('+'); rBuf.append(' '); - if(pPoint->msTextBody) - rBuf.append(pPoint->msTextBody->msText); + rBuf.append(pPoint->msTextBody->msText); rBuf.append('\n'); } @@ -353,7 +188,7 @@ std::vector<std::pair<OUString, OUString>> DiagramData::getChildren(const OUStri { aChildren[rCxn.mnSourceOrder] = std::make_pair( pChild->second->msModelId, - pChild->second->msTextBody ? pChild->second->msTextBody->msText : OUString()); + pChild->second->msTextBody->msText); } } @@ -381,7 +216,6 @@ OUString DiagramData::addNode(const OUString& rText) svx::diagram::Point aDataPoint; aDataPoint.mnXMLType = TypeConstant::XML_node; aDataPoint.msModelId = sNewNodeId; - aDataPoint.msTextBody = std::make_shared<TextBody>(); aDataPoint.msTextBody->msText = rText; OUString sDataSibling; @@ -482,6 +316,7 @@ void DiagramData::buildDiagramDataModel(bool /*bClearOoxShapes*/) maPointsPresNameMap.clear(); maConnectionNameMap.clear(); maPresOfNameMap.clear(); + msBackgroundShapeModelID.clear(); #ifdef DEBUG_OOX_DIAGRAM std::ofstream output("tree.dot"); @@ -522,7 +357,7 @@ void DiagramData::buildDiagramDataModel(bool /*bClearOoxShapes*/) #endif // does currpoint have any text set? - if(point.msTextBody && !point.msTextBody->msText.isEmpty()) + if(!point.msTextBody->msText.isEmpty()) { #ifdef DEBUG_OOX_DIAGRAM static sal_Int32 nCount=0; diff --git a/svx/source/svdraw/svdogrp.cxx b/svx/source/svdraw/svdogrp.cxx index 91e8174eea70..b1ad4b729e7e 100644 --- a/svx/source/svdraw/svdogrp.cxx +++ b/svx/source/svdraw/svdogrp.cxx @@ -34,7 +34,13 @@ #include <libxml/xmlwriter.h> #include <vcl/canvastools.hxx> -IDiagramHelper::IDiagramHelper() {} +IDiagramHelper::IDiagramHelper() +: mbUseDiagramThemeData(false) +, mbUseDiagramModelData(true) +, mbForceThemePtrReceation(false) +{ +} + IDiagramHelper::~IDiagramHelper() {} void IDiagramHelper::anchorToSdrObjGroup(SdrObjGroup& rTarget) |