diff options
author | Grzegorz Araminowicz <grzegorz.araminowicz@collabora.com> | 2019-06-26 10:42:28 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2019-07-01 12:04:14 +0200 |
commit | 5cdf0c71ae8bc9f1e4a52e6e4e2ea6d8550f1edd (patch) | |
tree | dccb27164e950b538916b2f4eef15bcf5db8acd2 /oox | |
parent | 9fbedb7929936a45967ae49bc15b985f95e2ebd3 (diff) |
SmartArt: all visitors follow data presentation nodes
* visitors now are keeping track of current presentation node instead of
looking it up by name
* extracted visitor base class that follows if/else and for-each nodes
* moved condition logic from ConditionAtom to visitor, as it depends on
visitor state
Change-Id: Iede86cd74a6098f2398a77b6cb3e9c6272dbfe4b
Reviewed-on: https://gerrit.libreoffice.org/74732
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Diffstat (limited to 'oox')
-rw-r--r-- | oox/Library_oox.mk | 1 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/diagram.cxx | 7 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/diagram.hxx | 4 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/diagramlayoutatoms.cxx | 128 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/diagramlayoutatoms.hxx | 26 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/layoutatomvisitorbase.cxx | 173 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/layoutatomvisitorbase.hxx | 99 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/layoutatomvisitors.cxx | 197 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/layoutatomvisitors.hxx | 93 |
9 files changed, 403 insertions, 325 deletions
diff --git a/oox/Library_oox.mk b/oox/Library_oox.mk index 7da04f81a6ce..2d4718a320cb 100644 --- a/oox/Library_oox.mk +++ b/oox/Library_oox.mk @@ -144,6 +144,7 @@ $(eval $(call gb_Library_add_exception_objects,oox,\ oox/source/drawingml/diagram/diagramdefinitioncontext \ oox/source/drawingml/diagram/diagramfragmenthandler \ oox/source/drawingml/diagram/diagramlayoutatoms \ + oox/source/drawingml/diagram/layoutatomvisitorbase \ oox/source/drawingml/diagram/layoutatomvisitors \ oox/source/drawingml/diagram/layoutnodecontext \ oox/source/drawingml/drawingmltypes \ diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx index 7460c52f1fed..2a5f2d054721 100644 --- a/oox/source/drawingml/diagram/diagram.cxx +++ b/oox/source/drawingml/diagram/diagram.cxx @@ -348,15 +348,16 @@ void Diagram::addTo( const ShapePtr & pParentShape ) pParentShape->setChildSize(pParentShape->getSize()); - if( mpLayout->getNode() ) + const dgm::Point* pRootPoint = mpData->getRootPoint(); + if (mpLayout->getNode() && pRootPoint) { // create Shape hierarchy - ShapeCreationVisitor aCreationVisitor(pParentShape, *this); + ShapeCreationVisitor aCreationVisitor(*this, pRootPoint, pParentShape); mpLayout->getNode()->setExistingShape(pParentShape); mpLayout->getNode()->accept(aCreationVisitor); // layout shapes - now all shapes are created - ShapeLayoutingVisitor aLayoutingVisitor; + ShapeLayoutingVisitor aLayoutingVisitor(*this, pRootPoint); mpLayout->getNode()->accept(aLayoutingVisitor); sortChildrenByZOrder(pParentShape); diff --git a/oox/source/drawingml/diagram/diagram.hxx b/oox/source/drawingml/diagram/diagram.hxx index cf12dce576a7..e8839d1b0fe6 100644 --- a/oox/source/drawingml/diagram/diagram.hxx +++ b/oox/source/drawingml/diagram/diagram.hxx @@ -208,6 +208,7 @@ private: typedef std::shared_ptr< DiagramData > DiagramDataPtr; typedef std::map<OUString, LayoutAtomPtr> LayoutAtomMap; +typedef std::map<const dgm::Point*, ShapePtr> PresPointShapeMap; class DiagramLayout { @@ -239,6 +240,8 @@ public: { return mpStyleData; } LayoutAtomMap & getLayoutAtomMap() { return maLayoutAtomMap; } + PresPointShapeMap & getPresPointShapeMap() + { return maPresPointShapeMap; } private: const Diagram& mrDgm; @@ -256,6 +259,7 @@ private: // clrData LayoutAtomMap maLayoutAtomMap; + PresPointShapeMap maPresPointShapeMap; }; typedef std::shared_ptr< DiagramLayout > DiagramLayoutPtr; diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx index 6497e3ba22cf..d4845c768331 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx @@ -19,6 +19,8 @@ #include "diagramlayoutatoms.hxx" +#include "layoutatomvisitorbase.hxx" + #include <basegfx/numeric/ftools.hxx> #include <sal/log.hxx> @@ -248,17 +250,6 @@ void ChooseAtom::accept( LayoutAtomVisitor& rVisitor ) rVisitor.visit(*this); } -const std::vector<LayoutAtomPtr>& ChooseAtom::getChildren() const -{ - for (const auto& pChild : mpChildNodes) - { - const ConditionAtomPtr pCond = std::dynamic_pointer_cast<ConditionAtom>(pChild); - if (pCond && pCond->getDecision()) - return pCond->getChildren(); - } - return maEmptyChildren; -} - ConditionAtom::ConditionAtom(LayoutNode& rLayoutNode, bool isElse, const Reference< XFastAttributeList >& xAttributes) : LayoutAtom(rLayoutNode), mIsElse(isElse) @@ -283,18 +274,6 @@ bool ConditionAtom::compareResult(sal_Int32 nOperator, sal_Int32 nFirst, sal_Int } } -const dgm::Point* ConditionAtom::getPresNode() const -{ - const DiagramData::PointsNameMap& rPoints = mrLayoutNode.getDiagram().getData()->getPointsPresNameMap(); - DiagramData::PointsNameMap::const_iterator aDataNode = rPoints.find(mrLayoutNode.getName()); - if (aDataNode != rPoints.end()) - { - SAL_WARN_IF(aDataNode->second.size() > 1, "oox.drawingml", "multiple nodes found; taking first one"); - return aDataNode->second.front(); - } - return nullptr; -} - namespace { /** @@ -325,69 +304,63 @@ OUString navigate(const LayoutNode& rLayoutNode, sal_Int32 nType, const OUString } } -sal_Int32 ConditionAtom::getNodeCount() const +sal_Int32 ConditionAtom::getNodeCount(const dgm::Point* pPresPoint) const { sal_Int32 nCount = 0; - const dgm::Point* pPoint = getPresNode(); - if (pPoint) - { - OUString sNodeId - = navigate(mrLayoutNode, XML_presOf, pPoint->msModelId, /*bSourceToDestination*/ false); + OUString sNodeId = navigate(mrLayoutNode, XML_presOf, pPresPoint->msModelId, /*bSourceToDestination*/ false); - if (sNodeId.isEmpty()) - { - // The current layout node is not a presentation of anything. Look - // up the first presentation child of the layout node. - OUString sFirstPresChildId = navigate(mrLayoutNode, XML_presParOf, pPoint->msModelId, - /*bSourceToDestination*/ true); - if (!sFirstPresChildId.isEmpty()) - // It has a presentation child: is that a presentation of a - // model node? - sNodeId = navigate(mrLayoutNode, XML_presOf, sFirstPresChildId, - /*bSourceToDestination*/ false); - } + if (sNodeId.isEmpty()) + { + // The current layout node is not a presentation of anything. Look + // up the first presentation child of the layout node. + OUString sFirstPresChildId = navigate(mrLayoutNode, XML_presParOf, pPresPoint->msModelId, + /*bSourceToDestination*/ true); + if (!sFirstPresChildId.isEmpty()) + // It has a presentation child: is that a presentation of a + // model node? + sNodeId = navigate(mrLayoutNode, XML_presOf, sFirstPresChildId, + /*bSourceToDestination*/ false); + } - if (!sNodeId.isEmpty()) - { - for (const auto& aCxn : mrLayoutNode.getDiagram().getData()->getConnections()) - if (aCxn.mnType == XML_parOf && aCxn.msSourceId == sNodeId) - nCount++; - } - else - { - // No presentation child is a presentation of a model node: just - // count presentation children. - for (const auto& aCxn : mrLayoutNode.getDiagram().getData()->getConnections()) - if (aCxn.mnType == XML_presParOf && aCxn.msSourceId == pPoint->msModelId) - nCount++; - } + if (!sNodeId.isEmpty()) + { + for (const auto& aCxn : mrLayoutNode.getDiagram().getData()->getConnections()) + if (aCxn.mnType == XML_parOf && aCxn.msSourceId == sNodeId) + nCount++; + } + else + { + // No presentation child is a presentation of a model node: just + // count presentation children. + for (const auto& aCxn : mrLayoutNode.getDiagram().getData()->getConnections()) + if (aCxn.mnType == XML_presParOf && aCxn.msSourceId == pPresPoint->msModelId) + nCount++; } + return nCount; } -bool ConditionAtom::getDecision() const +bool ConditionAtom::getDecision(const dgm::Point* pPresPoint) const { if (mIsElse) return true; + if (!pPresPoint) + return false; switch (maCond.mnFunc) { case XML_var: { - const dgm::Point* pPoint = getPresNode(); - if (!pPoint) - break; - if (maCond.mnArg == XML_dir) - return compareResult(maCond.mnOp, pPoint->mnDirection, maCond.mnVal); + return compareResult(maCond.mnOp, pPresPoint->mnDirection, maCond.mnVal); else if (maCond.mnArg == XML_hierBranch) { - sal_Int32 nHierarchyBranch = pPoint->moHierarchyBranch.get(XML_std); - if (!pPoint->moHierarchyBranch.has()) + sal_Int32 nHierarchyBranch = pPresPoint->moHierarchyBranch.get(XML_std); + if (!pPresPoint->moHierarchyBranch.has()) { // If <dgm:hierBranch> is missing in the current presentation // point, ask the parent. - OUString aParent = navigate(mrLayoutNode, XML_presParOf, pPoint->msModelId, + OUString aParent = navigate(mrLayoutNode, XML_presParOf, pPresPoint->msModelId, /*bSourceToDestination*/ false); DiagramData::PointNameMap& rPointNameMap = mrLayoutNode.getDiagram().getData()->getPointNameMap(); @@ -405,11 +378,18 @@ bool ConditionAtom::getDecision() const } case XML_cnt: - return compareResult(maCond.mnOp, getNodeCount(), maCond.msVal.toInt32()); + return compareResult(maCond.mnOp, getNodeCount(pPresPoint), maCond.msVal.toInt32()); case XML_maxDepth: + // TODO: probably depth from current point - docs are unclear return compareResult(maCond.mnOp, mrLayoutNode.getDiagram().getData()->getMaxDepth(), maCond.msVal.toInt32()); + case XML_depth: + case XML_pos: + case XML_revPos: + case XML_posEven: + case XML_posOdd: + // TODO default: SAL_WARN("oox.drawingml", "unknown function " << maCond.mnFunc); break; @@ -732,7 +712,12 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, // hierRoot is the manager -> employees vertical linear path, // hierChild is the first employee -> last employee horizontal // linear path. - const sal_Int32 nDir = mnType == XML_hierRoot ? XML_fromT : XML_fromL; + sal_Int32 nDir = XML_fromL; + if (mnType == XML_hierRoot) + nDir = XML_fromT; + else if (maMap.count(XML_linDir)) + nDir = maMap.find(XML_linDir)->second; + if (rShape->getChildren().empty() || rShape->getSize().Width == 0 || rShape->getSize().Height == 0) break; @@ -782,18 +767,25 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, aChildSize.Width /= nCount; aChildSize.Height *= fHeightScale; aChildSize.Width *= fWidthScale; + awt::Size aConnectorSize = aChildSize; + aConnectorSize.Width = 1; awt::Point aChildPos(nXOffset, 0); for (auto& pChild : rShape->getChildren()) { pChild->setPosition(aChildPos); - pChild->setSize(aChildSize); - pChild->setChildSize(aChildSize); if (mnType == XML_hierChild && pChild->getSubType() == XML_conn) + { // Connectors should not influence the position of // non-connect shapes. + pChild->setSize(aConnectorSize); + pChild->setChildSize(aConnectorSize); continue; + } + + pChild->setSize(aChildSize); + pChild->setChildSize(aChildSize); if (nDir == XML_fromT) aChildPos.Y += aChildSize.Height + aChildSize.Height * fSpace; diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx index ef99229b66ab..dc58fc4b8621 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx @@ -112,7 +112,7 @@ private: void setParent(const LayoutAtomPtr& pParent) { mpParent = pParent; } public: - virtual const std::vector<LayoutAtomPtr>& getChildren() const + const std::vector<LayoutAtomPtr>& getChildren() const { return mpChildNodes; } LayoutAtomPtr getParent() const { return mpParent.lock(); } @@ -208,11 +208,11 @@ class ConditionAtom public: explicit ConditionAtom(LayoutNode& rLayoutNode, bool isElse, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttributes); virtual void accept( LayoutAtomVisitor& ) override; - bool getDecision() const; + bool getDecision(const dgm::Point* pPresPoint) const; + private: static bool compareResult(sal_Int32 nOperator, sal_Int32 nFirst, sal_Int32 nSecond); - const dgm::Point* getPresNode() const; - sal_Int32 getNodeCount() const; + sal_Int32 getNodeCount(const dgm::Point* pPresPoint) const; bool const mIsElse; IteratorAttr maIter; @@ -228,14 +228,8 @@ class ChooseAtom public: ChooseAtom(LayoutNode& rLayoutNode) : LayoutAtom(rLayoutNode) -#if defined __clang__ && __clang_major__ == 3 && __clang_minor__ == 8 - , maEmptyChildren() -#endif {} virtual void accept( LayoutAtomVisitor& ) override; - virtual const std::vector<LayoutAtomPtr>& getChildren() const override; -private: - const std::vector<LayoutAtomPtr> maEmptyChildren; }; class LayoutNode @@ -298,18 +292,6 @@ private: typedef std::shared_ptr< ShapeAtom > ShapeAtomPtr; -struct LayoutAtomVisitor -{ - virtual ~LayoutAtomVisitor() {} - virtual void visit(ConstraintAtom& rAtom) = 0; - virtual void visit(AlgAtom& rAtom) = 0; - virtual void visit(ForEachAtom& rAtom) = 0; - virtual void visit(ConditionAtom& rAtom) = 0; - virtual void visit(ChooseAtom& rAtom) = 0; - virtual void visit(LayoutNode& rAtom) = 0; - virtual void visit(ShapeAtom& rAtom) = 0; -}; - } } #endif diff --git a/oox/source/drawingml/diagram/layoutatomvisitorbase.cxx b/oox/source/drawingml/diagram/layoutatomvisitorbase.cxx new file mode 100644 index 000000000000..49b1d801bee9 --- /dev/null +++ b/oox/source/drawingml/diagram/layoutatomvisitorbase.cxx @@ -0,0 +1,173 @@ +/* -*- 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 "layoutatomvisitorbase.hxx" + +#include <sal/log.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace oox { namespace drawingml { + +void LayoutAtomVisitorBase::defaultVisit(LayoutAtom const& rAtom) +{ + for (const auto& pAtom : rAtom.getChildren()) + pAtom->accept(*this); +} + +void LayoutAtomVisitorBase::visit(ChooseAtom& rAtom) +{ + for (const auto& pChild : rAtom.getChildren()) + { + const ConditionAtomPtr pCond = std::dynamic_pointer_cast<ConditionAtom>(pChild); + if (pCond && pCond->getDecision(mpCurrentNode)) + { + SAL_INFO("oox.drawingml", "Entering if node: " << pCond->getName()); + pCond->accept(*this); + break; + } + } +} + +void LayoutAtomVisitorBase::visit(ConditionAtom& rAtom) +{ + defaultVisit(rAtom); +} + +void LayoutAtomVisitorBase::visit(ForEachAtom& rAtom) +{ + if (!rAtom.getRef().isEmpty()) + { + if (LayoutAtomPtr pRefAtom = rAtom.getRefAtom()) + pRefAtom->accept(*this); + return; + } + + if (rAtom.iterator().mbHideLastTrans && rAtom.iterator().mnAxis == XML_followSib) + { + // If last transition is hidden and the axis is the follow sibling, + // then the last atom should not be visited. + if (mnCurrIdx + mnCurrStep >= mnCurrCnt) + return; + } + + sal_Int32 nChildren = 1; + // Approximate the non-assistant type with the node type. + if (rAtom.iterator().mnPtType == XML_node || rAtom.iterator().mnPtType == XML_nonAsst) + { + // count child data nodes - check all child Atoms for "name" + // attribute that is contained in diagram's + // getPointsPresNameMap() + ShallowPresNameVisitor aVisitor(mrDgm, mpCurrentNode); + for (const auto& pAtom : rAtom.getChildren()) + pAtom->accept(aVisitor); + nChildren = aVisitor.getCount(); + } + + const sal_Int32 nCnt = std::min( + nChildren, + rAtom.iterator().mnCnt==-1 ? nChildren : rAtom.iterator().mnCnt); + + const sal_Int32 nOldIdx = mnCurrIdx; + const sal_Int32 nOldStep = mnCurrStep; + const sal_Int32 nOldCnt = mnCurrCnt; + const sal_Int32 nStep = rAtom.iterator().mnStep; + mnCurrStep = nStep; + mnCurrCnt = nCnt; + for( mnCurrIdx=0; mnCurrIdx<nCnt && nStep>0; mnCurrIdx+=nStep ) + { + // TODO there is likely some conditions + for (const auto& pAtom : rAtom.getChildren()) + pAtom->accept(*this); + } + + // and restore idx + mnCurrIdx = nOldIdx; + mnCurrStep = nOldStep; + mnCurrCnt = nOldCnt; +} + +void LayoutAtomVisitorBase::visit(LayoutNode& rAtom) +{ + // TODO: deduplicate code in descendants + + // stop processing if it's not a child of previous LayoutNode + + const DiagramData::PointsNameMap::const_iterator aDataNode + = mrDgm.getData()->getPointsPresNameMap().find(rAtom.getName()); + if (aDataNode == mrDgm.getData()->getPointsPresNameMap().end() + || mnCurrIdx >= static_cast<sal_Int32>(aDataNode->second.size())) + return; + + const dgm::Point* pNewNode = aDataNode->second.at(mnCurrIdx); + if (!mpCurrentNode || !pNewNode) + return; + + bool bIsChild = false; + for (const auto& aConnection : mrDgm.getData()->getConnections()) + if (aConnection.msSourceId == mpCurrentNode->msModelId + && aConnection.msDestId == pNewNode->msModelId) + bIsChild = true; + + if (!bIsChild) + return; + + const dgm::Point* pPreviousNode = mpCurrentNode; + mpCurrentNode = pNewNode; + mnCurrLevel++; + + defaultVisit(rAtom); + + mnCurrLevel--; + mpCurrentNode = pPreviousNode; +} + +void ShallowPresNameVisitor::visit(ConstraintAtom& /*rAtom*/) +{ + // stop processing +} + +void ShallowPresNameVisitor::visit(AlgAtom& /*rAtom*/) +{ + // stop processing +} + +void ShallowPresNameVisitor::visit(ForEachAtom& rAtom) +{ + defaultVisit(rAtom); +} + +void ShallowPresNameVisitor::visit(LayoutNode& rAtom) +{ + DiagramData::PointsNameMap::const_iterator aDataNode = + mrDgm.getData()->getPointsPresNameMap().find(rAtom.getName()); + if( aDataNode != mrDgm.getData()->getPointsPresNameMap().end() ) + mnCnt = std::max(mnCnt, + aDataNode->second.size()); +} + +void ShallowPresNameVisitor::visit(ShapeAtom& /*rAtom*/) +{ + // stop processing +} + +} } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/drawingml/diagram/layoutatomvisitorbase.hxx b/oox/source/drawingml/diagram/layoutatomvisitorbase.hxx new file mode 100644 index 000000000000..25f2b4dea54b --- /dev/null +++ b/oox/source/drawingml/diagram/layoutatomvisitorbase.hxx @@ -0,0 +1,99 @@ +/* -*- 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_LAYOUTATOMVISITORBASE_HXX +#define INCLUDED_OOX_SOURCE_DRAWINGML_DIAGRAM_LAYOUTATOMVISITORBASE_HXX + +#include <memory> + +#include <oox/drawingml/shape.hxx> +#include "diagram.hxx" +#include "diagramlayoutatoms.hxx" + +namespace oox { namespace drawingml { + +struct LayoutAtomVisitor +{ + virtual ~LayoutAtomVisitor() {} + virtual void visit(ConstraintAtom& rAtom) = 0; + virtual void visit(AlgAtom& rAtom) = 0; + virtual void visit(ForEachAtom& rAtom) = 0; + virtual void visit(ConditionAtom& rAtom) = 0; + virtual void visit(ChooseAtom& rAtom) = 0; + virtual void visit(LayoutNode& rAtom) = 0; + virtual void visit(ShapeAtom& rAtom) = 0; +}; + +// basic visitor implementation that follows if/else and for-each nodes +// and keeps track of current position in data tree +class LayoutAtomVisitorBase : public LayoutAtomVisitor +{ +public: + LayoutAtomVisitorBase(const Diagram& rDgm, const dgm::Point* pRootPoint) : + mrDgm(rDgm), + mpCurrentNode(pRootPoint), + mnCurrIdx(0), + mnCurrStep(0), + mnCurrCnt(0), + mnCurrLevel(0) + {} + + void defaultVisit(LayoutAtom const& rAtom); + + using LayoutAtomVisitor::visit; + virtual void visit(ForEachAtom& rAtom) override; + virtual void visit(ConditionAtom& rAtom) override; + virtual void visit(ChooseAtom& rAtom) override; + virtual void visit(LayoutNode& rAtom) override; + +protected: + const Diagram& mrDgm; + const dgm::Point* mpCurrentNode; + sal_Int32 mnCurrIdx; + sal_Int32 mnCurrStep; + sal_Int32 mnCurrCnt; + sal_Int32 mnCurrLevel; +}; + +class ShallowPresNameVisitor : public LayoutAtomVisitorBase +{ +public: + explicit ShallowPresNameVisitor(const Diagram& rDgm, const dgm::Point* pRootPoint) : + LayoutAtomVisitorBase(rDgm, pRootPoint), + mnCnt(0) + {} + + using LayoutAtomVisitorBase::visit; + virtual void visit(ConstraintAtom& rAtom) override; + virtual void visit(AlgAtom& rAtom) override; + virtual void visit(ForEachAtom& rAtom) override; + virtual void visit(LayoutNode& rAtom) override; + virtual void visit(ShapeAtom& rAtom) override; + + size_t getCount() const { return mnCnt; } + +private: + size_t mnCnt; +}; + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/drawingml/diagram/layoutatomvisitors.cxx b/oox/source/drawingml/diagram/layoutatomvisitors.cxx index aa1d21b179f1..b72133033470 100644 --- a/oox/source/drawingml/diagram/layoutatomvisitors.cxx +++ b/oox/source/drawingml/diagram/layoutatomvisitors.cxx @@ -30,12 +30,6 @@ using namespace ::oox::core; namespace oox { namespace drawingml { -void ShapeCreationVisitor::defaultVisit(LayoutAtom const & rAtom) -{ - for (const auto& pAtom : rAtom.getChildren()) - pAtom->accept(*this); -} - void ShapeCreationVisitor::visit(ConstraintAtom& /*rAtom*/) { // stop processing @@ -46,71 +40,6 @@ void ShapeCreationVisitor::visit(AlgAtom& rAtom) mpParentShape->setAspectRatio(rAtom.getAspectRatio()); } -void ShapeCreationVisitor::visit(ForEachAtom& rAtom) -{ - if (!rAtom.getRef().isEmpty()) - { - if (LayoutAtomPtr pRefAtom = rAtom.getRefAtom()) - pRefAtom->accept(*this); - return; - } - - if (rAtom.iterator().mbHideLastTrans && rAtom.iterator().mnAxis == XML_followSib) - { - // If last transition is hidden and the axis is the follow sibling, - // then the last atom should not be visited. - if (mnCurrIdx + mnCurrStep >= mnCurrCnt) - return; - } - - const std::vector<LayoutAtomPtr>& rChildren=rAtom.getChildren(); - - sal_Int32 nChildren=1; - // Approximate the non-assistant type with the node type. - if (rAtom.iterator().mnPtType == XML_node || rAtom.iterator().mnPtType == XML_nonAsst) - { - // count child data nodes - check all child Atoms for "name" - // attribute that is contained in diagram's - // getPointsPresNameMap() - ShallowPresNameVisitor aVisitor(mrDgm); - for (const auto& pAtom : rChildren) - pAtom->accept(aVisitor); - nChildren = aVisitor.getCount(); - } - - const sal_Int32 nCnt = std::min( - nChildren, - rAtom.iterator().mnCnt==-1 ? nChildren : rAtom.iterator().mnCnt); - - const sal_Int32 nOldIdx=mnCurrIdx; - const sal_Int32 nOldStep = mnCurrStep; - const sal_Int32 nOldCnt = mnCurrCnt; - const sal_Int32 nStep=rAtom.iterator().mnStep; - mnCurrStep = nStep; - mnCurrCnt = nCnt; - for( mnCurrIdx=0; mnCurrIdx<nCnt && nStep>0; mnCurrIdx+=nStep ) - { - // TODO there is likely some conditions - for (const auto& pAtom : rChildren) - pAtom->accept(*this); - } - - // and restore idx - mnCurrIdx = nOldIdx; - mnCurrStep = nOldStep; - mnCurrCnt = nOldCnt; -} - -void ShapeCreationVisitor::visit(ConditionAtom& rAtom) -{ - defaultVisit(rAtom); -} - -void ShapeCreationVisitor::visit(ChooseAtom& rAtom) -{ - defaultVisit(rAtom); -} - void ShapeCreationVisitor::visit(LayoutNode& rAtom) { // stop processing if it's not a child of previous LayoutNode @@ -141,11 +70,12 @@ void ShapeCreationVisitor::visit(LayoutNode& rAtom) { pShape->setInternalName(rAtom.getName()); rAtom.addNodeShape(pShape, mnCurrLevel); + mrDgm.getLayout()->getPresPointShapeMap()[pNewNode] = pShape; } } else { - ShapeTemplateVisitor aTemplateVisitor; + ShapeTemplateVisitor aTemplateVisitor(mrDgm, pNewNode); aTemplateVisitor.defaultVisit(rAtom); ShapePtr pShape = aTemplateVisitor.getShapeCopy(); @@ -162,6 +92,7 @@ void ShapeCreationVisitor::visit(LayoutNode& rAtom) pCurrParent->addChild(pShape); pCurrParent = pShape; rAtom.addNodeShape(pShape, mnCurrLevel); + mrDgm.getLayout()->getPresPointShapeMap()[pNewNode] = pShape; } } else @@ -198,13 +129,6 @@ void ShapeCreationVisitor::visit(ShapeAtom& /*rAtom*/) // stop processing } -void ShapeTemplateVisitor::defaultVisit(LayoutAtom const & rAtom) -{ - // visit all children, one of them needs to be the layout algorithm - for (const auto& pAtom : rAtom.getChildren()) - pAtom->accept(*this); -} - void ShapeTemplateVisitor::visit(ConstraintAtom& /*rAtom*/) { // stop processing @@ -220,16 +144,6 @@ void ShapeTemplateVisitor::visit(ForEachAtom& /*rAtom*/) // stop processing } -void ShapeTemplateVisitor::visit(ConditionAtom& rAtom) -{ - defaultVisit(rAtom); -} - -void ShapeTemplateVisitor::visit(ChooseAtom& rAtom) -{ - defaultVisit(rAtom); -} - void ShapeTemplateVisitor::visit(LayoutNode& /*rAtom*/) { // stop processing - only traverse Condition/Choose atoms @@ -253,13 +167,6 @@ void ShapeTemplateVisitor::visit(ShapeAtom& rAtom) mpShape->cloneFillProperties(); } -void ShapeLayoutingVisitor::defaultVisit(LayoutAtom const & rAtom) -{ - // visit all children, one of them needs to be the layout algorithm - for (const auto& pAtom : rAtom.getChildren()) - pAtom->accept(*this); -} - void ShapeLayoutingVisitor::visit(ConstraintAtom& rAtom) { if (meLookFor == CONSTRAINT) @@ -270,46 +177,44 @@ void ShapeLayoutingVisitor::visit(AlgAtom& rAtom) { if (meLookFor == ALGORITHM) { - auto pShapes = rAtom.getLayoutNode().getNodeShapes().find(mnCurrLevel); - if (pShapes != rAtom.getLayoutNode().getNodeShapes().end()) - for (const auto& pShape : pShapes->second) - rAtom.layoutShape(pShape, maConstraints, mnCurrLevel); + const PresPointShapeMap aMap = rAtom.getLayoutNode().getDiagram().getLayout()->getPresPointShapeMap(); + auto pShape = aMap.find(mpCurrentNode); + if (pShape != aMap.end()) + rAtom.layoutShape(pShape->second, maConstraints, mnCurrLevel); } } -void ShapeLayoutingVisitor::visit(ForEachAtom& rAtom) +void ShapeLayoutingVisitor::visit(LayoutNode& rAtom) { - if (!rAtom.getRef().isEmpty()) - { - if (LayoutAtomPtr pRefAtom = rAtom.getRefAtom()) - pRefAtom->accept(*this); + if (meLookFor != LAYOUT_NODE) return; - } - - defaultVisit(rAtom); -} -void ShapeLayoutingVisitor::visit(ConditionAtom& rAtom) -{ - defaultVisit(rAtom); -} + // stop processing if it's not a child of previous LayoutNode -void ShapeLayoutingVisitor::visit(ChooseAtom& rAtom) -{ - defaultVisit(rAtom); -} + const DiagramData::PointsNameMap::const_iterator aDataNode + = mrDgm.getData()->getPointsPresNameMap().find(rAtom.getName()); + if (aDataNode == mrDgm.getData()->getPointsPresNameMap().end() + || mnCurrIdx >= static_cast<sal_Int32>(aDataNode->second.size())) + return; -void ShapeLayoutingVisitor::visit(LayoutNode& rAtom) -{ - if (meLookFor != LAYOUT_NODE) + const dgm::Point* pNewNode = aDataNode->second.at(mnCurrIdx); + if (!mpCurrentNode || !pNewNode) return; - // stop processing if there is no more shapes on this level - if (rAtom.getNodeShapes().empty() || mnCurrLevel > rAtom.getNodeShapes().rbegin()->first) + bool bIsChild = false; + for (const auto& aConnection : mrDgm.getData()->getConnections()) + if (aConnection.msSourceId == mpCurrentNode->msModelId + && aConnection.msDestId == pNewNode->msModelId) + bIsChild = true; + + if (!bIsChild) return; size_t nParentConstraintsNumber = maConstraints.size(); + const dgm::Point* pPreviousNode = mpCurrentNode; + mpCurrentNode = pNewNode; + // process alg atoms first, nested layout nodes afterwards meLookFor = CONSTRAINT; defaultVisit(rAtom); @@ -320,6 +225,7 @@ void ShapeLayoutingVisitor::visit(LayoutNode& rAtom) meLookFor = LAYOUT_NODE; defaultVisit(rAtom); mnCurrLevel--; + mpCurrentNode = pPreviousNode; // delete added constraints, keep parent constraints maConstraints.erase(maConstraints.begin() + nParentConstraintsNumber, maConstraints.end()); @@ -330,53 +236,6 @@ void ShapeLayoutingVisitor::visit(ShapeAtom& /*rAtom*/) // stop processing } -void ShallowPresNameVisitor::defaultVisit(LayoutAtom const & rAtom) -{ - // visit all children, at least one of them needs to have proper - // name set - for (const auto& pAtom : rAtom.getChildren()) - pAtom->accept(*this); -} - -void ShallowPresNameVisitor::visit(ConstraintAtom& /*rAtom*/) -{ - // stop processing -} - -void ShallowPresNameVisitor::visit(AlgAtom& /*rAtom*/) -{ - // stop processing -} - -void ShallowPresNameVisitor::visit(ForEachAtom& rAtom) -{ - defaultVisit(rAtom); -} - -void ShallowPresNameVisitor::visit(ConditionAtom& rAtom) -{ - defaultVisit(rAtom); -} - -void ShallowPresNameVisitor::visit(ChooseAtom& rAtom) -{ - defaultVisit(rAtom); -} - -void ShallowPresNameVisitor::visit(LayoutNode& rAtom) -{ - DiagramData::PointsNameMap::const_iterator aDataNode= - mrDgm.getData()->getPointsPresNameMap().find(rAtom.getName()); - if( aDataNode != mrDgm.getData()->getPointsPresNameMap().end() ) - mnCnt = std::max(mnCnt, - aDataNode->second.size()); -} - -void ShallowPresNameVisitor::visit(ShapeAtom& /*rAtom*/) -{ - // stop processing -} - } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/drawingml/diagram/layoutatomvisitors.hxx b/oox/source/drawingml/diagram/layoutatomvisitors.hxx index 4a61a75eb0f5..2950fb01a17c 100644 --- a/oox/source/drawingml/diagram/layoutatomvisitors.hxx +++ b/oox/source/drawingml/diagram/layoutatomvisitors.hxx @@ -25,101 +25,68 @@ #include <oox/drawingml/shape.hxx> #include "diagram.hxx" #include "diagramlayoutatoms.hxx" +#include "layoutatomvisitorbase.hxx" namespace oox { namespace drawingml { -class ShapeCreationVisitor : public LayoutAtomVisitor +class ShapeCreationVisitor : public LayoutAtomVisitorBase { - ShapePtr mpParentShape; - const Diagram& mrDgm; - sal_Int32 mnCurrIdx; - sal_Int32 mnCurrStep = 0; - sal_Int32 mnCurrCnt = 0; - sal_Int32 mnCurrLevel; - const dgm::Point* mpCurrentNode; - - void defaultVisit(LayoutAtom const & rAtom); +public: + ShapeCreationVisitor(const Diagram& rDgm, + const dgm::Point* pRootPoint, + const ShapePtr& rParentShape) : + LayoutAtomVisitorBase(rDgm, pRootPoint), + mpParentShape(rParentShape) + {} + + using LayoutAtomVisitorBase::visit; virtual void visit(ConstraintAtom& rAtom) override; virtual void visit(AlgAtom& rAtom) override; - virtual void visit(ForEachAtom& rAtom) override; - virtual void visit(ConditionAtom& rAtom) override; - virtual void visit(ChooseAtom& rAtom) override; virtual void visit(LayoutNode& rAtom) override; virtual void visit(ShapeAtom& rAtom) override; -public: - ShapeCreationVisitor(const ShapePtr& rParentShape, - const Diagram& rDgm) : - mpParentShape(rParentShape), - mrDgm(rDgm), - mnCurrIdx(0), - mnCurrLevel(0), - mpCurrentNode(rDgm.getData()->getRootPoint()) - {} +private: + ShapePtr mpParentShape; }; -class ShapeTemplateVisitor : public LayoutAtomVisitor +class ShapeTemplateVisitor : public LayoutAtomVisitorBase { - ShapePtr mpShape; +public: + ShapeTemplateVisitor(const Diagram& rDgm, const dgm::Point* pRootPoint) + : LayoutAtomVisitorBase(rDgm, pRootPoint) + {} + using LayoutAtomVisitorBase::visit; virtual void visit(ConstraintAtom& rAtom) override; virtual void visit(AlgAtom& rAtom) override; virtual void visit(ForEachAtom& rAtom) override; - virtual void visit(ConditionAtom& rAtom) override; - virtual void visit(ChooseAtom& rAtom) override; virtual void visit(LayoutNode& rAtom) override; virtual void visit(ShapeAtom& rAtom) override; -public: - void defaultVisit(LayoutAtom const & rAtom); ShapePtr const & getShapeCopy() const { return mpShape; } + +private: + ShapePtr mpShape; }; -class ShapeLayoutingVisitor : public LayoutAtomVisitor +class ShapeLayoutingVisitor : public LayoutAtomVisitorBase { - std::vector<Constraint> maConstraints; - enum {LAYOUT_NODE, CONSTRAINT, ALGORITHM} meLookFor; - sal_Int32 mnCurrLevel; - - void defaultVisit(LayoutAtom const & rAtom); - virtual void visit(ConstraintAtom& rAtom) override; - virtual void visit(AlgAtom& rAtom) override; - virtual void visit(ForEachAtom& rAtom) override; - virtual void visit(ConditionAtom& rAtom) override; - virtual void visit(ChooseAtom& rAtom) override; - virtual void visit(LayoutNode& rAtom) override; - virtual void visit(ShapeAtom& rAtom) override; - public: - ShapeLayoutingVisitor() : - meLookFor(LAYOUT_NODE), - mnCurrLevel(0) + ShapeLayoutingVisitor(const Diagram& rDgm, const dgm::Point* pRootPoint) : + LayoutAtomVisitorBase(rDgm, pRootPoint), + meLookFor(LAYOUT_NODE) {} -}; -class ShallowPresNameVisitor : public LayoutAtomVisitor -{ - const Diagram& mrDgm; - size_t mnCnt; - - void defaultVisit(LayoutAtom const & rAtom); + using LayoutAtomVisitorBase::visit; virtual void visit(ConstraintAtom& rAtom) override; virtual void visit(AlgAtom& rAtom) override; - virtual void visit(ForEachAtom& rAtom) override; - virtual void visit(ConditionAtom& rAtom) override; - virtual void visit(ChooseAtom& rAtom) override; virtual void visit(LayoutNode& rAtom) override; virtual void visit(ShapeAtom& rAtom) override; -public: - explicit ShallowPresNameVisitor(const Diagram& rDgm) : - mrDgm(rDgm), - mnCnt(0) - {} - - size_t getCount() const - { return mnCnt; } +private: + std::vector<Constraint> maConstraints; + enum {LAYOUT_NODE, CONSTRAINT, ALGORITHM} meLookFor; }; } } |