From 29855141a874fa2d0d36959af6ae765eb3a05408 Mon Sep 17 00:00:00 2001 From: Grzegorz Araminowicz Date: Tue, 17 Sep 2019 16:17:14 +0200 Subject: SmartArt: separate data model from diagram.cxx data model is having more and more code, so separate it from diagram.cxx as this file is getting too big Change-Id: I05193c518c47958d24739d97f7b6afbf821b5361 Reviewed-on: https://gerrit.libreoffice.org/79067 Tested-by: Jenkins Reviewed-by: Grzegorz Araminowicz --- oox/Library_oox.mk | 1 + oox/source/drawingml/diagram/datamodel.cxx | 417 +++++++++++++++++++++ oox/source/drawingml/diagram/datamodel.hxx | 207 ++++++++++ oox/source/drawingml/diagram/datamodelcontext.hxx | 4 +- oox/source/drawingml/diagram/diagram.cxx | 387 ------------------- oox/source/drawingml/diagram/diagram.hxx | 172 +-------- .../drawingml/diagram/diagramdefinitioncontext.cxx | 3 +- solenv/clang-format/blacklist | 2 + 8 files changed, 631 insertions(+), 562 deletions(-) create mode 100644 oox/source/drawingml/diagram/datamodel.cxx create mode 100644 oox/source/drawingml/diagram/datamodel.hxx diff --git a/oox/Library_oox.mk b/oox/Library_oox.mk index 7b5a26866f5d..dbc54f9ff4fb 100644 --- a/oox/Library_oox.mk +++ b/oox/Library_oox.mk @@ -139,6 +139,7 @@ $(eval $(call gb_Library_add_exception_objects,oox,\ oox/source/drawingml/customshapepresetdata \ oox/source/drawingml/customshapeproperties \ oox/source/drawingml/diagram/constraintlistcontext \ + oox/source/drawingml/diagram/datamodel \ oox/source/drawingml/diagram/datamodelcontext \ oox/source/drawingml/diagram/diagram \ oox/source/drawingml/diagram/diagramdefinitioncontext \ diff --git a/oox/source/drawingml/diagram/datamodel.cxx b/oox/source/drawingml/diagram/datamodel.cxx new file mode 100644 index 000000000000..1f1794b31854 --- /dev/null +++ b/oox/source/drawingml/diagram/datamodel.cxx @@ -0,0 +1,417 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "datamodel.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace ::com::sun::star; + +namespace oox { namespace drawingml { + +namespace dgm { + +void Connection::dump() const +{ + SAL_INFO( + "oox.drawingml", + "cnx modelId " << msModelId << ", srcId " << msSourceId << ", dstId " + << msDestId << ", parTransId " << msParTransId << ", presId " + << msPresId << ", sibTransId " << msSibTransId << ", srcOrd " + << mnSourceOrder << ", dstOrd " << mnDestOrder); +} + +void Point::dump() const +{ + SAL_INFO( + "oox.drawingml", + "pt text " << mpShape.get() << ", cnxId " << msCnxId << ", modelId " + << msModelId << ", type " << mnType); +} + +} // dgm namespace + +DiagramData::DiagramData() : + mpFillProperties( new FillProperties ) +{ +} + +const dgm::Point* DiagramData::getRootPoint() const +{ + for (const auto & aCurrPoint : maPoints) + if (aCurrPoint.mnType == XML_doc) + return &aCurrPoint; + + SAL_WARN("oox.drawingml", "No root point"); + return nullptr; +} + +void DiagramData::dump() const +{ + SAL_INFO("oox.drawingml", "Dgm: DiagramData # of cnx: " << maConnections.size() ); + for (const auto& rConnection : maConnections) + rConnection.dump(); + + SAL_INFO("oox.drawingml", "Dgm: DiagramData # of pt: " << maPoints.size() ); + for (const auto& rPoint : maPoints) + rPoint.dump(); +} + +void DiagramData::getChildrenString(OUStringBuffer& rBuf, const dgm::Point* pPoint, sal_Int32 nLevel) const +{ + if (!pPoint) + return; + + if (nLevel > 0) + { + for (sal_Int32 i = 0; i < nLevel-1; i++) + rBuf.append('\t'); + rBuf.append('+'); + rBuf.append(' '); + rBuf.append(pPoint->mpShape->getTextBody()->getParagraphs().front()->getRuns().front()->getText()); + rBuf.append('\n'); + } + + std::vector aChildren; + for (const auto& rCxn : maConnections) + if (rCxn.mnType == XML_parOf && rCxn.msSourceId == pPoint->msModelId) + { + if (rCxn.mnSourceOrder >= static_cast(aChildren.size())) + aChildren.resize(rCxn.mnSourceOrder + 1); + const auto pChild = maPointNameMap.find(rCxn.msDestId); + if (pChild != maPointNameMap.end()) + aChildren[rCxn.mnSourceOrder] = pChild->second; + } + + for (auto pChild : aChildren) + getChildrenString(rBuf, pChild, nLevel + 1); +} + +OUString DiagramData::getString() const +{ + OUStringBuffer aBuf; + const dgm::Point* pPoint = getRootPoint(); + getChildrenString(aBuf, pPoint, 0); + return aBuf.makeStringAndClear(); +} + +std::vector> DiagramData::getChildren(const OUString& rParentId) const +{ + const OUString sModelId = rParentId.isEmpty() ? getRootPoint()->msModelId : rParentId; + std::vector> aChildren; + for (const auto& rCxn : maConnections) + if (rCxn.mnType == XML_parOf && rCxn.msSourceId == sModelId) + { + if (rCxn.mnSourceOrder >= static_cast(aChildren.size())) + aChildren.resize(rCxn.mnSourceOrder + 1); + const auto pChild = maPointNameMap.find(rCxn.msDestId); + if (pChild != maPointNameMap.end()) + aChildren[rCxn.mnSourceOrder] = std::make_pair( + pChild->second->msModelId, + pChild->second->mpShape->getTextBody()->getParagraphs().front()->getRuns().front()->getText()); + } + return aChildren; +} + +void DiagramData::addConnection(sal_Int32 nType, const OUString& sSourceId, const OUString& sDestId) +{ + sal_Int32 nMaxOrd = -1; + for (const auto& aCxn : maConnections) + if (aCxn.mnType == nType && aCxn.msSourceId == sSourceId) + nMaxOrd = std::max(nMaxOrd, aCxn.mnSourceOrder); + + dgm::Connection& rCxn = maConnections.emplace_back(); + rCxn.mnType = nType; + rCxn.msSourceId = sSourceId; + rCxn.msDestId = sDestId; + rCxn.mnSourceOrder = nMaxOrd + 1; +} + +void DiagramData::addNode(const OUString& rText) +{ + const dgm::Point& rDataRoot = *getRootPoint(); + OUString sPresRoot; + for (const auto& aCxn : maConnections) + if (aCxn.mnType == XML_presOf && aCxn.msSourceId == rDataRoot.msModelId) + sPresRoot = aCxn.msDestId; + + if (sPresRoot.isEmpty()) + return; + + dgm::Point aDataPoint; + aDataPoint.mnType = XML_node; + aDataPoint.msModelId = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8); + aDataPoint.mpShape.reset(new Shape()); + aDataPoint.mpShape->setTextBody(std::make_shared()); + TextRunPtr pTextRun(new TextRun()); + pTextRun->getText() = rText; + aDataPoint.mpShape->getTextBody()->addParagraph().addRun(pTextRun); + + OUString sDataSibling; + for (const auto& aCxn : maConnections) + if (aCxn.mnType == XML_parOf && aCxn.msSourceId == rDataRoot.msModelId) + sDataSibling = aCxn.msDestId; + + OUString sPresSibling; + for (const auto& aCxn : maConnections) + if (aCxn.mnType == XML_presOf && aCxn.msSourceId == sDataSibling) + sPresSibling = aCxn.msDestId; + + dgm::Point aPresPoint; + aPresPoint.mnType = XML_pres; + aPresPoint.msModelId = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8); + aPresPoint.mpShape.reset(new Shape()); + aPresPoint.msPresentationAssociationId = aDataPoint.msModelId; + if (!sPresSibling.isEmpty()) + { + // no idea where to get these values from, so copy from previous sibling + const dgm::Point* pSiblingPoint = maPointNameMap[sPresSibling]; + aPresPoint.msPresentationLayoutName = pSiblingPoint->msPresentationLayoutName; + aPresPoint.msPresentationLayoutStyleLabel = pSiblingPoint->msPresentationLayoutStyleLabel; + aPresPoint.mnLayoutStyleIndex = pSiblingPoint->mnLayoutStyleIndex; + aPresPoint.mnLayoutStyleCount = pSiblingPoint->mnLayoutStyleCount; + } + + addConnection(XML_parOf, rDataRoot.msModelId, aDataPoint.msModelId); + addConnection(XML_presParOf, sPresRoot, aPresPoint.msModelId); + addConnection(XML_presOf, aDataPoint.msModelId, aPresPoint.msModelId); + + // adding at the end, so that references are not invalidated in between + maPoints.push_back(aDataPoint); + maPoints.push_back(aPresPoint); + + build(); +} + +#ifdef DEBUG_OOX_DIAGRAM +OString normalizeDotName( const OUString& rStr ) +{ + OUStringBuffer aBuf; + aBuf.append('N'); + + const sal_Int32 nLen(rStr.getLength()); + sal_Int32 nCurrIndex(0); + while( nCurrIndex < nLen ) + { + const sal_Int32 aChar=rStr.iterateCodePoints(&nCurrIndex); + if( aChar != '-' && aChar != '{' && aChar != '}' ) + aBuf.append((sal_Unicode)aChar); + } + + return OUStringToOString(aBuf.makeStringAndClear(), + RTL_TEXTENCODING_UTF8); +} +#endif + +static sal_Int32 calcDepth( const OUString& rNodeName, + const dgm::Connections& rCnx ) +{ + // find length of longest path in 'isChild' graph, ending with rNodeName + for (auto const& elem : rCnx) + { + if( !elem.msParTransId.isEmpty() && + !elem.msSibTransId.isEmpty() && + !elem.msSourceId.isEmpty() && + !elem.msDestId.isEmpty() && + elem.mnType == XML_parOf && + rNodeName == elem.msDestId ) + { + return calcDepth(elem.msSourceId, rCnx) + 1; + } + } + + return 0; +} + +void DiagramData::build() +{ + // build name-object maps + maPointNameMap.clear(); + maPointsPresNameMap.clear(); + maConnectionNameMap.clear(); + maPresOfNameMap.clear(); + +#ifdef DEBUG_OOX_DIAGRAM + std::ofstream output("tree.dot"); + + output << "digraph datatree {" << std::endl; +#endif + dgm::Points& rPoints = getPoints(); + for (auto & point : rPoints) + { +#ifdef DEBUG_OOX_DIAGRAM + output << "\t" + << normalizeDotName(point.msModelId).getStr() + << "["; + + if( !point.msPresentationLayoutName.isEmpty() ) + output << "label=\"" + << OUStringToOString( + point.msPresentationLayoutName, + RTL_TEXTENCODING_UTF8).getStr() << "\", "; + else + output << "label=\"" + << OUStringToOString( + point.msModelId, + RTL_TEXTENCODING_UTF8).getStr() << "\", "; + + switch( point.mnType ) + { + case XML_doc: output << "style=filled, color=red"; break; + case XML_asst: output << "style=filled, color=green"; break; + default: + case XML_node: output << "style=filled, color=blue"; break; + case XML_pres: output << "style=filled, color=yellow"; break; + case XML_parTrans: output << "color=grey"; break; + case XML_sibTrans: output << " "; break; + } + + output << "];" << std::endl; +#endif + + // does currpoint have any text set? + if( point.mpShape && + point.mpShape->getTextBody() && + !point.mpShape->getTextBody()->getParagraphs().empty() && + !point.mpShape->getTextBody()->getParagraphs().front()->getRuns().empty() ) + { +#ifdef DEBUG_OOX_DIAGRAM + static sal_Int32 nCount=0; + output << "\t" + << "textNode" << nCount + << " [" + << "label=\"" + << OUStringToOString( + point.mpShape->getTextBody()->getParagraphs().front()->getRuns().front()->getText(), + RTL_TEXTENCODING_UTF8).getStr() + << "\"" << "];" << std::endl; + output << "\t" + << normalizeDotName(point.msModelId).getStr() + << " -> " + << "textNode" << nCount++ + << ";" << std::endl; +#endif + } + + const bool bInserted1 = getPointNameMap().insert( + std::make_pair(point.msModelId,&point)).second; + + SAL_WARN_IF(!bInserted1, "oox.drawingml", "DiagramData::build(): non-unique point model id"); + + if( !point.msPresentationLayoutName.isEmpty() ) + { + DiagramData::PointsNameMap::value_type::second_type& rVec= + getPointsPresNameMap()[point.msPresentationLayoutName]; + rVec.push_back(&point); + } + } + + const dgm::Connections& rConnections = getConnections(); + for (auto const& connection : rConnections) + { +#ifdef DEBUG_OOX_DIAGRAM + if( !connection.msParTransId.isEmpty() || + !connection.msSibTransId.isEmpty() ) + { + if( !connection.msSourceId.isEmpty() || + !connection.msDestId.isEmpty() ) + { + output << "\t" + << normalizeDotName(connection.msSourceId).getStr() + << " -> " + << normalizeDotName(connection.msParTransId).getStr() + << " -> " + << normalizeDotName(connection.msSibTransId).getStr() + << " -> " + << normalizeDotName(connection.msDestId).getStr() + << " [style=dotted," + << ((connection.mnType == XML_presOf) ? " color=red, " : ((connection.mnType == XML_presParOf) ? " color=green, " : " ")) + << "label=\"" + << OUStringToOString(connection.msModelId, + RTL_TEXTENCODING_UTF8 ).getStr() + << "\"];" << std::endl; + } + else + { + output << "\t" + << normalizeDotName(connection.msParTransId).getStr() + << " -> " + << normalizeDotName(connection.msSibTransId).getStr() + << " [" + << ((connection.mnType == XML_presOf) ? " color=red, " : ((connection.mnType == XML_presParOf) ? " color=green, " : " ")) + << "label=\"" + << OUStringToOString(connection.msModelId, + RTL_TEXTENCODING_UTF8 ).getStr() + << "\"];" << std::endl; + } + } + else if( !connection.msSourceId.isEmpty() || + !connection.msDestId.isEmpty() ) + output << "\t" + << normalizeDotName(connection.msSourceId).getStr() + << " -> " + << normalizeDotName(connection.msDestId).getStr() + << " [label=\"" + << OUStringToOString(connection.msModelId, + RTL_TEXTENCODING_UTF8 ).getStr() + << ((connection.mnType == XML_presOf) ? "\", color=red]" : ((connection.mnType == XML_presParOf) ? "\", color=green]" : "\"]")) + << ";" << std::endl; +#endif + + const bool bInserted1 = getConnectionNameMap().insert( + std::make_pair(connection.msModelId,&connection)).second; + + SAL_WARN_IF(!bInserted1, "oox.drawingml", "DiagramData::build(): non-unique connection model id"); + + if( connection.mnType == XML_presOf ) + { + DiagramData::StringMap::value_type::second_type& rVec = getPresOfNameMap()[connection.msDestId]; + rVec[connection.mnDestOrder] = { connection.msSourceId, sal_Int32(0) }; + } + } + + // assign outline levels + DiagramData::StringMap& rStringMap = getPresOfNameMap(); + for (auto & elemPresOf : rStringMap) + { + for (auto & elem : elemPresOf.second) + { + const sal_Int32 nDepth = calcDepth(elem.second.msSourceId, getConnections()); + elem.second.mnDepth = nDepth != 0 ? nDepth : -1; + } + } +#ifdef DEBUG_OOX_DIAGRAM + output << "}" << std::endl; +#endif +} + +} } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/drawingml/diagram/datamodel.hxx b/oox/source/drawingml/diagram/datamodel.hxx new file mode 100644 index 000000000000..b4c7ce7f82f7 --- /dev/null +++ b/oox/source/drawingml/diagram/datamodel.hxx @@ -0,0 +1,207 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_OOX_SOURCE_DRAWINGML_DIAGRAM_DATAMODEL_HXX +#define INCLUDED_OOX_SOURCE_DRAWINGML_DIAGRAM_DATAMODEL_HXX + +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace oox { namespace drawingml { + +namespace dgm { + +/** A Connection + */ +struct Connection +{ + Connection() : + mnType( 0 ), + mnSourceOrder( 0 ), + mnDestOrder( 0 ) + {} + + void dump() const; + + sal_Int32 mnType; + OUString msModelId; + OUString msSourceId; + OUString msDestId; + OUString msParTransId; + OUString msPresId; + OUString msSibTransId; + sal_Int32 mnSourceOrder; + sal_Int32 mnDestOrder; + +}; + +typedef std::vector< Connection > Connections; + +/** A point + */ +struct Point +{ + Point() : + mnType(0), + mnMaxChildren(-1), + mnPreferredChildren(-1), + mnDirection(XML_norm), + mnResizeHandles(XML_rel), + mnCustomAngle(-1), + mnPercentageNeighbourWidth(-1), + mnPercentageNeighbourHeight(-1), + mnPercentageOwnWidth(-1), + mnPercentageOwnHeight(-1), + mnIncludeAngleScale(-1), + mnRadiusScale(-1), + mnWidthScale(-1), + mnHeightScale(-1), + mnWidthOverride(-1), + mnHeightOverride(-1), + mnLayoutStyleCount(-1), + mnLayoutStyleIndex(-1), + + mbOrgChartEnabled(false), + mbBulletEnabled(false), + mbCoherent3DOffset(false), + mbCustomHorizontalFlip(false), + mbCustomVerticalFlip(false), + mbCustomText(false), + mbIsPlaceholder(false) + {} + void dump() const; + + ShapePtr mpShape; + + OUString msCnxId; + OUString msModelId; + OUString msColorTransformCategoryId; + OUString msColorTransformTypeId; + OUString msLayoutCategoryId; + OUString msLayoutTypeId; + OUString msPlaceholderText; + OUString msPresentationAssociationId; + OUString msPresentationLayoutName; + OUString msPresentationLayoutStyleLabel; + OUString msQuickStyleCategoryId; + OUString msQuickStyleTypeId; + + sal_Int32 mnType; + sal_Int32 mnMaxChildren; + sal_Int32 mnPreferredChildren; + sal_Int32 mnDirection; + OptValue moHierarchyBranch; + sal_Int32 mnResizeHandles; + sal_Int32 mnCustomAngle; + sal_Int32 mnPercentageNeighbourWidth; + sal_Int32 mnPercentageNeighbourHeight; + sal_Int32 mnPercentageOwnWidth; + sal_Int32 mnPercentageOwnHeight; + sal_Int32 mnIncludeAngleScale; + sal_Int32 mnRadiusScale; + sal_Int32 mnWidthScale; + sal_Int32 mnHeightScale; + sal_Int32 mnWidthOverride; + sal_Int32 mnHeightOverride; + sal_Int32 mnLayoutStyleCount; + sal_Int32 mnLayoutStyleIndex; + + bool mbOrgChartEnabled; + bool mbBulletEnabled; + bool mbCoherent3DOffset; + bool mbCustomHorizontalFlip; + bool mbCustomVerticalFlip; + bool mbCustomText; + bool mbIsPlaceholder; +}; + +typedef std::vector< Point > Points; + +} + +class DiagramData : public DiagramDataInterface +{ +public: + typedef std::map< OUString, dgm::Point* > PointNameMap; + typedef std::map< OUString, + std::vector > PointsNameMap; + typedef std::map< OUString, const dgm::Connection* > ConnectionNameMap; + struct SourceIdAndDepth + { + OUString msSourceId; + sal_Int32 mnDepth = 0; + }; + /// Tracks connections: destination id -> {destination order, details} map. + typedef std::map< OUString, + std::map > StringMap; + + DiagramData(); + virtual ~DiagramData() {} + void build(); + FillPropertiesPtr & getFillProperties() + { return mpFillProperties; } + dgm::Connections & getConnections() + { return maConnections; } + dgm::Points & getPoints() + { return maPoints; } + ConnectionNameMap & getConnectionNameMap() + { return maConnectionNameMap; } + StringMap & getPresOfNameMap() + { return maPresOfNameMap; } + PointNameMap & getPointNameMap() + { return maPointNameMap; } + PointsNameMap & getPointsPresNameMap() + { return maPointsPresNameMap; } + ::std::vector &getExtDrawings() + { return maExtDrawings; } + const dgm::Point* getRootPoint() const; + void dump() const; + OUString getString() const override; + std::vector> getChildren(const OUString& rParentId) const override; + void addNode(const OUString& rText) override; + +private: + void getChildrenString(OUStringBuffer& rBuf, const dgm::Point* pPoint, sal_Int32 nLevel) const; + void addConnection(sal_Int32 nType, const OUString& sSourceId, const OUString& sDestId); + + ::std::vector maExtDrawings; + FillPropertiesPtr mpFillProperties; + dgm::Connections maConnections; + dgm::Points maPoints; + PointNameMap maPointNameMap; + PointsNameMap maPointsPresNameMap; + ConnectionNameMap maConnectionNameMap; + StringMap maPresOfNameMap; +}; + +typedef std::shared_ptr< DiagramData > DiagramDataPtr; + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/drawingml/diagram/datamodelcontext.hxx b/oox/source/drawingml/diagram/datamodelcontext.hxx index b41fe6c2dfd3..7228a8e6122d 100644 --- a/oox/source/drawingml/diagram/datamodelcontext.hxx +++ b/oox/source/drawingml/diagram/datamodelcontext.hxx @@ -20,10 +20,8 @@ #ifndef INCLUDED_OOX_SOURCE_DRAWINGML_DIAGRAM_DATAMODELCONTEXT_HXX #define INCLUDED_OOX_SOURCE_DRAWINGML_DIAGRAM_DATAMODELCONTEXT_HXX -#include - #include -#include "diagram.hxx" +#include "datamodel.hxx" namespace oox { namespace drawingml { diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx index af35c3fe2651..b2f3373ad113 100644 --- a/oox/source/drawingml/diagram/diagram.cxx +++ b/oox/source/drawingml/diagram/diagram.cxx @@ -26,247 +26,22 @@ #include #include #include -#include #include #include -#include -#include -#include #include #include -#include -#include #include #include #include -#include -#include #include "diagramlayoutatoms.hxx" #include "layoutatomvisitors.hxx" #include "diagramfragmenthandler.hxx" -#include -#include - using namespace ::com::sun::star; namespace oox { namespace drawingml { -namespace dgm { - -void Connection::dump() const -{ - SAL_INFO( - "oox.drawingml", - "cnx modelId " << msModelId << ", srcId " << msSourceId << ", dstId " - << msDestId << ", parTransId " << msParTransId << ", presId " - << msPresId << ", sibTransId " << msSibTransId << ", srcOrd " - << mnSourceOrder << ", dstOrd " << mnDestOrder); -} - -void Point::dump() const -{ - SAL_INFO( - "oox.drawingml", - "pt text " << mpShape.get() << ", cnxId " << msCnxId << ", modelId " - << msModelId << ", type " << mnType); -} - -} // dgm namespace - -DiagramData::DiagramData() : - mpFillProperties( new FillProperties ) -{ -} - -const dgm::Point* DiagramData::getRootPoint() const -{ - for (const auto & aCurrPoint : maPoints) - if (aCurrPoint.mnType == XML_doc) - return &aCurrPoint; - - SAL_WARN("oox.drawingml", "No root point"); - return nullptr; -} - -void DiagramData::dump() const -{ - SAL_INFO("oox.drawingml", "Dgm: DiagramData # of cnx: " << maConnections.size() ); - for (const auto& rConnection : maConnections) - rConnection.dump(); - - SAL_INFO("oox.drawingml", "Dgm: DiagramData # of pt: " << maPoints.size() ); - for (const auto& rPoint : maPoints) - rPoint.dump(); -} - -void DiagramData::getChildrenString(OUStringBuffer& rBuf, const dgm::Point* pPoint, sal_Int32 nLevel) const -{ - if (!pPoint) - return; - - if (nLevel > 0) - { - for (sal_Int32 i = 0; i < nLevel-1; i++) - rBuf.append('\t'); - rBuf.append('+'); - rBuf.append(' '); - rBuf.append(pPoint->mpShape->getTextBody()->getParagraphs().front()->getRuns().front()->getText()); - rBuf.append('\n'); - } - - std::vector aChildren; - for (const auto& rCxn : maConnections) - if (rCxn.mnType == XML_parOf && rCxn.msSourceId == pPoint->msModelId) - { - if (rCxn.mnSourceOrder >= static_cast(aChildren.size())) - aChildren.resize(rCxn.mnSourceOrder + 1); - const auto pChild = maPointNameMap.find(rCxn.msDestId); - if (pChild != maPointNameMap.end()) - aChildren[rCxn.mnSourceOrder] = pChild->second; - } - - for (auto pChild : aChildren) - getChildrenString(rBuf, pChild, nLevel + 1); -} - -OUString DiagramData::getString() const -{ - OUStringBuffer aBuf; - const dgm::Point* pPoint = getRootPoint(); - getChildrenString(aBuf, pPoint, 0); - return aBuf.makeStringAndClear(); -} - -std::vector> DiagramData::getChildren(const OUString& rParentId) const -{ - const OUString sModelId = rParentId.isEmpty() ? getRootPoint()->msModelId : rParentId; - std::vector> aChildren; - for (const auto& rCxn : maConnections) - if (rCxn.mnType == XML_parOf && rCxn.msSourceId == sModelId) - { - if (rCxn.mnSourceOrder >= static_cast(aChildren.size())) - aChildren.resize(rCxn.mnSourceOrder + 1); - const auto pChild = maPointNameMap.find(rCxn.msDestId); - if (pChild != maPointNameMap.end()) - aChildren[rCxn.mnSourceOrder] = std::make_pair( - pChild->second->msModelId, - pChild->second->mpShape->getTextBody()->getParagraphs().front()->getRuns().front()->getText()); - } - return aChildren; -} - -void DiagramData::addConnection(sal_Int32 nType, const OUString& sSourceId, const OUString& sDestId) -{ - sal_Int32 nMaxOrd = -1; - for (const auto& aCxn : maConnections) - if (aCxn.mnType == nType && aCxn.msSourceId == sSourceId) - nMaxOrd = std::max(nMaxOrd, aCxn.mnSourceOrder); - - dgm::Connection& rCxn = maConnections.emplace_back(); - rCxn.mnType = nType; - rCxn.msSourceId = sSourceId; - rCxn.msDestId = sDestId; - rCxn.mnSourceOrder = nMaxOrd + 1; -} - -void DiagramData::addNode(const OUString& rText) -{ - const dgm::Point& rDataRoot = *getRootPoint(); - OUString sPresRoot; - for (const auto& aCxn : maConnections) - if (aCxn.mnType == XML_presOf && aCxn.msSourceId == rDataRoot.msModelId) - sPresRoot = aCxn.msDestId; - - if (sPresRoot.isEmpty()) - return; - - dgm::Point aDataPoint; - aDataPoint.mnType = XML_node; - aDataPoint.msModelId = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8); - aDataPoint.mpShape.reset(new Shape()); - aDataPoint.mpShape->setTextBody(std::make_shared()); - TextRunPtr pTextRun(new TextRun()); - pTextRun->getText() = rText; - aDataPoint.mpShape->getTextBody()->addParagraph().addRun(pTextRun); - - OUString sDataSibling; - for (const auto& aCxn : maConnections) - if (aCxn.mnType == XML_parOf && aCxn.msSourceId == rDataRoot.msModelId) - sDataSibling = aCxn.msDestId; - - OUString sPresSibling; - for (const auto& aCxn : maConnections) - if (aCxn.mnType == XML_presOf && aCxn.msSourceId == sDataSibling) - sPresSibling = aCxn.msDestId; - - dgm::Point aPresPoint; - aPresPoint.mnType = XML_pres; - aPresPoint.msModelId = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8); - aPresPoint.mpShape.reset(new Shape()); - aPresPoint.msPresentationAssociationId = aDataPoint.msModelId; - if (!sPresSibling.isEmpty()) - { - // no idea where to get these values from, so copy from previous sibling - const dgm::Point* pSiblingPoint = maPointNameMap[sPresSibling]; - aPresPoint.msPresentationLayoutName = pSiblingPoint->msPresentationLayoutName; - aPresPoint.msPresentationLayoutStyleLabel = pSiblingPoint->msPresentationLayoutStyleLabel; - aPresPoint.mnLayoutStyleIndex = pSiblingPoint->mnLayoutStyleIndex; - aPresPoint.mnLayoutStyleCount = pSiblingPoint->mnLayoutStyleCount; - } - - addConnection(XML_parOf, rDataRoot.msModelId, aDataPoint.msModelId); - addConnection(XML_presParOf, sPresRoot, aPresPoint.msModelId); - addConnection(XML_presOf, aDataPoint.msModelId, aPresPoint.msModelId); - - // adding at the end, so that references are not invalidated in between - maPoints.push_back(aDataPoint); - maPoints.push_back(aPresPoint); - - build(); -} - -#ifdef DEBUG_OOX_DIAGRAM -OString normalizeDotName( const OUString& rStr ) -{ - OUStringBuffer aBuf; - aBuf.append('N'); - - const sal_Int32 nLen(rStr.getLength()); - sal_Int32 nCurrIndex(0); - while( nCurrIndex < nLen ) - { - const sal_Int32 aChar=rStr.iterateCodePoints(&nCurrIndex); - if( aChar != '-' && aChar != '{' && aChar != '}' ) - aBuf.append((sal_Unicode)aChar); - } - - return OUStringToOString(aBuf.makeStringAndClear(), - RTL_TEXTENCODING_UTF8); -} -#endif - -static sal_Int32 calcDepth( const OUString& rNodeName, - const dgm::Connections& rCnx ) -{ - // find length of longest path in 'isChild' graph, ending with rNodeName - for (auto const& elem : rCnx) - { - if( !elem.msParTransId.isEmpty() && - !elem.msSibTransId.isEmpty() && - !elem.msSourceId.isEmpty() && - !elem.msDestId.isEmpty() && - elem.mnType == XML_parOf && - rNodeName == elem.msDestId ) - { - return calcDepth(elem.msSourceId, rCnx) + 1; - } - } - - return 0; -} - static void sortChildrenByZOrder(const ShapePtr& pShape) { std::vector& rChildren = pShape->getChildren(); @@ -307,168 +82,6 @@ static void sortChildrenByZOrder(const ShapePtr& pShape) sortChildrenByZOrder(rChild); } -void DiagramData::build() -{ - // build name-object maps - maPointNameMap.clear(); - maPointsPresNameMap.clear(); - maConnectionNameMap.clear(); - maPresOfNameMap.clear(); - -#ifdef DEBUG_OOX_DIAGRAM - std::ofstream output("tree.dot"); - - output << "digraph datatree {" << std::endl; -#endif - dgm::Points& rPoints = getPoints(); - for (auto & point : rPoints) - { -#ifdef DEBUG_OOX_DIAGRAM - output << "\t" - << normalizeDotName(point.msModelId).getStr() - << "["; - - if( !point.msPresentationLayoutName.isEmpty() ) - output << "label=\"" - << OUStringToOString( - point.msPresentationLayoutName, - RTL_TEXTENCODING_UTF8).getStr() << "\", "; - else - output << "label=\"" - << OUStringToOString( - point.msModelId, - RTL_TEXTENCODING_UTF8).getStr() << "\", "; - - switch( point.mnType ) - { - case XML_doc: output << "style=filled, color=red"; break; - case XML_asst: output << "style=filled, color=green"; break; - default: - case XML_node: output << "style=filled, color=blue"; break; - case XML_pres: output << "style=filled, color=yellow"; break; - case XML_parTrans: output << "color=grey"; break; - case XML_sibTrans: output << " "; break; - } - - output << "];" << std::endl; -#endif - - // does currpoint have any text set? - if( point.mpShape && - point.mpShape->getTextBody() && - !point.mpShape->getTextBody()->getParagraphs().empty() && - !point.mpShape->getTextBody()->getParagraphs().front()->getRuns().empty() ) - { -#ifdef DEBUG_OOX_DIAGRAM - static sal_Int32 nCount=0; - output << "\t" - << "textNode" << nCount - << " [" - << "label=\"" - << OUStringToOString( - point.mpShape->getTextBody()->getParagraphs().front()->getRuns().front()->getText(), - RTL_TEXTENCODING_UTF8).getStr() - << "\"" << "];" << std::endl; - output << "\t" - << normalizeDotName(point.msModelId).getStr() - << " -> " - << "textNode" << nCount++ - << ";" << std::endl; -#endif - } - - const bool bInserted1 = getPointNameMap().insert( - std::make_pair(point.msModelId,&point)).second; - - SAL_WARN_IF(!bInserted1, "oox.drawingml", "DiagramData::build(): non-unique point model id"); - - if( !point.msPresentationLayoutName.isEmpty() ) - { - DiagramData::PointsNameMap::value_type::second_type& rVec= - getPointsPresNameMap()[point.msPresentationLayoutName]; - rVec.push_back(&point); - } - } - - const dgm::Connections& rConnections = getConnections(); - for (auto const& connection : rConnections) - { -#ifdef DEBUG_OOX_DIAGRAM - if( !connection.msParTransId.isEmpty() || - !connection.msSibTransId.isEmpty() ) - { - if( !connection.msSourceId.isEmpty() || - !connection.msDestId.isEmpty() ) - { - output << "\t" - << normalizeDotName(connection.msSourceId).getStr() - << " -> " - << normalizeDotName(connection.msParTransId).getStr() - << " -> " - << normalizeDotName(connection.msSibTransId).getStr() - << " -> " - << normalizeDotName(connection.msDestId).getStr() - << " [style=dotted," - << ((connection.mnType == XML_presOf) ? " color=red, " : ((connection.mnType == XML_presParOf) ? " color=green, " : " ")) - << "label=\"" - << OUStringToOString(connection.msModelId, - RTL_TEXTENCODING_UTF8 ).getStr() - << "\"];" << std::endl; - } - else - { - output << "\t" - << normalizeDotName(connection.msParTransId).getStr() - << " -> " - << normalizeDotName(connection.msSibTransId).getStr() - << " [" - << ((connection.mnType == XML_presOf) ? " color=red, " : ((connection.mnType == XML_presParOf) ? " color=green, " : " ")) - << "label=\"" - << OUStringToOString(connection.msModelId, - RTL_TEXTENCODING_UTF8 ).getStr() - << "\"];" << std::endl; - } - } - else if( !connection.msSourceId.isEmpty() || - !connection.msDestId.isEmpty() ) - output << "\t" - << normalizeDotName(connection.msSourceId).getStr() - << " -> " - << normalizeDotName(connection.msDestId).getStr() - << " [label=\"" - << OUStringToOString(connection.msModelId, - RTL_TEXTENCODING_UTF8 ).getStr() - << ((connection.mnType == XML_presOf) ? "\", color=red]" : ((connection.mnType == XML_presParOf) ? "\", color=green]" : "\"]")) - << ";" << std::endl; -#endif - - const bool bInserted1 = getConnectionNameMap().insert( - std::make_pair(connection.msModelId,&connection)).second; - - SAL_WARN_IF(!bInserted1, "oox.drawingml", "DiagramData::build(): non-unique connection model id"); - - if( connection.mnType == XML_presOf ) - { - DiagramData::StringMap::value_type::second_type& rVec = getPresOfNameMap()[connection.msDestId]; - rVec[connection.mnDestOrder] = { connection.msSourceId, sal_Int32(0) }; - } - } - - // assign outline levels - DiagramData::StringMap& rStringMap = getPresOfNameMap(); - for (auto & elemPresOf : rStringMap) - { - for (auto & elem : elemPresOf.second) - { - const sal_Int32 nDepth = calcDepth(elem.second.msSourceId, getConnections()); - elem.second.mnDepth = nDepth != 0 ? nDepth : -1; - } - } -#ifdef DEBUG_OOX_DIAGRAM - output << "}" << std::endl; -#endif -} - void Diagram::addTo( const ShapePtr & pParentShape ) { if (pParentShape->getSize().Width == 0 || pParentShape->getSize().Height == 0) diff --git a/oox/source/drawingml/diagram/diagram.hxx b/oox/source/drawingml/diagram/diagram.hxx index 84526a55425c..576c4007e29f 100644 --- a/oox/source/drawingml/diagram/diagram.hxx +++ b/oox/source/drawingml/diagram/diagram.hxx @@ -22,14 +22,11 @@ #include #include -#include #include +#include "datamodel.hxx" #include -#include -#include -#include namespace com { namespace sun { namespace star { namespace xml { namespace dom { class XDocument; } } @@ -37,116 +34,6 @@ namespace com { namespace sun { namespace star { namespace oox { namespace drawingml { -namespace dgm { - -/** A Connection - */ -struct Connection -{ - Connection() : - mnType( 0 ), - mnSourceOrder( 0 ), - mnDestOrder( 0 ) - {} - - void dump() const; - - sal_Int32 mnType; - OUString msModelId; - OUString msSourceId; - OUString msDestId; - OUString msParTransId; - OUString msPresId; - OUString msSibTransId; - sal_Int32 mnSourceOrder; - sal_Int32 mnDestOrder; - -}; - -typedef std::vector< Connection > Connections; - -/** A point - */ -struct Point -{ - Point() : - mnType(0), - mnMaxChildren(-1), - mnPreferredChildren(-1), - mnDirection(XML_norm), - mnResizeHandles(XML_rel), - mnCustomAngle(-1), - mnPercentageNeighbourWidth(-1), - mnPercentageNeighbourHeight(-1), - mnPercentageOwnWidth(-1), - mnPercentageOwnHeight(-1), - mnIncludeAngleScale(-1), - mnRadiusScale(-1), - mnWidthScale(-1), - mnHeightScale(-1), - mnWidthOverride(-1), - mnHeightOverride(-1), - mnLayoutStyleCount(-1), - mnLayoutStyleIndex(-1), - - mbOrgChartEnabled(false), - mbBulletEnabled(false), - mbCoherent3DOffset(false), - mbCustomHorizontalFlip(false), - mbCustomVerticalFlip(false), - mbCustomText(false), - mbIsPlaceholder(false) - {} - void dump() const; - - ShapePtr mpShape; - - OUString msCnxId; - OUString msModelId; - OUString msColorTransformCategoryId; - OUString msColorTransformTypeId; - OUString msLayoutCategoryId; - OUString msLayoutTypeId; - OUString msPlaceholderText; - OUString msPresentationAssociationId; - OUString msPresentationLayoutName; - OUString msPresentationLayoutStyleLabel; - OUString msQuickStyleCategoryId; - OUString msQuickStyleTypeId; - - sal_Int32 mnType; - sal_Int32 mnMaxChildren; - sal_Int32 mnPreferredChildren; - sal_Int32 mnDirection; - OptValue moHierarchyBranch; - sal_Int32 mnResizeHandles; - sal_Int32 mnCustomAngle; - sal_Int32 mnPercentageNeighbourWidth; - sal_Int32 mnPercentageNeighbourHeight; - sal_Int32 mnPercentageOwnWidth; - sal_Int32 mnPercentageOwnHeight; - sal_Int32 mnIncludeAngleScale; - sal_Int32 mnRadiusScale; - sal_Int32 mnWidthScale; - sal_Int32 mnHeightScale; - sal_Int32 mnWidthOverride; - sal_Int32 mnHeightOverride; - sal_Int32 mnLayoutStyleCount; - sal_Int32 mnLayoutStyleIndex; - - bool mbOrgChartEnabled; - bool mbBulletEnabled; - bool mbCoherent3DOffset; - bool mbCustomHorizontalFlip; - bool mbCustomVerticalFlip; - bool mbCustomText; - bool mbIsPlaceholder; -}; - -typedef std::vector< Point > Points; - -} - class Diagram; class LayoutNode; typedef std::shared_ptr< LayoutNode > LayoutNodePtr; @@ -155,63 +42,6 @@ typedef std::shared_ptr LayoutAtomPtr; typedef std::map< OUString, css::uno::Reference > DiagramDomMap; -class DiagramData : public DiagramDataInterface -{ -public: - typedef std::map< OUString, dgm::Point* > PointNameMap; - typedef std::map< OUString, - std::vector > PointsNameMap; - typedef std::map< OUString, const dgm::Connection* > ConnectionNameMap; - struct SourceIdAndDepth - { - OUString msSourceId; - sal_Int32 mnDepth = 0; - }; - /// Tracks connections: destination id -> {destination order, details} map. - typedef std::map< OUString, - std::map > StringMap; - - DiagramData(); - virtual ~DiagramData() {} - void build(); - FillPropertiesPtr & getFillProperties() - { return mpFillProperties; } - dgm::Connections & getConnections() - { return maConnections; } - dgm::Points & getPoints() - { return maPoints; } - ConnectionNameMap & getConnectionNameMap() - { return maConnectionNameMap; } - StringMap & getPresOfNameMap() - { return maPresOfNameMap; } - PointNameMap & getPointNameMap() - { return maPointNameMap; } - PointsNameMap & getPointsPresNameMap() - { return maPointsPresNameMap; } - ::std::vector &getExtDrawings() - { return maExtDrawings; } - const dgm::Point* getRootPoint() const; - void dump() const; - OUString getString() const override; - std::vector> getChildren(const OUString& rParentId) const override; - void addNode(const OUString& rText) override; - -private: - void getChildrenString(OUStringBuffer& rBuf, const dgm::Point* pPoint, sal_Int32 nLevel) const; - void addConnection(sal_Int32 nType, const OUString& sSourceId, const OUString& sDestId); - - ::std::vector maExtDrawings; - FillPropertiesPtr mpFillProperties; - dgm::Connections maConnections; - dgm::Points maPoints; - PointNameMap maPointNameMap; - PointsNameMap maPointsPresNameMap; - ConnectionNameMap maConnectionNameMap; - StringMap maPresOfNameMap; -}; - -typedef std::shared_ptr< DiagramData > DiagramDataPtr; - typedef std::map LayoutAtomMap; typedef std::map PresPointShapeMap; diff --git a/oox/source/drawingml/diagram/diagramdefinitioncontext.cxx b/oox/source/drawingml/diagram/diagramdefinitioncontext.cxx index 7b404761b441..731cec9a4702 100644 --- a/oox/source/drawingml/diagram/diagramdefinitioncontext.cxx +++ b/oox/source/drawingml/diagram/diagramdefinitioncontext.cxx @@ -18,8 +18,9 @@ */ #include "diagramdefinitioncontext.hxx" -#include "layoutnodecontext.hxx" +#include "datamodel.hxx" #include "datamodelcontext.hxx" +#include "layoutnodecontext.hxx" #include #include diff --git a/solenv/clang-format/blacklist b/solenv/clang-format/blacklist index fcf6e3c6ed84..b4d2cbcadf64 100644 --- a/solenv/clang-format/blacklist +++ b/solenv/clang-format/blacklist @@ -8903,6 +8903,8 @@ oox/source/drawingml/customshapepresetdata.cxx oox/source/drawingml/customshapeproperties.cxx oox/source/drawingml/diagram/constraintlistcontext.cxx oox/source/drawingml/diagram/constraintlistcontext.hxx +oox/source/drawingml/diagram/datamodel.cxx +oox/source/drawingml/diagram/datamodel.hxx oox/source/drawingml/diagram/datamodelcontext.cxx oox/source/drawingml/diagram/datamodelcontext.hxx oox/source/drawingml/diagram/diagram.cxx -- cgit