From 711c0b6331958da4fd53eb6c4f9ecd5a422bb186 Mon Sep 17 00:00:00 2001 From: Grzegorz Araminowicz Date: Fri, 20 Sep 2019 12:53:45 +0200 Subject: SmartArt Edit UI: remove node Removes data node from data model including associated presentation nodes, transition nodes and all connections between them (child-parent and presentation-of). It still doesn't update order of remaining connections after removal, so empty entries can happen. Additional step is needed or using better data structures. Change-Id: I96e0752b6ec5a19ae8e972dbd421314e6c442b53 Reviewed-on: https://gerrit.libreoffice.org/79279 Tested-by: Jenkins Reviewed-by: Grzegorz Araminowicz --- oox/source/drawingml/diagram/datamodel.cxx | 68 ++++++++++++++++++++++++++++-- oox/source/drawingml/diagram/datamodel.hxx | 3 +- 2 files changed, 67 insertions(+), 4 deletions(-) (limited to 'oox/source/drawingml/diagram') diff --git a/oox/source/drawingml/diagram/datamodel.cxx b/oox/source/drawingml/diagram/datamodel.cxx index 1f1794b31854..6b7d05ebe58d 100644 --- a/oox/source/drawingml/diagram/datamodel.cxx +++ b/oox/source/drawingml/diagram/datamodel.cxx @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -137,6 +138,12 @@ std::vector> DiagramData::getChildren(const OUStri pChild->second->msModelId, pChild->second->mpShape->getTextBody()->getParagraphs().front()->getRuns().front()->getText()); } + + // HACK: empty items shouldn't appear there + aChildren.erase(std::remove_if(aChildren.begin(), aChildren.end(), + [](const std::pair& aItem) { return aItem.first.isEmpty(); }), + aChildren.end()); + return aChildren; } @@ -154,7 +161,7 @@ void DiagramData::addConnection(sal_Int32 nType, const OUString& sSourceId, cons rCxn.mnSourceOrder = nMaxOrd + 1; } -void DiagramData::addNode(const OUString& rText) +OUString DiagramData::addNode(const OUString& rText) { const dgm::Point& rDataRoot = *getRootPoint(); OUString sPresRoot; @@ -163,11 +170,13 @@ void DiagramData::addNode(const OUString& rText) sPresRoot = aCxn.msDestId; if (sPresRoot.isEmpty()) - return; + return OUString(); + + OUString sNewNodeId = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8); dgm::Point aDataPoint; aDataPoint.mnType = XML_node; - aDataPoint.msModelId = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8); + aDataPoint.msModelId = sNewNodeId; aDataPoint.mpShape.reset(new Shape()); aDataPoint.mpShape->setTextBody(std::make_shared()); TextRunPtr pTextRun(new TextRun()); @@ -208,6 +217,59 @@ void DiagramData::addNode(const OUString& rText) maPoints.push_back(aPresPoint); build(); + return sNewNodeId; +} + +bool DiagramData::removeNode(const OUString& rNodeId) +{ + // check if it doesn't have children + for (const auto& aCxn : maConnections) + if (aCxn.mnType == XML_parOf && aCxn.msSourceId == rNodeId) + { + SAL_WARN("oox.drawingml", "Node has children - can't be removed"); + return false; + } + + dgm::Connection aParCxn; + for (const auto& aCxn : maConnections) + if (aCxn.mnType == XML_parOf && aCxn.msDestId == rNodeId) + aParCxn = aCxn; + + std::unordered_set aIdsToRemove; + aIdsToRemove.insert(rNodeId); + if (!aParCxn.msParTransId.isEmpty()) + aIdsToRemove.insert(aParCxn.msParTransId); + if (!aParCxn.msSibTransId.isEmpty()) + aIdsToRemove.insert(aParCxn.msSibTransId); + + for (const dgm::Point& rPoint : maPoints) + if (aIdsToRemove.count(rPoint.msPresentationAssociationId)) + aIdsToRemove.insert(rPoint.msModelId); + + // instert also transition nodes + for (const auto& aCxn : maConnections) + if (aIdsToRemove.count(aCxn.msSourceId) || aIdsToRemove.count(aCxn.msDestId)) + if (!aCxn.msPresId.isEmpty()) + aIdsToRemove.insert(aCxn.msPresId); + + // remove connections + maConnections.erase(std::remove_if(maConnections.begin(), maConnections.end(), + [aIdsToRemove](const dgm::Connection& rCxn) { + return aIdsToRemove.count(rCxn.msSourceId) || aIdsToRemove.count(rCxn.msDestId); + }), + maConnections.end()); + + // remove data and presentation nodes + maPoints.erase(std::remove_if(maPoints.begin(), maPoints.end(), + [aIdsToRemove](const dgm::Point& rPoint) { + return aIdsToRemove.count(rPoint.msModelId); + }), + maPoints.end()); + + // TODO: fix source/dest order + + build(); + return true; } #ifdef DEBUG_OOX_DIAGRAM diff --git a/oox/source/drawingml/diagram/datamodel.hxx b/oox/source/drawingml/diagram/datamodel.hxx index b4c7ce7f82f7..7f7f0f4910c5 100644 --- a/oox/source/drawingml/diagram/datamodel.hxx +++ b/oox/source/drawingml/diagram/datamodel.hxx @@ -182,7 +182,8 @@ public: void dump() const; OUString getString() const override; std::vector> getChildren(const OUString& rParentId) const override; - void addNode(const OUString& rText) override; + OUString addNode(const OUString& rText) override; + bool removeNode(const OUString& rNodeId) override; private: void getChildrenString(OUStringBuffer& rBuf, const dgm::Point* pPoint, sal_Int32 nLevel) const; -- cgit